[automerger] Add strings rewrite support into Jetifier. am: 77d16b08dd

Change-Id: I1e2d06c0a5c31a6e1cd75b76710e16ba39784241
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 7b2174e..7dc4050 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -46,6 +46,8 @@
 
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android-support-v*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/support.aidl)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android-support-customtabs_intermediates/src/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android-support-annotations_intermediates)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/annotations/Android.mk b/annotations/Android.mk
index 41abfaa..684a77a 100644
--- a/annotations/Android.mk
+++ b/annotations/Android.mk
@@ -15,11 +15,9 @@
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
 LOCAL_MODULE := android-support-annotations
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under,src/main/java)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/annotations/src/main/java/android/support/annotation/IntDef.java b/annotations/src/main/java/android/support/annotation/IntDef.java
index f621b7f..9945726 100644
--- a/annotations/src/main/java/android/support/annotation/IntDef.java
+++ b/annotations/src/main/java/android/support/annotation/IntDef.java
@@ -46,12 +46,14 @@
  *      flag = true,
  *      value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
  * </code></pre>
+ *
+ * @see LongDef
  */
 @Retention(SOURCE)
 @Target({ANNOTATION_TYPE})
 public @interface IntDef {
     /** Defines the allowed constants for this element */
-    long[] value() default {};
+    int[] value() default {};
 
     /** Defines whether the constants can be used as a flag, or just as an enum (the default) */
     boolean flag() default false;
diff --git a/annotations/src/main/java/android/support/annotation/LongDef.java b/annotations/src/main/java/android/support/annotation/LongDef.java
new file mode 100644
index 0000000..3dea338
--- /dev/null
+++ b/annotations/src/main/java/android/support/annotation/LongDef.java
@@ -0,0 +1,60 @@
+/*
+ * 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.annotation;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that the annotated long element represents
+ * a logical type and that its value should be one of the explicitly
+ * named constants. If the LongDef#flag() attribute is set to true,
+ * multiple constants can be combined.
+ * <p>
+ * Example:
+ * <pre><code>
+ *  &#64;Retention(SOURCE)
+ *  &#64;LongDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
+ *  public @interface NavigationMode {}
+ *  public static final long NAVIGATION_MODE_STANDARD = 0;
+ *  public static final long NAVIGATION_MODE_LIST = 1;
+ *  public static final long NAVIGATION_MODE_TABS = 2;
+ *  ...
+ *  public abstract void setNavigationMode(@NavigationMode long mode);
+ *  &#64;NavigationMode
+ *  public abstract long getNavigationMode();
+ * </code></pre>
+ * For a flag, set the flag attribute:
+ * <pre><code>
+ *  &#64;LongDef(
+ *      flag = true,
+ *      value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
+ * </code></pre>
+ *
+ * @see IntDef
+ */
+@Retention(SOURCE)
+@Target({ANNOTATION_TYPE})
+public @interface LongDef {
+    /** Defines the allowed constants for this element */
+    long[] value() default {};
+
+    /** Defines whether the constants can be used as a flag, or just as an enum (the default) */
+    boolean flag() default false;
+}
\ No newline at end of file
diff --git a/app-toolkit/common/build.gradle b/app-toolkit/common/build.gradle
index bd10317..db61b3f 100644
--- a/app-toolkit/common/build.gradle
+++ b/app-toolkit/common/build.gradle
@@ -24,7 +24,7 @@
 }
 
 dependencies {
-    compile libs.support.annotations
+    compile(SUPPORT_ANNOTATIONS)
 
     testCompile(JUNIT)
     testCompile(MOCKITO_CORE)
diff --git a/app-toolkit/core-testing/build.gradle b/app-toolkit/core-testing/build.gradle
index dca8810..8e7ccfb 100644
--- a/app-toolkit/core-testing/build.gradle
+++ b/app-toolkit/core-testing/build.gradle
@@ -23,15 +23,9 @@
     id("SupportAndroidLibraryPlugin")
 }
 
-android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-}
-
 dependencies {
     api(project(":arch:runtime"))
-    api libs.support.annotations
+    api(SUPPORT_ANNOTATIONS)
     api(JUNIT)
     api(MOCKITO_CORE, libs.exclude_bytebuddy)
 
diff --git a/app-toolkit/dependencies.gradle b/app-toolkit/dependencies.gradle
index b794c10..008385c 100644
--- a/app-toolkit/dependencies.gradle
+++ b/app-toolkit/dependencies.gradle
@@ -14,40 +14,6 @@
  * limitations under the License.
  */
 
-def ffLibs
-if (hasProperty("libs")) {
-    ffLibs = libs
-} else {
-    apply from: "${ext.supportRootFolder}/buildSrc/dependencies.gradle"
-    ffLibs = libs
-}
-def ffVersions = [:]
-ffVersions.support_lib = "26.1.0"
-
-def getSupportLib(String name, String version, String artifactName = null) {
-    def sourceProject = findProject(name)
-    if (sourceProject != null) {
-        return sourceProject
-    }
-    if (artifactName == null) {
-        artifactName = name
-    }
-    return "com.android.support$artifactName:$version"
-}
-ffLibs.support = [
-        annotations : getSupportLib(":support-annotations", ffVersions.support_lib),
-        core_utils : getSupportLib(':support-core-utils', ffVersions.support_lib),
-        fragments : getSupportLib(':support-fragment', ffVersions.support_lib),
-        app_compat : getSupportLib(':appcompat-v7', ffVersions.support_lib),
-        design : getSupportLib(':design', ffVersions.support_lib),
-        recyclerview : getSupportLib(':recyclerview-v7', ffVersions.support_lib)
-]
-
-ffLibs.support_exclude_config = {
-    exclude group: 'android.arch.core'
-    exclude group: 'android.arch.lifecycle'
-}
-
 ext.tools = [:]
 ext.tools.current_sdk = gradle.ext.currentSdk
 ext.tools.build_tools_version = rootProject.ext.buildToolsVersion
diff --git a/app-toolkit/init.gradle b/app-toolkit/init.gradle
index 3e20eaa..4a334b6 100644
--- a/app-toolkit/init.gradle
+++ b/app-toolkit/init.gradle
@@ -15,50 +15,10 @@
  */
 
 import android.support.DacOptions
-import android.support.LibraryVersions
 import org.gradle.internal.os.OperatingSystem
 
-def root = ext.supportRootFolder
-ext.inAppToolkitProject = rootProject.name == "app-toolkit"
-
-if (ext.inAppToolkitProject) {
-    apply from: "${ext.supportRootFolder}/buildSrc/init.gradle"
-    init.setSdkInLocalPropertiesFile()
-}
-
-def checkoutRoot = "${root}/../.."
-ext.checkoutRoot = checkoutRoot
-ext.prebuiltsRoot = "$checkoutRoot/prebuilts"
-ext.prebuiltsRootUri = "file://${prebuiltsRoot}"
-
-final String platform = OperatingSystem.current().isMacOsX() ? 'darwin' : 'linux'
-final String fullSdkPath = new File("${checkoutRoot}/prebuilts/fullsdk-${platform}").getCanonicalPath()
-System.setProperty('android.home', fullSdkPath)
-File props = file("local.properties")
-props.write "sdk.dir=${fullSdkPath}"
-
-def buildDir
-def distDir
-def supportLibBuildDir
-
-if (ext.runningInBuildServer) {
-    supportLibBuildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/support/build').getCanonicalFile();
-    buildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/app-toolkit/build').getCanonicalFile()
-    distDir = new File(System.env.DIST_DIR).getCanonicalFile()
-} else {
-    supportLibBuildDir = file("${checkoutRoot}/out/host/gradle/frameworks/support/build")
-    buildDir = file("${checkoutRoot}/out/host/gradle/frameworks/app-toolkit/build")
-    distDir = file("${checkoutRoot}/out/dist")
-}
-
-def localMavenRepo = "file://${new File(buildDir, "flatfoot_repo").absolutePath}"
-ext.testApkDistOut = distDir
-ext.testResultsDistDir = new File(distDir, "host-test-reports")
-ext.localMavenRepo = localMavenRepo
-file(localMavenRepo).delete()
-file(localMavenRepo).mkdirs()
-
-ext.repoNames += ["file://${new File(supportLibBuildDir, "support_repo").absolutePath}"]
+apply from: "${ext.supportRootFolder}/buildSrc/init.gradle"
+init.setSdkInLocalPropertiesFile()
 
 apply from: "${ext.supportRootFolder}/app-toolkit/dependencies.gradle"
 
@@ -66,17 +26,13 @@
 def buildServerAnchorTask = rootProject.tasks.create(name : "runBuildServerCompilationTasks",
     description: "Anchor task for everything we want to run in build server.")
 
-if (ext.inAppToolkitProject) {
-    // always build offline docs for flatfoot specific builds.
-    ext.docsDac = new DacOptions("android/arch", "ARCH_DATA")
-    repos.addMavenRepositories(repositories)
-    init.setupRepoOutAndBuildNumber()
-    init.configureSubProjects()
-    init.setupRelease()
-    init.enableDoclavaAndJDiff(this)
-    rootProject.tasks["generateDocs"].exclude '**/R.java'
-}
-
+repos.addMavenRepositories(repositories)
+init.setupRepoOutAndBuildNumber()
+init.configureSubProjects()
+init.setupRelease()
+// always build offline docs for flatfoot specific builds.
+init.enableDoclavaAndJDiff(this, new DacOptions("android/arch", "ARCH_DATA"))
+rootProject.tasks["generateDocs"].exclude '**/R.java'
 
 // flatfoot docs
 def zipFlatfootDocsTask = rootProject.tasks.create(name : "createFlatfootDocsArchive", type : Zip) {
@@ -91,25 +47,6 @@
 buildServerAnchorTask.dependsOn createArchive
 
 subprojects {
-    repos.addMavenRepositories(project.repositories)
-    if (project.name == 'doclava' || project.name == 'jdiff') {
-        project.tasks.whenTaskAdded { task ->
-            if (task instanceof org.gradle.api.tasks.testing.Test) {
-                task.enabled = false
-            }
-        }
-        return
-    }
-
-    if (project.getPath().contains("integration-tests")) {
-        // disable upload tasks
-        project.tasks.whenTaskAdded { task ->
-            if (task instanceof Upload || task.name == "generateSourceProps") {
-                task.enabled = false
-            }
-        }
-    }
-
     project.tasks.whenTaskAdded { task ->
         if (task.name.startsWith("assembleAndroidTest")) {
             buildServerAnchorTask.dependsOn task
diff --git a/app-toolkit/runtime/build.gradle b/app-toolkit/runtime/build.gradle
index 83d4293..cd74aae 100644
--- a/app-toolkit/runtime/build.gradle
+++ b/app-toolkit/runtime/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.SupportLibraryExtension
 import android.support.LibraryVersions
@@ -22,14 +23,8 @@
     id("SupportAndroidLibraryPlugin")
 }
 
-android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-}
-
 dependencies {
-    api libs.support.annotations
+    api(SUPPORT_ANNOTATIONS)
     api(project(":arch:common"))
 }
 
diff --git a/app-toolkit/settings.gradle b/app-toolkit/settings.gradle
index aa0db94..303e4fa 100644
--- a/app-toolkit/settings.gradle
+++ b/app-toolkit/settings.gradle
@@ -98,15 +98,6 @@
 
 /////////////////////////////
 //
-// SupportLib
-//
-/////////////////////////////
-if (inAppToolkitProject && System.getenv("USE_SUPPORT_LIB_SOURCE")) {
-    apply from: "${supportRoot.absolutePath}/app-toolkit/settings_support_lib.gradle"
-}
-
-/////////////////////////////
-//
 // External
 //
 /////////////////////////////
diff --git a/build.gradle b/build.gradle
index ec83da5..7bbeb56 100644
--- a/build.gradle
+++ b/build.gradle
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import android.support.DacOptions
 
 buildscript {
     ext.supportRootFolder = project.projectDir
@@ -25,6 +26,7 @@
     dependencies {
         classpath build_libs.gradle
         classpath build_libs.jacoco
+        classpath build_libs.jetifier
     }
 }
 
@@ -38,7 +40,7 @@
 
 init.setupRelease()
 
-init.enableDoclavaAndJDiff(this)
+init.enableDoclavaAndJDiff(this, new DacOptions("android/support", "SUPPORT_DATA"))
 
 ///// FLATFOOT START
 
diff --git a/buildSrc/build_dependencies.gradle b/buildSrc/build_dependencies.gradle
index be135b9..d68b769 100644
--- a/buildSrc/build_dependencies.gradle
+++ b/buildSrc/build_dependencies.gradle
@@ -29,6 +29,10 @@
 build_libs.jarjar_gradle = 'org.anarres.jarjar:jarjar-gradle:1.0.0'
 build_libs.error_prone = 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.13'
 build_libs.jacoco = 'org.jacoco:org.jacoco.core:0.7.8'
+build_libs.jetifier = 'androidx.tools.jetifier:gradle-plugin:0.1'
 build_libs.kotlin = [gradle_plugin: "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.0"]
+// jdiff dependencies
+build_libs.xml_parser_apis = 'xerces:xmlParserAPIs:2.6.2'
+build_libs.xerces_impl = 'xerces:xercesImpl:2.6.2'
 
 rootProject.ext['build_libs'] = build_libs
diff --git a/buildSrc/dependencies.gradle b/buildSrc/dependencies.gradle
index 48d3eb9..baf1ba0 100644
--- a/buildSrc/dependencies.gradle
+++ b/buildSrc/dependencies.gradle
@@ -16,6 +16,11 @@
 // Add ext.libs for library versions
 def libs = [:]
 
+libs.exclude_annotations_transitive = {
+    exclude group: 'com.android.support'
+    transitive = true
+}
+
 libs.exclude_bytebuddy = {
     exclude group: 'net.bytebuddy'
 }
@@ -24,11 +29,9 @@
     exclude group: 'com.android.support'
 }
 
-//arch components
-libs.arch_lifecycle_runtime = "android.arch.lifecycle:runtime:1.0.3@aar"
-
-// Other dependencies
-libs.xml_parser_apis = 'xerces:xmlParserAPIs:2.6.2'
-libs.xerces_impl = 'xerces:xercesImpl:2.6.2'
+libs.support_exclude_config = {
+    exclude group: 'android.arch.core'
+    exclude group: 'android.arch.lifecycle'
+}
 
 rootProject.ext['libs'] = libs
diff --git a/buildSrc/init.gradle b/buildSrc/init.gradle
index a0df393..64c5f3f 100644
--- a/buildSrc/init.gradle
+++ b/buildSrc/init.gradle
@@ -15,14 +15,12 @@
  */
 
 
-import android.support.DacOptions
 import android.support.DiffAndDocs
-import android.support.LibraryVersions
+import android.support.gmaven.GMavenVersionChecker
 import com.android.build.gradle.internal.coverage.JacocoPlugin
 import com.android.build.gradle.internal.coverage.JacocoReportTask
 import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask
 import org.gradle.api.logging.configuration.ShowStacktrace
-import android.support.gmaven.GMavenVersionChecker
 
 def supportRoot = ext.supportRootFolder
 if (supportRoot == null) {
@@ -36,9 +34,9 @@
 ext.runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null
 
 apply from: "${supportRoot}/buildSrc/dependencies.gradle"
-ext.docsDac = new DacOptions("android/support", "SUPPORT_DATA")
+apply from: "${supportRoot}/buildSrc/build_dependencies.gradle"
 
-def enableDoclavaAndJDiff(p) {
+def enableDoclavaAndJDiff(p, dacOptions) {
     p.configurations {
         doclava
         jdiff
@@ -47,10 +45,11 @@
     p.dependencies {
         doclava project(':doclava')
         jdiff project(':jdiff')
-        jdiff libs.xml_parser_apis
-        jdiff libs.xerces_impl
+        jdiff build_libs.xml_parser_apis
+        jdiff build_libs.xerces_impl
     }
-    DiffAndDocs.configureDiffAndDocs(rootProject, createArchive, supportRootFolder)
+    def allChecks = DiffAndDocs.configureDiffAndDocs(rootProject, supportRootFolder, dacOptions)
+    createArchive.dependsOn(allChecks)
 }
 
 def getFullSdkPath() {
@@ -65,7 +64,7 @@
     ext.buildToolsVersion = '27.0.1'
     final String fullSdkPath = getFullSdkPath();
     if (file(fullSdkPath).exists()) {
-        gradle.ext.currentSdk = 26
+        gradle.ext.currentSdk = 28
         project.ext.androidJar =
                 files("${fullSdkPath}/platforms/android-${gradle.currentSdk}/android.jar")
         project.ext.androidSrcJar =
diff --git a/buildSrc/repos.gradle b/buildSrc/repos.gradle
index 156ec66..ad5a621 100644
--- a/buildSrc/repos.gradle
+++ b/buildSrc/repos.gradle
@@ -37,7 +37,6 @@
 
 ext.repoNames = ["${repos.prebuiltsRoot}/gradle-plugin",
                  "${repos.prebuiltsRoot}/tools/common/m2/repository",
-                 "${repos.prebuiltsRoot}/tools/common/m2/internal",
                  "${repos.prebuiltsRoot}/maven_repo/android",
                  "${getFullSdkPath(repos.prebuiltsRoot)}/extras/m2repository"]
 
diff --git a/buildSrc/src/main/java/android/support/LibraryGroups.java b/buildSrc/src/main/java/android/support/LibraryGroups.java
index feaefbc..19c0a92 100644
--- a/buildSrc/src/main/java/android/support/LibraryGroups.java
+++ b/buildSrc/src/main/java/android/support/LibraryGroups.java
@@ -27,4 +27,5 @@
     public static final String ARCH_CORE = "android.arch.core";
     public static final String PAGING = "android.arch.paging";
     public static final String NAVIGATION = "android.arch.navigation";
+    public static final String SLICES = "androidx.app.slice";
 }
diff --git a/buildSrc/src/main/java/android/support/LibraryVersions.java b/buildSrc/src/main/java/android/support/LibraryVersions.java
index c8dd1e3..b5c74e3 100644
--- a/buildSrc/src/main/java/android/support/LibraryVersions.java
+++ b/buildSrc/src/main/java/android/support/LibraryVersions.java
@@ -23,7 +23,7 @@
     /**
      * Version code of the support library components.
      */
-    public static final Version SUPPORT_LIBRARY = new Version("27.1.0-SNAPSHOT");
+    public static final Version SUPPORT_LIBRARY = new Version("28.0.0-SNAPSHOT");
 
     /**
      * Version code for flatfoot 1.0 projects (room, lifecycles)
diff --git a/buildSrc/src/main/java/android/support/Version.java b/buildSrc/src/main/java/android/support/Version.java
index 69b7f5e..36c7728 100644
--- a/buildSrc/src/main/java/android/support/Version.java
+++ b/buildSrc/src/main/java/android/support/Version.java
@@ -16,6 +16,7 @@
 
 package android.support;
 
+import java.io.File;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -23,17 +24,28 @@
  * Utility class which represents a version
  */
 public class Version implements Comparable<Version> {
+    private static final Pattern VERSION_FILE_REGEX = Pattern.compile("^(\\d+\\.\\d+\\.\\d+).txt$");
+    private static final Pattern VERSION_REGEX = Pattern
+            .compile("^(\\d+)\\.(\\d+)\\.(\\d+)(-.+)?$");
+
     private final int mMajor;
     private final int mMinor;
     private final int mPatch;
     private final String mExtra;
 
     public Version(String versionString) {
-        Pattern compile = Pattern.compile("^(\\d+)\\.(\\d+)\\.(\\d+)(-.+)?$");
-        Matcher matcher = compile.matcher(versionString);
+        this(checkedMatcher(versionString));
+    }
+
+    private static Matcher checkedMatcher(String versionString) {
+        Matcher matcher = VERSION_REGEX.matcher(versionString);
         if (!matcher.matches()) {
             throw new IllegalArgumentException("Can not parse version: " + versionString);
         }
+        return matcher;
+    }
+
+    private Version(Matcher matcher) {
         mMajor = Integer.parseInt(matcher.group(1));
         mMinor = Integer.parseInt(matcher.group(2));
         mPatch = Integer.parseInt(matcher.group(3));
@@ -117,4 +129,29 @@
         result = 31 * result + (mExtra != null ? mExtra.hashCode() : 0);
         return result;
     }
+
+    /**
+     * @return Version or null, if a name of the given file doesn't match
+     */
+    public static Version from(File file) {
+        if (!file.isFile()) {
+            return null;
+        }
+        Matcher matcher = VERSION_FILE_REGEX.matcher(file.getName());
+        if (!matcher.matches()) {
+            return null;
+        }
+        return new Version(matcher.group(1));
+    }
+
+    /**
+     * @return Version or null, if the given string doesn't match
+     */
+    public static Version from(String versionString) {
+        Matcher matcher = VERSION_REGEX.matcher(versionString);
+        if (!matcher.matches()) {
+            return null;
+        }
+        return new Version(matcher);
+    }
 }
diff --git a/buildSrc/src/main/kotlin/android/support/DiffAndDocs.kt b/buildSrc/src/main/kotlin/android/support/DiffAndDocs.kt
index 3432cbf..fefc3ed 100644
--- a/buildSrc/src/main/kotlin/android/support/DiffAndDocs.kt
+++ b/buildSrc/src/main/kotlin/android/support/DiffAndDocs.kt
@@ -20,6 +20,7 @@
 import android.support.checkapi.CheckApiTask
 import android.support.checkapi.UpdateApiTask
 import android.support.doclava.DoclavaTask
+import android.support.docs.GenerateDocsTask
 import android.support.jdiff.JDiffTask
 import com.android.build.gradle.LibraryExtension
 import com.android.build.gradle.api.LibraryVariant
@@ -42,8 +43,8 @@
     @JvmStatic
     fun configureDiffAndDocs(
             root: Project,
-            createArchiveTask: Task,
-            supportRootFolder: File) = configure(root, createArchiveTask, supportRootFolder)
+            supportRootFolder: File,
+            dacOptions: DacOptions) = configure(root, supportRootFolder, dacOptions)
 }
 
 private data class CheckApiConfig(
@@ -58,6 +59,7 @@
                 "visibility, you may exclude it from public API by using the @hide javadoc\n" +
                 "annotation paired with the @RestrictTo(LIBRARY_GROUP) code annotation."
 
+@Suppress("DEPRECATION")
 private fun hasJavaSources(variant: LibraryVariant) = !variant.javaCompile.source
         .filter { file -> file.name != "R.java" && file.name != "BuildConfig.java" }
         .isEmpty
@@ -98,22 +100,17 @@
 
 private fun stripExtension(fileName: String) = fileName.substringBeforeLast('.')
 
-private fun getLastReleasedApiFile(rootFolder: File, refApi: String): File? {
-    val refVersion = Version(refApi)
+private fun getLastReleasedApiFile(rootFolder: File, refVersion: Version): File? {
     val apiDir = File(rootFolder, "api")
 
     var lastFile: File? = null
     var lastVersion: Version? = null
-    val regex = Regex("(\\d+)\\.(\\d+)\\.0\\.txt")
-    // Only look at released versions and snapshots thereof, ex. X.Y.0.txt.
-    apiDir.listFiles().filter { file ->
-        regex.matches(file.name) && file.isFile
-    }.forEach { file ->
-        val version = Version(stripExtension(file.name))
-
-        if ((lastFile == null || lastVersion!! < version) && version < refVersion) {
-            lastFile = file
-            lastVersion = version
+    apiDir.listFiles().forEach { file ->
+        Version.from(file)?.let { version ->
+            if ((lastFile == null || lastVersion!! < version) && version < refVersion) {
+                lastFile = file
+                lastVersion = version
+            }
         }
     }
     return lastFile
@@ -163,7 +160,6 @@
             }
         }
 
-
 // Generates API files
 private fun createGenerateApiTask(project: Project, docletpathParam: Collection<File>) =
         project.tasks.createWithConfig("generateApi", DoclavaTask::class.java) {
@@ -216,12 +212,15 @@
 
 // configuration file for setting up api diffs and api docs
 private fun registerAndroidProjectForDocsTask(task: Javadoc, releaseVariant: LibraryVariant) {
+    @Suppress("DEPRECATION")
     task.dependsOn(releaseVariant.javaCompile)
     val packageDir = releaseVariant.applicationId.replace('.', '/')
+    @Suppress("DEPRECATION")
     val sources = releaseVariant.javaCompile.source.filter { file ->
         file.name != "R.java" || file.parent.endsWith(packageDir)
     }
     task.source(sources)
+    @Suppress("DEPRECATION")
     task.classpath += releaseVariant.getCompileClasspath(null) +
             task.project.files(releaseVariant.javaCompile.destinationDir)
 }
@@ -248,15 +247,14 @@
  */
 private fun createOldApiXml(project: Project, doclavaConfig: Configuration) =
         project.tasks.createWithConfig("oldApiXml", ApiXmlConversionTask::class.java) {
-            val regex = Regex("(\\d+\\.){2}\\d+")
-            val toApi = project.processProperty("toApi")
+            val toApi = project.processProperty("toApi")?.let(Version::from)
             val fromApi = project.processProperty("fromApi")
             classpath = project.files(doclavaConfig.resolve())
             val rootFolder = project.projectDir
             if (fromApi != null) {
                 // Use an explicit API file.
                 inputApiFile = File(rootFolder, "api/$fromApi.txt")
-            } else if (toApi != null && regex.matches(toApi)) {
+            } else if (toApi != null) {
                 // If toApi matches released API (X.Y.Z) format, use the most recently
                 // released API file prior to toApi.
                 inputApiFile = getLastReleasedApiFile(rootFolder, toApi)
@@ -285,7 +283,7 @@
 
             if (toApi != null) {
                 // Use an explicit API file.
-                inputApiFile = File(project.projectDir, "api/${toApi}.txt")
+                inputApiFile = File(project.projectDir, "api/$toApi.txt")
             } else {
                 // Use the current API file (e.g. current.txt).
                 inputApiFile = generateApi.apiFile
@@ -296,7 +294,6 @@
                     "release/${stripExtension(inputApiFile.name)}.xml")
         }
 
-
 /**
  * Generates API diffs.
  * <p>
@@ -352,7 +349,6 @@
             dependsOn(oldApiTask, newApiTask, jdiffConfig)
         }
 
-
 // Generates a distribution artifact for online docs.
 private fun createDistDocsTask(project: Project, generateDocs: DoclavaTask) =
         project.tasks.createWithConfig("distDocs", Zip::class.java) {
@@ -404,7 +400,8 @@
         project: Project,
         generateSdkApiTask: Task,
         doclavaConfig: Configuration,
-        supportRootFolder: File) =
+        supportRootFolder: File,
+        dacOptions: DacOptions) =
         project.tasks.createWithConfig("generateDocs", GenerateDocsTask::class.java) {
             dependsOn(generateSdkApiTask, doclavaConfig)
             group = JavaBasePlugin.DOCUMENTATION_GROUP
@@ -442,8 +439,8 @@
                 if (!offline) {
                     addStringOption("toroot", "/")
                     addBooleanOption("devsite", true)
-                    addStringOption("dac_libraryroot", project.docsDac().libraryroot)
-                    addStringOption("dac_dataname", project.docsDac().dataname)
+                    addStringOption("dac_libraryroot", dacOptions.libraryroot)
+                    addStringOption("dac_dataname", dacOptions.dataname)
                 }
 
                 exclude("**/BuildConfig.java")
@@ -452,10 +449,12 @@
             addArtifactsAndSince()
         }
 
-private fun initializeApiChecksForProject(
-        project: Project,
-        generateDocs: GenerateDocsTask,
-        createArchive: Task): Pair<DoclavaTask, JDiffTask> {
+private data class Tasks(
+        val generateApi: DoclavaTask,
+        val generateDiffs: JDiffTask,
+        val checkApiTask: CheckApiTask)
+
+private fun initializeApiChecksForProject(project: Project, generateDocs: GenerateDocsTask): Tasks {
     if (!project.hasProperty("docsDir")) {
         project.extensions.add("docsDir", File(project.rootProject.docsDir(), project.name))
     }
@@ -470,7 +469,7 @@
     val verifyUpdateTask = createVerifyUpdateApiAllowedTask(project)
 
     // Make sure the API surface has not broken since the last release.
-    val lastReleasedApiFile = getLastReleasedApiFile(workingDir, version.toString())
+    val lastReleasedApiFile = getLastReleasedApiFile(workingDir, version)
 
     val whitelistFile = lastReleasedApiFile?.let { apiFile ->
         File(lastReleasedApiFile.parentFile, stripExtension(apiFile.name) + ".ignore")
@@ -523,69 +522,36 @@
     // Associate current API surface with the Maven artifact.
     generateDocs.addArtifact(generateApi.apiFile!!.absolutePath, artifact)
     generateDocs.dependsOn(generateApi)
-    createArchive.dependsOn(checkApi)
-    return (generateApi to generateDiffTask)
+    return Tasks(generateApi, generateDiffTask, checkApi)
 }
 
-private open class GenerateDocsTask : DoclavaTask() {
-
-    private data class Since(val path: String, val apiLevel: String)
-    private data class Artifact(val path: String, val artifact: String)
-
-    private val sinces = mutableListOf<Since>()
-    private val artifacts = mutableListOf<Artifact>()
-
-    fun addArtifactsAndSince() {
-        doFirst {
-            coreJavadocOptions {
-                if (sinces.isNotEmpty()) {
-                    addMultilineMultiValueOption("since").value = sinces.map { (path, apiLevel) ->
-                        listOf(path, apiLevel)
-                    }
-                }
-
-                if (artifacts.isNotEmpty()) {
-                    addMultilineMultiValueOption("artifact").value = artifacts.map { artifact ->
-                        listOf(artifact.path, artifact.artifact)
-                    }
-                }
-            }
-        }
-    }
-
-    fun addSinceFilesFrom(dir: File) {
-        val regex = Regex("(\\d+\\.\\d+\\.\\d).txt")
-        val apiDir = File(dir, "api")
-        apiDir.listFiles { file ->
-            file.isFile && regex.matches(file.name)
-        }.forEach { apiFile ->
-            val matchResult = regex.matchEntire(apiFile.name)!!
-            sinces.add(Since(apiFile.absolutePath, matchResult.groups[1]!!.value))
-        }
-    }
-
-    fun addArtifact(path: String, artifact: String) = artifacts.add(Artifact(path, artifact))
-}
-
-private fun configure(root: Project, createArchiveTask: Task, supportRootFolder: File) {
+private fun configure(root: Project, supportRootFolder: File, dacOptions: DacOptions): Task {
+    val allChecks = root.tasks.create("AnchorCheckApis")
     val doclavaConfiguration = root.configurations.getByName("doclava")
     val generateSdkApiTask = createGenerateSdkApiTask(root, doclavaConfiguration)
 
     val generateDocsTask = createGenerateDocsTask(root, generateSdkApiTask,
-            doclavaConfiguration, supportRootFolder)
+            doclavaConfiguration, supportRootFolder, dacOptions)
     createDistDocsTask(root, generateDocsTask)
 
     root.subprojects { subProject ->
         subProject.afterEvaluate { project ->
-            if (project.hasProperty("noDocs") && (project.properties["noDocs"] as Boolean)) {
-                project.logger.info("Project $project.name specified noDocs, ignoring API tasks.")
-                return@afterEvaluate
+            val extension = if (project.hasProperty("supportLibrary")) {
+                project.properties["supportLibrary"] as SupportLibraryExtension
+            } else {
+                null
             }
-            if (project.hasProperty("supportLibrary")
-                    && !(project.properties["supportLibrary"] as SupportLibraryExtension).publish) {
+            if (extension == null || !extension.publish) {
                 project.logger.info("Project ${project.name} is not published, ignoring API tasks.")
                 return@afterEvaluate
             }
+
+            if (!extension.generateDocs) {
+                project.logger.info("Project ${project.name} specified generateDocs = false, " +
+                        "ignoring API tasks.")
+                return@afterEvaluate
+            }
+
             val library = project.extensions.findByType(LibraryExtension::class.java)
             if (library != null) {
                 library.libraryVariants.all { variant ->
@@ -599,41 +565,41 @@
                                     "an api folder, ignoring API tasks.")
                             return@all
                         }
-                        val (generateApi, generateDiffs) = initializeApiChecksForProject(project,
-                                generateDocsTask, createArchiveTask)
-                        registerAndroidProjectForDocsTask(generateApi, variant)
-                        registerAndroidProjectForDocsTask(generateDiffs, variant)
+                        val tasks = initializeApiChecksForProject(project, generateDocsTask)
+                        registerAndroidProjectForDocsTask(tasks.generateApi, variant)
+                        registerAndroidProjectForDocsTask(tasks.generateDiffs, variant)
+                        allChecks.dependsOn(tasks.checkApiTask)
                     }
                 }
             } else if (project.hasProperty("compileJava")) {
                 val compileJava = project.properties["compileJava"] as JavaCompile
                 registerJavaProjectForDocsTask(generateDocsTask, compileJava)
                 if (!hasApiFolder(project)) {
-                    project.logger.info("Project $project.name doesn't have an api folder, " +
+                    project.logger.info("Project ${project.name} doesn't have an api folder, " +
                             "ignoring API tasks.")
                     return@afterEvaluate
                 }
                 project.afterEvaluate { proj ->
-                    val (generateApi, generateDiffs) = initializeApiChecksForProject(proj,
-                            generateDocsTask,
-                            createArchiveTask)
-                    registerJavaProjectForDocsTask(generateApi, compileJava)
-                    registerJavaProjectForDocsTask(generateDiffs, compileJava)
+                    val tasks = initializeApiChecksForProject(proj, generateDocsTask)
+                    registerJavaProjectForDocsTask(tasks.generateApi, compileJava)
+                    registerJavaProjectForDocsTask(tasks.generateDiffs, compileJava)
+                    allChecks.dependsOn(tasks.checkApiTask)
                 }
             }
         }
     }
+    return allChecks
 }
 
-
 private fun sdkApiFile(project: Project) = File(project.docsDir(), "release/sdk_current.txt")
 private fun removedSdkApiFile(project: Project) = File(project.docsDir(), "release/sdk_removed.txt")
 
 private fun TaskContainer.createWithConfig(name: String, config: Task.() -> Unit) =
         create(name) { task -> task.config() }
 
-private fun <T : Task> TaskContainer.createWithConfig(name: String, taskClass: Class<T>,
-                                                      config: T.() -> Unit) =
+private fun <T : Task> TaskContainer.createWithConfig(
+        name: String, taskClass: Class<T>,
+        config: T.() -> Unit) =
         create(name, taskClass) { task -> task.config() }
 
 // Nasty part. Get rid of that eventually!
@@ -643,15 +609,12 @@
 
 private fun Project.androidSrcJar() = rootProject.properties["androidSrcJar"] as File
 
-private fun Project.version() = Version(project.properties["version"] as String)
+private fun Project.version() = Version(project.version as String)
 
 private fun Project.buildNumber() = properties["buildNumber"] as String
 
 private fun Project.androidApiTxt() = properties["androidApiTxt"] as? File
 
-
-private fun Project.docsDac() = properties["docsDac"] as DacOptions
-
 private fun Project.processProperty(name: String) =
         if (hasProperty(name)) {
             properties[name] as String
diff --git a/buildSrc/src/main/kotlin/android/support/SupportAndroidLibraryPlugin.kt b/buildSrc/src/main/kotlin/android/support/SupportAndroidLibraryPlugin.kt
index 5eaa7dd..b18b5e3 100644
--- a/buildSrc/src/main/kotlin/android/support/SupportAndroidLibraryPlugin.kt
+++ b/buildSrc/src/main/kotlin/android/support/SupportAndroidLibraryPlugin.kt
@@ -43,6 +43,8 @@
             val library = project.extensions.findByType(LibraryExtension::class.java)
                     ?: return@afterEvaluate
 
+            library.defaultConfig.minSdkVersion(supportLibraryExtension.minSdkVersion)
+
             if (supportLibraryExtension.legacySourceLocation) {
                 // We use a non-standard manifest path.
                 library.sourceSets.getByName("main").manifest.srcFile("AndroidManifest.xml")
@@ -161,6 +163,9 @@
     lintOptions.isAbortOnError = true
     lintOptions.isIgnoreWarnings = true
 
+    // Skip lintVital tasks on assemble. We explicitly run lintRelease for libraries.
+    lintOptions.isCheckReleaseBuilds = false
+
     // Write output directly to the console (and nowhere else).
     lintOptions.textOutput("stderr")
     lintOptions.textReport = true
diff --git a/buildSrc/src/main/kotlin/android/support/SupportLibraryExtension.kt b/buildSrc/src/main/kotlin/android/support/SupportLibraryExtension.kt
index 088e169..82f1e91 100644
--- a/buildSrc/src/main/kotlin/android/support/SupportLibraryExtension.kt
+++ b/buildSrc/src/main/kotlin/android/support/SupportLibraryExtension.kt
@@ -34,6 +34,17 @@
     var java8Library = false
     var legacySourceLocation = false
     var publish = false
+    /**
+     * This flag works only if publish flag is "true".
+     * It is useful for modules that are used for tooling. For example room annotation
+     * processor module is published, but we don't want to expose any docs, because we don't
+     * support using it as a library.
+     */
+    var generateDocs = true
+    /**
+     * If unset minSdkVersion will be 14.
+     */
+    var minSdkVersion: Int = 14
 
     fun license(closure: Closure<*>): License {
         val license = project.configure(License(), closure) as License
@@ -47,7 +58,8 @@
 
     companion object {
         @JvmField
-        val ARCHITECTURE_URL = "https://developer.android.com/topic/libraries/architecture/index.html"
+        val ARCHITECTURE_URL
+                = "https://developer.android.com/topic/libraries/architecture/index.html"
         @JvmField
         val SUPPORT_URL = "http://developer.android.com/tools/extras/support-library.html"
     }
diff --git a/buildSrc/src/main/kotlin/android/support/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/android/support/dependencies/Dependencies.kt
index e32cacd..adf656e 100644
--- a/buildSrc/src/main/kotlin/android/support/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/android/support/dependencies/Dependencies.kt
@@ -31,6 +31,7 @@
 const val JUNIT = "junit:junit:4.12"
 const val KOTLIN_STDLIB = "org.jetbrains.kotlin:kotlin-stdlib:1.2.0"
 const val MOCKITO_CORE = "org.mockito:mockito-core:2.7.6"
+const val MULTIDEX = "com.android.support:multidex:1.0.1"
 const val REACTIVE_STREAMS = "org.reactivestreams:reactive-streams:1.0.0"
 const val RX_JAVA = "io.reactivex.rxjava2:rxjava:2.0.6"
 const val TEST_RUNNER = "com.android.support.test:runner:1.0.1"
@@ -40,4 +41,20 @@
  * https://github.com/xerial/sqlite-jdbc/issues/97
  * https://github.com/xerial/sqlite-jdbc/issues/267
  */
-const val XERIAL = "org.xerial:sqlite-jdbc:3.20.1"
\ No newline at end of file
+const val XERIAL = "org.xerial:sqlite-jdbc:3.20.1"
+
+// Support library dependencies needed for projects that compile against prebuilt versions
+// instead of source directly.
+private const val SUPPORT_VERSION = "26.1.0"
+const val SUPPORT_ANNOTATIONS = "com.android.support:support-annotations:$SUPPORT_VERSION"
+const val SUPPORT_APPCOMPAT = "com.android.support:appcompat-v7:$SUPPORT_VERSION"
+const val SUPPORT_CARDVIEW = "com.android.support:cardview-v7:$SUPPORT_VERSION"
+const val SUPPORT_CORE_UTILS = "com.android.support:support-core-utils:$SUPPORT_VERSION"
+const val SUPPORT_DESIGN = "com.android.support:design:$SUPPORT_VERSION"
+const val SUPPORT_FRAGMENTS = "com.android.support:support-fragment:$SUPPORT_VERSION"
+const val SUPPORT_RECYCLERVIEW = "com.android.support:recyclerview-v7:$SUPPORT_VERSION"
+const val SUPPORT_V4 = "com.android.support:support-v4:$SUPPORT_VERSION"
+
+// Arch libraries
+const val ARCH_LIFECYCLE_RUNTIME = "android.arch.lifecycle:runtime:1.0.3@aar"
+const val ARCH_LIFECYCLE_EXTENSIONS = "android.arch.lifecycle:extensions:1.0.0@aar"
diff --git a/buildSrc/src/main/kotlin/android/support/docs/GenerateDocsTask.kt b/buildSrc/src/main/kotlin/android/support/docs/GenerateDocsTask.kt
new file mode 100644
index 0000000..2183b88
--- /dev/null
+++ b/buildSrc/src/main/kotlin/android/support/docs/GenerateDocsTask.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 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.docs
+
+import android.support.Version
+import android.support.doclava.DoclavaTask
+import java.io.File
+
+open class GenerateDocsTask : DoclavaTask() {
+
+    private data class Since(val path: String, val apiLevel: String)
+    private data class Artifact(val path: String, val artifact: String)
+
+    private val sinces = mutableListOf<Since>()
+    private val artifacts = mutableListOf<Artifact>()
+
+    fun addArtifactsAndSince() {
+        doFirst {
+            coreJavadocOptions {
+                if (sinces.isNotEmpty()) {
+                    addMultilineMultiValueOption("since").value = sinces.map { (path, apiLevel) ->
+                        listOf(path, apiLevel)
+                    }
+                }
+
+                if (artifacts.isNotEmpty()) {
+                    addMultilineMultiValueOption("artifact").value = artifacts.map { artifact ->
+                        listOf(artifact.path, artifact.artifact)
+                    }
+                }
+            }
+        }
+    }
+
+    fun addSinceFilesFrom(dir: File) {
+        File(dir, "api").listFiles().forEach { file ->
+            Version.from(file)?.let { version ->
+                sinces.add(Since(file.absolutePath, version.toString()))
+            }
+        }
+    }
+
+    fun addArtifact(path: String, artifact: String) = artifacts.add(Artifact(path, artifact))
+}
\ No newline at end of file
diff --git a/car/Android.mk b/car/Android.mk
index fa20f26..18f08e4 100644
--- a/car/Android.mk
+++ b/car/Android.mk
@@ -27,8 +27,9 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+        android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
-        android-support-annotations \
         android-support-v4 \
         android-support-v7-appcompat \
         android-support-v7-cardview \
diff --git a/car/build.gradle b/car/build.gradle
index 3970df9..7ea0873 100644
--- a/car/build.gradle
+++ b/car/build.gradle
@@ -1,5 +1,6 @@
 import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
+import android.support.LibraryVersions
 
 plugins {
     id("SupportAndroidLibraryPlugin")
@@ -20,10 +21,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 24
-    }
-
     sourceSets {
         main.res.srcDirs 'res', 'res-public'
     }
@@ -32,9 +29,11 @@
 supportLibrary {
     name = "Android Car Support UI"
     publish = false
+    mavenVersion = LibraryVersions.SUPPORT_LIBRARY
     mavenGroup = LibraryGroups.SUPPORT
     inceptionYear = "2017"
     description = "Android Car Support UI"
     java8Library = true
     legacySourceLocation = true
+    minSdkVersion = 24
 }
diff --git a/car/res/layout/car_paged_list_item_content.xml b/car/res/layout/car_paged_list_item_content.xml
index 0e6b809..5d01c59 100644
--- a/car/res/layout/car_paged_list_item_content.xml
+++ b/car/res/layout/car_paged_list_item_content.xml
@@ -32,9 +32,10 @@
         android:id="@+id/title"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_toStartOf="@id/supplemental_actions"
+        android:layout_toStartOf="@+id/supplemental_actions"
         android:singleLine="true"
         android:ellipsize="end"/>
+
     <TextView
         android:id="@+id/body"
         android:layout_width="match_parent"
@@ -43,7 +44,7 @@
 
     <!-- Supplemental action(s) - supports either 1 supplemental icon or up to 2 action buttons. -->
     <LinearLayout
-        android:id="@+id/supplemental_actions"
+        android:id="@id/supplemental_actions"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_alignParentEnd="true"
diff --git a/car/res/layout/car_paged_recycler_view.xml b/car/res/layout/car_paged_recycler_view.xml
index d3ca4a3..e7b1f61 100644
--- a/car/res/layout/car_paged_recycler_view.xml
+++ b/car/res/layout/car_paged_recycler_view.xml
@@ -19,7 +19,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <androidx.car.widget.CarRecyclerView
+    <android.support.v7.widget.RecyclerView
         android:id="@+id/recycler_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
diff --git a/car/res/layout/car_paged_scrollbar_buttons.xml b/car/res/layout/car_paged_scrollbar_buttons.xml
index d49b532..6f3287b 100644
--- a/car/res/layout/car_paged_scrollbar_buttons.xml
+++ b/car/res/layout/car_paged_scrollbar_buttons.xml
@@ -29,7 +29,6 @@
         android:background="@drawable/car_pagination_background"
         android:focusable="false"
         android:hapticFeedbackEnabled="false"
-        android:scaleType="center"
         android:src="@drawable/ic_up" />
 
     <FrameLayout
@@ -43,7 +42,7 @@
         <ImageView
             android:id="@+id/scrollbar_thumb"
             android:layout_width="@dimen/car_scroll_bar_thumb_width"
-            android:layout_height="0dp"
+            android:layout_height="@dimen/car_min_scroll_bar_thumb_height"
             android:layout_gravity="center_horizontal"
             android:background="@color/car_scrollbar_thumb" />
     </FrameLayout>
@@ -55,6 +54,5 @@
         android:background="@drawable/car_pagination_background"
         android:focusable="false"
         android:hapticFeedbackEnabled="false"
-        android:scaleType="center"
         android:src="@drawable/ic_down" />
 </LinearLayout>
diff --git a/car/res/values-night/colors.xml b/car/res/values-night/colors.xml
index 2ca5b02..12eb594 100644
--- a/car/res/values-night/colors.xml
+++ b/car/res/values-night/colors.xml
@@ -16,6 +16,7 @@
   -->
 <resources>
     <color name="car_title">@color/car_title_light</color>
+    <color name="car_title2">@color/car_title2_light</color>
     <color name="car_body1">@color/car_body1_light</color>
     <color name="car_body2">@color/car_body2_light</color>
 
diff --git a/car/res/values/attrs.xml b/car/res/values/attrs.xml
index 01ed95f..630d0d6 100644
--- a/car/res/values/attrs.xml
+++ b/car/res/values/attrs.xml
@@ -23,8 +23,6 @@
 
     <!-- The configurable attributes in PagedListView. -->
     <declare-styleable name="PagedListView">
-        <!-- Fade duration in ms -->
-        <attr name="fadeLastItem" format="boolean" />
         <!-- Set to true/false to offset rows as they slide off screen. Defaults to true -->
         <attr name="offsetRows" format="boolean" />
         <!-- Whether or not to offset the list view by the width of scroll bar. Setting this to
diff --git a/car/res/values/colors.xml b/car/res/values/colors.xml
index 00c6cf9..5b90125 100644
--- a/car/res/values/colors.xml
+++ b/car/res/values/colors.xml
@@ -63,6 +63,10 @@
     <color name="car_title_dark">@color/car_grey_900</color>
     <color name="car_title">@color/car_title_dark</color>
 
+    <color name="car_title2_light">@color/car_grey_100</color>
+    <color name="car_title2_dark">@color/car_grey_900</color>
+    <color name="car_title2">@color/car_title2_dark</color>
+
     <color name="car_headline1_light">@color/car_grey_100</color>
     <color name="car_headline1_dark">@color/car_grey_800</color>
     <color name="car_headline1">@color/car_headline1_dark</color>
diff --git a/car/res/values/styles.xml b/car/res/values/styles.xml
index d84f4c8..606bdc5 100644
--- a/car/res/values/styles.xml
+++ b/car/res/values/styles.xml
@@ -31,6 +31,23 @@
         <item name="android:textColor">@color/car_title_light</item>
     </style>
 
+    <!-- The styling for title2 text. The color of this text changes based on day/night mode. -->
+    <style name="CarTitle2">
+        <item name="android:textStyle">normal</item>
+        <item name="android:textSize">@dimen/car_title2_size</item>
+        <item name="android:textColor">@color/car_title2</item>
+    </style>
+
+    <!-- Title2 text that is permanently a dark color. -->
+    <style name="CarTitle2.Dark">
+        <item name="android:textColor">@color/car_title2_dark</item>
+    </style>
+
+    <!-- Title2 text that is permanently a light color. -->
+    <style name="CarTitle2.Light">
+        <item name="android:textColor">@color/car_title2_light</item>
+    </style>
+
     <!-- The styling for the main headline text. The color of this text changes based on the
          day/night mode. -->
     <style name="CarHeadline1">
diff --git a/car/src/main/java/androidx/car/widget/CarItemAnimator.java b/car/src/main/java/androidx/car/widget/CarItemAnimator.java
deleted file mode 100644
index e6bfd05..0000000
--- a/car/src/main/java/androidx/car/widget/CarItemAnimator.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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 androidx.car.widget;
-
-import android.support.v7.widget.DefaultItemAnimator;
-import android.support.v7.widget.RecyclerView;
-
-/** {@link DefaultItemAnimator} with a few minor changes where it had undesired behavior. */
-public class CarItemAnimator extends DefaultItemAnimator {
-
-    private final PagedLayoutManager mLayoutManager;
-
-    public CarItemAnimator(PagedLayoutManager layoutManager) {
-        mLayoutManager = layoutManager;
-    }
-
-    @Override
-    public boolean animateChange(RecyclerView.ViewHolder oldHolder,
-            RecyclerView.ViewHolder newHolder,
-            int fromX,
-            int fromY,
-            int toX,
-            int toY) {
-        // The default behavior will cross fade the old view and the new one. However, if we
-        // have a card on a colored background, it will make it appear as if a changing card
-        // fades in and out.
-        float alpha = 0f;
-        if (newHolder != null) {
-            alpha = newHolder.itemView.getAlpha();
-        }
-        boolean ret = super.animateChange(oldHolder, newHolder, fromX, fromY, toX, toY);
-        if (newHolder != null) {
-            newHolder.itemView.setAlpha(alpha);
-        }
-        return ret;
-    }
-
-    @Override
-    public void onMoveFinished(RecyclerView.ViewHolder item) {
-        // The item animator uses translation heavily internally. However, we also use translation
-        // to create the paging affect. When an item's move is animated, it will mess up the
-        // translation we have set on it so we must re-offset the rows once the animations finish.
-
-        // isRunning(ItemAnimationFinishedListener) is the awkward API used to determine when all
-        // animations have finished.
-        isRunning(mFinishedListener);
-    }
-
-    private final ItemAnimatorFinishedListener mFinishedListener =
-            new ItemAnimatorFinishedListener() {
-                @Override
-                public void onAnimationsFinished() {
-                    mLayoutManager.offsetRows();
-                }
-            };
-}
diff --git a/car/src/main/java/androidx/car/widget/CarRecyclerView.java b/car/src/main/java/androidx/car/widget/CarRecyclerView.java
deleted file mode 100644
index 1d89ed1..0000000
--- a/car/src/main/java/androidx/car/widget/CarRecyclerView.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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 androidx.car.widget;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Custom {@link RecyclerView} that helps {@link PagedLayoutManager} properly fling and paginate.
- *
- * <p>It also has the ability to fade children as they scroll off screen that can be set with {@link
- * #setFadeLastItem(boolean)}.
- */
-public class CarRecyclerView extends RecyclerView {
-    private boolean mFadeLastItem;
-    /**
-     * If the user releases the list with a velocity of 0, {@link #fling(int, int)} will not be
-     * called. However, we want to make sure that the list still snaps to the next page when this
-     * happens.
-     */
-    private boolean mWasFlingCalledForGesture;
-
-    public CarRecyclerView(Context context) {
-        this(context, null);
-    }
-
-    public CarRecyclerView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public CarRecyclerView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        setFocusableInTouchMode(false);
-        setFocusable(false);
-    }
-
-    @Override
-    public boolean fling(int velocityX, int velocityY) {
-        mWasFlingCalledForGesture = true;
-        return ((PagedLayoutManager) getLayoutManager()).settleScrollForFling(this, velocityY);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent e) {
-        // We want the parent to handle all touch events. There's a lot going on there,
-        // and there is no reason to overwrite that functionality. If we do, bad things will happen.
-        final boolean ret = super.onTouchEvent(e);
-
-        int action = e.getActionMasked();
-        if (action == MotionEvent.ACTION_UP) {
-            if (!mWasFlingCalledForGesture) {
-                ((PagedLayoutManager) getLayoutManager()).settleScrollForFling(this, 0);
-            }
-            mWasFlingCalledForGesture = false;
-        }
-
-        return ret;
-    }
-
-    @Override
-    public boolean drawChild(@NonNull Canvas canvas, @NonNull View child, long drawingTime) {
-        if (mFadeLastItem) {
-            float onScreen = 1f;
-            if ((child.getTop() < getBottom() && child.getBottom() > getBottom())) {
-                onScreen = ((float) (getBottom() - child.getTop())) / (float) child.getHeight();
-            } else if ((child.getTop() < getTop() && child.getBottom() > getTop())) {
-                onScreen = ((float) (child.getBottom() - getTop())) / (float) child.getHeight();
-            }
-            float alpha = 1 - (1 - onScreen) * (1 - onScreen);
-            fadeChild(child, alpha);
-        }
-
-        return super.drawChild(canvas, child, drawingTime);
-    }
-
-    public void setFadeLastItem(boolean fadeLastItem) {
-        mFadeLastItem = fadeLastItem;
-    }
-
-    /**
-     * Scrolls the contents of this {@link CarRecyclerView} up one page. A page is defined as the
-     * number of items that fit completely on the screen.
-     */
-    public void pageUp() {
-        PagedLayoutManager lm = (PagedLayoutManager) getLayoutManager();
-        int pageUpPosition = lm.getPageUpPosition();
-        if (pageUpPosition == -1) {
-            return;
-        }
-
-        smoothScrollToPosition(pageUpPosition);
-    }
-
-    /**
-     * Scrolls the contents of this {@link CarRecyclerView} down one page. A page is defined as the
-     * number of items that fit completely on the screen.
-     */
-    public void pageDown() {
-        PagedLayoutManager lm = (PagedLayoutManager) getLayoutManager();
-        int pageDownPosition = lm.getPageDownPosition();
-        if (pageDownPosition == -1) {
-            return;
-        }
-
-        smoothScrollToPosition(pageDownPosition);
-    }
-
-    /**
-     * Fades child by alpha. If child is a {@link ViewGroup} then it will recursively fade its
-     * children instead.
-     */
-    private void fadeChild(@NonNull View child, float alpha) {
-        if (child instanceof ViewGroup) {
-            ViewGroup vg = (ViewGroup) child;
-            for (int i = 0; i < vg.getChildCount(); i++) {
-                fadeChild(vg.getChildAt(i), alpha);
-            }
-        } else {
-            child.setAlpha(alpha);
-        }
-    }
-}
diff --git a/car/src/main/java/androidx/car/widget/ListItem.java b/car/src/main/java/androidx/car/widget/ListItem.java
index c5b93d9..08cc48e 100644
--- a/car/src/main/java/androidx/car/widget/ListItem.java
+++ b/car/src/main/java/androidx/car/widget/ListItem.java
@@ -276,6 +276,8 @@
          * margin otherwise align center vertically.
          */
         private void setPrimaryIconLayout() {
+            // Set all relevant fields in layout params to avoid carried over params when the item
+            // gets bound to a recycled view holder.
             switch (mPrimaryActionType) {
                 case PRIMARY_ACTION_TYPE_SMALL_ICON:
                     mBinders.add(vh -> {
@@ -293,11 +295,13 @@
 
                         if (!TextUtils.isEmpty(mBody)) {
                             // Set top margin.
+                            layoutParams.removeRule(RelativeLayout.CENTER_VERTICAL);
                             layoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
                                     R.dimen.car_padding_4);
                         } else {
                             // Centered vertically.
                             layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
+                            layoutParams.topMargin = 0;
                         }
                         vh.getPrimaryIcon().setLayoutParams(layoutParams);
                     });
@@ -317,6 +321,7 @@
 
                         // Always centered vertically.
                         layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
+                        layoutParams.topMargin = 0;
 
                         vh.getPrimaryIcon().setLayoutParams(layoutParams);
                     });
@@ -396,12 +401,15 @@
          * Sets top/bottom margins of {@code Title} and {@code Body}.
          */
         private void setTextVerticalMargin() {
+            // Set all relevant fields in layout params to avoid carried over params when the item
+            // gets bound to a recycled view holder.
             if (!TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mBody)) {
                 // Title only - view is aligned center vertically by itself.
                 mBinders.add(vh -> {
                     RelativeLayout.LayoutParams layoutParams =
                             (RelativeLayout.LayoutParams) vh.getTitle().getLayoutParams();
                     layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
+                    layoutParams.topMargin = 0;
                     vh.getTitle().setLayoutParams(layoutParams);
                 });
             } else if (TextUtils.isEmpty(mTitle) && !TextUtils.isEmpty(mBody)) {
@@ -412,6 +420,7 @@
                     RelativeLayout.LayoutParams layoutParams =
                             (RelativeLayout.LayoutParams) vh.getBody().getLayoutParams();
                     layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
+                    layoutParams.removeRule(RelativeLayout.BELOW);
                     layoutParams.topMargin = margin;
                     layoutParams.bottomMargin = margin;
                     vh.getBody().setLayoutParams(layoutParams);
@@ -422,13 +431,16 @@
                     Resources resources = mContext.getResources();
                     int padding1 = resources.getDimensionPixelSize(R.dimen.car_padding_1);
                     int padding3 = resources.getDimensionPixelSize(R.dimen.car_padding_3);
+
                     RelativeLayout.LayoutParams titleLayoutParams =
                             (RelativeLayout.LayoutParams) vh.getTitle().getLayoutParams();
+                    titleLayoutParams.removeRule(RelativeLayout.CENTER_VERTICAL);
                     titleLayoutParams.topMargin = padding3;
                     vh.getTitle().setLayoutParams(titleLayoutParams);
                     // Body is below title with a margin, and has bottom margin.
                     RelativeLayout.LayoutParams bodyLayoutParams =
                             (RelativeLayout.LayoutParams) vh.getBody().getLayoutParams();
+                    bodyLayoutParams.removeRule(RelativeLayout.CENTER_VERTICAL);
                     bodyLayoutParams.addRule(RelativeLayout.BELOW, R.id.title);
                     bodyLayoutParams.topMargin = padding1;
                     bodyLayoutParams.bottomMargin = padding3;
@@ -452,6 +464,8 @@
                         vh.getSupplementalIcon().setImageResource(mSupplementalIconResId);
                         vh.getSupplementalIcon().setOnClickListener(
                                 mSupplementalIconOnClickListener);
+                        vh.getSupplementalIcon().setClickable(
+                                mSupplementalIconOnClickListener != null);
                     });
                     break;
                 case SUPPLEMENTAL_ACTION_TWO_ACTIONS:
@@ -644,6 +658,9 @@
             if (TextUtils.isEmpty(text)) {
                 throw new IllegalArgumentException("Action text cannot be empty.");
             }
+            if (listener == null) {
+                throw new IllegalArgumentException("Action OnClickListener cannot be null.");
+            }
             mSupplementalActionType = SUPPLEMENTAL_ACTION_ONE_ACTION;
 
             mAction1Text = text;
@@ -664,11 +681,11 @@
                 View.OnClickListener action1OnClickListener,
                 String action2Text, boolean showAction2Divider,
                 View.OnClickListener action2OnClickListener) {
-            if (TextUtils.isEmpty(action1Text)) {
-                throw new IllegalArgumentException("Action1 text cannot be empty.");
+            if (TextUtils.isEmpty(action1Text) || TextUtils.isEmpty(action2Text)) {
+                throw new IllegalArgumentException("Action text cannot be empty.");
             }
-            if (TextUtils.isEmpty(action2Text)) {
-                throw new IllegalArgumentException("Action2 text cannot be empty.");
+            if (action1OnClickListener == null || action2OnClickListener == null) {
+                throw new IllegalArgumentException("Action OnClickListener cannot be null.");
             }
             mSupplementalActionType = SUPPLEMENTAL_ACTION_TWO_ACTIONS;
 
diff --git a/car/src/main/java/androidx/car/widget/PagedLayoutManager.java b/car/src/main/java/androidx/car/widget/PagedLayoutManager.java
deleted file mode 100644
index cf3b75d..0000000
--- a/car/src/main/java/androidx/car/widget/PagedLayoutManager.java
+++ /dev/null
@@ -1,1688 +0,0 @@
-/*
- * Copyright 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 androidx.car.widget;
-
-import android.content.Context;
-import android.graphics.PointF;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.support.annotation.IntDef;
-import android.support.annotation.NonNull;
-import android.support.annotation.VisibleForTesting;
-import android.support.v7.widget.LinearSmoothScroller;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.Recycler;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.LruCache;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.Animation;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.Transformation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-
-import androidx.car.R;
-
-/**
- * Custom {@link RecyclerView.LayoutManager} that behaves similar to LinearLayoutManager except that
- * it has a few tricks up its sleeve.
- *
- * <ol>
- *   <li>In a normal ListView, when views reach the top of the list, they are clipped. In
- *       PagedLayoutManager, views have the option of flying off of the top of the screen as the
- *       next row settles in to place. This functionality can be enabled or disabled with
- *       {@link #setOffsetRows(boolean)}.
- *   <li>Standard list physics is disabled. Instead, when the user scrolls, it will settle on the
- *       next page.
- *   <li>Items can scroll past the bottom edge of the screen. This helps with pagination so that the
- *       last page can be properly aligned.
- * </ol>
- *
- * This LayoutManger should be used with {@link CarRecyclerView}.
- */
-public class PagedLayoutManager extends RecyclerView.LayoutManager {
-    private static final String TAG = "PagedLayoutManager";
-
-    /**
-     * Any fling below the threshold will just scroll to the top fully visible row. The units is
-     * whatever {@link android.widget.Scroller} would return.
-     *
-     * <p>A reasonable value is ~200
-     *
-     * <p>This can be disabled by setting the threshold to -1.
-     */
-    private static final int FLING_THRESHOLD_TO_PAGINATE = -1;
-
-    /**
-     * Any fling shorter than this threshold (in px) will just scroll to the top fully visible row.
-     *
-     * <p>A reasonable value is 15.
-     *
-     * <p>This can be disabled by setting the distance to -1.
-     */
-    private static final int DRAG_DISTANCE_TO_PAGINATE = -1;
-
-    /**
-     * If you scroll really quickly, you can hit the end of the laid out rows before Android has a
-     * chance to layout more. To help counter this, we can layout a number of extra rows past
-     * wherever the focus is if necessary.
-     */
-    private static final int NUM_EXTRA_ROWS_TO_LAYOUT_PAST_FOCUS = 2;
-
-    /**
-     * Scroll bar calculation is a bit complicated. This basically defines the granularity we want
-     * our scroll bar to move. Set this to 1 means our scrollbar will have really jerky movement.
-     * Setting it too big will risk an overflow (although there is no performance impact). Ideally
-     * we want to set this higher than the height of our list view. We can't use our list view
-     * height directly though because we might run into situations where getHeight() returns 0,
-     * for example, when the view is not yet measured.
-     */
-    private static final int SCROLL_RANGE = 1000;
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({BEFORE, AFTER})
-    private @interface LayoutDirection {}
-
-    private static final int BEFORE = 0;
-    private static final int AFTER = 1;
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({ROW_OFFSET_MODE_INDIVIDUAL, ROW_OFFSET_MODE_PAGE})
-    public @interface RowOffsetMode {}
-
-    public static final int ROW_OFFSET_MODE_INDIVIDUAL = 0;
-    public static final int ROW_OFFSET_MODE_PAGE = 1;
-
-    private final AccelerateInterpolator mDanglingRowInterpolator = new AccelerateInterpolator(2);
-    private final Context mContext;
-
-    /** Determines whether or not rows will be offset as they slide off screen * */
-    private boolean mOffsetRows;
-
-    /** Determines whether rows will be offset individually or a page at a time * */
-    @RowOffsetMode private int mRowOffsetMode = ROW_OFFSET_MODE_PAGE;
-
-    /**
-     * The LayoutManager only gets {@link #onScrollStateChanged(int)} updates. This enables the
-     * scroll state to be used anywhere.
-     */
-    private int mScrollState = RecyclerView.SCROLL_STATE_IDLE;
-
-    /** Used to inspect the current scroll state to help with the various calculations. */
-    private CarSmoothScroller mSmoothScroller;
-
-    private PagedListView.OnScrollListener mOnScrollListener;
-
-    /** The distance that the list has actually scrolled in the most recent drag gesture. */
-    private int mLastDragDistance = 0;
-
-    /** {@code True} if the current drag was limited/capped because it was at some boundary. */
-    private boolean mReachedLimitOfDrag;
-
-    /** The index of the first item on the current page. */
-    private int mAnchorPageBreakPosition = 0;
-
-    /** The index of the first item on the previous page. */
-    private int mUpperPageBreakPosition = -1;
-
-    /** The index of the first item on the next page. */
-    private int mLowerPageBreakPosition = -1;
-
-    /** Used in the bookkeeping of mario style scrolling to prevent extra calculations. */
-    private int mLastChildPositionToRequestFocus = -1;
-
-    private int mSampleViewHeight = -1;
-
-    /** Used for onPageUp and onPageDown */
-    private int mViewsPerPage = 1;
-
-    private int mCurrentPage = 0;
-
-    private static final int MAX_ANIMATIONS_IN_CACHE = 30;
-    /**
-     * Cache of TranslateAnimation per child view. These are needed since using a single animation
-     * for all children doesn't apply the animation effect multiple times. Key = the view the
-     * animation will transform.
-     */
-    private LruCache<View, TranslateAnimation> mFlyOffscreenAnimations;
-
-    /** Set the anchor to the following position on the next layout pass. */
-    private int mPendingScrollPosition = -1;
-
-    public PagedLayoutManager(Context context) {
-        mContext = context;
-    }
-
-    @Override
-    public RecyclerView.LayoutParams generateDefaultLayoutParams() {
-        return new RecyclerView.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-    }
-
-    @Override
-    public boolean canScrollVertically() {
-        return true;
-    }
-
-    /**
-     * onLayoutChildren is sort of like a "reset" for the layout state. At a high level, it should:
-     *
-     * <ol>
-     *   <li>Check the current views to get the current state of affairs
-     *   <li>Detach all views from the window (a lightweight operation) so that rows not re-added
-     *       will be removed after onLayoutChildren.
-     *   <li>Re-add rows as necessary.
-     * </ol>
-     *
-     * @see super#onLayoutChildren(RecyclerView.Recycler, RecyclerView.State)
-     */
-    @Override
-    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
-        /*
-         * The anchor view is the first fully visible view on screen at the beginning of
-         * onLayoutChildren (or 0 if there is none). This row will be laid out first. After that,
-         * layoutNextRow will layout rows above and below it until the boundaries of what should be
-         * laid out have been reached. See shouldLayoutNextRow(View, int) for more info.
-         */
-        int anchorPosition = 0;
-        int anchorTop = -1;
-        if (mPendingScrollPosition == -1) {
-            View anchor = getFirstFullyVisibleChild();
-            if (anchor != null) {
-                anchorPosition = getPosition(anchor);
-                anchorTop = getDecoratedTop(anchor);
-            }
-        } else {
-            anchorPosition = mPendingScrollPosition;
-            mPendingScrollPosition = -1;
-            mAnchorPageBreakPosition = anchorPosition;
-            mUpperPageBreakPosition = -1;
-            mLowerPageBreakPosition = -1;
-        }
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(
-                    TAG,
-                    String.format(
-                            ":: onLayoutChildren anchorPosition:%s, anchorTop:%s,"
-                                    + " mPendingScrollPosition: %s, mAnchorPageBreakPosition:%s,"
-                                    + " mUpperPageBreakPosition:%s, mLowerPageBreakPosition:%s",
-                            anchorPosition,
-                            anchorTop,
-                            mPendingScrollPosition,
-                            mAnchorPageBreakPosition,
-                            mUpperPageBreakPosition,
-                            mLowerPageBreakPosition));
-        }
-
-        /*
-         * Detach all attached view for 2 reasons:
-         *
-         * 1) So that views are put in the scrap heap. This enables us to call {@link
-         *    RecyclerView.Recycler#getViewForPosition(int)} which will either return one of these
-         *    detached views if it is in the scrap heap, one from the recycled pool (will only call
-         *    onBind in the adapter), or create an entirely new row if needed (will call onCreate
-         *    and onBind in the adapter).
-         * 2) So that views are automatically removed if they are not manually re-added.
-         */
-        detachAndScrapAttachedViews(recycler);
-
-        /*
-         * Layout the views recursively.
-         *
-         * It's possible that this re-layout is triggered because an item gets removed. If the
-         * anchor view is at the end of the list, the anchor view position will be bigger than the
-         * number of available items. Correct that, and only start the layout if the anchor
-         * position is valid.
-         */
-        anchorPosition = Math.min(anchorPosition, getItemCount() - 1);
-        if (anchorPosition >= 0) {
-            View anchor = layoutAnchor(recycler, anchorPosition, anchorTop);
-            View adjacentRow = anchor;
-            while (shouldLayoutNextRow(state, adjacentRow, BEFORE)) {
-                adjacentRow = layoutNextRow(recycler, adjacentRow, BEFORE);
-            }
-            adjacentRow = anchor;
-            while (shouldLayoutNextRow(state, adjacentRow, AFTER)) {
-                adjacentRow = layoutNextRow(recycler, adjacentRow, AFTER);
-            }
-        }
-
-        updatePageBreakPositions();
-        offsetRows();
-
-        if (Log.isLoggable(TAG, Log.VERBOSE) && getChildCount() > 1) {
-            Log.v(TAG, "Currently showing "
-                    + getChildCount()
-                    + " views "
-                    + getPosition(getChildAt(0))
-                    + " to "
-                    + getPosition(getChildAt(getChildCount() - 1))
-                    + " anchor "
-                    + anchorPosition);
-        }
-        // Should be at least 1
-        mViewsPerPage =
-                Math.max(getLastFullyVisibleChildIndex() + 1 - getFirstFullyVisibleChildIndex(), 1);
-        mCurrentPage = getFirstFullyVisibleChildPosition() / mViewsPerPage;
-        Log.v(TAG, "viewsPerPage " + mViewsPerPage);
-    }
-
-    /**
-     * scrollVerticallyBy does the work of what should happen when the list scrolls in addition to
-     * handling cases where the list hits the end. It should be lighter weight than
-     * onLayoutChildren. It doesn't have to detach all views. It only looks at the end of the list
-     * and removes views that have gone out of bounds and lays out new ones that scroll in.
-     *
-     * @param dy The amount that the list is supposed to scroll. > 0 means the list is scrolling
-     *     down. < 0 means the list is scrolling up.
-     * @param recycler The recycler that enables views to be reused or created as they scroll in.
-     * @param state Various information about the current state of affairs.
-     * @return The amount the list actually scrolled.
-     * @see super#scrollVerticallyBy(int, RecyclerView.Recycler, RecyclerView.State)
-     */
-    @Override
-    public int scrollVerticallyBy(
-            int dy, @NonNull RecyclerView.Recycler recycler, @NonNull RecyclerView.State state) {
-        // If the list is empty, we can prevent the overscroll glow from showing by just
-        // telling RecycerView that we scrolled.
-        if (getItemCount() == 0) {
-            return dy;
-        }
-
-        // Prevent redundant computations if there is definitely nowhere to scroll to.
-        if (getChildCount() <= 1 || dy == 0) {
-            mReachedLimitOfDrag = true;
-            return 0;
-        }
-
-        View firstChild = getChildAt(0);
-        if (firstChild == null) {
-            mReachedLimitOfDrag = true;
-            return 0;
-        }
-        int firstChildPosition = getPosition(firstChild);
-        RecyclerView.LayoutParams firstChildParams = getParams(firstChild);
-        int firstChildTopWithMargin = getDecoratedTop(firstChild) - firstChildParams.topMargin;
-
-        View lastFullyVisibleView = getChildAt(getLastFullyVisibleChildIndex());
-        if (lastFullyVisibleView == null) {
-            mReachedLimitOfDrag = true;
-            return 0;
-        }
-        boolean isLastViewVisible = getPosition(lastFullyVisibleView) == getItemCount() - 1;
-
-        View firstFullyVisibleChild = getFirstFullyVisibleChild();
-        if (firstFullyVisibleChild == null) {
-            mReachedLimitOfDrag = true;
-            return 0;
-        }
-        int firstFullyVisiblePosition = getPosition(firstFullyVisibleChild);
-        RecyclerView.LayoutParams firstFullyVisibleChildParams = getParams(firstFullyVisibleChild);
-        int topRemainingSpace =
-                getDecoratedTop(firstFullyVisibleChild)
-                        - firstFullyVisibleChildParams.topMargin
-                        - getPaddingTop();
-
-        if (isLastViewVisible
-                && firstFullyVisiblePosition == mAnchorPageBreakPosition
-                && dy > topRemainingSpace
-                && dy > 0) {
-            // Prevent dragging down more than 1 page. As a side effect, this also prevents you
-            // from dragging past the bottom because if you are on the second to last page, it
-            // prevents you from dragging past the last page.
-            dy = topRemainingSpace;
-            mReachedLimitOfDrag = true;
-        } else if (dy < 0
-                && firstChildPosition == 0
-                && firstChildTopWithMargin + Math.abs(dy) > getPaddingTop()) {
-            // Prevent scrolling past the beginning
-            dy = firstChildTopWithMargin - getPaddingTop();
-            mReachedLimitOfDrag = true;
-        } else {
-            mReachedLimitOfDrag = false;
-        }
-
-        boolean isDragging = mScrollState == RecyclerView.SCROLL_STATE_DRAGGING;
-        if (isDragging) {
-            mLastDragDistance += dy;
-        }
-        // We offset by -dy because the views translate in the opposite direction that the
-        // list scrolls (think about it.)
-        offsetChildrenVertical(-dy);
-
-        // The last item in the layout should never scroll above the viewport
-        View view = getChildAt(getChildCount() - 1);
-        if (view.getTop() < 0) {
-            view.setTop(0);
-        }
-
-        // This is the meat of this function. We remove views on the trailing edge of the scroll
-        // and add views at the leading edge as necessary.
-        View adjacentRow;
-        if (dy > 0) {
-            recycleChildrenFromStart(recycler);
-            adjacentRow = getChildAt(getChildCount() - 1);
-            while (shouldLayoutNextRow(state, adjacentRow, AFTER)) {
-                adjacentRow = layoutNextRow(recycler, adjacentRow, AFTER);
-            }
-        } else {
-            recycleChildrenFromEnd(recycler);
-            adjacentRow = getChildAt(0);
-            while (shouldLayoutNextRow(state, adjacentRow, BEFORE)) {
-                adjacentRow = layoutNextRow(recycler, adjacentRow, BEFORE);
-            }
-        }
-        // Now that the correct views are laid out, offset rows as necessary so we can do whatever
-        // fancy animation we want such as having the top view fly off the screen as the next one
-        // settles in to place.
-        updatePageBreakPositions();
-        offsetRows();
-
-        if (getChildCount() > 1) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(
-                        TAG,
-                        String.format(
-                                "Currently showing  %d views (%d to %d)",
-                                getChildCount(),
-                                getPosition(getChildAt(0)),
-                                getPosition(getChildAt(getChildCount() - 1))));
-            }
-        }
-        updatePagedState();
-        return dy;
-    }
-
-    private void updatePagedState() {
-        int page = getFirstFullyVisibleChildPosition() / mViewsPerPage;
-        if (mOnScrollListener != null) {
-            if (page > mCurrentPage) {
-                mOnScrollListener.onPageDown();
-            } else if (page < mCurrentPage) {
-                mOnScrollListener.onPageUp();
-            }
-        }
-        mCurrentPage = page;
-    }
-
-    @Override
-    public void scrollToPosition(int position) {
-        mPendingScrollPosition = position;
-        requestLayout();
-    }
-
-    @Override
-    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
-            int position) {
-        /*
-         * startSmoothScroll will handle stopping the old one if there is one. We only keep a copy
-         * of it to handle the translation of rows as they slide off the screen in
-         * offsetRowsWithPageBreak().
-         */
-        mSmoothScroller = new CarSmoothScroller(mContext, position);
-        mSmoothScroller.setTargetPosition(position);
-        startSmoothScroll(mSmoothScroller);
-    }
-
-    /** Miscellaneous bookkeeping. */
-    @Override
-    public void onScrollStateChanged(int state) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, ":: onScrollStateChanged " + state);
-        }
-        if (state == RecyclerView.SCROLL_STATE_IDLE) {
-            // If the focused view is off screen, give focus to one that is.
-            // If the first fully visible view is first in the list, focus the first item.
-            // Otherwise, focus the second so that you have the first item as scrolling context.
-            View focusedChild = getFocusedChild();
-            if (focusedChild != null
-                    && (getDecoratedTop(focusedChild) >= getHeight() - getPaddingBottom()
-                    || getDecoratedBottom(focusedChild) <= getPaddingTop())) {
-                focusedChild.clearFocus();
-                requestLayout();
-            }
-
-        } else if (state == RecyclerView.SCROLL_STATE_DRAGGING) {
-            mLastDragDistance = 0;
-        }
-
-        if (state != RecyclerView.SCROLL_STATE_SETTLING) {
-            mSmoothScroller = null;
-        }
-
-        mScrollState = state;
-        updatePageBreakPositions();
-    }
-
-    @Override
-    public void onItemsChanged(RecyclerView recyclerView) {
-        super.onItemsChanged(recyclerView);
-        // When item changed, our sample view height is no longer accurate, and need to be
-        // recomputed.
-        mSampleViewHeight = -1;
-    }
-
-    /**
-     * Gives us the opportunity to override the order of the focused views. By default, it will just
-     * go from top to bottom. However, if there is no focused views, we take over the logic and
-     * start the focused views from the middle of what is visible and move from there until the
-     * end of the laid out views in the specified direction.
-     */
-    @Override
-    public boolean onAddFocusables(
-            RecyclerView recyclerView, ArrayList<View> views, int direction, int focusableMode) {
-        View focusedChild = getFocusedChild();
-        if (focusedChild != null) {
-            // If there is a view that already has focus, we can just return false and the normal
-            // Android addFocusables will work fine.
-            return false;
-        }
-
-        // Now we know that there isn't a focused view. We need to set up focusables such that
-        // instead of just focusing the first item that has been laid out, it focuses starting
-        // from a visible item.
-
-        int firstFullyVisibleChildIndex = getFirstFullyVisibleChildIndex();
-        if (firstFullyVisibleChildIndex == -1) {
-            // Somehow there is a focused view but there is no fully visible view. There shouldn't
-            // be a way for this to happen but we'd better stop here and return instead of
-            // continuing on with -1.
-            Log.w(TAG, "There is a focused child but no first fully visible child.");
-            return false;
-        }
-        View firstFullyVisibleChild = getChildAt(firstFullyVisibleChildIndex);
-        int firstFullyVisibleChildPosition = getPosition(firstFullyVisibleChild);
-
-        int firstFocusableChildIndex = firstFullyVisibleChildIndex;
-        if (firstFullyVisibleChildPosition > 0 && firstFocusableChildIndex + 1 < getItemCount()) {
-            // We are somewhere in the middle of the list. Instead of starting focus on the first
-            // item, start focus on the second item to give some context that we aren't at
-            // the beginning.
-            firstFocusableChildIndex++;
-        }
-
-        if (direction == View.FOCUS_FORWARD) {
-            // Iterate from the first focusable view to the end.
-            for (int i = firstFocusableChildIndex; i < getChildCount(); i++) {
-                views.add(getChildAt(i));
-            }
-            return true;
-        } else if (direction == View.FOCUS_BACKWARD) {
-            // Iterate from the first focusable view to the beginning.
-            for (int i = firstFocusableChildIndex; i >= 0; i--) {
-                views.add(getChildAt(i));
-            }
-            return true;
-        } else if (direction == View.FOCUS_DOWN) {
-            // Framework calls onAddFocusables with FOCUS_DOWN direction when the focus is first
-            // gained. Thereafter, it calls onAddFocusables with FOCUS_FORWARD or FOCUS_BACKWARD.
-            // First we try to put the focus back on the last focused item, if it is visible
-            int lastFocusedVisibleChildIndex = getLastFocusedChildIndexIfVisible();
-            if (lastFocusedVisibleChildIndex != -1) {
-                views.add(getChildAt(lastFocusedVisibleChildIndex));
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public View onFocusSearchFailed(
-            View focused, int direction, RecyclerView.Recycler recycler, RecyclerView.State state) {
-        // This doesn't seem to get called the way focus is handled in gearhead...
-        return null;
-    }
-
-    /**
-     * This is the function that decides where to scroll to when a new view is focused. You can get
-     * the position of the currently focused child through the child parameter. Once you have that,
-     * determine where to smooth scroll to and scroll there.
-     *
-     * @param parent The RecyclerView hosting this LayoutManager
-     * @param state Current state of RecyclerView
-     * @param child Direct child of the RecyclerView containing the newly focused view
-     * @param focused The newly focused view. This may be the same view as child or it may be null
-     * @return {@code true} if the default scroll behavior should be suppressed
-     */
-    @Override
-    public boolean onRequestChildFocus(
-            RecyclerView parent, RecyclerView.State state, View child, View focused) {
-        if (child == null) {
-            Log.w(TAG, "onRequestChildFocus with a null child!");
-            return true;
-        }
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, String.format(":: onRequestChildFocus child: %s, focused: %s", child,
-                    focused));
-        }
-
-        return onRequestChildFocusMarioStyle(parent, child);
-    }
-
-    /**
-     * Goal: the scrollbar maintains the same size throughout scrolling and that the scrollbar
-     * reaches the bottom of the screen when the last item is fully visible. This is because there
-     * are multiple points that could be considered the bottom since the last item can scroll past
-     * the bottom edge of the screen.
-     *
-     * <p>To find the extent, we divide the number of items that can fit on screen by the number of
-     * items in total.
-     */
-    @Override
-    public int computeVerticalScrollExtent(RecyclerView.State state) {
-        if (getChildCount() <= 1) {
-            return 0;
-        }
-
-        int sampleViewHeight = getSampleViewHeight();
-        int availableHeight = getAvailableHeight();
-        int sampleViewsThatCanFitOnScreen = availableHeight / sampleViewHeight;
-
-        if (state.getItemCount() <= sampleViewsThatCanFitOnScreen) {
-            return SCROLL_RANGE;
-        } else {
-            return SCROLL_RANGE * sampleViewsThatCanFitOnScreen / state.getItemCount();
-        }
-    }
-
-    /**
-     * The scrolling offset is calculated by determining what position is at the top of the list.
-     * However, instead of using fixed integer positions for each row, the scroll position is
-     * factored in and the position is recalculated as a float that takes in to account the
-     * current scroll state. This results in a smooth animation for the scrollbar when the user
-     * scrolls the list.
-     */
-    @Override
-    public int computeVerticalScrollOffset(RecyclerView.State state) {
-        View firstChild = getFirstFullyVisibleChild();
-        if (firstChild == null) {
-            return 0;
-        }
-
-        RecyclerView.LayoutParams params = getParams(firstChild);
-        int firstChildPosition = getPosition(firstChild);
-        float previousChildHieght = (float) (getDecoratedMeasuredHeight(firstChild)
-                + params.topMargin + params.bottomMargin);
-
-        // Assume the previous view is the same height as the current one.
-        float percentOfPreviousViewShowing = (getDecoratedTop(firstChild) - params.topMargin)
-                / previousChildHieght;
-        // If the previous view is actually larger than the current one then this the percent
-        // can be greater than 1.
-        percentOfPreviousViewShowing = Math.min(percentOfPreviousViewShowing, 1);
-
-        float currentPosition = (float) firstChildPosition - percentOfPreviousViewShowing;
-
-        int sampleViewHeight = getSampleViewHeight();
-        int availableHeight = getAvailableHeight();
-        int numberOfSampleViewsThatCanFitOnScreen = availableHeight / sampleViewHeight;
-        int positionWhenLastItemIsVisible =
-                state.getItemCount() - numberOfSampleViewsThatCanFitOnScreen;
-
-        if (positionWhenLastItemIsVisible <= 0) {
-            return 0;
-        }
-
-        if (currentPosition >= positionWhenLastItemIsVisible) {
-            return SCROLL_RANGE;
-        }
-
-        return (int) (SCROLL_RANGE * currentPosition / positionWhenLastItemIsVisible);
-    }
-
-    /**
-     * The range of the scrollbar can be understood as the granularity of how we want the scrollbar
-     * to scroll.
-     */
-    @Override
-    public int computeVerticalScrollRange(RecyclerView.State state) {
-        return SCROLL_RANGE;
-    }
-
-    @Override
-    public void onAttachedToWindow(RecyclerView view) {
-        super.onAttachedToWindow(view);
-        // The purpose of calling this is so that any animation offsets are re-applied. These are
-        // cleared in View.onDetachedFromWindow().
-        // This fixes b/27672379
-        updatePageBreakPositions();
-        offsetRows();
-    }
-
-    @Override
-    public void onDetachedFromWindow(RecyclerView recyclerView, Recycler recycler) {
-        super.onDetachedFromWindow(recyclerView, recycler);
-    }
-
-    /**
-     * @return The first view that starts on screen. It assumes that it fully fits on the screen
-     *     though. If the first fully visible child is also taller than the screen then it will
-     *     still be returned. However, since the LayoutManager snaps to view starts, having a row
-     *     that tall would lead to a broken experience anyways.
-     */
-    public int getFirstFullyVisibleChildIndex() {
-        for (int i = 0; i < getChildCount(); i++) {
-            View child = getChildAt(i);
-            RecyclerView.LayoutParams params = getParams(child);
-            if (getDecoratedTop(child) - params.topMargin >= getPaddingTop()) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * @return The position of first visible child in the list. -1 will be returned if there is no
-     *     child.
-     */
-    public int getFirstFullyVisibleChildPosition() {
-        View child = getFirstFullyVisibleChild();
-        if (child == null) {
-            return -1;
-        }
-        return getPosition(child);
-    }
-
-    /**
-     * @return The position of last visible child in the list. -1 will be returned if there is no
-     *     child.
-     */
-    public int getLastFullyVisibleChildPosition() {
-        View child = getLastFullyVisibleChild();
-        if (child == null) {
-            return -1;
-        }
-        return getPosition(child);
-    }
-
-    /** @return The first View that is completely visible on-screen. */
-    public View getFirstFullyVisibleChild() {
-        int firstFullyVisibleChildIndex = getFirstFullyVisibleChildIndex();
-        View firstChild = null;
-        if (firstFullyVisibleChildIndex != -1) {
-            firstChild = getChildAt(firstFullyVisibleChildIndex);
-        }
-        return firstChild;
-    }
-
-    /** @return The last View that is completely visible on-screen. */
-    public View getLastFullyVisibleChild() {
-        int lastFullyVisibleChildIndex = getLastFullyVisibleChildIndex();
-        View lastChild = null;
-        if (lastFullyVisibleChildIndex != -1) {
-            lastChild = getChildAt(lastFullyVisibleChildIndex);
-        }
-        return lastChild;
-    }
-
-    /**
-     * @return The last view that ends on screen. It assumes that the start is also on screen
-     *     though. If the last fully visible child is also taller than the screen then it will
-     *     still be returned. However, since the LayoutManager snaps to view starts, having a row
-     *     that tall would lead to a broken experience anyways.
-     */
-    public int getLastFullyVisibleChildIndex() {
-        for (int i = getChildCount() - 1; i >= 0; i--) {
-            View child = getChildAt(i);
-            RecyclerView.LayoutParams params = getParams(child);
-            int childBottom = getDecoratedBottom(child) + params.bottomMargin;
-            int listBottom = getHeight() - getPaddingBottom();
-            if (childBottom <= listBottom) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Returns the index of the child in the list that was last focused and is currently visible to
-     * the user. If no child is found, returns -1.
-     */
-    public int getLastFocusedChildIndexIfVisible() {
-        if (mLastChildPositionToRequestFocus == -1) {
-            return -1;
-        }
-        for (int i = 0; i < getChildCount(); i++) {
-            View child = getChildAt(i);
-            if (getPosition(child) == mLastChildPositionToRequestFocus) {
-                RecyclerView.LayoutParams params = getParams(child);
-                int childBottom = getDecoratedBottom(child) + params.bottomMargin;
-                int listBottom = getHeight() - getPaddingBottom();
-                if (childBottom <= listBottom) {
-                    return i;
-                }
-                break;
-            }
-        }
-        return -1;
-    }
-
-    /** @return Whether or not the first view is fully visible. */
-    public boolean isAtTop() {
-        // getFirstFullyVisibleChildIndex() can return -1 which indicates that there are no views
-        // and also means that the list is at the top.
-        return getFirstFullyVisibleChildIndex() <= 0;
-    }
-
-    /** @return Whether or not the last view is fully visible. */
-    public boolean isAtBottom() {
-        int lastFullyVisibleChildIndex = getLastFullyVisibleChildIndex();
-        if (lastFullyVisibleChildIndex == -1) {
-            return true;
-        }
-        View lastFullyVisibleChild = getChildAt(lastFullyVisibleChildIndex);
-        return getPosition(lastFullyVisibleChild) == getItemCount() - 1;
-    }
-
-    /**
-     * Sets whether or not the rows have an offset animation when it scrolls off-screen. The type
-     * of offset is determined by {@link #setRowOffsetMode(int)}.
-     *
-     * <p>A row being offset means that when they reach the top of the screen, the row is flung off
-     * respectively to the rest of the list. This creates a gap between the offset row(s) and the
-     * list.
-     *
-     * @param offsetRows {@code true} if the rows should be offset.
-     */
-    public void setOffsetRows(boolean offsetRows) {
-        mOffsetRows = offsetRows;
-        if (offsetRows) {
-            // Card animation offsets are only needed when we use the flying off the screen effect
-            if (mFlyOffscreenAnimations == null) {
-                mFlyOffscreenAnimations = new LruCache<>(MAX_ANIMATIONS_IN_CACHE);
-            }
-            offsetRows();
-        } else {
-            int childCount = getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                setCardFlyingEffectOffset(getChildAt(i), 0);
-            }
-            mFlyOffscreenAnimations = null;
-        }
-    }
-
-    /**
-     * Sets the manner of offsetting the rows when they are scrolled off-screen. The rows are either
-     * offset individually or the entire page being scrolled off is offset.
-     *
-     * @param mode One of {@link #ROW_OFFSET_MODE_INDIVIDUAL} or {@link #ROW_OFFSET_MODE_PAGE}.
-     */
-    public void setRowOffsetMode(@RowOffsetMode int mode) {
-        if (mode == mRowOffsetMode) {
-            return;
-        }
-
-        mRowOffsetMode = mode;
-        offsetRows();
-    }
-
-    /**
-     * Sets the listener that will be notified of various scroll events in the list.
-     *
-     * @param listener The on-scroll listener.
-     */
-    public void setOnScrollListener(PagedListView.OnScrollListener listener) {
-        mOnScrollListener = listener;
-    }
-
-    /**
-     * Finish the pagination taking into account where the gesture started (not where we are now).
-     *
-     * @return Whether the list was scrolled as a result of the fling.
-     */
-    public boolean settleScrollForFling(RecyclerView parent, int flingVelocity) {
-        if (getChildCount() == 0) {
-            return false;
-        }
-
-        if (mReachedLimitOfDrag) {
-            return false;
-        }
-
-        // If the fling was too slow or too short, settle on the first fully visible row instead.
-        if (Math.abs(flingVelocity) <= FLING_THRESHOLD_TO_PAGINATE
-                || Math.abs(mLastDragDistance) <= DRAG_DISTANCE_TO_PAGINATE) {
-            int firstFullyVisibleChildIndex = getFirstFullyVisibleChildIndex();
-            if (firstFullyVisibleChildIndex != -1) {
-                int scrollPosition = getPosition(getChildAt(firstFullyVisibleChildIndex));
-                parent.smoothScrollToPosition(scrollPosition);
-                return true;
-            }
-            return false;
-        }
-
-        // Finish the pagination taking into account where the gesture
-        // started (not where we are now).
-        boolean isDownGesture = flingVelocity > 0 || (flingVelocity == 0 && mLastDragDistance >= 0);
-        boolean isUpGesture = flingVelocity < 0 || (flingVelocity == 0 && mLastDragDistance < 0);
-        if (isDownGesture && mLowerPageBreakPosition != -1) {
-            // If the last view is fully visible then only settle on the first fully visible view
-            // instead of the original page down position. However, don't page down if the last
-            // item has come fully into view.
-            parent.smoothScrollToPosition(mAnchorPageBreakPosition);
-            if (mOnScrollListener != null) {
-                mOnScrollListener.onGestureDown();
-            }
-            return true;
-        } else if (isUpGesture && mUpperPageBreakPosition != -1) {
-            parent.smoothScrollToPosition(mUpperPageBreakPosition);
-            if (mOnScrollListener != null) {
-                mOnScrollListener.onGestureUp();
-            }
-            return true;
-        } else {
-            Log.e(
-                    TAG,
-                    "Error setting scroll for fling! flingVelocity: \t"
-                            + flingVelocity
-                            + "\tlastDragDistance: "
-                            + mLastDragDistance
-                            + "\tpageUpAtStartOfDrag: "
-                            + mUpperPageBreakPosition
-                            + "\tpageDownAtStartOfDrag: "
-                            + mLowerPageBreakPosition);
-            // As a last resort, at the last smooth scroller target position if there is one.
-            if (mSmoothScroller != null) {
-                parent.smoothScrollToPosition(mSmoothScroller.getTargetPosition());
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /** @return The position that paging up from the current position would settle at. */
-    public int getPageUpPosition() {
-        return mUpperPageBreakPosition;
-    }
-
-    /** @return The position that paging down from the current position would settle at. */
-    public int getPageDownPosition() {
-        return mLowerPageBreakPosition;
-    }
-
-    @Override
-    public Parcelable onSaveInstanceState() {
-        SavedState savedState = new SavedState();
-        savedState.mFirstChildPosition = getFirstFullyVisibleChildPosition();
-        return savedState;
-    }
-
-    @Override
-    public void onRestoreInstanceState(Parcelable state) {
-        if (state instanceof SavedState) {
-            scrollToPosition(((SavedState) state).mFirstChildPosition);
-        }
-    }
-
-    /** The state that will be saved across configuration changes. */
-    static class SavedState implements Parcelable {
-        /** The position of the first visible child view in the list. */
-        int mFirstChildPosition;
-
-        SavedState() {}
-
-        private SavedState(Parcel in) {
-            mFirstChildPosition = in.readInt();
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeInt(mFirstChildPosition);
-        }
-
-        public static final Parcelable.Creator<SavedState> CREATOR =
-                new Parcelable.Creator<SavedState>() {
-                    @Override
-                    public SavedState createFromParcel(Parcel in) {
-                        return new SavedState(in);
-                    }
-
-                    @Override
-                    public SavedState[] newArray(int size) {
-                        return new SavedState[size];
-                    }
-                };
-    }
-
-    /**
-     * Layout the anchor row. The anchor row is the first fully visible row.
-     *
-     * @param anchorTop The decorated top of the anchor. If it is not known or should be reset to
-     *     the top, pass -1.
-     */
-    private View layoutAnchor(RecyclerView.Recycler recycler, int anchorPosition, int anchorTop) {
-        View anchor = recycler.getViewForPosition(anchorPosition);
-        RecyclerView.LayoutParams params = getParams(anchor);
-        measureChildWithMargins(anchor, 0, 0);
-        int left = getPaddingLeft() + params.leftMargin;
-        int top = (anchorTop == -1) ? params.topMargin : anchorTop;
-        int right = left + getDecoratedMeasuredWidth(anchor);
-        int bottom = top + getDecoratedMeasuredHeight(anchor);
-        layoutDecorated(anchor, left, top, right, bottom);
-        addView(anchor);
-        return anchor;
-    }
-
-    /**
-     * Lays out the next row in the specified direction next to the specified adjacent row.
-     *
-     * @param recycler The recycler from which a new view can be created.
-     * @param adjacentRow The View of the adjacent row which will be used to position the new one.
-     * @param layoutDirection The side of the adjacent row that the new row will be laid out on.
-     * @return The new row that was laid out.
-     */
-    private View layoutNextRow(RecyclerView.Recycler recycler, View adjacentRow,
-            @LayoutDirection int layoutDirection) {
-        int adjacentRowPosition = getPosition(adjacentRow);
-        int newRowPosition = adjacentRowPosition;
-        if (layoutDirection == BEFORE) {
-            newRowPosition = adjacentRowPosition - 1;
-        } else if (layoutDirection == AFTER) {
-            newRowPosition = adjacentRowPosition + 1;
-        }
-
-        // Because we detach all rows in onLayoutChildren, this will often just return a view from
-        // the scrap heap.
-        View newRow = recycler.getViewForPosition(newRowPosition);
-
-        measureChildWithMargins(newRow, 0, 0);
-        RecyclerView.LayoutParams newRowParams =
-                (RecyclerView.LayoutParams) newRow.getLayoutParams();
-        RecyclerView.LayoutParams adjacentRowParams =
-                (RecyclerView.LayoutParams) adjacentRow.getLayoutParams();
-        int left = getPaddingLeft() + newRowParams.leftMargin;
-        int right = left + getDecoratedMeasuredWidth(newRow);
-        int top;
-        int bottom;
-        if (layoutDirection == BEFORE) {
-            bottom = adjacentRow.getTop() - adjacentRowParams.topMargin - newRowParams.bottomMargin;
-            top = bottom - getDecoratedMeasuredHeight(newRow);
-        } else {
-            top = getDecoratedBottom(adjacentRow) + adjacentRowParams.bottomMargin
-                    + newRowParams.topMargin;
-            bottom = top + getDecoratedMeasuredHeight(newRow);
-        }
-        layoutDecorated(newRow, left, top, right, bottom);
-
-        if (layoutDirection == BEFORE) {
-            addView(newRow, 0);
-        } else {
-            addView(newRow);
-        }
-
-        return newRow;
-    }
-
-    /** @return Whether another row should be laid out in the specified direction. */
-    private boolean shouldLayoutNextRow(
-            RecyclerView.State state, View adjacentRow, @LayoutDirection int layoutDirection) {
-        int adjacentRowPosition = getPosition(adjacentRow);
-
-        if (layoutDirection == BEFORE) {
-            if (adjacentRowPosition == 0) {
-                // We already laid out the first row.
-                return false;
-            }
-        } else if (layoutDirection == AFTER) {
-            if (adjacentRowPosition >= state.getItemCount() - 1) {
-                // We already laid out the last row.
-                return false;
-            }
-        }
-
-        // If we are scrolling layout views until the target position.
-        if (mSmoothScroller != null) {
-            if (layoutDirection == BEFORE
-                    && adjacentRowPosition >= mSmoothScroller.getTargetPosition()) {
-                return true;
-            } else if (layoutDirection == AFTER
-                    && adjacentRowPosition <= mSmoothScroller.getTargetPosition()) {
-                return true;
-            }
-        }
-
-        View focusedRow = getFocusedChild();
-        if (focusedRow != null) {
-            int focusedRowPosition = getPosition(focusedRow);
-            if (layoutDirection == BEFORE && adjacentRowPosition
-                    >= focusedRowPosition - NUM_EXTRA_ROWS_TO_LAYOUT_PAST_FOCUS) {
-                return true;
-            } else if (layoutDirection == AFTER && adjacentRowPosition
-                    <= focusedRowPosition + NUM_EXTRA_ROWS_TO_LAYOUT_PAST_FOCUS) {
-                return true;
-            }
-        }
-
-        RecyclerView.LayoutParams params = getParams(adjacentRow);
-        int adjacentRowTop = getDecoratedTop(adjacentRow) - params.topMargin;
-        int adjacentRowBottom = getDecoratedBottom(adjacentRow) - params.bottomMargin;
-        if (layoutDirection == BEFORE && adjacentRowTop < getPaddingTop() - getHeight()) {
-            // View is more than 1 page past the top of the screen and also past where the user has
-            // scrolled to. We want to keep one page past the top to make the scroll up calculation
-            // easier and scrolling smoother.
-            return false;
-        } else if (layoutDirection == AFTER
-                && adjacentRowBottom > getHeight() - getPaddingBottom()) {
-            // View is off of the bottom and also past where the user has scrolled to.
-            return false;
-        }
-
-        return true;
-    }
-
-    /** Remove and recycle views that are no longer needed. */
-    private void recycleChildrenFromStart(RecyclerView.Recycler recycler) {
-        // Start laying out children one page before the top of the viewport.
-        int childrenStart = getPaddingTop() - getHeight();
-
-        int focusedChildPosition = Integer.MAX_VALUE;
-        View focusedChild = getFocusedChild();
-        if (focusedChild != null) {
-            focusedChildPosition = getPosition(focusedChild);
-        }
-
-        // Count the number of views that should be removed.
-        int detachedCount = 0;
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            final View child = getChildAt(i);
-            int childEnd = getDecoratedBottom(child);
-            int childPosition = getPosition(child);
-
-            if (childEnd >= childrenStart || childPosition >= focusedChildPosition - 1) {
-                break;
-            }
-
-            detachedCount++;
-        }
-
-        // Remove the number of views counted above. Done by removing the first child n times.
-        while (--detachedCount >= 0) {
-            final View child = getChildAt(0);
-            removeAndRecycleView(child, recycler);
-        }
-    }
-
-    /** Remove and recycle views that are no longer needed. */
-    private void recycleChildrenFromEnd(RecyclerView.Recycler recycler) {
-        // Layout views until the end of the viewport.
-        int childrenEnd = getHeight();
-
-        int focusedChildPosition = Integer.MIN_VALUE + 1;
-        View focusedChild = getFocusedChild();
-        if (focusedChild != null) {
-            focusedChildPosition = getPosition(focusedChild);
-        }
-
-        // Count the number of views that should be removed.
-        int firstDetachedPos = 0;
-        int detachedCount = 0;
-        int childCount = getChildCount();
-        for (int i = childCount - 1; i >= 0; i--) {
-            final View child = getChildAt(i);
-            int childStart = getDecoratedTop(child);
-            int childPosition = getPosition(child);
-
-            if (childStart <= childrenEnd || childPosition <= focusedChildPosition - 1) {
-                break;
-            }
-
-            firstDetachedPos = i;
-            detachedCount++;
-        }
-
-        while (--detachedCount >= 0) {
-            final View child = getChildAt(firstDetachedPos);
-            removeAndRecycleView(child, recycler);
-        }
-    }
-
-    /**
-     * Offset rows to do fancy animations. If offset rows was not enabled with
-     * {@link #setOffsetRows}, this will do nothing.
-     *
-     * @see #offsetRowsIndividually
-     * @see #offsetRowsByPage
-     * @see #setOffsetRows
-     */
-    public void offsetRows() {
-        if (!mOffsetRows) {
-            return;
-        }
-
-        if (mRowOffsetMode == ROW_OFFSET_MODE_PAGE) {
-            offsetRowsByPage();
-        } else if (mRowOffsetMode == ROW_OFFSET_MODE_INDIVIDUAL) {
-            offsetRowsIndividually();
-        }
-    }
-
-    /**
-     * Offset the single row that is scrolling off the screen such that by the time the next row
-     * reaches the top, it will have accelerated completely off of the screen.
-     */
-    private void offsetRowsIndividually() {
-        if (getChildCount() == 0) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, ":: offsetRowsIndividually getChildCount=0");
-            }
-            return;
-        }
-
-        // Identify the dangling row. It will be the first row that is at the top of the
-        // list or above.
-        int danglingChildIndex = -1;
-        for (int i = getChildCount() - 1; i >= 0; i--) {
-            View child = getChildAt(i);
-            if (getDecoratedTop(child) - getParams(child).topMargin <= getPaddingTop()) {
-                danglingChildIndex = i;
-                break;
-            }
-        }
-
-        mAnchorPageBreakPosition = danglingChildIndex;
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, ":: offsetRowsIndividually danglingChildIndex: " + danglingChildIndex);
-        }
-
-        // Calculate the total amount that the view will need to scroll in order to go completely
-        // off screen.
-        RecyclerView rv = (RecyclerView) getChildAt(0).getParent();
-        int[] locs = new int[2];
-        rv.getLocationInWindow(locs);
-        int listTopInWindow = locs[1] + rv.getPaddingTop();
-        int maxDanglingViewTranslation;
-
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            RecyclerView.LayoutParams params = getParams(child);
-
-            maxDanglingViewTranslation = listTopInWindow;
-            // If the child has a negative margin, we'll actually need to translate the view a
-            // little but further to get it completely off screen.
-            if (params.topMargin < 0) {
-                maxDanglingViewTranslation -= params.topMargin;
-            }
-            if (params.bottomMargin < 0) {
-                maxDanglingViewTranslation -= params.bottomMargin;
-            }
-
-            if (i < danglingChildIndex) {
-                child.setAlpha(0f);
-            } else if (i > danglingChildIndex) {
-                child.setAlpha(1f);
-                setCardFlyingEffectOffset(child, 0);
-            } else {
-                int totalScrollDistance =
-                        getDecoratedMeasuredHeight(child) + params.topMargin + params.bottomMargin;
-
-                int distanceLeftInScroll =
-                        getDecoratedBottom(child) + params.bottomMargin - getPaddingTop();
-                float percentageIntoScroll = 1 - distanceLeftInScroll / (float) totalScrollDistance;
-                float interpolatedPercentage =
-                        mDanglingRowInterpolator.getInterpolation(percentageIntoScroll);
-
-                child.setAlpha(1f);
-                setCardFlyingEffectOffset(child, -(maxDanglingViewTranslation
-                        * interpolatedPercentage));
-            }
-        }
-    }
-
-    /**
-     * When the list scrolls, the entire page of rows will offset in one contiguous block. This
-     * significantly reduces the amount of extra motion at the top of the screen.
-     */
-    private void offsetRowsByPage() {
-        View anchorView = findViewByPosition(mAnchorPageBreakPosition);
-        if (anchorView == null) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, ":: offsetRowsByPage anchorView null");
-            }
-            return;
-        }
-        int anchorViewTop = getDecoratedTop(anchorView) - getParams(anchorView).topMargin;
-
-        View upperPageBreakView = findViewByPosition(mUpperPageBreakPosition);
-        int upperViewTop =
-                getDecoratedTop(upperPageBreakView) - getParams(upperPageBreakView).topMargin;
-
-        int scrollDistance = upperViewTop - anchorViewTop;
-
-        int distanceLeft = anchorViewTop - getPaddingTop();
-        float scrollPercentage =
-                (Math.abs(scrollDistance) - distanceLeft) / (float) Math.abs(scrollDistance);
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, String.format(":: offsetRowsByPage scrollDistance:%s, distanceLeft:%s, "
-                            + "scrollPercentage:%s",
-                    scrollDistance, distanceLeft, scrollPercentage));
-        }
-
-        // Calculate the total amount that the view will need to scroll in order to go completely
-        // off screen.
-        RecyclerView rv = (RecyclerView) getChildAt(0).getParent();
-        int[] locs = new int[2];
-        rv.getLocationInWindow(locs);
-        int listTopInWindow = locs[1] + rv.getPaddingTop();
-
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            int position = getPosition(child);
-            if (position < mUpperPageBreakPosition) {
-                child.setAlpha(0f);
-                setCardFlyingEffectOffset(child, -listTopInWindow);
-            } else if (position < mAnchorPageBreakPosition) {
-                // If the child has a negative margin, we need to offset the row by a little bit
-                // extra so that it moves completely off screen.
-                RecyclerView.LayoutParams params = getParams(child);
-                int extraTranslation = 0;
-                if (params.topMargin < 0) {
-                    extraTranslation -= params.topMargin;
-                }
-                if (params.bottomMargin < 0) {
-                    extraTranslation -= params.bottomMargin;
-                }
-                int translation = (int) ((listTopInWindow + extraTranslation)
-                        * mDanglingRowInterpolator.getInterpolation(scrollPercentage));
-                child.setAlpha(1f);
-                setCardFlyingEffectOffset(child, -translation);
-            } else {
-                child.setAlpha(1f);
-                setCardFlyingEffectOffset(child, 0);
-            }
-        }
-    }
-
-    /**
-     * Apply an offset to this view. This offset is applied post-layout so it doesn't affect when
-     * views are recycled
-     *
-     * @param child The view to apply this to
-     * @param verticalOffset The offset for this child.
-     */
-    private void setCardFlyingEffectOffset(View child, float verticalOffset) {
-        // Ideally instead of doing all this, we could use View.setTranslationY(). However, the
-        // default RecyclerView.ItemAnimator also uses this method which causes layout issues.
-        // See: http://b/25977087
-        TranslateAnimation anim = mFlyOffscreenAnimations.get(child);
-        if (anim == null) {
-            anim = new TranslateAnimation();
-            anim.setFillEnabled(true);
-            anim.setFillAfter(true);
-            anim.setDuration(0);
-            mFlyOffscreenAnimations.put(child, anim);
-        } else if (anim.verticalOffset == verticalOffset) {
-            return;
-        }
-
-        anim.reset();
-        anim.verticalOffset = verticalOffset;
-        anim.setStartTime(Animation.START_ON_FIRST_FRAME);
-        child.setAnimation(anim);
-        anim.startNow();
-    }
-
-    /**
-     * Update the page break positions based on the position of the views on screen. This should be
-     * called whenever view move or change such as during a scroll or layout.
-     */
-    private void updatePageBreakPositions() {
-        if (getChildCount() == 0) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, ":: updatePageBreakPosition getChildCount: 0");
-            }
-            return;
-        }
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, String.format(":: #BEFORE updatePageBreakPositions "
-                            + "mAnchorPageBreakPosition:%s, mUpperPageBreakPosition:%s, "
-                            + "mLowerPageBreakPosition:%s",
-                            mAnchorPageBreakPosition, mUpperPageBreakPosition,
-                            mLowerPageBreakPosition));
-        }
-
-        mAnchorPageBreakPosition = getPosition(getFirstFullyVisibleChild());
-
-        if (mAnchorPageBreakPosition == -1) {
-            Log.w(TAG, "Unable to update anchor positions. There is no anchor position.");
-            return;
-        }
-
-        View anchorPageBreakView = findViewByPosition(mAnchorPageBreakPosition);
-        if (anchorPageBreakView == null) {
-            return;
-        }
-        int topMargin = getParams(anchorPageBreakView).topMargin;
-        int anchorTop = getDecoratedTop(anchorPageBreakView) - topMargin;
-        View upperPageBreakView = findViewByPosition(mUpperPageBreakPosition);
-        int upperPageBreakTop = upperPageBreakView == null
-                ? Integer.MIN_VALUE
-                : getDecoratedTop(upperPageBreakView) - getParams(upperPageBreakView).topMargin;
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, String.format(":: #MID updatePageBreakPositions topMargin:%s, anchorTop:%s"
-                            + " mAnchorPageBreakPosition:%s, mUpperPageBreakPosition:%s,"
-                            + " mLowerPageBreakPosition:%s",
-                            topMargin,
-                            anchorTop,
-                            mAnchorPageBreakPosition,
-                            mUpperPageBreakPosition,
-                            mLowerPageBreakPosition));
-        }
-
-        if (anchorTop < getPaddingTop()) {
-            // The anchor has moved above the viewport. We are now on the next page. Shift the page
-            // break positions and calculate a new lower one.
-            mUpperPageBreakPosition = mAnchorPageBreakPosition;
-            mAnchorPageBreakPosition = mLowerPageBreakPosition;
-            mLowerPageBreakPosition = calculateNextPageBreakPosition(mAnchorPageBreakPosition);
-        } else if (mAnchorPageBreakPosition > 0 && upperPageBreakTop >= getPaddingTop()) {
-            // The anchor has moved below the viewport. We are now on the previous page. Shift
-            // the page break positions and calculate a new upper one.
-            mLowerPageBreakPosition = mAnchorPageBreakPosition;
-            mAnchorPageBreakPosition = mUpperPageBreakPosition;
-            mUpperPageBreakPosition = calculatePreviousPageBreakPosition(mAnchorPageBreakPosition);
-        } else {
-            mUpperPageBreakPosition = calculatePreviousPageBreakPosition(mAnchorPageBreakPosition);
-            mLowerPageBreakPosition = calculateNextPageBreakPosition(mAnchorPageBreakPosition);
-        }
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, String.format(":: #AFTER updatePageBreakPositions"
-                            + " mAnchorPageBreakPosition:%s, mUpperPageBreakPosition:%s,"
-                            + " mLowerPageBreakPosition:%s",
-                            mAnchorPageBreakPosition, mUpperPageBreakPosition,
-                    mLowerPageBreakPosition));
-        }
-    }
-
-    /**
-     * @return The page break position of the page before the anchor page break position. However,
-     *     if it reaches the end of the laid out children or position 0, it will just return that.
-     */
-    @VisibleForTesting
-    int calculatePreviousPageBreakPosition(int position) {
-        if (position == -1) {
-            return -1;
-        }
-        View referenceView = findViewByPosition(position);
-        int referenceViewTop = getDecoratedTop(referenceView) - getParams(referenceView).topMargin;
-
-        int previousPagePosition = position;
-        while (previousPagePosition > 0) {
-            previousPagePosition--;
-            View child = findViewByPosition(previousPagePosition);
-            if (child == null) {
-                // View has not been laid out yet.
-                return previousPagePosition + 1;
-            }
-
-            int childTop = getDecoratedTop(child) - getParams(child).topMargin;
-            if (childTop < referenceViewTop - getHeight()) {
-                return previousPagePosition + 1;
-            }
-        }
-        // Beginning of the list.
-        return 0;
-    }
-
-    /**
-     * @return The page break position of the next page after the anchor page break position.
-     *     However, if it reaches the end of the laid out children or end of the list, it will just
-     *     return that.
-     */
-    @VisibleForTesting
-    int calculateNextPageBreakPosition(int position) {
-        if (position == -1) {
-            return -1;
-        }
-
-        View referenceView = findViewByPosition(position);
-        if (referenceView == null) {
-            return position;
-        }
-        int referenceViewTop = getDecoratedTop(referenceView) - getParams(referenceView).topMargin;
-
-        int nextPagePosition = position;
-
-        // Search for the first child item after the referenceView that didn't fully fit on to the
-        // screen. The next page should start from the item before this child, so that users have
-        // a visual anchoring point of the page change.
-        while (nextPagePosition < getItemCount() - 1) {
-            nextPagePosition++;
-            View child = findViewByPosition(nextPagePosition);
-            if (child == null) {
-                // The next view has not been laid out yet.
-                return nextPagePosition - 1;
-            }
-
-            int childTop = getDecoratedTop(child) - getParams(child).topMargin;
-            if (childTop > referenceViewTop + getHeight()) {
-                // If choosing the previous child causes the view to snap back to the referenceView
-                // position, then skip that and go directly to the child. This avoids the case
-                // where a tall card in the layout causes the view to constantly snap back to
-                // the top when scrolled.
-                return nextPagePosition - 1 == position ? nextPagePosition : nextPagePosition - 1;
-            }
-        }
-        // End of the list.
-        return nextPagePosition;
-    }
-
-    /**
-     * In this style, the focus will scroll down to the middle of the screen and lock there so that
-     * moving in either direction will move the entire list by 1.
-     */
-    private boolean onRequestChildFocusMarioStyle(RecyclerView parent, View child) {
-        int focusedPosition = getPosition(child);
-        if (focusedPosition == mLastChildPositionToRequestFocus) {
-            return true;
-        }
-        mLastChildPositionToRequestFocus = focusedPosition;
-
-        int availableHeight = getAvailableHeight();
-        int focusedChildTop = getDecoratedTop(child);
-        int focusedChildBottom = getDecoratedBottom(child);
-
-        int childIndex = parent.indexOfChild(child);
-        // Iterate through children starting at the focused child to find the child above it to
-        // smooth scroll to such that the focused child will be as close to the middle of the screen
-        // as possible.
-        for (int i = childIndex; i >= 0; i--) {
-            View childAtI = getChildAt(i);
-            if (childAtI == null) {
-                Log.e(TAG, "Child is null at index " + i);
-                continue;
-            }
-            // We haven't found a view that is more than half of the recycler view height above it
-            // but we've reached the top so we can't go any further.
-            if (i == 0) {
-                parent.smoothScrollToPosition(getPosition(childAtI));
-                break;
-            }
-
-            // Because we want to scroll to the first view that is less than half of the screen
-            // away from the focused view, we "look ahead" one view. When the look ahead view
-            // is more than availableHeight / 2 away, the current child at i is the one we want to
-            // scroll to. However, sometimes, that view can be null (ie, if the view is in
-            // transition). In that case, just skip that view.
-
-            View childBefore = getChildAt(i - 1);
-            if (childBefore == null) {
-                continue;
-            }
-            int distanceToChildBeforeFromTop = focusedChildTop - getDecoratedTop(childBefore);
-            int distanceToChildBeforeFromBottom = focusedChildBottom - getDecoratedTop(childBefore);
-
-            if (distanceToChildBeforeFromTop > availableHeight / 2
-                    || distanceToChildBeforeFromBottom > availableHeight) {
-                parent.smoothScrollToPosition(getPosition(childAtI));
-                break;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * We don't actually know the size of every single view, only what is currently laid out. This
-     * makes it difficult to do accurate scrollbar calculations. However, lists in the car often
-     * consist of views with identical heights. Because of that, we can use a single sample view to
-     * do our calculations for. The main exceptions are in the first items of a list (hero card,
-     * last call card, etc) so if the first view is at position 0, we pick the next one.
-     *
-     * @return The decorated measured height of the sample view plus its margins.
-     */
-    private int getSampleViewHeight() {
-        if (mSampleViewHeight != -1) {
-            return mSampleViewHeight;
-        }
-        int sampleViewIndex = getFirstFullyVisibleChildIndex();
-        View sampleView = getChildAt(sampleViewIndex);
-        if (getPosition(sampleView) == 0 && sampleViewIndex < getChildCount() - 1) {
-            sampleView = getChildAt(++sampleViewIndex);
-        }
-        RecyclerView.LayoutParams params = getParams(sampleView);
-        int height = getDecoratedMeasuredHeight(sampleView) + params.topMargin
-                + params.bottomMargin;
-        if (height == 0) {
-            // This can happen if the view isn't measured yet.
-            Log.w(
-                    TAG,
-                    "The sample view has a height of 0. Returning a dummy value for now "
-                            + "that won't be cached.");
-            height = mContext.getResources().getDimensionPixelSize(R.dimen.car_sample_row_height);
-        } else {
-            mSampleViewHeight = height;
-        }
-        return height;
-    }
-
-    /** @return The height of the RecyclerView excluding padding. */
-    private int getAvailableHeight() {
-        return getHeight() - getPaddingTop() - getPaddingBottom();
-    }
-
-    /**
-     * @return {@link RecyclerView.LayoutParams} for the given view or null if it isn't a child of
-     *     {@link RecyclerView}.
-     */
-    private static RecyclerView.LayoutParams getParams(View view) {
-        return (RecyclerView.LayoutParams) view.getLayoutParams();
-    }
-
-    /**
-     * Custom {@link LinearSmoothScroller} that has: a) Custom control over the speed of scrolls. b)
-     * Scrolling snaps to start. All of our scrolling logic depends on that. c) Keeps track of some
-     * state of the current scroll so that can aid in things like the scrollbar calculations.
-     */
-    private final class CarSmoothScroller extends LinearSmoothScroller {
-        /** This value (150) was hand tuned by UX for what felt right. * */
-        private static final float MILLISECONDS_PER_INCH = 150f;
-        /** This value (0.45) was hand tuned by UX for what felt right. * */
-        private static final float DECELERATION_TIME_DIVISOR = 0.45f;
-
-        /** This value (1.8) was hand tuned by UX for what felt right. * */
-        private final Interpolator mInterpolator = new DecelerateInterpolator(1.8f);
-
-        private final int mTargetPosition;
-
-        CarSmoothScroller(Context context, int targetPosition) {
-            super(context);
-            mTargetPosition = targetPosition;
-        }
-
-        @Override
-        public PointF computeScrollVectorForPosition(int i) {
-            if (getChildCount() == 0) {
-                return null;
-            }
-            final int firstChildPos = getPosition(getChildAt(getFirstFullyVisibleChildIndex()));
-            final int direction = (mTargetPosition < firstChildPos) ? -1 : 1;
-            return new PointF(0, direction);
-        }
-
-        @Override
-        protected int getVerticalSnapPreference() {
-            // This is key for most of the scrolling logic that guarantees that scrolling
-            // will settle with a view aligned to the top.
-            return LinearSmoothScroller.SNAP_TO_START;
-        }
-
-        @Override
-        protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
-            int dy = calculateDyToMakeVisible(targetView, SNAP_TO_START);
-            if (dy == 0) {
-                if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Scroll distance is 0");
-                }
-                return;
-            }
-
-            final int time = calculateTimeForDeceleration(dy);
-            if (time > 0) {
-                action.update(0, -dy, time, mInterpolator);
-            }
-        }
-
-        @Override
-        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
-            return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
-        }
-
-        @Override
-        protected int calculateTimeForDeceleration(int dx) {
-            return (int) Math.ceil(calculateTimeForScrolling(dx) / DECELERATION_TIME_DIVISOR);
-        }
-
-        @Override
-        public int getTargetPosition() {
-            return mTargetPosition;
-        }
-    }
-
-    /**
-     * Animation that translates a view by the specified amount. Used for card flying off the screen
-     * effect.
-     */
-    private static class TranslateAnimation extends Animation {
-        public float verticalOffset;
-
-        @Override
-        protected void applyTransformation(float interpolatedTime, Transformation t) {
-            super.applyTransformation(interpolatedTime, t);
-            t.getMatrix().setTranslate(0, verticalOffset);
-        }
-    }
-}
diff --git a/car/src/main/java/androidx/car/widget/PagedListView.java b/car/src/main/java/androidx/car/widget/PagedListView.java
index 16593b9..4e960d4 100644
--- a/car/src/main/java/androidx/car/widget/PagedListView.java
+++ b/car/src/main/java/androidx/car/widget/PagedListView.java
@@ -16,8 +16,6 @@
 
 package androidx.car.widget;
 
-import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -25,32 +23,49 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
 import android.os.Handler;
-import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.annotation.ColorRes;
 import android.support.annotation.IdRes;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.annotation.RestrictTo;
 import android.support.annotation.UiThread;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
-import android.view.MotionEvent;
 import android.view.View;
 import android.widget.FrameLayout;
 
 import androidx.car.R;
 
 /**
- * Custom {@link android.support.v7.widget.RecyclerView} that displays a list of items that
- * resembles a {@link android.widget.ListView} but also has page up and page down arrows on the
- * left side.
+ * View that wraps a {@link android.support.v7.widget.RecyclerView} and a scroll bar that has
+ * page up and down arrows. Interaction with this view is similar to a {@code RecyclerView} as it
+ * takes the same adapter.
+ *
+ * <p>By default, this PagedListView utilizes a vertical {@link LinearLayoutManager} to display
+ * its items.
  */
 public class PagedListView extends FrameLayout {
+    /**
+     * The key used to save the state of this PagedListView's super class in
+     * {@link #onSaveInstanceState()}.
+     */
+    private static final String SAVED_SUPER_STATE_KEY = "PagedListViewSuperState";
+
+    /**
+     * The key used to save the state of {@link #mRecyclerView} so that it can be restored
+     * on configuration change. The actual saving of state will be controlled by the LayoutManager
+     * of the RecyclerView; this value simply ensures the state is passed on to the LayoutManager.
+     */
+    private static final String SAVED_RECYCLER_VIEW_STATE_KEY = "RecyclerViewState";
+
     /** Default maximum number of clicks allowed on a list */
     public static final int DEFAULT_MAX_CLICKS = 6;
 
@@ -64,30 +79,47 @@
      * The amount of time after settling to wait before autoscrolling to the next page when the user
      * holds down a pagination button.
      */
-    protected static final int PAGINATION_HOLD_DELAY_MS = 400;
+    private static final int PAGINATION_HOLD_DELAY_MS = 400;
+
+    /**
+     * A fling distance to use when the up button is pressed. This value is arbitrary and just needs
+     * to be large enough so that the maximum amount of fling is applied. The
+     * {@link PagedSnapHelper} will handle capping this value so that the RecyclerView is scrolled
+     * one page upwards.
+     */
+    private static final int FLING_UP_DISTANCE = -10000;
+
+    /**
+     * A fling distance to use when the down button is pressed. This value is arbitrary and just
+     * needs to be large enough so that the maximum amount of fling is applied. The
+     * {@link PagedSnapHelper} will handle capping this value so that the RecyclerView is scrolled
+     * one page downwards.
+     */
+    private static final int FLING_DOWN_DISTANCE = 10000;
 
     private static final String TAG = "PagedListView";
     private static final int INVALID_RESOURCE_ID = -1;
 
-    protected final CarRecyclerView mRecyclerView;
-    protected final PagedLayoutManager mLayoutManager;
-    protected final Handler mHandler = new Handler();
+    private final RecyclerView mRecyclerView;
+    private final PagedSnapHelper mSnapHelper;
+    private final Handler mHandler = new Handler();
     private final boolean mScrollBarEnabled;
-    private final PagedScrollBarView mScrollBarView;
+    @VisibleForTesting
+    final PagedScrollBarView mScrollBarView;
 
     private int mRowsPerPage = -1;
-    protected RecyclerView.Adapter<? extends RecyclerView.ViewHolder> mAdapter;
+    private RecyclerView.Adapter<? extends RecyclerView.ViewHolder> mAdapter;
 
     /** Maximum number of pages to show. */
     private int mMaxPages;
 
-    protected OnScrollListener mOnScrollListener;
+    private OnScrollListener mOnScrollListener;
 
     /** Number of visible rows per page */
     private int mDefaultMaxPages = DEFAULT_MAX_CLICKS;
 
     /** Used to check if there are more items added to the list. */
-    private int mLastItemCount = 0;
+    private int mLastItemCount;
 
     private boolean mNeedsFocus;
 
@@ -188,19 +220,19 @@
 
         TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.PagedListView, defStyleAttrs, defStyleRes);
-        mRecyclerView = (CarRecyclerView) findViewById(R.id.recycler_view);
-        boolean fadeLastItem = a.getBoolean(R.styleable.PagedListView_fadeLastItem, false);
-        mRecyclerView.setFadeLastItem(fadeLastItem);
-        boolean offsetRows = a.getBoolean(R.styleable.PagedListView_offsetRows, false);
+        mRecyclerView = findViewById(R.id.recycler_view);
 
         mMaxPages = getDefaultMaxPages();
 
-        mLayoutManager = new PagedLayoutManager(context);
-        mLayoutManager.setOffsetRows(offsetRows);
-        mRecyclerView.setLayoutManager(mLayoutManager);
+        RecyclerView.LayoutManager layoutManager =
+                new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
+        mRecyclerView.setLayoutManager(layoutManager);
+
+        mSnapHelper = new PagedSnapHelper();
+        mSnapHelper.attachToRecyclerView(mRecyclerView);
+
         mRecyclerView.setOnScrollListener(mRecyclerViewOnScrollListener);
         mRecyclerView.getRecycledViewPool().setMaxRecycledViews(0, 12);
-        mRecyclerView.setItemAnimator(new CarItemAnimator(mLayoutManager));
 
         if (a.hasValue(R.styleable.PagedListView_gutter)) {
             int gutter = a.getInt(R.styleable.PagedListView_gutter, Gutter.BOTH);
@@ -244,25 +276,24 @@
 
         mScrollBarEnabled = a.getBoolean(R.styleable.PagedListView_scrollBarEnabled, true);
         mScrollBarView = (PagedScrollBarView) findViewById(R.id.paged_scroll_view);
-        mScrollBarView.setPaginationListener(
-                new PagedScrollBarView.PaginationListener() {
-                    @Override
-                    public void onPaginate(int direction) {
-                        if (direction == PagedScrollBarView.PaginationListener.PAGE_UP) {
-                            mRecyclerView.pageUp();
-                            if (mOnScrollListener != null) {
-                                mOnScrollListener.onScrollUpButtonClicked();
-                            }
-                        } else if (direction == PagedScrollBarView.PaginationListener.PAGE_DOWN) {
-                            mRecyclerView.pageDown();
-                            if (mOnScrollListener != null) {
-                                mOnScrollListener.onScrollDownButtonClicked();
-                            }
-                        } else {
-                            Log.e(TAG, "Unknown pagination direction (" + direction + ")");
-                        }
+        mScrollBarView.setPaginationListener(direction -> {
+            switch (direction) {
+                case PagedScrollBarView.PaginationListener.PAGE_UP:
+                    pageUp();
+                    if (mOnScrollListener != null) {
+                        mOnScrollListener.onScrollUpButtonClicked();
                     }
-                });
+                    break;
+                case PagedScrollBarView.PaginationListener.PAGE_DOWN:
+                    pageDown();
+                    if (mOnScrollListener != null) {
+                        mOnScrollListener.onScrollDownButtonClicked();
+                    }
+                    break;
+                default:
+                    Log.e(TAG, "Unknown pagination direction (" + direction + ")");
+            }
+        });
 
         Drawable upButtonIcon = a.getDrawable(R.styleable.PagedListView_upButtonIcon);
         if (upButtonIcon != null) {
@@ -293,24 +324,6 @@
         mHandler.removeCallbacks(mUpdatePaginationRunnable);
     }
 
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent e) {
-        if (e.getAction() == MotionEvent.ACTION_DOWN) {
-            // The user has interacted with the list using touch. All movements will now paginate
-            // the list.
-            mLayoutManager.setRowOffsetMode(PagedLayoutManager.ROW_OFFSET_MODE_PAGE);
-        }
-        return super.onInterceptTouchEvent(e);
-    }
-
-    @Override
-    public void requestChildFocus(View child, View focused) {
-        super.requestChildFocus(child, focused);
-        // The user has interacted with the list using the controller. Movements through the list
-        // will now be one row at a time.
-        mLayoutManager.setRowOffsetMode(PagedLayoutManager.ROW_OFFSET_MODE_INDIVIDUAL);
-    }
-
     /**
      * Returns the position of the given View in the list.
      *
@@ -318,10 +331,11 @@
      * @return The position or -1 if the given View is {@code null} or not in the list.
      */
     public int positionOf(@Nullable View v) {
-        if (v == null || v.getParent() != mRecyclerView) {
+        if (v == null || v.getParent() != mRecyclerView
+                || mRecyclerView.getLayoutManager() == null) {
             return -1;
         }
-        return mLayoutManager.getPosition(v);
+        return mRecyclerView.getLayoutManager().getPosition(v);
     }
 
     /**
@@ -350,7 +364,7 @@
     }
 
     @NonNull
-    public CarRecyclerView getRecyclerView() {
+    public RecyclerView getRecyclerView() {
         return mRecyclerView;
     }
 
@@ -360,10 +374,17 @@
      * @param position The position in the list to scroll to.
      */
     public void scrollToPosition(int position) {
-        mLayoutManager.scrollToPosition(position);
+        if (mRecyclerView.getLayoutManager() == null) {
+            return;
+        }
+
+        PagedSmoothScroller smoothScroller = new PagedSmoothScroller(getContext());
+        smoothScroller.setTargetPosition(position);
+
+        mRecyclerView.getLayoutManager().startSmoothScroll(smoothScroller);
 
         // Sometimes #scrollToPosition doesn't change the scroll state so we need to make sure
-        // the pagination arrows actually get updated. See b/http://b/15801119
+        // the pagination arrows actually get updated. See b/15801119
         mHandler.post(mUpdatePaginationRunnable);
     }
 
@@ -391,13 +412,6 @@
         updateMaxItems();
     }
 
-    /** @hide */
-    @RestrictTo(LIBRARY_GROUP)
-    @NonNull
-    public PagedLayoutManager getLayoutManager() {
-        return mLayoutManager;
-    }
-
     @Nullable
     @SuppressWarnings("unchecked")
     public RecyclerView.Adapter<? extends RecyclerView.ViewHolder> getAdapter() {
@@ -449,22 +463,6 @@
     }
 
     /**
-     * @return The position of first visible child in the list. -1 will be returned if there is no
-     *     child.
-     */
-    public int getFirstFullyVisibleChildPosition() {
-        return mLayoutManager.getFirstFullyVisibleChildPosition();
-    }
-
-    /**
-     * @return The position of last visible child in the list. -1 will be returned if there is no
-     *     child.
-     */
-    public int getLastFullyVisibleChildPosition() {
-        return mLayoutManager.getLastFullyVisibleChildPosition();
-    }
-
-    /**
      * Adds an {@link android.support.v7.widget.RecyclerView.ItemDecoration} to this PagedListView.
      *
      * @param decor The decoration to add.
@@ -514,6 +512,25 @@
     }
 
     /**
+     * Sets the color of scrollbar.
+     *
+     * <p>Custom color ignores {@link DayNightStyle}. Calling {@link #resetScrollbarColor} resets to
+     * default color.
+     *
+     * @param color Resource identifier of the color.
+     */
+    public void setScrollbarColor(@ColorRes int color) {
+        mScrollBarView.setThumbColor(color);
+    }
+
+    /**
+     * Resets the color of scrollbar to default.
+     */
+    public void resetScrollbarColor() {
+        mScrollBarView.resetThumbColor();
+    }
+
+    /**
      * Adds an {@link android.support.v7.widget.RecyclerView.OnItemTouchListener} to this
      * PagedListView.
      *
@@ -536,6 +553,7 @@
     public void removeOnItemTouchListener(@NonNull RecyclerView.OnItemTouchListener touchListener) {
         mRecyclerView.removeOnItemTouchListener(touchListener);
     }
+
     /**
      * Sets how this {@link PagedListView} responds to day/night configuration changes. By
      * default, the PagedListView is darker in the day and lighter at night.
@@ -557,30 +575,6 @@
     }
 
     /**
-     * Returns the {@link android.support.v7.widget.RecyclerView.ViewHolder} that corresponds to the
-     * last child in the PagedListView that is fully visible.
-     *
-     * @return The corresponding ViewHolder or {@code null} if none exists.
-     */
-    @Nullable
-    public RecyclerView.ViewHolder getLastViewHolder() {
-        View lastFullyVisible = mLayoutManager.getLastFullyVisibleChild();
-        if (lastFullyVisible == null) {
-            return null;
-        }
-        int lastFullyVisibleAdapterPosition = mLayoutManager.getPosition(lastFullyVisible);
-        RecyclerView.ViewHolder lastViewHolder = getRecyclerView()
-                .findViewHolderForAdapterPosition(lastFullyVisibleAdapterPosition + 1);
-        // We want to get the very last ViewHolder in the list, even if it's only fully visible
-        // If it doesn't exist, return the last fully visible ViewHolder.
-        if (lastViewHolder == null) {
-            lastViewHolder = getRecyclerView()
-                    .findViewHolderForAdapterPosition(lastFullyVisibleAdapterPosition);
-        }
-        return lastViewHolder;
-    }
-
-    /**
      * Sets the {@link OnScrollListener} that will be notified of scroll events within the
      * PagedListView.
      *
@@ -588,7 +582,6 @@
      */
     public void setOnScrollListener(OnScrollListener listener) {
         mOnScrollListener = listener;
-        mLayoutManager.setOnScrollListener(mOnScrollListener);
     }
 
     /** Returns the page the given position is on, starting with page 0. */
@@ -602,6 +595,16 @@
         return position / mRowsPerPage;
     }
 
+    /** Scrolls the contents of the RecyclerView up a page. */
+    private void pageUp() {
+        mRecyclerView.fling(0, FLING_UP_DISTANCE);
+    }
+
+    /** Scrolls the contents of the RecyclerView down a page. */
+    private void pageDown() {
+        mRecyclerView.fling(0, FLING_DOWN_DISTANCE);
+    }
+
     /**
      * Sets the default number of pages that this PagedListView is limited to.
      *
@@ -616,7 +619,7 @@
     }
 
     /** Returns the default number of pages the list should have */
-    protected int getDefaultMaxPages() {
+    private int getDefaultMaxPages() {
         // assume list shown in response to a click, so, reduce number of clicks by one
         return mDefaultMaxPages - 1;
     }
@@ -634,11 +637,16 @@
         // if the focus is not on the formerly first item, then we don't need to do anything. Let
         // the layout manager do the job and scroll the viewport so the currently focused item
         // is visible.
+        RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
+
+        if (layoutManager == null) {
+            return;
+        }
 
         // we need to calculate whether we want to request focus here, before the super call,
         // because after the super call, the first born might be changed.
-        View focusedChild = mLayoutManager.getFocusedChild();
-        View firstBorn = mLayoutManager.getChildAt(0);
+        View focusedChild = layoutManager.getFocusedChild();
+        View firstBorn = layoutManager.getChildAt(0);
 
         super.onLayout(changed, left, top, right, bottom);
 
@@ -674,6 +682,7 @@
             }
             mLastItemCount = itemCount;
         }
+
         // We need to update the scroll buttons after layout has happened.
         // Determining if a scrollbar is necessary requires looking at the layout of the child
         // views. Therefore, this determination can only be done after layout has happened.
@@ -682,17 +691,6 @@
     }
 
     /**
-     * Returns the View at the given position within the list.
-     *
-     * @param position A position within the list.
-     * @return The View or {@code null} if no View exists at the given position.
-     */
-    @Nullable
-    public View findViewByPosition(int position) {
-        return mLayoutManager.findViewByPosition(position);
-    }
-
-    /**
      * Determines if scrollbar should be visible or not and shows/hides it accordingly. If this is
      * being called as a result of adapter changes, it should be called after the new layout has
      * been calculated because the method of determining scrollbar visibility uses the current
@@ -702,39 +700,55 @@
      * @param animate {@code true} if the scrollbar should animate to its new position.
      *                {@code false} if no animation is used
      */
-    protected void updatePaginationButtons(boolean animate) {
+    private void updatePaginationButtons(boolean animate) {
         if (!mScrollBarEnabled) {
             // Don't change the visibility of the ScrollBar unless it's enabled.
             return;
         }
 
-        if ((mLayoutManager.isAtTop() && mLayoutManager.isAtBottom())
-                || mLayoutManager.getItemCount() == 0) {
+        boolean isAtStart = isAtStart();
+        boolean isAtEnd = isAtEnd();
+        RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
+
+        if ((isAtStart && isAtEnd) || layoutManager == null || layoutManager.getItemCount() == 0) {
             mScrollBarView.setVisibility(View.INVISIBLE);
         } else {
             mScrollBarView.setVisibility(View.VISIBLE);
         }
-        mScrollBarView.setUpEnabled(shouldEnablePageUpButton());
-        mScrollBarView.setDownEnabled(shouldEnablePageDownButton());
+        mScrollBarView.setUpEnabled(!isAtStart);
+        mScrollBarView.setDownEnabled(!isAtEnd);
 
-        mScrollBarView.setParameters(
-                mRecyclerView.computeVerticalScrollRange(),
-                mRecyclerView.computeVerticalScrollOffset(),
-                mRecyclerView.computeVerticalScrollExtent(),
-                animate);
+        if (layoutManager == null) {
+            return;
+        }
+
+        if (mRecyclerView.getLayoutManager().canScrollVertically()) {
+            mScrollBarView.setParameters(
+                    mRecyclerView.computeVerticalScrollRange(),
+                    mRecyclerView.computeVerticalScrollOffset(),
+                    mRecyclerView.computeHorizontalScrollExtent(), animate);
+        } else {
+            mScrollBarView.setParameters(
+                    mRecyclerView.computeHorizontalScrollRange(),
+                    mRecyclerView.computeHorizontalScrollOffset(),
+                    mRecyclerView.computeHorizontalScrollRange(), animate);
+        }
+
         invalidate();
     }
 
-    protected boolean shouldEnablePageUpButton() {
-        return !mLayoutManager.isAtTop();
+    /** Returns {@code true} if the RecyclerView is completely displaying the first item. */
+    public boolean isAtStart() {
+        return mSnapHelper.isAtStart(mRecyclerView.getLayoutManager());
     }
 
-    protected boolean shouldEnablePageDownButton() {
-        return !mLayoutManager.isAtBottom();
+    /** Returns {@code true} if the RecyclerView is completely displaying the last item. */
+    public boolean isAtEnd() {
+        return mSnapHelper.isAtEnd(mRecyclerView.getLayoutManager());
     }
 
     @UiThread
-    protected void updateMaxItems() {
+    private void updateMaxItems() {
         if (mAdapter == null) {
             return;
         }
@@ -761,8 +775,13 @@
         }
     }
 
-    protected int calculateMaxItemCount() {
-        final View firstChild = mLayoutManager.getChildAt(0);
+    private int calculateMaxItemCount() {
+        RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
+        if (layoutManager == null) {
+            return -1;
+        }
+
+        View firstChild = layoutManager.getChildAt(0);
         if (firstChild == null || firstChild.getHeight() == 0) {
             return -1;
         } else {
@@ -774,8 +793,14 @@
      * Updates the rows number per current page, which is used for calculating how many items we
      * want to show.
      */
-    protected void updateRowsPerPage() {
-        final View firstChild = mLayoutManager.getChildAt(0);
+    private void updateRowsPerPage() {
+        RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
+        if (layoutManager == null) {
+            mRowsPerPage = 1;
+            return;
+        }
+
+        View firstChild = layoutManager.getChildAt(0);
         if (firstChild == null || firstChild.getHeight() == 0) {
             mRowsPerPage = 1;
         } else {
@@ -784,24 +809,36 @@
     }
 
     @Override
-    protected Parcelable onSaveInstanceState() {
-        SavedState savedState = new SavedState(super.onSaveInstanceState());
-        savedState.mLayoutManagerState = mLayoutManager.onSaveInstanceState();
-        return savedState;
+    public Parcelable onSaveInstanceState() {
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(SAVED_SUPER_STATE_KEY, super.onSaveInstanceState());
+
+        SparseArray<Parcelable> recyclerViewState = new SparseArray<>();
+        mRecyclerView.saveHierarchyState(recyclerViewState);
+        bundle.putSparseParcelableArray(SAVED_RECYCLER_VIEW_STATE_KEY, recyclerViewState);
+
+        return bundle;
     }
 
     @Override
-    protected void onRestoreInstanceState(Parcelable state) {
-        SavedState savedState = (SavedState) state;
-        mLayoutManager.onRestoreInstanceState(savedState.mLayoutManagerState);
-        super.onRestoreInstanceState(savedState.getSuperState());
+    public void onRestoreInstanceState(Parcelable state) {
+        if (!(state instanceof Bundle)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        Bundle bundle = (Bundle) state;
+        mRecyclerView.restoreHierarchyState(
+                bundle.getSparseParcelableArray(SAVED_RECYCLER_VIEW_STATE_KEY));
+
+        super.onRestoreInstanceState(bundle.getParcelable(SAVED_SUPER_STATE_KEY));
     }
 
     @Override
     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
         // There is the possibility of multiple PagedListViews on a page. This means that the ids
         // of the child Views of PagedListView are no longer unique, and onSaveInstanceState()
-        // cannot be used. As a result, PagedListViews needs to manually dispatch the instance
+        // cannot be used as is. As a result, PagedListViews needs to manually dispatch the instance
         // states. Call dispatchFreezeSelfOnly() so that no child views have onSaveInstanceState()
         // called by the system.
         dispatchFreezeSelfOnly(container);
@@ -815,56 +852,15 @@
         dispatchThawSelfOnly(container);
     }
 
-    /** The state that will be saved across configuration changes. */
-    private static class SavedState extends BaseSavedState {
-        /** The state of the {@link #mLayoutManager} of this PagedListView. */
-        Parcelable mLayoutManagerState;
-
-        SavedState(Parcelable superState) {
-            super(superState);
-        }
-
-        private SavedState(Parcel in) {
-            super(in);
-            mLayoutManagerState =
-                    in.readParcelable(PagedLayoutManager.SavedState.class.getClassLoader());
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int flags) {
-            super.writeToParcel(out, flags);
-            out.writeParcelable(mLayoutManagerState, flags);
-        }
-
-        public static final ClassLoaderCreator<SavedState> CREATOR =
-                new ClassLoaderCreator<SavedState>() {
-                    @Override
-                    public SavedState createFromParcel(Parcel source, ClassLoader loader) {
-                        return new SavedState(source);
-                    }
-
-                    @Override
-                    public SavedState createFromParcel(Parcel source) {
-                        return createFromParcel(source, null /* loader */);
-                    }
-
-                    @Override
-                    public SavedState[] newArray(int size) {
-                        return new SavedState[size];
-                    }
-                };
-    }
-
     private final RecyclerView.OnScrollListener mRecyclerViewOnScrollListener =
             new RecyclerView.OnScrollListener() {
                 @Override
                 public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                     if (mOnScrollListener != null) {
                         mOnScrollListener.onScrolled(recyclerView, dx, dy);
-                        if (!mLayoutManager.isAtTop() && mLayoutManager.isAtBottom()) {
+
+                        if (!isAtStart() && isAtEnd()) {
                             mOnScrollListener.onReachBottom();
-                        } else if (mLayoutManager.isAtTop() || !mLayoutManager.isAtBottom()) {
-                            mOnScrollListener.onLeaveBottom();
                         }
                     }
                     updatePaginationButtons(false);
@@ -881,7 +877,7 @@
                 }
             };
 
-    protected final Runnable mPaginationRunnable =
+    private final Runnable mPaginationRunnable =
             new Runnable() {
                 @Override
                 public void run() {
@@ -891,35 +887,24 @@
                         return;
                     }
                     if (upPressed) {
-                        mRecyclerView.pageUp();
+                        pageUp();
                     } else if (downPressed) {
-                        mRecyclerView.pageDown();
+                        pageDown();
                     }
                 }
             };
 
     private final Runnable mUpdatePaginationRunnable =
-            new Runnable() {
-                @Override
-                public void run() {
-                    updatePaginationButtons(true /*animate*/);
-                }
-            };
+            () -> updatePaginationButtons(true /*animate*/);
 
     /** Used to listen for {@code PagedListView} scroll events. */
     public abstract static class OnScrollListener {
         /** Called when menu reaches the bottom */
         public void onReachBottom() {}
-        /** Called when menu leaves the bottom */
-        public void onLeaveBottom() {}
         /** Called when scroll up button is clicked */
         public void onScrollUpButtonClicked() {}
         /** Called when scroll down button is clicked */
         public void onScrollDownButtonClicked() {}
-        /** Called when scrolling to the previous page via up gesture */
-        public void onGestureUp() {}
-        /** Called when scrolling to the next page via down gesture */
-        public void onGestureDown() {}
 
         /**
          * Called when RecyclerView.OnScrollListener#onScrolled is called. See
@@ -929,12 +914,6 @@
 
         /** See RecyclerView.OnScrollListener */
         public void onScrollStateChanged(RecyclerView recyclerView, int newState) {}
-
-        /** Called when the view scrolls up a page */
-        public void onPageUp() {}
-
-        /** Called when the view scrolls down a page */
-        public void onPageDown() {}
     }
 
     /**
@@ -942,32 +921,31 @@
      * between each item in the RecyclerView that it is added to.
      */
     private static class ItemSpacingDecoration extends RecyclerView.ItemDecoration {
-
-        private int mHalfItemSpacing;
+        private int mItemSpacing;
 
         private ItemSpacingDecoration(int itemSpacing) {
-            mHalfItemSpacing = itemSpacing / 2;
+            mItemSpacing = itemSpacing;
         }
 
         @Override
         public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
                 RecyclerView.State state) {
             super.getItemOffsets(outRect, view, parent, state);
-            // Skip top offset for first item and bottom offset for last.
             int position = parent.getChildAdapterPosition(view);
-            if (position > 0) {
-                outRect.top = mHalfItemSpacing;
+
+            // Skip offset for last item.
+            if (position == state.getItemCount() - 1) {
+                return;
             }
-            if (position < state.getItemCount() - 1) {
-                outRect.bottom = mHalfItemSpacing;
-            }
+
+            outRect.bottom = mItemSpacing;
         }
 
         /**
          * @param itemSpacing sets spacing between each item.
          */
         public void setItemSpacing(int itemSpacing) {
-            mHalfItemSpacing = itemSpacing / 2;
+            mItemSpacing = itemSpacing;
         }
     }
 
@@ -1033,8 +1011,18 @@
                     continue;
                 }
 
-                int left = mDividerStartMargin + startChild.getLeft();
-                int right = endChild.getRight();
+                Rect containerRect = new Rect();
+                container.getGlobalVisibleRect(containerRect);
+
+                Rect startRect = new Rect();
+                startChild.getGlobalVisibleRect(startRect);
+
+                Rect endRect = new Rect();
+                endChild.getGlobalVisibleRect(endRect);
+
+                int left = container.getLeft() + mDividerStartMargin
+                        + (startRect.left - containerRect.left);
+                int right = container.getRight() - (endRect.right - containerRect.right);
                 int bottom = container.getBottom() + spacing / 2 + mDividerHeight / 2;
                 int top = bottom - mDividerHeight;
 
diff --git a/car/src/main/java/androidx/car/widget/PagedScrollBarView.java b/car/src/main/java/androidx/car/widget/PagedScrollBarView.java
index 6843fb6..1855f2b 100644
--- a/car/src/main/java/androidx/car/widget/PagedScrollBarView.java
+++ b/car/src/main/java/androidx/car/widget/PagedScrollBarView.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorRes;
+import android.support.annotation.VisibleForTesting;
 import android.support.v4.content.ContextCompat;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -49,13 +51,16 @@
 
     private final ImageView mUpButton;
     private final ImageView mDownButton;
-    private final ImageView mScrollThumb;
+    @VisibleForTesting
+    final ImageView mScrollThumb;
     /** The "filler" view between the up and down buttons */
     private final View mFiller;
 
     private final Interpolator mPaginationInterpolator = new AccelerateDecelerateInterpolator();
     private final int mMinThumbLength;
     private final int mMaxThumbLength;
+    private boolean mUseCustomThumbBackground;
+    @ColorRes private int mCustomThumbBackgroundResId;
     private PaginationListener mPaginationListener;
 
     public PagedScrollBarView(Context context, AttributeSet attrs) {
@@ -133,6 +138,11 @@
 
     /** Sets the range, offset and extent of the scroll bar. See {@link View}. */
     public void setParameters(int range, int offset, int extent, boolean animate) {
+        // If the scroll bars aren't visible, then no need to update.
+        if (getVisibility() == View.GONE || range == 0) {
+            return;
+        }
+
         // This method is where we take the computed parameters from the PagedLayoutManager and
         // render it within the specified constraints ({@link #mMaxThumbLength} and
         // {@link #mMinThumbLength}).
@@ -149,7 +159,8 @@
         }
 
         // Sets the size of the thumb and request a redraw if needed.
-        final ViewGroup.LayoutParams lp = mScrollThumb.getLayoutParams();
+        ViewGroup.LayoutParams lp = mScrollThumb.getLayoutParams();
+
         if (lp.height != thumbLength) {
             lp.height = thumbLength;
             mScrollThumb.requestLayout();
@@ -199,43 +210,65 @@
         return mDownButton.isEnabled();
     }
 
+    /**
+     * Sets the color of thumb.
+     *
+     * <p>Custom thumb color ignores {@link DayNightStyle}. Calling {@link #resetThumbColor} resets
+     * to default color.
+     *
+     * @param color Resource identifier of the color.
+     */
+    public void setThumbColor(@ColorRes int color) {
+        mUseCustomThumbBackground = true;
+        mCustomThumbBackgroundResId = color;
+        reloadColors();
+    }
+
+    /**
+     * Resets the color of thumb to default.
+     */
+    public void resetThumbColor() {
+        mUseCustomThumbBackground = false;
+        reloadColors();
+    }
+
     /** Reload the colors for the current {@link DayNightStyle}. */
     private void reloadColors() {
-        int tint;
-        int thumbBackground;
+        int tintResId;
+        int thumbBackgroundResId;
         int upDownBackgroundResId;
 
         switch (mDayNightStyle) {
             case DayNightStyle.AUTO:
-                tint = ContextCompat.getColor(getContext(), R.color.car_tint);
-                thumbBackground = ContextCompat.getColor(getContext(),
-                        R.color.car_scrollbar_thumb);
+                tintResId = R.color.car_tint;
+                thumbBackgroundResId = R.color.car_scrollbar_thumb;
                 upDownBackgroundResId = R.drawable.car_pagination_background;
                 break;
             case DayNightStyle.AUTO_INVERSE:
-                tint = ContextCompat.getColor(getContext(), R.color.car_tint_inverse);
-                thumbBackground = ContextCompat.getColor(getContext(),
-                        R.color.car_scrollbar_thumb_inverse);
+                tintResId = R.color.car_tint_inverse;
+                thumbBackgroundResId = R.color.car_scrollbar_thumb_inverse;
                 upDownBackgroundResId = R.drawable.car_pagination_background_inverse;
                 break;
             case DayNightStyle.FORCE_NIGHT:
-                tint = ContextCompat.getColor(getContext(), R.color.car_tint_light);
-                thumbBackground = ContextCompat.getColor(getContext(),
-                        R.color.car_scrollbar_thumb_light);
+                tintResId = R.color.car_tint_light;
+                thumbBackgroundResId = R.color.car_scrollbar_thumb_light;
                 upDownBackgroundResId = R.drawable.car_pagination_background_night;
                 break;
             case DayNightStyle.FORCE_DAY:
-                tint = ContextCompat.getColor(getContext(), R.color.car_tint_dark);
-                thumbBackground = ContextCompat.getColor(getContext(),
-                        R.color.car_scrollbar_thumb_dark);
+                tintResId =  R.color.car_tint_dark;
+                thumbBackgroundResId = R.color.car_scrollbar_thumb_dark;
                 upDownBackgroundResId = R.drawable.car_pagination_background_day;
                 break;
             default:
                 throw new IllegalArgumentException("Unknown DayNightStyle: " + mDayNightStyle);
         }
 
-        mScrollThumb.setBackgroundColor(thumbBackground);
+        if (mUseCustomThumbBackground) {
+            thumbBackgroundResId = mCustomThumbBackgroundResId;
+        }
+        mScrollThumb.setBackgroundColor(ContextCompat.getColor(getContext(), thumbBackgroundResId));
 
+        int tint = ContextCompat.getColor(getContext(), tintResId);
         mUpButton.setColorFilter(tint, PorterDuff.Mode.SRC_IN);
         mUpButton.setBackgroundResource(upDownBackgroundResId);
 
diff --git a/car/src/main/java/androidx/car/widget/PagedSmoothScroller.java b/car/src/main/java/androidx/car/widget/PagedSmoothScroller.java
new file mode 100644
index 0000000..cbd7862
--- /dev/null
+++ b/car/src/main/java/androidx/car/widget/PagedSmoothScroller.java
@@ -0,0 +1,74 @@
+/*
+ * 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 androidx.car.widget;
+
+import android.content.Context;
+import android.support.v7.widget.LinearSmoothScroller;
+import android.support.v7.widget.RecyclerView;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+/**
+ * Custom {@link LinearSmoothScroller} that has:
+ *
+ * <ul>
+ * <li>Custom control over the speed of scrolls.
+ * <li>Scrolling that snaps to start of a child view.
+ * </ul>
+ */
+public final class PagedSmoothScroller extends LinearSmoothScroller {
+    private static final float MILLISECONDS_PER_INCH = 150f;
+    private static final float DECELERATION_TIME_DIVISOR = 0.45f;
+
+    private final Interpolator mInterpolator = new DecelerateInterpolator(1.8f);
+
+    public PagedSmoothScroller(Context context) {
+        super(context);
+    }
+
+    @Override
+    protected int getVerticalSnapPreference() {
+        // This is key for most of the scrolling logic that guarantees that scrolling
+        // will settle with a view aligned to the top.
+        return SNAP_TO_START;
+    }
+
+    @Override
+    protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
+        int dy = calculateDyToMakeVisible(targetView, SNAP_TO_START);
+        if (dy == 0) {
+            return;
+        }
+
+        final int time = calculateTimeForDeceleration(dy);
+        if (time > 0) {
+            action.update(0, -dy, time, mInterpolator);
+        }
+    }
+
+    @Override
+    protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
+        return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
+    }
+
+    @Override
+    protected int calculateTimeForDeceleration(int dx) {
+        return (int) Math.ceil(calculateTimeForScrolling(dx) / DECELERATION_TIME_DIVISOR);
+    }
+}
diff --git a/car/src/main/java/androidx/car/widget/PagedSnapHelper.java b/car/src/main/java/androidx/car/widget/PagedSnapHelper.java
new file mode 100644
index 0000000..ad1c710
--- /dev/null
+++ b/car/src/main/java/androidx/car/widget/PagedSnapHelper.java
@@ -0,0 +1,269 @@
+/*
+ * 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 androidx.car.widget;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.LinearSnapHelper;
+import android.support.v7.widget.OrientationHelper;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+/**
+ * Extension of a {@link LinearSnapHelper} that will snap to the start of the target child view to
+ * the start of the attached {@link RecyclerView}. The start of the view is defined as the top
+ * if the RecyclerView is scrolling vertically; it is defined as the left (or right if RTL) if the
+ * RecyclerView is scrolling horizontally.
+ */
+public class PagedSnapHelper extends LinearSnapHelper {
+    /**
+     * The percentage of a View that needs to be completely visible for it to be a viable snap
+     * target.
+     */
+    private static final float VIEW_VISIBLE_THRESHOLD = 0.5f;
+
+    private RecyclerView mRecyclerView;
+
+    // Orientation helpers are lazily created per LayoutManager.
+    @Nullable
+    private OrientationHelper mVerticalHelper;
+
+    @Nullable
+    private OrientationHelper mHorizontalHelper;
+
+    @Override
+    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager,
+            @NonNull View targetView) {
+        int[] out = new int[2];
+
+        out[0] = layoutManager.canScrollHorizontally()
+                ? getHorizontalHelper(layoutManager).getDecoratedStart(targetView)
+                : 0;
+
+        out[1] = layoutManager.canScrollVertically()
+                ? getVerticalHelper(layoutManager).getDecoratedStart(targetView)
+                : 0;
+
+        return out;
+    }
+
+    /**
+     * Finds the view to snap to. The view to snap to is the child of the LayoutManager that is
+     * closest to the start of the RecyclerView. The "start" depends on if the LayoutManager
+     * is scrolling horizontally or vertically. If it is horizontally scrolling, then the
+     * start is the view on the left (right if RTL). Otherwise, it is the top-most view.
+     *
+     * @param layoutManager The current {@link RecyclerView.LayoutManager} for the attached
+     *                      RecyclerView.
+     * @return The View closest to the start of the RecyclerView.
+     */
+    @Override
+    @Nullable
+    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
+        int childCount = layoutManager.getChildCount();
+        if (childCount == 0) {
+            return null;
+        }
+
+        // If there's only one child, then that will be the snap target.
+        if (childCount == 1) {
+            return layoutManager.getChildAt(0);
+        }
+
+        OrientationHelper orientationHelper = layoutManager.canScrollVertically()
+                ? getVerticalHelper(layoutManager)
+                : getHorizontalHelper(layoutManager);
+
+        View lastVisibleChild = layoutManager.getChildAt(childCount - 1);
+
+        // Check if the last child visible is the last item in the list.
+        boolean lastItemVisible =
+                layoutManager.getPosition(lastVisibleChild) == layoutManager.getItemCount() - 1;
+
+        // If it is, then check how much of that view is visible.
+        float lastItemPercentageVisible = lastItemVisible
+                ? getPercentageVisible(lastVisibleChild, orientationHelper) : 0;
+
+        View closestChild = null;
+        int closestDistanceToStart = Integer.MAX_VALUE;
+        float closestPercentageVisible = 0.f;
+
+        for (int i = 0; i < childCount; i++) {
+            View child = layoutManager.getChildAt(i);
+            int startOffset = orientationHelper.getDecoratedStart(child);
+
+            if (Math.abs(startOffset) < closestDistanceToStart) {
+                float percentageVisible = getPercentageVisible(child, orientationHelper);
+
+                // Only snap to the child that is closest to the top and is more than
+                // half-way visible.
+                if (percentageVisible > VIEW_VISIBLE_THRESHOLD
+                        && percentageVisible > closestPercentageVisible) {
+                    closestDistanceToStart = startOffset;
+                    closestChild = child;
+                    closestPercentageVisible = percentageVisible;
+                }
+            }
+        }
+
+        // Snap to the last child in the list if it's the last item in the list, and it's more
+        // visible than the closest item to the top of the list.
+        return (lastItemVisible && lastItemPercentageVisible > closestPercentageVisible)
+                ? lastVisibleChild
+                : closestChild;
+    }
+
+    /**
+     * Returns the percentage of the given view that is visible, relative to its containing
+     * RecyclerView.
+     *
+     * @param view The View to get the percentage visible of.
+     * @param helper An {@link OrientationHelper} to aid with calculation.
+     * @return A float indicating the percentage of the given view that is visible.
+     */
+    private float getPercentageVisible(View view, OrientationHelper helper) {
+        int start = 0;
+        int end = helper.getEnd();
+
+        int viewStart = helper.getDecoratedStart(view);
+        int viewEnd = helper.getDecoratedEnd(view);
+
+        if (viewStart >= start && viewEnd <= end) {
+            // The view is within the bounds of the RecyclerView, so it's fully visible.
+            return 1.f;
+        } else if (viewStart <= start && viewEnd >= end) {
+            // The view is larger than the height of the RecyclerView.
+            int viewHeight = helper.getDecoratedMeasurement(view);
+            return 1.f - ((float) (Math.abs(viewStart) + Math.abs(viewEnd)) / viewHeight);
+        } else if (viewStart < start) {
+            // The view is above the start of the RecyclerView, so subtract the start offset
+            // from the total height.
+            return 1.f - ((float) Math.abs(viewStart) / helper.getDecoratedMeasurement(view));
+        } else {
+            // The view is below the end of the RecyclerView, so subtract the end offset from the
+            // total height.
+            return 1.f - ((float) Math.abs(viewEnd) / helper.getDecoratedMeasurement(view));
+        }
+    }
+
+    @Override
+    public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {
+        super.attachToRecyclerView(recyclerView);
+        mRecyclerView = recyclerView;
+    }
+
+    /**
+     * Calculate the estimated scroll distance in each direction given velocities on both axes.
+     * This method will clamp the maximum scroll distance so that a single fling will never scroll
+     * more than one page.
+     *
+     * @param velocityX Fling velocity on the horizontal axis.
+     * @param velocityY Fling velocity on the vertical axis.
+     * @return An array holding the calculated distances in x and y directions respectively.
+     */
+    @Override
+    public int[] calculateScrollDistance(int velocityX, int velocityY) {
+        int[] outDist = super.calculateScrollDistance(velocityX, velocityY);
+
+        if (mRecyclerView == null) {
+            return outDist;
+        }
+
+        RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
+        if (layoutManager == null || layoutManager.getChildCount() == 0) {
+            return outDist;
+        }
+
+        int lastChildPosition = isAtEnd(layoutManager) ? 0 : layoutManager.getChildCount() - 1;
+
+        // The max and min distance is the total height of the RecyclerView minus the height of
+        // the last child. This ensures that each scroll will never scroll more than a single
+        // page on the RecyclerView. That is, the max scroll will make the last child the
+        // first child and vice versa when scrolling the opposite way.
+        int maxDistance = layoutManager.getHeight() - layoutManager.getDecoratedMeasuredHeight(
+                layoutManager.getChildAt(lastChildPosition));
+        int minDistance = -maxDistance;
+
+        outDist[0] = clamp(outDist[0], minDistance, maxDistance);
+        outDist[1] = clamp(outDist[1], minDistance, maxDistance);
+
+        return outDist;
+    }
+
+    /** Returns {@code true} if the RecyclerView is completely displaying the first item. */
+    public boolean isAtStart(RecyclerView.LayoutManager layoutManager) {
+        if (layoutManager == null || layoutManager.getChildCount() == 0) {
+            return true;
+        }
+
+        View firstChild = layoutManager.getChildAt(0);
+        OrientationHelper orientationHelper = layoutManager.canScrollVertically()
+                ? getVerticalHelper(layoutManager)
+                : getHorizontalHelper(layoutManager);
+
+        // Check that the first child is completely visible and is the first item in the list.
+        return orientationHelper.getDecoratedStart(firstChild) >= 0
+                && layoutManager.getPosition(firstChild) == 0;
+    }
+
+    /** Returns {@code true} if the RecyclerView is completely displaying the last item. */
+    public boolean isAtEnd(RecyclerView.LayoutManager layoutManager) {
+        if (layoutManager == null || layoutManager.getChildCount() == 0) {
+            return true;
+        }
+
+        int childCount = layoutManager.getChildCount();
+        View lastVisibleChild = layoutManager.getChildAt(childCount - 1);
+
+        // The list has reached the bottom if the last child that is visible is the last item
+        // in the list and it's fully shown.
+        return layoutManager.getPosition(lastVisibleChild) == (layoutManager.getItemCount() - 1)
+                && layoutManager.getDecoratedBottom(lastVisibleChild) <= layoutManager.getHeight();
+    }
+
+    @NonNull
+    private OrientationHelper getVerticalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
+        if (mVerticalHelper == null || mVerticalHelper.getLayoutManager() != layoutManager) {
+            mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager);
+        }
+        return mVerticalHelper;
+    }
+
+    @NonNull
+    private OrientationHelper getHorizontalHelper(
+            @NonNull RecyclerView.LayoutManager layoutManager) {
+        if (mHorizontalHelper == null || mHorizontalHelper.getLayoutManager() != layoutManager) {
+            mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
+        }
+        return mHorizontalHelper;
+    }
+
+    /**
+     * Ensures that the given value falls between the range given by the min and max values. This
+     * method does not check that the min value is greater than or equal to the max value. If the
+     * parameters are not well-formed, this method's behavior is undefined.
+     *
+     * @param value The value to clamp.
+     * @param min The minimum value the given value can be.
+     * @param max The maximum value the given value can be.
+     * @return A number that falls between {@code min} or {@code max} or one of those values if the
+     * given value is less than or greater than {@code min} and {@code max} respectively.
+     */
+    private static int clamp(int value, int min, int max) {
+        return Math.max(min, Math.min(max, value));
+    }
+}
diff --git a/car/tests/src/androidx/car/widget/ListItemTest.java b/car/tests/src/androidx/car/widget/ListItemTest.java
index 2b974c3..bdf3e29 100644
--- a/car/tests/src/androidx/car/widget/ListItemTest.java
+++ b/car/tests/src/androidx/car/widget/ListItemTest.java
@@ -40,8 +40,10 @@
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.v7.widget.CardView;
+import android.support.v7.widget.LinearLayoutManager;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.RelativeLayout;
 
 import org.hamcrest.Matcher;
 import org.junit.Before;
@@ -112,7 +114,7 @@
     public void testEmptyItemHidesAllViews() {
         ListItem item = new ListItem.Builder(mActivity).build();
         setupPagedListView(Arrays.asList(item));
-        verifyViewIsHidden(mPagedListView.findViewByPosition(0));
+        verifyViewIsHidden(mPagedListView.getRecyclerView().getLayoutManager().getChildAt(0));
     }
 
     @Test
@@ -156,11 +158,11 @@
                         .withSupplementalIcon(android.R.drawable.sym_def_app_icon, true)
                         .build(),
                 new ListItem.Builder(mActivity)
-                        .withAction("text", true, null)
+                        .withAction("text", true, v -> { /* Do nothing. */ })
                         .build(),
                 new ListItem.Builder(mActivity)
-                        .withActions("text", true, null,
-                                 "text", true, null)
+                        .withActions("text", true, v -> { /* Do nothing. */ },
+                                 "text", true, v -> { /* Do nothing. */ })
                         .build());
         setupPagedListView(items);
 
@@ -187,11 +189,11 @@
                         .withSupplementalIcon(android.R.drawable.sym_def_app_icon, false)
                         .build(),
                 new ListItem.Builder(mActivity)
-                        .withAction("text", false, null)
+                        .withAction("text", false, v -> { /* Do nothing. */ })
                         .build(),
                 new ListItem.Builder(mActivity)
-                        .withActions("text", false, null,
-                                "text", false, null)
+                        .withActions("text", false, v -> { /* Do nothing. */ },
+                                "text", false, v -> { /* Do nothing. */ })
                         .build());
         setupPagedListView(items);
 
@@ -268,8 +270,10 @@
         double singleLineHeight = InstrumentationRegistry.getContext().getResources().getDimension(
                 R.dimen.car_single_line_list_item_height);
 
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) mPagedListView.getRecyclerView().getLayoutManager();
         for (int i = 0; i < items.size(); i++) {
-            assertThat((double) mPagedListView.findViewByPosition(i).getHeight(),
+            assertThat((double) layoutManager.findViewByPosition(i).getHeight(),
                     is(closeTo(singleLineHeight, 1.0d)));
         }
     }
@@ -296,8 +300,10 @@
                 (int) InstrumentationRegistry.getContext().getResources().getDimension(
                         R.dimen.car_double_line_list_item_height);
 
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) mPagedListView.getRecyclerView().getLayoutManager();
         for (int i = 0; i < items.size(); i++) {
-            assertThat(mPagedListView.findViewByPosition(i).getHeight(),
+            assertThat(layoutManager.findViewByPosition(i).getHeight(),
                     is(greaterThanOrEqualTo(doubleLineHeight)));
         }
     }
@@ -367,9 +373,9 @@
         final boolean[] clicked = {false, false};
         List<ListItem> items = Arrays.asList(
                 new ListItem.Builder(mActivity)
-                        .withOnClickListener((v) -> clicked[0] = true)
+                        .withOnClickListener(v -> clicked[0] = true)
                         .withSupplementalIcon(android.R.drawable.sym_def_app_icon, true,
-                                (v) -> clicked[1] = true)
+                                v -> clicked[1] = true)
                         .build());
         setupPagedListView(items);
 
@@ -388,7 +394,7 @@
         List<ListItem> items = Arrays.asList(
                 new ListItem.Builder(mActivity)
                         .withSupplementalIcon(android.R.drawable.sym_def_app_icon, true,
-                                (v) -> clicked[0] = true)
+                                v -> clicked[0] = true)
                         .build());
         setupPagedListView(items);
 
@@ -398,11 +404,23 @@
     }
 
     @Test
+    public void testSupplementalIconWithoutClickListenerIsNotClickable() {
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withSupplementalIcon(android.R.drawable.sym_def_app_icon, true)
+                        .build());
+        setupPagedListView(items);
+
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        assertFalse(viewHolder.getSupplementalIcon().isClickable());
+    }
+
+    @Test
     public void testClickingSupplementalAction() {
         final boolean[] clicked = {false};
         List<ListItem> items = Arrays.asList(
                 new ListItem.Builder(mActivity)
-                        .withAction("action", true, (v) -> clicked[0] = true)
+                        .withAction("action", true, v -> clicked[0] = true)
                         .build());
         setupPagedListView(items);
 
@@ -416,8 +434,8 @@
         final boolean[] clicked = {false, false};
         List<ListItem> items = Arrays.asList(
                 new ListItem.Builder(mActivity)
-                        .withActions("action 1", true, (v) -> clicked[0] = true,
-                                "action 2", true, (v) -> clicked[1] = true)
+                        .withActions("action 1", true, v -> clicked[0] = true,
+                                "action 2", true, v -> clicked[1] = true)
                         .build());
         setupPagedListView(items);
 
@@ -497,6 +515,46 @@
                 is(equalTo(bodyPrimary.getBody().getTextColors())));
     }
 
+    @Test
+    public void testNoCarriedOverLayoutParamsForTextView() throws Throwable {
+        ListItem singleLine = new ListItem.Builder(mActivity).withTitle("t").build();
+        setupPagedListView(Arrays.asList(singleLine));
+
+        // Manually rebind the view holder of a single line item to a double line item.
+        ListItem doubleLine = new ListItem.Builder(mActivity).withTitle("t").withBody("b").build();
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        mActivityRule.runOnUiThread(() -> doubleLine.bind(viewHolder));
+
+        RelativeLayout.LayoutParams titleLayoutParams =
+                (RelativeLayout.LayoutParams) viewHolder.getTitle().getLayoutParams();
+        RelativeLayout.LayoutParams bodyLayoutParams =
+                (RelativeLayout.LayoutParams) viewHolder.getTitle().getLayoutParams();
+        assertThat(titleLayoutParams.getRule(RelativeLayout.CENTER_VERTICAL), is(equalTo(0)));
+        assertThat(bodyLayoutParams.getRule(RelativeLayout.CENTER_VERTICAL), is(equalTo(0)));
+    }
+
+    @Test
+    public void testNoCarriedOverLayoutParamsForPrimaryIcon() throws Throwable {
+        ListItem smallIcon = new ListItem.Builder(mActivity)
+                .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                .withBody("body")  // Small icon of items with body text should use top margin.
+                .build();
+        setupPagedListView(Arrays.asList(smallIcon));
+
+        // Manually rebind the view holder.
+        ListItem largeIcon = new ListItem.Builder(mActivity)
+                .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true)
+                .build();
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        mActivityRule.runOnUiThread(() -> largeIcon.bind(viewHolder));
+
+        RelativeLayout.LayoutParams iconLayoutParams =
+                (RelativeLayout.LayoutParams) viewHolder.getPrimaryIcon().getLayoutParams();
+        assertThat(iconLayoutParams.getRule(RelativeLayout.CENTER_VERTICAL),
+                is(equalTo(RelativeLayout.TRUE)));
+        assertThat(iconLayoutParams.topMargin, is(equalTo(0)));
+    }
+
     private static ViewAction clickChildViewWithId(final int id) {
         return new ViewAction() {
             @Override
diff --git a/car/tests/src/androidx/car/widget/PagedListViewSavedStateTest.java b/car/tests/src/androidx/car/widget/PagedListViewSavedStateTest.java
index b134e10..a5405ac 100644
--- a/car/tests/src/androidx/car/widget/PagedListViewSavedStateTest.java
+++ b/car/tests/src/androidx/car/widget/PagedListViewSavedStateTest.java
@@ -32,6 +32,7 @@
 import android.support.test.filters.Suppress;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -124,20 +125,25 @@
             return;
         }
 
+        LinearLayoutManager layoutManager1 =
+                (LinearLayoutManager) mPagedListView1.getRecyclerView().getLayoutManager();
+        LinearLayoutManager layoutManager2 =
+                (LinearLayoutManager) mPagedListView2.getRecyclerView().getLayoutManager();
+
         Random random = new Random();
         IdlingRegistry.getInstance().register(new PagedListViewScrollingIdlingResource(
                 mPagedListView1, mPagedListView2));
 
         // Add 1 to this random number to ensure it is a value between 1 and NUM_OF_PAGES.
-        int numOfClicks = random.nextInt(NUM_OF_PAGES) + 1;
+        int numOfClicks = 2;
         clickPageDownButton(onPagedListView1(), numOfClicks);
         int topPositionOfPagedListView1 =
-                mPagedListView1.getLayoutManager().getFirstFullyVisibleChildPosition();
+                layoutManager1.findFirstVisibleItemPosition();
 
-        numOfClicks = random.nextInt(NUM_OF_PAGES) + 1;
+        numOfClicks = 3;
         clickPageDownButton(onPagedListView2(), numOfClicks);
         int topPositionOfPagedListView2 =
-                mPagedListView2.getLayoutManager().getFirstFullyVisibleChildPosition();
+                layoutManager2.findFirstVisibleItemPosition();
 
         // Perform a configuration change by rotating the screen.
         mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
@@ -145,9 +151,9 @@
 
         // Check that the positions are the same after the change.
         assertEquals(topPositionOfPagedListView1,
-                mPagedListView1.getLayoutManager().getFirstFullyVisibleChildPosition());
+                layoutManager1.findFirstVisibleItemPosition());
         assertEquals(topPositionOfPagedListView2,
-                mPagedListView2.getLayoutManager().getFirstFullyVisibleChildPosition());
+                layoutManager2.findFirstVisibleItemPosition());
     }
 
     /** Clicks the page down button on the given PagedListView for the given number of times. */
diff --git a/car/tests/src/androidx/car/widget/PagedListViewTest.java b/car/tests/src/androidx/car/widget/PagedListViewTest.java
index e924f4b..67d97e3 100644
--- a/car/tests/src/androidx/car/widget/PagedListViewTest.java
+++ b/car/tests/src/androidx/car/widget/PagedListViewTest.java
@@ -20,6 +20,7 @@
 import static android.support.test.espresso.action.ViewActions.click;
 import static android.support.test.espresso.action.ViewActions.swipeDown;
 import static android.support.test.espresso.action.ViewActions.swipeUp;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
 import static android.support.test.espresso.assertion.ViewAssertions.matches;
 import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
 import static android.support.test.espresso.contrib.RecyclerViewActions.scrollToPosition;
@@ -28,22 +29,24 @@
 import static android.support.test.espresso.matcher.ViewMatchers.withId;
 import static android.support.test.espresso.matcher.ViewMatchers.withText;
 
-import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 
 import android.content.pm.PackageManager;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.espresso.Espresso;
 import android.support.test.espresso.IdlingResource;
 import android.support.test.espresso.matcher.ViewMatchers;
-import android.support.test.filters.SmallTest;
-import android.support.test.filters.Suppress;
+import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -64,7 +67,7 @@
 
 /** Unit tests for {@link PagedListView}. */
 @RunWith(AndroidJUnit4.class)
-@SmallTest
+@MediumTest
 public final class PagedListViewTest {
 
     /**
@@ -100,19 +103,17 @@
         }
     }
 
+    /** Returns {@code true} if the testing device has the automotive feature flag. */
     private boolean isAutoDevice() {
         PackageManager packageManager = mActivityRule.getActivity().getPackageManager();
         return packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
     }
 
+    /** Sets up {@link #mPagedListView} with the given number of items. */
     private void setUpPagedListView(int itemCount) {
-        setUpPagedListView(itemCount, PagedListView.ItemCap.UNLIMITED);
-    }
-
-    private void setUpPagedListView(int itemCount, int maxPages) {
         try {
             mActivityRule.runOnUiThread(() -> {
-                mPagedListView.setMaxPages(maxPages);
+                mPagedListView.setMaxPages(PagedListView.ItemCap.UNLIMITED);
                 mPagedListView.setAdapter(
                         new TestAdapter(itemCount, mPagedListView.getMeasuredHeight()));
             });
@@ -122,124 +123,39 @@
         }
     }
 
-    /** Initializes {@link #mPagedListView} with an adapter that does not implement ItemCap. */
-    public void setUpNonItemCapPagedListView(int itemCount, int maxPages) {
-        try {
-            mActivityRule.runOnUiThread(() -> {
-                mPagedListView.setMaxPages(maxPages);
-                mPagedListView.setAdapter(
-                        new NoItemCapAdapter(itemCount, mPagedListView.getMeasuredHeight()));
-            });
-        } catch (Throwable throwable) {
-            throwable.printStackTrace();
-            throw new RuntimeException(throwable);
-        }
-    }
-
     @Test
-    public void scrollBarIsInvisibleIfItemsDoNotFillOnePage() {
-        setUpPagedListView(1 /* itemCount */);
+    public void testScrollBarIsInvisibleIfItemsDoNotFillOnePage() {
+        if (!isAutoDevice()) {
+            return;
+        }
 
+        setUpPagedListView(1 /* itemCount */);
         onView(withId(R.id.paged_scroll_view)).check(matches(not(isDisplayed())));
     }
 
     @Test
-    public void pageUpDownButtonIsDisabledOnListEnds() throws Throwable {
-        final int itemCount = ITEMS_PER_PAGE * 3;
+    public void testPageUpButtonDisabledAtTop() {
+        if (!isAutoDevice()) {
+            return;
+        }
+
+        int itemCount = ITEMS_PER_PAGE * 3;
         setUpPagedListView(itemCount);
+
         // Initially page_up button is disabled.
         onView(withId(R.id.page_up)).check(matches(not(isEnabled())));
 
-        // Moving to middle of list enables page_up button.
-        onView(withId(R.id.recycler_view)).perform(scrollToPosition(itemCount / 2));
+        // Moving down, should enable the up bottom.
+        onView(withId(R.id.page_down)).perform(click());
         onView(withId(R.id.page_up)).check(matches(isEnabled()));
 
-        // Moving to page end, page_down button is disabled.
-        onView(withId(R.id.recycler_view)).perform(scrollToPosition(itemCount));
-        onView(withId(R.id.page_down)).check(matches(not(isEnabled())));
+        // Move back up; this should disable the up bottom again.
+        onView(withId(R.id.page_up)).perform(click())
+                .check(matches(not(isEnabled())));
     }
 
     @Test
-    public void testMaxPageGetterSetterDefaultValue() {
-        final int maxPages = 2;
-        final int defaultMaxPages = 3;
-
-        // setMaxPages
-        setUpPagedListView(ITEMS_PER_PAGE, maxPages);
-        assertThat(mPagedListView.getMaxPages(), is(equalTo(maxPages)));
-
-        // resetMaxPages
-        mPagedListView.resetMaxPages();
-        // Max pages is equal to max clicks - 1
-        assertThat(mPagedListView.getMaxPages(), is(equalTo(PagedListView.DEFAULT_MAX_CLICKS - 1)));
-
-        // setDefaultMaxPages
-        mPagedListView.setDefaultMaxPages(defaultMaxPages);
-        mPagedListView.resetMaxPages();
-        assertThat(mPagedListView.getMaxPages(), is(equalTo(defaultMaxPages - 1)));
-    }
-
-    @Test
-    public void setMaxPagesLimitsNumberOfClicks() {
-        if (!isAutoDevice()) {
-            return;
-        }
-
-        setUpPagedListView(ITEMS_PER_PAGE * 3 /* itemCount */, 2 /* maxPages */);
-
-        onView(withId(R.id.page_down)).perform(click());
-        onView(withId(R.id.page_down)).check(matches(not(isEnabled())));
-    }
-
-    @Test
-    public void testMaxPagesDoesNothingIfAdapterDoesNotImplementItemCap() {
-        if (!isAutoDevice()) {
-            return;
-        }
-
-        int numOfPages = 20;
-        int maxPages = 2;
-
-        setUpNonItemCapPagedListView(ITEMS_PER_PAGE * numOfPages, maxPages);
-
-        // There should be no limit on the scroll even though a max number of pages was set.
-        for (int i = 0; i < maxPages; i++) {
-            onView(withId(R.id.page_down)).perform(click());
-        }
-        onView(withId(R.id.page_down)).check(matches(isEnabled()));
-
-        // Next scroll all the way to bottom and check this is possible.
-        for (int i = 0; i < numOfPages - maxPages; i++) {
-            onView(withId(R.id.page_down)).perform(click());
-        }
-        onView(withId(R.id.page_down)).check(matches(not(isEnabled())));
-    }
-
-    @Suppress
-    @Test
-    public void resetMaxPagesToDefaultUnlimitedExtendsList() throws Throwable {
-        if (!isAutoDevice()) {
-            return;
-        }
-
-        final int itemCount = ITEMS_PER_PAGE * 4;
-        setUpPagedListView(itemCount, 2 /* maxPages */);
-
-        // Move to next page - should reach end of list.
-        onView(withId(R.id.page_down)).perform(click()).check(matches(not(isEnabled())));
-
-        // After resetting max pages (default unlimited), we scroll to the known total number of
-        // items.
-        mActivityRule.runOnUiThread(() -> mPagedListView.resetMaxPages());
-        onView(withId(R.id.recycler_view)).perform(scrollToPosition(itemCount - 1));
-
-        // Verify the last item that would've been hidden due to max pages is now shown.
-        onView(allOf(withId(R.id.text_view), withText(itemText(itemCount - 1))))
-                .check(matches(isDisplayed()));
-    }
-
-    @Test
-    public void scrollbarKeepsItemSnappedToTopOfList() {
+    public void testItemSnappedToTopOfListOnScroll() throws InterruptedException {
         if (!isAutoDevice()) {
             return;
         }
@@ -250,25 +166,31 @@
         // Going down one page and first item is snapped to top
         onView(withId(R.id.page_down)).perform(click());
         verifyItemSnappedToListTop();
+    }
 
-        // Go down another page and we reach the last page.
+    @Test
+    public void testLastItemSnappedWhenBottomReached() {
+        if (!isAutoDevice()) {
+            return;
+        }
+
+        // 2.5 so last page is not full
+        setUpPagedListView((int) (ITEMS_PER_PAGE * 2.5 /* itemCount */));
+
+        // Go down 2 pages so the bottom is reached.
+        onView(withId(R.id.page_down)).perform(click());
         onView(withId(R.id.page_down)).perform(click()).check(matches(not(isEnabled())));
-        verifyItemSnappedToListTop();
+
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) mPagedListView.getRecyclerView().getLayoutManager();
+
+        // Check that the last item is completely visible.
+        assertEquals(layoutManager.findLastCompletelyVisibleItemPosition(),
+                layoutManager.getItemCount() - 1);
     }
 
-    @Suppress
     @Test
-    public void swipeUpKeepsItemSnappedToTopOfList() {
-        setUpPagedListView(ITEMS_PER_PAGE * 2 /* itemCount */);
-
-        onView(withId(R.id.recycler_view)).perform(actionOnItemAtPosition(1, swipeUp()));
-
-        verifyItemSnappedToListTop();
-    }
-
-    @Suppress
-    @Test
-    public void swipeDownKeepsItemSnappedToTopOfList() throws Throwable {
+    public void testSwipeDownKeepsItemSnappedToTopOfList() {
         setUpPagedListView(ITEMS_PER_PAGE * 2 /* itemCount */);
 
         // Go down one page, then swipe down (going up).
@@ -280,7 +202,18 @@
     }
 
     @Test
-    public void pageUpAndDownMoveSameDistance() {
+    public void testSwipeUpKeepsItemSnappedToTopOfList() {
+        setUpPagedListView(ITEMS_PER_PAGE * 2 /* itemCount */);
+
+        // Swipe up (going down).
+        onView(withId(R.id.recycler_view))
+                .perform(actionOnItemAtPosition(ITEMS_PER_PAGE, swipeUp()));
+
+        verifyItemSnappedToListTop();
+    }
+
+    @Test
+    public void testPageUpAndDownMoveSameDistance() {
         if (!isAutoDevice()) {
             return;
         }
@@ -289,27 +222,36 @@
 
         // Move down one page so there will be sufficient pages for up and downs.
         onView(withId(R.id.page_down)).perform(click());
-        final int topPosition = mPagedListView.getFirstFullyVisibleChildPosition();
+
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) mPagedListView.getRecyclerView().getLayoutManager();
+
+        int topPosition = layoutManager.findFirstVisibleItemPosition();
 
         for (int i = 0; i < 3; i++) {
             onView(withId(R.id.page_down)).perform(click());
             onView(withId(R.id.page_up)).perform(click());
         }
 
-        assertThat(mPagedListView.getFirstFullyVisibleChildPosition(), is(equalTo(topPosition)));
+        assertThat(layoutManager.findFirstVisibleItemPosition(), is(equalTo(topPosition)));
     }
 
-    @Suppress
     @Test
     public void setItemSpacing() throws Throwable {
+        if (!isAutoDevice()) {
+            return;
+        }
+
         final int itemCount = 3;
         setUpPagedListView(itemCount /* itemCount */);
+        RecyclerView.LayoutManager layoutManager =
+                mPagedListView.getRecyclerView().getLayoutManager();
 
         // Initial spacing is 0.
         final View[] views = new View[itemCount];
         mActivityRule.runOnUiThread(() -> {
-            for (int i = 0; i < itemCount; i++) {
-                views[i] = mPagedListView.findViewByPosition(i);
+            for (int i = 0; i < layoutManager.getChildCount(); i++) {
+                views[i] = layoutManager.getChildAt(i);
             }
         });
         for (int i = 0; i < itemCount - 1; i++) {
@@ -323,8 +265,8 @@
             mPagedListView.setItemSpacing(itemSpacing);
         });
         mActivityRule.runOnUiThread(() -> {
-            for (int i = 0; i < itemCount; i++) {
-                views[i] = mPagedListView.findViewByPosition(i);
+            for (int i = 0; i < layoutManager.getChildCount(); i++) {
+                views[i] = layoutManager.getChildAt(i);
             }
         });
         for (int i = 0; i < itemCount - 1; i++) {
@@ -336,8 +278,8 @@
             mPagedListView.setItemSpacing(0);
         });
         mActivityRule.runOnUiThread(() -> {
-            for (int i = 0; i < itemCount; i++) {
-                views[i] = mPagedListView.findViewByPosition(i);
+            for (int i = 0; i < layoutManager.getChildCount(); i++) {
+                views[i] = layoutManager.getChildAt(i);
             }
         });
         for (int i = 0; i < itemCount - 1; i++) {
@@ -348,6 +290,10 @@
     @Test
     @UiThreadTest
     public void testSetScrollBarButtonIcons() throws Throwable {
+        if (!isAutoDevice()) {
+            return;
+        }
+
         // Set up a pagedListView with a large item count to ensure the scroll bar buttons are
         // always showing.
         setUpPagedListView(100 /* itemCount */);
@@ -367,25 +313,68 @@
                 is(equalTo(downDrawable.getConstantState())));
     }
 
+    @Test
+    public void testSettingAndResettingScrollbarColor() {
+        setUpPagedListView(0);
+
+        final int color = R.color.car_teal_700;
+
+        // Setting non-zero res ID changes color.
+        mPagedListView.setScrollbarColor(color);
+        assertThat(((ColorDrawable)
+                        mPagedListView.mScrollBarView.mScrollThumb.getBackground()).getColor(),
+                is(equalTo(InstrumentationRegistry.getContext().getColor(color))));
+
+        // Resets to default color.
+        mPagedListView.resetScrollbarColor();
+        assertThat(((ColorDrawable)
+                        mPagedListView.mScrollBarView.mScrollThumb.getBackground()).getColor(),
+                is(equalTo(InstrumentationRegistry.getContext().getColor(
+                        R.color.car_scrollbar_thumb))));
+    }
+
+    @Test
+    public void testSettingScrollbarColorIgnoresDayNightStyle() {
+        setUpPagedListView(0);
+
+        final int color = R.color.car_teal_700;
+        mPagedListView.setScrollbarColor(color);
+
+        for (int style : new int[] {DayNightStyle.AUTO, DayNightStyle.AUTO_INVERSE,
+                DayNightStyle.FORCE_NIGHT, DayNightStyle.FORCE_DAY}) {
+            mPagedListView.setDayNightStyle(style);
+
+            assertThat(((ColorDrawable)
+                            mPagedListView.mScrollBarView.mScrollThumb.getBackground()).getColor(),
+                    is(equalTo(InstrumentationRegistry.getContext().getColor(color))));
+        }
+    }
+
     private static String itemText(int index) {
         return "Data " + index;
     }
 
+    /**
+     * Checks that the first item in the list is completely shown and no part of a previous item
+     * is shown.
+     */
     private void verifyItemSnappedToListTop() {
-        int firstVisiblePosition = mPagedListView.getFirstFullyVisibleChildPosition();
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) mPagedListView.getRecyclerView().getLayoutManager();
+        int firstVisiblePosition = layoutManager.findFirstCompletelyVisibleItemPosition();
         if (firstVisiblePosition > 1) {
             int lastInPreviousPagePosition = firstVisiblePosition - 1;
             onView(withText(itemText(lastInPreviousPagePosition)))
-                    .check(matches(not(isDisplayed())));
+                    .check(doesNotExist());
         }
     }
 
     /** A base adapter that will handle inflating the test view and binding data to it. */
-    private abstract class BaseTestAdapter extends RecyclerView.Adapter<TestViewHolder> {
-        protected List<String> mData;
-        protected int mParentHeight;
+    private class TestAdapter extends RecyclerView.Adapter<TestViewHolder> {
+        private List<String> mData;
+        private int mParentHeight;
 
-        BaseTestAdapter(int itemCount, int parentHeight) {
+        TestAdapter(int itemCount, int parentHeight) {
             mData = new ArrayList<>();
             for (int i = 0; i < itemCount; i++) {
                 mData.add(itemText(i));
@@ -406,33 +395,6 @@
             holder.itemView.setMinimumHeight(height);
             holder.bind(mData.get(position));
         }
-    }
-
-    private class TestAdapter extends BaseTestAdapter implements PagedListView.ItemCap {
-        private int mMaxItems;
-
-        TestAdapter(int itemCount, int parentHeight) {
-            super(itemCount, parentHeight);
-        }
-
-        @Override
-        public void setMaxItems(int maxItems) {
-            mMaxItems = maxItems;
-        }
-
-        @Override
-        public int getItemCount() {
-            return mMaxItems > 0 ? Math.min(mData.size(), mMaxItems) : mData.size();
-        }
-    }
-
-    /**
-     * A variant of a {@link BaseTestAdapter} that does not implement {@link PagedListView.ItemCap}.
-     */
-    private class NoItemCapAdapter extends BaseTestAdapter {
-        NoItemCapAdapter(int itemCount, int parentHeight) {
-            super(itemCount, parentHeight);
-        }
 
         @Override
         public int getItemCount() {
@@ -453,8 +415,11 @@
         }
     }
 
+    /**
+     * An {@link IdlingResource} that will prevent assertions from running while the
+     * {@link #mPagedListView} is scrolling.
+     */
     private class PagedListViewScrollingIdlingResource implements IdlingResource {
-
         private boolean mIdle = true;
         private ResourceCallback mResourceCallback;
 
diff --git a/compat/Android.mk b/compat/Android.mk
index e16bba6..720a1eb 100644
--- a/compat/Android.mk
+++ b/compat/Android.mk
@@ -30,7 +30,7 @@
     $(call all-java-files-under,src/main/java) \
     $(call all-Iaidl-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := \
+LOCAL_JAVA_LIBRARIES := \
     android-support-annotations
 LOCAL_STATIC_JAVA_LIBRARIES := \
     apptoolkit-arch-core-common \
diff --git a/compat/build.gradle b/compat/build.gradle
index a26eac8..8f44285 100644
--- a/compat/build.gradle
+++ b/compat/build.gradle
@@ -8,10 +8,7 @@
 
 dependencies {
     api(project(":support-annotations"))
-    api (libs.arch_lifecycle_runtime)  {
-        exclude module: 'support-annotations'
-        transitive = true
-    }
+    api(ARCH_LIFECYCLE_RUNTIME, libs.exclude_annotations_transitive)
 
     androidTestImplementation(TEST_RUNNER)
     androidTestImplementation(ESPRESSO_CORE)
@@ -23,10 +20,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.aidl.srcDirs = ['src/main/java']
         main.res.srcDirs 'res', 'res-public'
diff --git a/compat/res-public/values/public_attrs.xml b/compat/res-public/values/public_attrs.xml
index e45f8c2..38d858e 100644
--- a/compat/res-public/values/public_attrs.xml
+++ b/compat/res-public/values/public_attrs.xml
@@ -26,4 +26,6 @@
      <public type="attr" name="fontStyle"/>
      <public type="attr" name="font"/>
      <public type="attr" name="fontWeight"/>
+     <public type="attr" name="fontVariationSettings"/>
+     <public type="attr" name="ttcIndex"/>
 </resources>
diff --git a/compat/res/values/attrs.xml b/compat/res/values/attrs.xml
index 04d7690..1a721a8 100644
--- a/compat/res/values/attrs.xml
+++ b/compat/res/values/attrs.xml
@@ -79,10 +79,19 @@
          common values are 400 for regular weight and 700 for bold weight. If unspecified, the value
          in the font's header tables will be used. -->
         <attr name="fontWeight" format="integer" />
-
+        <!-- The variation settings to be applied to the font. The string should be in the following
+         format: "'tag1' value1, 'tag2' value2, ...". If the default variation settings should be
+         used, or the font used does not support variation settings, this attribute needs not be
+         specified. -->
+        <attr name="fontVariationSettings" format="string" />
+        <!-- The index of the font in the tcc font file. If the font file referenced is not in the
+        tcc format, this attribute needs not be specified. -->
+        <attr name="ttcIndex" format="integer" />
         <!-- References to the framework attrs -->
         <attr name="android:fontStyle" />
         <attr name="android:font" />
         <attr name="android:fontWeight" />
+        <attr name="android:fontVariationSettings" />
+        <attr name="android:ttcIndex" />
     </declare-styleable>
 </resources>
diff --git a/compat/src/main/java/android/support/v4/content/res/FontResourcesParserCompat.java b/compat/src/main/java/android/support/v4/content/res/FontResourcesParserCompat.java
index 8ad07d3..f597e68 100644
--- a/compat/src/main/java/android/support/v4/content/res/FontResourcesParserCompat.java
+++ b/compat/src/main/java/android/support/v4/content/res/FontResourcesParserCompat.java
@@ -102,13 +102,17 @@
         private final @NonNull String mFileName;
         private int mWeight;
         private boolean mItalic;
+        private String mVariationSettings;
+        private int mTtcIndex;
         private int mResourceId;
 
         public FontFileResourceEntry(@NonNull String fileName, int weight, boolean italic,
-                int resourceId) {
+                @Nullable String variationSettings, int ttcIndex, int resourceId) {
             mFileName = fileName;
             mWeight = weight;
             mItalic = italic;
+            mVariationSettings = variationSettings;
+            mTtcIndex = ttcIndex;
             mResourceId = resourceId;
         }
 
@@ -124,6 +128,14 @@
             return mItalic;
         }
 
+        public @Nullable String getVariationSettings() {
+            return mVariationSettings;
+        }
+
+        public int getTtcIndex() {
+            return mTtcIndex;
+        }
+
         public int getResourceId() {
             return mResourceId;
         }
@@ -260,6 +272,15 @@
                 ? R.styleable.FontFamilyFont_fontStyle
                 : R.styleable.FontFamilyFont_android_fontStyle;
         boolean isItalic = ITALIC == array.getInt(styleAttr, 0);
+        final int ttcIndexAttr = array.hasValue(R.styleable.FontFamilyFont_ttcIndex)
+                ? R.styleable.FontFamilyFont_ttcIndex
+                : R.styleable.FontFamilyFont_android_ttcIndex;
+        final int variationSettingsAttr =
+                array.hasValue(R.styleable.FontFamilyFont_fontVariationSettings)
+                        ? R.styleable.FontFamilyFont_fontVariationSettings
+                        : R.styleable.FontFamilyFont_android_fontVariationSettings;
+        String variationSettings = array.getString(variationSettingsAttr);
+        int ttcIndex = array.getInt(ttcIndexAttr, 0);
         final int resourceAttr = array.hasValue(R.styleable.FontFamilyFont_font)
                 ? R.styleable.FontFamilyFont_font
                 : R.styleable.FontFamilyFont_android_font;
@@ -269,7 +290,8 @@
         while (parser.next() != XmlPullParser.END_TAG) {
             skip(parser);
         }
-        return new FontFileResourceEntry(filename, weight, isItalic, resourceId);
+        return new FontFileResourceEntry(filename, weight, isItalic, variationSettings, ttcIndex,
+                resourceId);
     }
 
     private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
diff --git a/compat/src/main/java/android/support/v4/graphics/TypefaceCompat.java b/compat/src/main/java/android/support/v4/graphics/TypefaceCompat.java
index 3c55df6..b763101 100644
--- a/compat/src/main/java/android/support/v4/graphics/TypefaceCompat.java
+++ b/compat/src/main/java/android/support/v4/graphics/TypefaceCompat.java
@@ -32,10 +32,10 @@
 import android.support.v4.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry;
 import android.support.v4.content.res.FontResourcesParserCompat.ProviderResourceEntry;
 import android.support.v4.content.res.ResourcesCompat;
+import android.support.v4.os.BuildCompat;
 import android.support.v4.provider.FontsContractCompat;
 import android.support.v4.provider.FontsContractCompat.FontInfo;
 import android.support.v4.util.LruCache;
-
 /**
  * Helper for accessing features in {@link Typeface}.
  * @hide
@@ -46,7 +46,9 @@
 
     private static final TypefaceCompatImpl sTypefaceCompatImpl;
     static {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+        if (BuildCompat.isAtLeastP()) {
+            sTypefaceCompatImpl = new TypefaceCompatApi28Impl();
+        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             sTypefaceCompatImpl = new TypefaceCompatApi26Impl();
         } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
                 && TypefaceCompatApi24Impl.isUsable()) {
diff --git a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java
index 89a6ec4..a8c1988 100644
--- a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java
+++ b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java
@@ -159,8 +159,7 @@
             if (buffer == null) {
                 return null;
             }
-            // TODO: support ttc index.
-            if (!addFontWeightStyle(family, buffer, 0, e.getWeight(), e.isItalic())) {
+            if (!addFontWeightStyle(family, buffer, e.getTtcIndex(), e.getWeight(), e.isItalic())) {
                 return null;
             }
         }
diff --git a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java
index 28ab3ed..955284e 100644
--- a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java
+++ b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java
@@ -60,76 +60,70 @@
             "createFromFamiliesWithDefault";
     private static final String FREEZE_METHOD = "freeze";
     private static final String ABORT_CREATION_METHOD = "abortCreation";
-    private static final Class sFontFamily;
-    private static final Constructor sFontFamilyCtor;
-    private static final Method sAddFontFromAssetManager;
-    private static final Method sAddFontFromBuffer;
-    private static final Method sFreeze;
-    private static final Method sAbortCreation;
-    private static final Method sCreateFromFamiliesWithDefault;
     private static final int RESOLVE_BY_FONT_TABLE = -1;
+    private static final String DEFAULT_FAMILY = "sans-serif";
 
-    static {
-        Class fontFamilyClass;
+    protected final Class mFontFamily;
+    protected final Constructor mFontFamilyCtor;
+    protected final Method mAddFontFromAssetManager;
+    protected final Method mAddFontFromBuffer;
+    protected final Method mFreeze;
+    protected final Method mAbortCreation;
+    protected final Method mCreateFromFamiliesWithDefault;
+
+    public TypefaceCompatApi26Impl() {
+        Class fontFamily;
         Constructor fontFamilyCtor;
-        Method addFontMethod;
-        Method addFromBufferMethod;
-        Method freezeMethod;
-        Method abortCreationMethod;
-        Method createFromFamiliesWithDefaultMethod;
+        Method addFontFromAssetManager;
+        Method addFontFromBuffer;
+        Method freeze;
+        Method abortCreation;
+        Method createFromFamiliesWithDefault;
         try {
-            fontFamilyClass = Class.forName(FONT_FAMILY_CLASS);
-            fontFamilyCtor = fontFamilyClass.getConstructor();
-            addFontMethod = fontFamilyClass.getMethod(ADD_FONT_FROM_ASSET_MANAGER_METHOD,
-                    AssetManager.class, String.class, Integer.TYPE, Boolean.TYPE, Integer.TYPE,
-                    Integer.TYPE, Integer.TYPE, FontVariationAxis[].class);
-            addFromBufferMethod = fontFamilyClass.getMethod(ADD_FONT_FROM_BUFFER_METHOD,
-                    ByteBuffer.class, Integer.TYPE, FontVariationAxis[].class, Integer.TYPE,
-                    Integer.TYPE);
-            freezeMethod = fontFamilyClass.getMethod(FREEZE_METHOD);
-            abortCreationMethod = fontFamilyClass.getMethod(ABORT_CREATION_METHOD);
-            Object familyArray = Array.newInstance(fontFamilyClass, 1);
-            createFromFamiliesWithDefaultMethod =
-                    Typeface.class.getDeclaredMethod(CREATE_FROM_FAMILIES_WITH_DEFAULT_METHOD,
-                            familyArray.getClass(), Integer.TYPE, Integer.TYPE);
-            createFromFamiliesWithDefaultMethod.setAccessible(true);
+            fontFamily = obtainFontFamily();
+            fontFamilyCtor = obtainFontFamilyCtor(fontFamily);
+            addFontFromAssetManager = obtainAddFontFromAssetManagerMethod(fontFamily);
+            addFontFromBuffer = obtainAddFontFromBufferMethod(fontFamily);
+            freeze = obtainFreezeMethod(fontFamily);
+            abortCreation = obtainAbortCreationMethod(fontFamily);
+            createFromFamiliesWithDefault = obtainCreateFromFamiliesWithDefaultMethod(fontFamily);
         } catch (ClassNotFoundException | NoSuchMethodException e) {
             Log.e(TAG, "Unable to collect necessary methods for class " + e.getClass().getName(),
                     e);
-            fontFamilyClass = null;
+            fontFamily = null;
             fontFamilyCtor = null;
-            addFontMethod = null;
-            addFromBufferMethod = null;
-            freezeMethod = null;
-            abortCreationMethod = null;
-            createFromFamiliesWithDefaultMethod = null;
+            addFontFromAssetManager = null;
+            addFontFromBuffer = null;
+            freeze = null;
+            abortCreation = null;
+            createFromFamiliesWithDefault = null;
         }
-        sFontFamilyCtor = fontFamilyCtor;
-        sFontFamily = fontFamilyClass;
-        sAddFontFromAssetManager = addFontMethod;
-        sAddFontFromBuffer = addFromBufferMethod;
-        sFreeze = freezeMethod;
-        sAbortCreation = abortCreationMethod;
-        sCreateFromFamiliesWithDefault = createFromFamiliesWithDefaultMethod;
+        mFontFamily = fontFamily;
+        mFontFamilyCtor = fontFamilyCtor;
+        mAddFontFromAssetManager = addFontFromAssetManager;
+        mAddFontFromBuffer = addFontFromBuffer;
+        mFreeze = freeze;
+        mAbortCreation = abortCreation;
+        mCreateFromFamiliesWithDefault = createFromFamiliesWithDefault;
     }
 
     /**
-     * Returns true if API26 implementation is usable.
+     * Returns true if all the necessary methods were found.
      */
-    private static boolean isFontFamilyPrivateAPIAvailable() {
-        if (sAddFontFromAssetManager == null) {
+    private boolean isFontFamilyPrivateAPIAvailable() {
+        if (mAddFontFromAssetManager == null) {
             Log.w(TAG, "Unable to collect necessary private methods. "
                     + "Fallback to legacy implementation.");
         }
-        return sAddFontFromAssetManager != null;
+        return mAddFontFromAssetManager != null;
     }
 
     /**
      * Create a new FontFamily instance
      */
-    private static Object newFamily() {
+    private Object newFamily() {
         try {
-            return sFontFamilyCtor.newInstance();
+            return mFontFamilyCtor.newInstance();
         } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
             throw new RuntimeException(e);
         }
@@ -139,12 +133,12 @@
      * Call FontFamily#addFontFromAssetManager(AssetManager mgr, String path, int cookie,
      *      boolean isAsset, int ttcIndex, int weight, int isItalic, FontVariationAxis[] axes)
      */
-    private static boolean addFontFromAssetManager(Context context, Object family, String fileName,
-            int ttcIndex, int weight, int style) {
+    private boolean addFontFromAssetManager(Context context, Object family, String fileName,
+            int ttcIndex, int weight, int style, @Nullable FontVariationAxis[] axes) {
         try {
-            final Boolean result = (Boolean) sAddFontFromAssetManager.invoke(family,
+            final Boolean result = (Boolean) mAddFontFromAssetManager.invoke(family,
                     context.getAssets(), fileName, 0 /* cookie */, false /* isAsset */, ttcIndex,
-                    weight, style, null /* axes */);
+                    weight, style, axes);
             return result.booleanValue();
         } catch (IllegalAccessException | InvocationTargetException e) {
             throw new RuntimeException(e);
@@ -155,10 +149,10 @@
      * Call FontFamily#addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes,
      *      int weight, int italic)
      */
-    private static boolean addFontFromBuffer(Object family, ByteBuffer buffer,
+    private boolean addFontFromBuffer(Object family, ByteBuffer buffer,
             int ttcIndex, int weight, int style) {
         try {
-            final Boolean result = (Boolean) sAddFontFromBuffer.invoke(family,
+            final Boolean result = (Boolean) mAddFontFromBuffer.invoke(family,
                     buffer, ttcIndex, null /* axes */, weight, style);
             return result.booleanValue();
         } catch (IllegalAccessException | InvocationTargetException e) {
@@ -167,14 +161,14 @@
     }
 
     /**
-     * Call static method Typeface#createFromFamiliesWithDefault(
+     * Call method Typeface#createFromFamiliesWithDefault(
      *      FontFamily[] families, int weight, int italic)
      */
-    private static Typeface createFromFamiliesWithDefault(Object family) {
+    protected Typeface createFromFamiliesWithDefault(Object family) {
         try {
-            Object familyArray = Array.newInstance(sFontFamily, 1);
+            Object familyArray = Array.newInstance(mFontFamily, 1);
             Array.set(familyArray, 0, family);
-            return (Typeface) sCreateFromFamiliesWithDefault.invoke(null /* static method */,
+            return (Typeface) mCreateFromFamiliesWithDefault.invoke(null /* static method */,
                     familyArray, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
         } catch (IllegalAccessException | InvocationTargetException e) {
             throw new RuntimeException(e);
@@ -184,9 +178,9 @@
     /**
      * Call FontFamily#freeze()
      */
-    private static boolean freeze(Object family) {
+    private boolean freeze(Object family) {
         try {
-            Boolean result = (Boolean) sFreeze.invoke(family);
+            Boolean result = (Boolean) mFreeze.invoke(family);
             return result.booleanValue();
         } catch (IllegalAccessException | InvocationTargetException e) {
             throw new RuntimeException(e);
@@ -196,9 +190,9 @@
     /**
      * Call FontFamily#abortCreation()
      */
-    private static void abortCreation(Object family) {
+    private void abortCreation(Object family) {
         try {
-            sAbortCreation.invoke(family);
+            mAbortCreation.invoke(family);
         } catch (IllegalAccessException | InvocationTargetException e) {
             throw new RuntimeException(e);
         }
@@ -213,9 +207,9 @@
         }
         Object fontFamily = newFamily();
         for (final FontFileResourceEntry fontFile : entry.getEntries()) {
-            // TODO: Add ttc and variation font support. (b/37853920)
             if (!addFontFromAssetManager(context, fontFamily, fontFile.getFileName(),
-                    0 /* ttcIndex */, fontFile.getWeight(), fontFile.isItalic() ? 1 : 0)) {
+                    fontFile.getTtcIndex(), fontFile.getWeight(), fontFile.isItalic() ? 1 : 0,
+                    FontVariationAxis.fromFontVariationSettings(fontFile.getVariationSettings()))) {
                 abortCreation(fontFamily);
                 return null;
             }
@@ -292,7 +286,7 @@
         Object fontFamily = newFamily();
         if (!addFontFromAssetManager(context, fontFamily, path,
                 0 /* ttcIndex */, RESOLVE_BY_FONT_TABLE /* weight */,
-                RESOLVE_BY_FONT_TABLE /* italic */)) {
+                RESOLVE_BY_FONT_TABLE /* italic */, null /* axes */)) {
             abortCreation(fontFamily);
             return null;
         }
@@ -301,4 +295,47 @@
         }
         return createFromFamiliesWithDefault(fontFamily);
     }
+
+    // The following getters retrieve by reflection the Typeface methods, belonging to the
+    // framework code, which will be invoked. Since the definitions of these methods can change
+    // across different API versions, inheriting classes should override these getters in order to
+    // reflect the method definitions in the API versions they represent.
+    //===========================================================================================
+    protected Class obtainFontFamily() throws ClassNotFoundException {
+        return Class.forName(FONT_FAMILY_CLASS);
+    }
+
+    protected Constructor obtainFontFamilyCtor(Class fontFamily) throws NoSuchMethodException {
+        return fontFamily.getConstructor();
+    }
+
+    protected Method obtainAddFontFromAssetManagerMethod(Class fontFamily)
+            throws NoSuchMethodException {
+        return fontFamily.getMethod(ADD_FONT_FROM_ASSET_MANAGER_METHOD,
+                AssetManager.class, String.class, Integer.TYPE, Boolean.TYPE, Integer.TYPE,
+                Integer.TYPE, Integer.TYPE, FontVariationAxis[].class);
+    }
+
+    protected Method obtainAddFontFromBufferMethod(Class fontFamily) throws NoSuchMethodException {
+        return fontFamily.getMethod(ADD_FONT_FROM_BUFFER_METHOD,
+                ByteBuffer.class, Integer.TYPE, FontVariationAxis[].class, Integer.TYPE,
+                Integer.TYPE);
+    }
+
+    protected Method obtainFreezeMethod(Class fontFamily) throws NoSuchMethodException {
+        return fontFamily.getMethod(FREEZE_METHOD);
+    }
+
+    protected Method obtainAbortCreationMethod(Class fontFamily) throws NoSuchMethodException {
+        return fontFamily.getMethod(ABORT_CREATION_METHOD);
+    }
+
+    protected Method obtainCreateFromFamiliesWithDefaultMethod(Class fontFamily)
+            throws NoSuchMethodException {
+        Object familyArray = Array.newInstance(fontFamily, 1);
+        Method m =  Typeface.class.getDeclaredMethod(CREATE_FROM_FAMILIES_WITH_DEFAULT_METHOD,
+                familyArray.getClass(), Integer.TYPE, Integer.TYPE);
+        m.setAccessible(true);
+        return m;
+    }
 }
diff --git a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi28Impl.java b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi28Impl.java
new file mode 100644
index 0000000..baa2ce6
--- /dev/null
+++ b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi28Impl.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 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.graphics;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.graphics.Typeface;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.RestrictTo;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Implementation of the Typeface compat methods for API 28 and above.
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+@RequiresApi(28)
+public class TypefaceCompatApi28Impl extends TypefaceCompatApi26Impl {
+    private static final String TAG = "TypefaceCompatApi28Impl";
+
+    private static final String CREATE_FROM_FAMILIES_WITH_DEFAULT_METHOD =
+            "createFromFamiliesWithDefault";
+    private static final int RESOLVE_BY_FONT_TABLE = -1;
+    private static final String DEFAULT_FAMILY = "sans-serif";
+
+    /**
+     * Call method Typeface#createFromFamiliesWithDefault(
+     *      FontFamily[] families, String fallbackName, int weight, int italic)
+     */
+    @Override
+    protected Typeface createFromFamiliesWithDefault(Object family) {
+        try {
+            Object familyArray = Array.newInstance(mFontFamily, 1);
+            Array.set(familyArray, 0, family);
+            return (Typeface) mCreateFromFamiliesWithDefault.invoke(null /* static method */,
+                    familyArray, DEFAULT_FAMILY, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    protected Method obtainCreateFromFamiliesWithDefaultMethod(Class fontFamily)
+            throws NoSuchMethodException {
+        Object familyArray = Array.newInstance(fontFamily, 1);
+        Method m =  Typeface.class.getDeclaredMethod(CREATE_FROM_FAMILIES_WITH_DEFAULT_METHOD,
+                familyArray.getClass(), String.class, Integer.TYPE, Integer.TYPE);
+        m.setAccessible(true);
+        return m;
+    }
+}
diff --git a/compat/src/main/java/android/support/v4/util/ArraySet.java b/compat/src/main/java/android/support/v4/util/ArraySet.java
index a9a8806..ab080fa 100644
--- a/compat/src/main/java/android/support/v4/util/ArraySet.java
+++ b/compat/src/main/java/android/support/v4/util/ArraySet.java
@@ -16,6 +16,9 @@
 
 package android.support.v4.util;
 
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.support.annotation.RestrictTo;
 import android.util.Log;
 
 import java.lang.reflect.Array;
@@ -71,6 +74,7 @@
     static Object[] sTwiceBaseCache;
     static int sTwiceBaseCacheSize;
 
+    final boolean mIdentityHashCode;
     int[] mHashes;
     Object[] mArray;
     int mSize;
@@ -234,13 +238,19 @@
      * will grow once items are added to it.
      */
     public ArraySet() {
-        this(0);
+        this(0, false);
     }
 
     /**
      * Create a new ArraySet with a given initial capacity.
      */
     public ArraySet(int capacity) {
+        this(capacity, false);
+    }
+
+    /** {@hide} */
+    public ArraySet(int capacity, boolean identityHashCode) {
+        mIdentityHashCode = identityHashCode;
         if (capacity == 0) {
             mHashes = INT;
             mArray = OBJECT;
@@ -260,6 +270,14 @@
         }
     }
 
+    /** {@hide} */
+    public ArraySet(Collection<E> set) {
+        this();
+        if (set != null) {
+            addAll(set);
+        }
+    }
+
     /**
      * Make the array map empty.  All storage is released.
      */
@@ -308,7 +326,8 @@
      * @return Returns the index of the value if it exists, else a negative integer.
      */
     public int indexOf(Object key) {
-        return key == null ? indexOfNull() : indexOf(key, key.hashCode());
+        return key == null ? indexOfNull()
+                : indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
     }
 
     /**
@@ -345,7 +364,7 @@
             hash = 0;
             index = indexOfNull();
         } else {
-            hash = value.hashCode();
+            hash = mIdentityHashCode ? System.identityHashCode(value) : value.hashCode();
             index = indexOf(value, hash);
         }
         if (index >= 0) {
@@ -387,6 +406,36 @@
     }
 
     /**
+     * Special fast path for appending items to the end of the array without validation.
+     * The array must already be large enough to contain the item.
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    public void append(E value) {
+        final int index = mSize;
+        final int hash = value == null ? 0
+                : (mIdentityHashCode ? System.identityHashCode(value) : value.hashCode());
+        if (index >= mHashes.length) {
+            throw new IllegalStateException("Array is full");
+        }
+        if (index > 0 && mHashes[index - 1] > hash) {
+            // Cannot optimize since it would break the sorted order - fallback to add()
+            if (DEBUG) {
+                RuntimeException e = new RuntimeException("here");
+                e.fillInStackTrace();
+                Log.w(TAG, "New hash " + hash
+                        + " is before end of array hash " + mHashes[index - 1]
+                        + " at index " + index, e);
+            }
+            add(value);
+            return;
+        }
+        mSize = index + 1;
+        mHashes[index] = hash;
+        mArray[index] = value;
+    }
+
+    /**
      * Perform a {@link #add(Object)} of all values in <var>array</var>
      * @param array The array whose contents are to be retrieved.
      */
diff --git a/compat/tests/java/android/support/v4/content/res/FontResourcesParserCompatTest.java b/compat/tests/java/android/support/v4/content/res/FontResourcesParserCompatTest.java
index 6120eed..f503d99 100644
--- a/compat/tests/java/android/support/v4/content/res/FontResourcesParserCompatTest.java
+++ b/compat/tests/java/android/support/v4/content/res/FontResourcesParserCompatTest.java
@@ -63,7 +63,7 @@
     @Test
     public void testParse() throws XmlPullParserException, IOException {
         @SuppressLint("ResourceType")
-        XmlResourceParser parser = mResources.getXml(R.font.samplexmlfont);
+        XmlResourceParser parser = mResources.getXml(R.font.samplexmlfontforparsing);
 
         FamilyResourceEntry result = FontResourcesParserCompat.parse(parser, mResources);
 
@@ -74,18 +74,26 @@
         FontFileResourceEntry font1 = fileEntries[0];
         assertEquals(400, font1.getWeight());
         assertEquals(false, font1.isItalic());
+        assertEquals("'wdth' 0.8", font1.getVariationSettings());
+        assertEquals(0, font1.getTtcIndex());
         assertEquals(R.font.samplefont, font1.getResourceId());
         FontFileResourceEntry font2 = fileEntries[1];
         assertEquals(400, font2.getWeight());
         assertEquals(true, font2.isItalic());
+        assertEquals("'contrast' 0.5", font2.getVariationSettings());
+        assertEquals(1, font2.getTtcIndex());
         assertEquals(R.font.samplefont2, font2.getResourceId());
         FontFileResourceEntry font3 = fileEntries[2];
         assertEquals(700, font3.getWeight());
         assertEquals(false, font3.isItalic());
+        assertEquals("'wdth' 500.0, 'wght' 300.0", font3.getVariationSettings());
+        assertEquals(2, font3.getTtcIndex());
         assertEquals(R.font.samplefont3, font3.getResourceId());
         FontFileResourceEntry font4 = fileEntries[3];
         assertEquals(700, font4.getWeight());
         assertEquals(true, font4.isItalic());
+        assertEquals(null, font4.getVariationSettings());
+        assertEquals(0, font4.getTtcIndex());
         assertEquals(R.font.samplefont4, font4.getResourceId());
     }
 
@@ -98,7 +106,7 @@
         }
 
         @SuppressLint("ResourceType")
-        XmlResourceParser parser = mResources.getXml(R.font.samplexmlfont2);
+        XmlResourceParser parser = mResources.getXml(R.font.samplexmlfontforparsing2);
 
         FamilyResourceEntry result = FontResourcesParserCompat.parse(parser, mResources);
 
@@ -109,18 +117,26 @@
         FontFileResourceEntry font1 = fileEntries[0];
         assertEquals(400, font1.getWeight());
         assertEquals(false, font1.isItalic());
+        assertEquals("'wdth' 0.8", font1.getVariationSettings());
+        assertEquals(0, font1.getTtcIndex());
         assertEquals(R.font.samplefont, font1.getResourceId());
         FontFileResourceEntry font2 = fileEntries[1];
         assertEquals(400, font2.getWeight());
         assertEquals(true, font2.isItalic());
+        assertEquals("'contrast' 0.5", font2.getVariationSettings());
+        assertEquals(1, font2.getTtcIndex());
         assertEquals(R.font.samplefont2, font2.getResourceId());
         FontFileResourceEntry font3 = fileEntries[2];
         assertEquals(700, font3.getWeight());
         assertEquals(false, font3.isItalic());
+        assertEquals("'wdth' 500.0, 'wght' 300.0", font3.getVariationSettings());
+        assertEquals(2, font3.getTtcIndex());
         assertEquals(R.font.samplefont3, font3.getResourceId());
         FontFileResourceEntry font4 = fileEntries[3];
         assertEquals(700, font4.getWeight());
         assertEquals(true, font4.isItalic());
+        assertEquals(null, font4.getVariationSettings());
+        assertEquals(0, font4.getTtcIndex());
         assertEquals(R.font.samplefont4, font4.getResourceId());
     }
 
diff --git a/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java b/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java
index dff4c33..9c27966 100644
--- a/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java
+++ b/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java
@@ -31,6 +31,7 @@
 import android.content.res.Resources;
 import android.graphics.Paint;
 import android.graphics.Typeface;
+import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.compat.test.R;
 import android.support.test.InstrumentationRegistry;
@@ -356,6 +357,81 @@
         assertEquals(R.font.large_d, getSelectedFontResourceId(typeface));
     }
 
+    private Typeface getLargerTypeface(String text, Typeface typeface1, Typeface typeface2) {
+        Paint p1 = new Paint();
+        p1.setTypeface(typeface1);
+        float width1 = p1.measureText(text);
+        Paint p2 = new Paint();
+        p2.setTypeface(typeface2);
+        float width2 = p2.measureText(text);
+
+        if (width1 > width2) {
+            return typeface1;
+        } else if (width1 < width2) {
+            return typeface2;
+        } else {
+            assertTrue(false);
+            return null;
+        }
+    }
+
+    @Test
+    public void testCreateFromResourcesFamilyXml_resourceTtcFont() throws Exception {
+        // Here we test that building typefaces by indexing in font collections works correctly.
+        // We want to ensure that the built typefaces correspond to the fonts with the right index.
+        // sample_font_collection.ttc contains two fonts (with indices 0 and 1). The first one has
+        // glyph "a" of 3em width, and all the other glyphs 1em. The second one has glyph "b" of
+        // 3em width, and all the other glyphs 1em. Hence, we can compare the width of these
+        // glyphs to assert that ttc indexing works.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+            // Creating typefaces with ttc index was only supported in the API starting with N.
+            return;
+        }
+        final FamilyResourceEntry entry1 = FontResourcesParserCompat.parse(
+                mResources.getXml(R.font.ttctestfont1), mResources);
+        Typeface typeface1 = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry1,
+                mResources, R.font.ttctestfont1, Typeface.NORMAL, null /* callback */,
+                null /*handler */, false /* isXmlRequest */);
+        assertNotNull(typeface1);
+        final FamilyResourceEntry entry2 = FontResourcesParserCompat.parse(
+                mResources.getXml(R.font.ttctestfont2), mResources);
+        Typeface typeface2 = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry2,
+                mResources, R.font.ttctestfont2, Typeface.NORMAL, null /* callback */,
+                null /*handler */, false /* isXmlRequest */);
+        assertNotNull(typeface2);
+
+        assertEquals(getLargerTypeface("a", typeface1, typeface2), typeface1);
+        assertEquals(getLargerTypeface("b", typeface1, typeface2), typeface2);
+    }
+
+    @Test
+    public void testCreateFromResourcesFamilyXml_resourceFontWithVariationSettings()
+            throws Exception {
+        // Here we test that specifying variation settings for fonts in XMLs works correctly.
+        // We build typefaces from two families containing one font each, using the same font
+        // resource, but having different values for the 'wdth' tag. Then we measure the painted
+        // text to ensure that the tag affects the text width. The font resource used supports
+        // the 'wdth' axis for the dash (-) character.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+            // Variation settings are only supported on O and newer.
+            return;
+        }
+        final FamilyResourceEntry entry1 = FontResourcesParserCompat.parse(
+                mResources.getXml(R.font.variationsettingstestfont1), mResources);
+        Typeface typeface1 = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry1,
+                mResources, R.font.variationsettingstestfont1, Typeface.NORMAL, null /* callback */,
+                null /*handler */, false /* isXmlRequest */);
+        assertNotNull(typeface1);
+        final FamilyResourceEntry entry2 = FontResourcesParserCompat.parse(
+                mResources.getXml(R.font.variationsettingstestfont2), mResources);
+        Typeface typeface2 = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry2,
+                mResources, R.font.variationsettingstestfont2, Typeface.NORMAL, null /* callback */,
+                null /*handler */, false /* isXmlRequest */);
+        assertNotNull(typeface2);
+
+        assertEquals(getLargerTypeface("-", typeface1, typeface2), typeface2);
+    }
+
     @Test
     public void testCreateFromResourcesFontFile() {
         Typeface typeface = TypefaceCompat.createFromResourcesFontFile(mContext, mResources,
diff --git a/compat/tests/res/font/sample_font_collection.ttc b/compat/tests/res/font/sample_font_collection.ttc
new file mode 100644
index 0000000..9252f3d
--- /dev/null
+++ b/compat/tests/res/font/sample_font_collection.ttc
Binary files differ
diff --git a/compat/tests/res/font/samplexmlfontforparsing.xml b/compat/tests/res/font/samplexmlfontforparsing.xml
new file mode 100644
index 0000000..a96385c
--- /dev/null
+++ b/compat/tests/res/font/samplexmlfontforparsing.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android"
+             xmlns:app="http://schemas.android.com/apk/res-auto">
+    <font app:fontStyle="normal" app:fontWeight="400" app:fontVariationSettings="'wdth' 0.8"
+          app:font="@font/samplefont" app:ttcIndex="0" />
+    <font app:fontStyle="italic" app:fontWeight="400" app:fontVariationSettings="'contrast' 0.5"
+          app:font="@font/samplefont2" app:ttcIndex="1" />
+    <font app:fontStyle="normal" app:fontWeight="700" app:fontVariationSettings="'wdth' 500.0, 'wght' 300.0"
+          app:font="@font/samplefont3" app:ttcIndex="2" />
+    <font app:fontStyle="italic" app:fontWeight="700" app:font="@font/samplefont4" />
+</font-family>
diff --git a/compat/tests/res/font/samplexmlfontforparsing2.xml b/compat/tests/res/font/samplexmlfontforparsing2.xml
new file mode 100644
index 0000000..eb310ba
--- /dev/null
+++ b/compat/tests/res/font/samplexmlfontforparsing2.xml
@@ -0,0 +1,26 @@
+<?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.
+  -->
+
+<font-family xmlns:android="http://schemas.android.com/apk/res/android" >
+    <font android:fontStyle="normal" android:fontWeight="400" android:fontVariationSettings="'wdth' 0.8"
+          android:font="@font/samplefont" android:ttcIndex="0" />
+    <font android:fontStyle="italic" android:fontWeight="400" android:fontVariationSettings="'contrast' 0.5"
+          android:font="@font/samplefont2" android:ttcIndex="1" />
+    <font android:fontStyle="normal" android:fontWeight="700" android:fontVariationSettings="'wdth' 500.0, 'wght' 300.0"
+          android:font="@font/samplefont3" android:ttcIndex="2" />
+    <font android:fontStyle="italic" android:fontWeight="700" android:font="@font/samplefont4" />
+</font-family>
diff --git a/compat/tests/res/font/ttctestfont1.xml b/compat/tests/res/font/ttctestfont1.xml
new file mode 100644
index 0000000..a2b75e3
--- /dev/null
+++ b/compat/tests/res/font/ttctestfont1.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
+    <font app:font="@font/sample_font_collection" app:ttcIndex="0" />
+</font-family>
diff --git a/compat/tests/res/font/ttctestfont2.xml b/compat/tests/res/font/ttctestfont2.xml
new file mode 100644
index 0000000..e64ed6a
--- /dev/null
+++ b/compat/tests/res/font/ttctestfont2.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
+    <font app:font="@font/sample_font_collection" app:ttcIndex="1" />
+</font-family>
diff --git a/compat/tests/res/font/variable_width_dash_font.ttf b/compat/tests/res/font/variable_width_dash_font.ttf
new file mode 100644
index 0000000..f7a256a
--- /dev/null
+++ b/compat/tests/res/font/variable_width_dash_font.ttf
Binary files differ
diff --git a/compat/tests/res/font/variationsettingstestfont1.xml b/compat/tests/res/font/variationsettingstestfont1.xml
new file mode 100644
index 0000000..39052a6
--- /dev/null
+++ b/compat/tests/res/font/variationsettingstestfont1.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
+    <font app:font="@font/variable_width_dash_font" app:fontVariationSettings="'wdth' 100.0" />
+</font-family>
diff --git a/compat/tests/res/font/variationsettingstestfont2.xml b/compat/tests/res/font/variationsettingstestfont2.xml
new file mode 100644
index 0000000..90382d0
--- /dev/null
+++ b/compat/tests/res/font/variationsettingstestfont2.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
+    <font app:font="@font/variable_width_dash_font" app:fontVariationSettings="'wdth' 500.0" />
+</font-family>
diff --git a/content/Android.mk b/content/Android.mk
index 32caf53..1eca4f5 100644
--- a/content/Android.mk
+++ b/content/Android.mk
@@ -20,9 +20,10 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-compat \
+LOCAL_JAVA_LIBRARIES := \
     android-support-annotations
+LOCAL_SHARED_ANDROID_LIBRARIES := \
+    android-support-compat
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/content/build.gradle b/content/build.gradle
index 9091053..cff7db7 100644
--- a/content/build.gradle
+++ b/content/build.gradle
@@ -31,12 +31,6 @@
     androidTestImplementation(ESPRESSO_CORE)
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-}
-
 supportLibrary {
     name = "Android Support Content"
     publish = true
diff --git a/core-ui/Android.mk b/core-ui/Android.mk
index 47846a9..1473381 100644
--- a/core-ui/Android.mk
+++ b/core-ui/Android.mk
@@ -28,11 +28,13 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-compat \
-    android-support-core-utils \
-    android-support-annotations
+    android-support-core-utils
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
+LOCAL_EXPORT_PROGUARD_FLAG_FILES := proguard-rules.pro
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/core-ui/build.gradle b/core-ui/build.gradle
index f7cd2d7..4ff27cb 100644
--- a/core-ui/build.gradle
+++ b/core-ui/build.gradle
@@ -23,17 +23,12 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.res.srcDirs = [
                 'res',
                 'res-public'
         ]
     }
-
     buildTypes.all {
         consumerProguardFiles 'proguard-rules.pro'
     }
diff --git a/core-ui/src/main/java/android/support/design/widget/CoordinatorLayout.java b/core-ui/src/main/java/android/support/design/widget/CoordinatorLayout.java
index c45810e..03cce02 100644
--- a/core-ui/src/main/java/android/support/design/widget/CoordinatorLayout.java
+++ b/core-ui/src/main/java/android/support/design/widget/CoordinatorLayout.java
@@ -400,6 +400,7 @@
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
             lp.resetTouchBehaviorTracking();
         }
+        mBehaviorTouchView = null;
         mDisallowInterceptReset = false;
     }
 
diff --git a/core-ui/src/main/java/android/support/v4/widget/NestedScrollView.java b/core-ui/src/main/java/android/support/v4/widget/NestedScrollView.java
index 73ff084..6fe1928 100644
--- a/core-ui/src/main/java/android/support/v4/widget/NestedScrollView.java
+++ b/core-ui/src/main/java/android/support/v4/widget/NestedScrollView.java
@@ -23,6 +23,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -1820,10 +1821,20 @@
             final int scrollY = getScrollY();
             if (!mEdgeGlowTop.isFinished()) {
                 final int restoreCount = canvas.save();
-                final int width = getWidth() - getPaddingLeft() - getPaddingRight();
-
-                canvas.translate(getPaddingLeft(), Math.min(0, scrollY));
-                mEdgeGlowTop.setSize(width, getHeight());
+                int width = getWidth();
+                int height = getHeight();
+                int xTranslation = 0;
+                int yTranslation = Math.min(0, scrollY);
+                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || getClipToPadding()) {
+                    width -= getPaddingLeft() + getPaddingRight();
+                    xTranslation += getPaddingLeft();
+                }
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && getClipToPadding()) {
+                    height -= getPaddingTop() + getPaddingBottom();
+                    yTranslation += getPaddingTop();
+                }
+                canvas.translate(xTranslation, yTranslation);
+                mEdgeGlowTop.setSize(width, height);
                 if (mEdgeGlowTop.draw(canvas)) {
                     ViewCompat.postInvalidateOnAnimation(this);
                 }
@@ -1831,11 +1842,19 @@
             }
             if (!mEdgeGlowBottom.isFinished()) {
                 final int restoreCount = canvas.save();
-                final int width = getWidth() - getPaddingLeft() - getPaddingRight();
-                final int height = getHeight();
-
-                canvas.translate(-width + getPaddingLeft(),
-                        Math.max(getScrollRange(), scrollY) + height);
+                int width = getWidth();
+                int height = getHeight();
+                int xTranslation = 0;
+                int yTranslation = Math.max(getScrollRange(), scrollY) + height;
+                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || getClipToPadding()) {
+                    width -= getPaddingLeft() + getPaddingRight();
+                    xTranslation += getPaddingLeft();
+                }
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && getClipToPadding()) {
+                    height -= getPaddingTop() + getPaddingBottom();
+                    yTranslation -= getPaddingBottom();
+                }
+                canvas.translate(xTranslation - width, yTranslation);
                 canvas.rotate(180, width, 0);
                 mEdgeGlowBottom.setSize(width, height);
                 if (mEdgeGlowBottom.draw(canvas)) {
diff --git a/core-utils/Android.mk b/core-utils/Android.mk
index 6dda862..751091b 100644
--- a/core-utils/Android.mk
+++ b/core-utils/Android.mk
@@ -31,9 +31,10 @@
     $(call all-java-files-under,api21) \
     $(call all-java-files-under,java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-compat \
+LOCAL_JAVA_LIBRARIES := \
     android-support-annotations
+LOCAL_SHARED_ANDROID_LIBRARIES := \
+    android-support-compat
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/core-utils/build.gradle b/core-utils/build.gradle
index 3f1efa1..75555c0 100644
--- a/core-utils/build.gradle
+++ b/core-utils/build.gradle
@@ -17,10 +17,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.java.srcDirs = [
                 'kitkat',
diff --git a/customtabs/Android.mk b/customtabs/Android.mk
index f9195e8..30132a1 100644
--- a/customtabs/Android.mk
+++ b/customtabs/Android.mk
@@ -31,8 +31,9 @@
     $(call all-java-files-under,src/main/java) \
     $(call all-Iaidl-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-annotations \
     android-support-compat
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/customtabs/build.gradle b/customtabs/build.gradle
index 75e28f7..cf1c775 100644
--- a/customtabs/build.gradle
+++ b/customtabs/build.gradle
@@ -16,10 +16,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion(15)
-    }
-
     sourceSets {
         main.aidl.srcDirs = ["src/main/java"]
     }
@@ -33,4 +29,5 @@
     inceptionYear = "2015"
     description = "Android Support Custom Tabs"
     legacySourceLocation = true
+    minSdkVersion = 15
 }
diff --git a/design/Android.mk b/design/Android.mk
index 4a51f77..f856de6 100644
--- a/design/Android.mk
+++ b/design/Android.mk
@@ -27,6 +27,7 @@
 # in their makefiles to include the resources and their dependencies in their package.
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
+LOCAL_AAPT2_ONLY := true
 LOCAL_MODULE := android-support-design
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := \
@@ -34,6 +35,8 @@
     $(call all-java-files-under,lollipop) \
     $(call all-java-files-under,src)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-transition \
     android-support-v7-appcompat \
@@ -42,10 +45,10 @@
     android-support-media-compat \
     android-support-core-utils \
     android-support-core-ui \
-    android-support-fragment \
-    android-support-annotations
+    android-support-fragment
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := \
     --no-version-vectors \
     --add-javadoc-annotation doconly
+LOCAL_EXPORT_PROGUARD_FLAG_FILES := proguard-rules.pro
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/design/api/27.0.0-SNAPSHOT.ignore b/design/api/27.0.0-SNAPSHOT.ignore
new file mode 100644
index 0000000..533cc49
--- /dev/null
+++ b/design/api/27.0.0-SNAPSHOT.ignore
@@ -0,0 +1,5 @@
+197ce1d
+88bc57e
+9761c3e
+86b38bf
+c6abd5e
diff --git a/design/build.gradle b/design/build.gradle
index e7ebc91..baa94ea 100644
--- a/design/build.gradle
+++ b/design/build.gradle
@@ -22,7 +22,6 @@
 
 android {
     defaultConfig {
-        minSdkVersion 14
         // This disables the builds tools automatic vector -> PNG generation
         generatedDensities = []
     }
diff --git a/dynamic-animation/Android.mk b/dynamic-animation/Android.mk
index 11aa484..98e8f45 100644
--- a/dynamic-animation/Android.mk
+++ b/dynamic-animation/Android.mk
@@ -20,9 +20,10 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-compat \
+LOCAL_JAVA_LIBRARIES := \
     android-support-annotations
+LOCAL_SHARED_ANDROID_LIBRARIES := \
+    android-support-compat
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/dynamic-animation/build.gradle b/dynamic-animation/build.gradle
index ac5623d..10e49e0 100644
--- a/dynamic-animation/build.gradle
+++ b/dynamic-animation/build.gradle
@@ -15,12 +15,6 @@
     androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-}
-
 supportLibrary {
     name = "Android Support DynamicAnimation"
     publish = true
diff --git a/emoji/appcompat/Android.mk b/emoji/appcompat/Android.mk
index f04d158..0ef8cb7 100644
--- a/emoji/appcompat/Android.mk
+++ b/emoji/appcompat/Android.mk
@@ -30,8 +30,9 @@
 LOCAL_MODULE := android-support-emoji-appcompat
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-annotations \
     android-support-v7-appcompat \
     android-support-emoji \
     android-support-compat
diff --git a/emoji/appcompat/build.gradle b/emoji/appcompat/build.gradle
index 3fe04d8..a4aaff2 100644
--- a/emoji/appcompat/build.gradle
+++ b/emoji/appcompat/build.gradle
@@ -22,17 +22,10 @@
 }
 
 dependencies {
-    api fileTree(include: ['*.jar'], dir: 'libs')
     api(project(":support-emoji"))
     api(project(":appcompat-v7"))
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-}
-
 supportLibrary {
     name = "Android Emoji AppCompat"
     publish = true
diff --git a/emoji/bundled/Android.mk b/emoji/bundled/Android.mk
index 29f0d58..c5c1ac9 100644
--- a/emoji/bundled/Android.mk
+++ b/emoji/bundled/Android.mk
@@ -29,8 +29,9 @@
 LOCAL_MODULE := android-support-emoji-bundled
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-annotations \
     android-support-emoji \
     android-support-compat
 LOCAL_JAR_EXCLUDE_FILES := none
diff --git a/emoji/bundled/build.gradle b/emoji/bundled/build.gradle
index 013ab85..a2760d3 100644
--- a/emoji/bundled/build.gradle
+++ b/emoji/bundled/build.gradle
@@ -10,10 +10,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.assets.srcDirs new File(fontDir, "font").getAbsolutePath()
     }
diff --git a/emoji/core/Android.mk b/emoji/core/Android.mk
index 8b7a032..89426f0 100644
--- a/emoji/core/Android.mk
+++ b/emoji/core/Android.mk
@@ -31,8 +31,9 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/src/main/res
 LOCAL_STATIC_JAVA_LIBRARIES := \
     noto-emoji-compat-java
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-annotations \
     android-support-compat
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
diff --git a/emoji/core/api/current.txt b/emoji/core/api/current.txt
index d5ce666..40bd7d8 100644
--- a/emoji/core/api/current.txt
+++ b/emoji/core/api/current.txt
@@ -32,6 +32,8 @@
     method public android.support.text.emoji.EmojiCompat.Config setEmojiSpanIndicatorColor(int);
     method public android.support.text.emoji.EmojiCompat.Config setEmojiSpanIndicatorEnabled(boolean);
     method public android.support.text.emoji.EmojiCompat.Config setReplaceAll(boolean);
+    method public android.support.text.emoji.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean);
+    method public android.support.text.emoji.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean, java.util.List<java.lang.Integer>);
     method public android.support.text.emoji.EmojiCompat.Config unregisterInitCallback(android.support.text.emoji.EmojiCompat.InitCallback);
   }
 
diff --git a/emoji/core/build.gradle b/emoji/core/build.gradle
index a311f25..8d470f0 100644
--- a/emoji/core/build.gradle
+++ b/emoji/core/build.gradle
@@ -32,10 +32,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main {
             // We use a non-standard manifest path.
diff --git a/emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java
index 5436aa2..413a9dd 100644
--- a/emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java
+++ b/emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java
@@ -184,6 +184,16 @@
     private final boolean mReplaceAll;
 
     /**
+     * @see Config#setUseEmojiAsDefaultStyle(boolean)
+     */
+    private final boolean mUseEmojiAsDefaultStyle;
+
+    /**
+     * @see Config#setUseEmojiAsDefaultStyle(boolean, List)
+     */
+    private final int[] mEmojiAsDefaultStyleExceptions;
+
+    /**
      * @see Config#setEmojiSpanIndicatorEnabled(boolean)
      */
     private final boolean mEmojiSpanIndicatorEnabled;
@@ -201,6 +211,8 @@
     private EmojiCompat(@NonNull final Config config) {
         mInitLock = new ReentrantReadWriteLock();
         mReplaceAll = config.mReplaceAll;
+        mUseEmojiAsDefaultStyle = config.mUseEmojiAsDefaultStyle;
+        mEmojiAsDefaultStyleExceptions = config.mEmojiAsDefaultStyleExceptions;
         mEmojiSpanIndicatorEnabled = config.mEmojiSpanIndicatorEnabled;
         mEmojiSpanIndicatorColor = config.mEmojiSpanIndicatorColor;
         mMetadataLoader = config.mMetadataLoader;
@@ -787,6 +799,8 @@
     public abstract static class Config {
         private final MetadataRepoLoader mMetadataLoader;
         private boolean mReplaceAll;
+        private boolean mUseEmojiAsDefaultStyle;
+        private int[] mEmojiAsDefaultStyleExceptions;
         private Set<InitCallback> mInitCallbacks;
         private boolean mEmojiSpanIndicatorEnabled;
         private int mEmojiSpanIndicatorColor = Color.GREEN;
@@ -849,6 +863,56 @@
         }
 
         /**
+         * Determines whether EmojiCompat should use the emoji presentation style for emojis
+         * that have text style as default. By default, the text style would be used, unless these
+         * are followed by the U+FE0F variation selector.
+         * Details about emoji presentation and text presentation styles can be found here:
+         * http://unicode.org/reports/tr51/#Presentation_Style
+         * If useEmojiAsDefaultStyle is true, the emoji presentation style will be used for all
+         * emojis, including potentially unexpected ones (such as digits or other keycap emojis). If
+         * this is not the expected behaviour, method
+         * {@link #setUseEmojiAsDefaultStyle(boolean, List)} can be used to specify the
+         * exception emojis that should be still presented as text style.
+         *
+         * @param useEmojiAsDefaultStyle whether to use the emoji style presentation for all emojis
+         *                               that would be presented as text style by default
+         */
+        public Config setUseEmojiAsDefaultStyle(final boolean useEmojiAsDefaultStyle) {
+            return setUseEmojiAsDefaultStyle(useEmojiAsDefaultStyle, null);
+        }
+
+        /**
+         * @see #setUseEmojiAsDefaultStyle(boolean)
+         *
+         * @param emojiAsDefaultStyleExceptions Contains the exception emojis which will be still
+         *                                      presented as text style even if the
+         *                                      useEmojiAsDefaultStyle flag is set to {@code true}.
+         *                                      This list will be ignored if useEmojiAsDefaultStyle
+         *                                      is {@code false}. Note that emojis with default
+         *                                      emoji style presentation will remain emoji style
+         *                                      regardless the value of useEmojiAsDefaultStyle or
+         *                                      whether they are included in the exceptions list or
+         *                                      not. When no exception is wanted, the method
+         *                                      {@link #setUseEmojiAsDefaultStyle(boolean)} should
+         *                                      be used instead.
+         */
+        public Config setUseEmojiAsDefaultStyle(final boolean useEmojiAsDefaultStyle,
+                @Nullable final List<Integer> emojiAsDefaultStyleExceptions) {
+            mUseEmojiAsDefaultStyle = useEmojiAsDefaultStyle;
+            if (mUseEmojiAsDefaultStyle && emojiAsDefaultStyleExceptions != null) {
+                mEmojiAsDefaultStyleExceptions = new int[emojiAsDefaultStyleExceptions.size()];
+                int i = 0;
+                for (Integer exception : emojiAsDefaultStyleExceptions) {
+                    mEmojiAsDefaultStyleExceptions[i++] = exception;
+                }
+                Arrays.sort(mEmojiAsDefaultStyleExceptions);
+            } else {
+                mEmojiAsDefaultStyleExceptions = null;
+            }
+            return this;
+        }
+
+        /**
          * Determines whether a background will be drawn for the emojis that are found and
          * replaced by EmojiCompat. Should be used only for debugging purposes. The indicator color
          * can be set using {@link #setEmojiSpanIndicatorColor(int)}.
@@ -1020,7 +1084,9 @@
             }
 
             mMetadataRepo = metadataRepo;
-            mProcessor = new EmojiProcessor(mMetadataRepo, new SpanFactory());
+            mProcessor = new EmojiProcessor(mMetadataRepo, new SpanFactory(),
+                    mEmojiCompat.mUseEmojiAsDefaultStyle,
+                    mEmojiCompat.mEmojiAsDefaultStyleExceptions);
 
             mEmojiCompat.onMetadataLoadSuccess();
         }
diff --git a/emoji/core/src/main/java/android/support/text/emoji/EmojiProcessor.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiProcessor.java
index 3feb36d..f711704 100644
--- a/emoji/core/src/main/java/android/support/text/emoji/EmojiProcessor.java
+++ b/emoji/core/src/main/java/android/support/text/emoji/EmojiProcessor.java
@@ -22,6 +22,7 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.IntRange;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
 import android.support.text.emoji.widget.SpannableBuilder;
@@ -40,6 +41,8 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Processes the CharSequence and adds the emojis.
@@ -90,14 +93,29 @@
      */
     private GlyphChecker mGlyphChecker = new GlyphChecker();
 
+    /**
+     * @see EmojiCompat.Config#setUseEmojiAsDefaultStyle(boolean)
+     */
+    private final boolean mUseEmojiAsDefaultStyle;
+
+    /**
+     * @see EmojiCompat.Config#setUseEmojiAsDefaultStyle(boolean, List)
+     */
+    private final int[] mEmojiAsDefaultStyleExceptions;
+
     EmojiProcessor(@NonNull final MetadataRepo metadataRepo,
-            @NonNull final EmojiCompat.SpanFactory spanFactory) {
+            @NonNull final EmojiCompat.SpanFactory spanFactory,
+            final boolean useEmojiAsDefaultStyle,
+            @Nullable final int[] emojiAsDefaultStyleExceptions) {
         mSpanFactory = spanFactory;
         mMetadataRepo = metadataRepo;
+        mUseEmojiAsDefaultStyle = useEmojiAsDefaultStyle;
+        mEmojiAsDefaultStyleExceptions = emojiAsDefaultStyleExceptions;
     }
 
     EmojiMetadata getEmojiMetadata(@NonNull final CharSequence charSequence) {
-        final ProcessorSm sm = new ProcessorSm(mMetadataRepo.getRootNode());
+        final ProcessorSm sm = new ProcessorSm(mMetadataRepo.getRootNode(),
+                mUseEmojiAsDefaultStyle, mEmojiAsDefaultStyleExceptions);
         final int end = charSequence.length();
         int currentOffset = 0;
 
@@ -189,7 +207,8 @@
             }
             // add new ones
             int addedCount = 0;
-            final ProcessorSm sm = new ProcessorSm(mMetadataRepo.getRootNode());
+            final ProcessorSm sm = new ProcessorSm(mMetadataRepo.getRootNode(),
+                    mUseEmojiAsDefaultStyle, mEmojiAsDefaultStyleExceptions);
 
             int currentOffset = start;
             int codePoint = Character.codePointAt(charSequence, currentOffset);
@@ -483,9 +502,22 @@
          */
         private int mCurrentDepth;
 
-        ProcessorSm(MetadataRepo.Node rootNode) {
+        /**
+         * @see EmojiCompat.Config#setUseEmojiAsDefaultStyle(boolean)
+         */
+        private final boolean mUseEmojiAsDefaultStyle;
+
+        /**
+         * @see EmojiCompat.Config#setUseEmojiAsDefaultStyle(boolean, List)
+         */
+        private final int[] mEmojiAsDefaultStyleExceptions;
+
+        ProcessorSm(MetadataRepo.Node rootNode, boolean useEmojiAsDefaultStyle,
+                int[] emojiAsDefaultStyleExceptions) {
             mRootNode = rootNode;
             mCurrentNode = rootNode;
+            mUseEmojiAsDefaultStyle = useEmojiAsDefaultStyle;
+            mEmojiAsDefaultStyleExceptions = emojiAsDefaultStyleExceptions;
         }
 
         @Action
@@ -505,8 +537,7 @@
                             action = ACTION_ADVANCE_END;
                         } else if (mCurrentNode.getData() != null) {
                             if (mCurrentDepth == 1) {
-                                if (mCurrentNode.getData().isDefaultEmoji()
-                                        || isEmojiStyle(mLastCodepoint)) {
+                                if (shouldUseEmojiPresentationStyleForSingleCodepoint()) {
                                     mFlushNode = mCurrentNode;
                                     action = ACTION_FLUSH;
                                     reset();
@@ -571,9 +602,32 @@
          */
         boolean isInFlushableState() {
             return mState == STATE_WALKING && mCurrentNode.getData() != null
-                    && (mCurrentNode.getData().isDefaultEmoji()
-                    || isEmojiStyle(mLastCodepoint)
-                    || mCurrentDepth > 1);
+                    && (mCurrentDepth > 1 || shouldUseEmojiPresentationStyleForSingleCodepoint());
+        }
+
+        private boolean shouldUseEmojiPresentationStyleForSingleCodepoint() {
+            if (mCurrentNode.getData().isDefaultEmoji()) {
+                // The codepoint is emoji style by default.
+                return true;
+            }
+            if (isEmojiStyle(mLastCodepoint)) {
+                // The codepoint was followed by the emoji style variation selector.
+                return true;
+            }
+            if (mUseEmojiAsDefaultStyle) {
+                // Emoji presentation style for text style default emojis is enabled. We have
+                // to check that the current codepoint is not an exception.
+                if (mEmojiAsDefaultStyleExceptions == null) {
+                    return true;
+                }
+                final int codepoint = mCurrentNode.getData().getCodepointAt(0);
+                final int index = Arrays.binarySearch(mEmojiAsDefaultStyleExceptions, codepoint);
+                if (index < 0) {
+                    // Index is negative, so the codepoint was not found in the array of exceptions.
+                    return true;
+                }
+            }
+            return false;
         }
 
         /**
diff --git a/emoji/core/tests/java/android/support/text/emoji/EmojiCompatTest.java b/emoji/core/tests/java/android/support/text/emoji/EmojiCompatTest.java
index 0ce26e4..724f8a0 100644
--- a/emoji/core/tests/java/android/support/text/emoji/EmojiCompatTest.java
+++ b/emoji/core/tests/java/android/support/text/emoji/EmojiCompatTest.java
@@ -87,8 +87,10 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 @SmallTest
@@ -729,6 +731,58 @@
         assertFalse(EmojiCompat.handleOnKeyDown(editable, event.getKeyCode(), event));
     }
 
+    @Test
+    @SdkSuppress(minSdkVersion = 19)
+    public void testUseEmojiAsDefaultStyle_whenEmojiInTheMiddle() {
+        final Config config = new TestConfig().setReplaceAll(true);
+        EmojiCompat.reset(config);
+        String s = new TestString(0x0061, CHAR_DEFAULT_TEXT_STYLE, 0x0062).toString();
+        // no span should be added as the emoji is text style presented by default
+        assertThat(EmojiCompat.get().process(s), not(hasEmoji()));
+        // a span should be added when we use the emoji style presentation as default
+        EmojiCompat.reset(config.setUseEmojiAsDefaultStyle(true));
+        assertThat(EmojiCompat.get().process(s), hasEmojiAt(DEFAULT_TEXT_STYLE, 1, 2));
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = 19)
+    public void testUseEmojiAsDefaultStyle_whenEmojiAtTheEnd() {
+        final Config config = new TestConfig().setReplaceAll(true);
+        EmojiCompat.reset(config);
+        String s = new TestString(0x0061, CHAR_DEFAULT_TEXT_STYLE).toString();
+        // no span should be added as the emoji is text style presented by default
+        assertThat(EmojiCompat.get().process(s), not(hasEmoji()));
+        // a span should be added when we use the emoji style presentation as default
+        EmojiCompat.reset(config.setUseEmojiAsDefaultStyle(true));
+        assertThat(EmojiCompat.get().process(s), hasEmojiAt(DEFAULT_TEXT_STYLE, 1, 2));
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = 19)
+    public void testUseEmojiAsDefaultStyle_noEmojisAdded_whenMarkedAsException() {
+        final String s = new TestString(CHAR_DEFAULT_TEXT_STYLE).toString();
+        final List<Integer> exceptions =
+                Arrays.asList(CHAR_DEFAULT_TEXT_STYLE + 1, CHAR_DEFAULT_TEXT_STYLE);
+        final Config config = new TestConfig().setReplaceAll(true)
+                .setUseEmojiAsDefaultStyle(true, exceptions);
+        EmojiCompat.reset(config);
+        // no span should be added as the text style codepoint is marked as exception
+        assertThat(EmojiCompat.get().process(s), not(hasEmoji()));
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = 19)
+    public void testUseEmojiAsDefaultStyle_emojisAdded_whenNotMarkedAsException() {
+        final String s = new TestString(CHAR_DEFAULT_TEXT_STYLE).toString();
+        final List<Integer> exceptions =
+                Arrays.asList(CHAR_DEFAULT_TEXT_STYLE - 1, CHAR_DEFAULT_TEXT_STYLE + 1);
+        final Config config = new TestConfig().setReplaceAll(true)
+                .setUseEmojiAsDefaultStyle(true, exceptions);
+        EmojiCompat.reset(config);
+        // a span should be added as the codepoint is not included in the set of exceptions
+        assertThat(EmojiCompat.get().process(s), hasEmojiAt(DEFAULT_TEXT_STYLE, 0, 1));
+    }
+
     private void assertCodePointMatch(EmojiMapping emoji) {
         assertCodePointMatch(emoji.id(), emoji.codepoints());
     }
diff --git a/exifinterface/Android.mk b/exifinterface/Android.mk
index 4e5bdc0..1571116 100644
--- a/exifinterface/Android.mk
+++ b/exifinterface/Android.mk
@@ -25,7 +25,7 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := \
+LOCAL_JAVA_LIBRARIES := \
     android-support-annotations
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
diff --git a/exifinterface/build.gradle b/exifinterface/build.gradle
index fa4d7b4..67b458f 100644
--- a/exifinterface/build.gradle
+++ b/exifinterface/build.gradle
@@ -12,12 +12,6 @@
     androidTestImplementation(TEST_RUNNER)
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-}
-
 supportLibrary {
     name = "Android Support ExifInterface"
     publish = true
diff --git a/fragment/Android.mk b/fragment/Android.mk
index efac954..6513542 100644
--- a/fragment/Android.mk
+++ b/fragment/Android.mk
@@ -32,11 +32,12 @@
 LOCAL_SRC_FILES := \
     $(call all-java-files-under, src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-compat \
     android-support-core-ui \
-    android-support-core-utils \
-    android-support-annotations
+    android-support-core-utils
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/fragment/build.gradle b/fragment/build.gradle
index b1cc47e..d5371f5 100644
--- a/fragment/build.gradle
+++ b/fragment/build.gradle
@@ -21,12 +21,6 @@
     }
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-}
-
 supportLibrary {
     name = "Android Support Library fragment"
     publish = true
diff --git a/fragment/src/main/java/android/support/v4/app/Fragment.java b/fragment/src/main/java/android/support/v4/app/Fragment.java
index e734a27..5b560cd 100644
--- a/fragment/src/main/java/android/support/v4/app/Fragment.java
+++ b/fragment/src/main/java/android/support/v4/app/Fragment.java
@@ -1816,8 +1816,9 @@
      * use the same value as set in {@link #setEnterTransition(Object)}.
      *
      * @param transition The Transition to use to move Views out of the Scene when the Fragment
-     *                   is preparing to close. <code>transition</code> must be an
-     *                   android.transition.Transition.
+     *         is preparing to close. <code>transition</code> must be an
+     *         {@link android.transition.Transition android.transition.Transition} or
+     *         {@link android.support.transition.Transition android.support.transition.Transition}.
      */
     public void setReturnTransition(@Nullable Object transition) {
         ensureAnimationInfo().mReturnTransition = transition;
@@ -1854,8 +1855,10 @@
      * remain unaffected.
      *
      * @param transition The Transition to use to move Views out of the Scene when the Fragment
-     *                   is being closed not due to popping the back stack. <code>transition</code>
-     *                   must be an android.transition.Transition.
+     *          is being closed not due to popping the back stack. <code>transition</code>
+     *          must be an
+     *          {@link android.transition.Transition android.transition.Transition} or
+     *          {@link android.support.transition.Transition android.support.transition.Transition}.
      */
     public void setExitTransition(@Nullable Object transition) {
         ensureAnimationInfo().mExitTransition = transition;
@@ -1891,8 +1894,10 @@
      * transition as {@link #setExitTransition(Object)}.
      *
      * @param transition The Transition to use to move Views into the scene when reentering from a
-     *                   previously-started Activity. <code>transition</code>
-     *                   must be an android.transition.Transition.
+     *          previously-started Activity. <code>transition</code>
+     *          must be an
+     *          {@link android.transition.Transition android.transition.Transition} or
+     *          {@link android.support.transition.Transition android.support.transition.Transition}.
      */
     public void setReenterTransition(@Nullable Object transition) {
         ensureAnimationInfo().mReenterTransition = transition;
@@ -1925,7 +1930,9 @@
      * value will cause transferred shared elements to blink to the final position.
      *
      * @param transition The Transition to use for shared elements transferred into the content
-     *                   Scene.  <code>transition</code> must be an android.transition.Transition.
+     *          Scene.  <code>transition</code> must be an
+     *          {@link android.transition.Transition android.transition.Transition} or
+     *          {@link android.support.transition.Transition android.support.transition.Transition}.
      */
     public void setSharedElementEnterTransition(@Nullable Object transition) {
         ensureAnimationInfo().mSharedElementEnterTransition = transition;
@@ -1958,7 +1965,9 @@
      * {@link #setSharedElementEnterTransition(Object)}.
      *
      * @param transition The Transition to use for shared elements transferred out of the content
-     *                   Scene. <code>transition</code> must be an android.transition.Transition.
+     *          Scene. <code>transition</code> must be an
+     *          {@link android.transition.Transition android.transition.Transition} or
+     *          {@link android.support.transition.Transition android.support.transition.Transition}.
      */
     public void setSharedElementReturnTransition(@Nullable Object transition) {
         ensureAnimationInfo().mSharedElementReturnTransition = transition;
diff --git a/graphics/drawable/Android.mk b/graphics/drawable/Android.mk
index b1f0b38..6667dd9 100644
--- a/graphics/drawable/Android.mk
+++ b/graphics/drawable/Android.mk
@@ -26,9 +26,10 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, static/src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/static/res
 LOCAL_MANIFEST_FILE := static/AndroidManifest.xml
-LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-compat \
+LOCAL_JAVA_LIBRARIES := \
     android-support-annotations
+LOCAL_SHARED_ANDROID_LIBRARIES := \
+    android-support-compat
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
 include $(BUILD_STATIC_JAVA_LIBRARY)
@@ -45,10 +46,11 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, animated/src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/animated/res
 LOCAL_MANIFEST_FILE := animated/AndroidManifest.xml
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-compat \
     android-support-vectordrawable \
-    android-support-annotations \
     android-support-core-ui
 LOCAL_AAPT_FLAGS := --no-version-vectors --add-javadoc-annotation doconly
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
diff --git a/graphics/drawable/animated/build.gradle b/graphics/drawable/animated/build.gradle
index e76f846..30827a9 100644
--- a/graphics/drawable/animated/build.gradle
+++ b/graphics/drawable/animated/build.gradle
@@ -16,7 +16,6 @@
 
 android {
     defaultConfig {
-        minSdkVersion(14)
         // This disables the builds tools automatic vector -> PNG generation
         generatedDensities = []
     }
diff --git a/graphics/drawable/static/build.gradle b/graphics/drawable/static/build.gradle
index 8575d6a..f0ac9f0 100644
--- a/graphics/drawable/static/build.gradle
+++ b/graphics/drawable/static/build.gradle
@@ -15,7 +15,6 @@
 
 android {
     defaultConfig {
-        minSdkVersion 14
         // This disables the builds tools automatic vector -> PNG generation
         generatedDensities = []
     }
diff --git a/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierExtension.kt b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierExtension.kt
index b215d27..7b516ec 100644
--- a/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierExtension.kt
+++ b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierExtension.kt
@@ -26,7 +26,7 @@
  * Defines methods that can be used in gradle on the "jetifier" object and triggers [JetifyLibsTask]
  * or [JetifyGlobalTask] based on its usage.
  */
-open class JetifierExtension(val project : Project) {
+open class JetifierExtension(val project: Project) {
 
     /**
      * Adds dependency defined via string notation to be processed by jetifyLibs task.
@@ -42,6 +42,24 @@
     }
 
     /**
+     * Adds dependency defined via string notation to be processed by jetifyLibs task while also
+     * applying the given exclude rules.
+     *
+     *
+     * Example usage in Gradle:
+     * dependencies {
+     *   compile jetifier.processAndExclude('groupId:artifactId:1.0',
+     *     [group: 'some.package', module: 'moduleName'])
+     * }
+     */
+    fun processAndExclude(
+        dependencyNotation: String,
+        vararg excludes: Map<String, String>
+    ): FileCollection {
+        return processAndExclude(project.dependencies.create(dependencyNotation), *excludes)
+    }
+
+    /**
      * Adds dependency to be processed by jetifyLibs task.
      */
     fun process(dependency: Dependency): FileCollection {
@@ -51,6 +69,20 @@
     }
 
     /**
+     * Adds dependency to be processed by jetifyLibs task while also applying the given excludes
+     * rules.
+     */
+    fun processAndExclude(
+        dependency: Dependency,
+        vararg excludes: Map<String, String>
+    ): FileCollection {
+        val configuration = project.configurations.detachedConfiguration()
+        configuration.dependencies.add(dependency)
+        excludes.forEach { configuration.exclude(it) }
+        return process(configuration)
+    }
+
+    /**
      * Adds dependencies defined via file collection to be processed by jetifyLibs task.
      *
      * Example usage in Gradle for a single file:
@@ -113,5 +145,4 @@
     fun setConfigFile(configFilePath: String) {
         TasksCommon.configFilePath = Paths.get(configFilePath)
     }
-
 }
\ No newline at end of file
diff --git a/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierPlugin.kt b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierPlugin.kt
index 109e4c4..4c26406 100644
--- a/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierPlugin.kt
+++ b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierPlugin.kt
@@ -16,20 +16,45 @@
 
 package android.support.tools.jetifier.plugin.gradle
 
+import android.support.tools.jetifier.core.utils.Log
 import org.gradle.api.Plugin
 import org.gradle.api.Project
 
 /**
  * This serves as the main entry point of this plugin and registers the extension object.
  */
-open class JetifierPlugin : Plugin<Project>  {
+open class JetifierPlugin : Plugin<Project> {
 
     companion object {
-        const val GROOVY_OBJECT_NAME : String = "jetifier"
+        const val GROOVY_OBJECT_NAME: String = "jetifier"
     }
 
     override fun apply(project: Project) {
         project.extensions.create(GROOVY_OBJECT_NAME, JetifierExtension::class.java, project)
-    }
 
+        project.afterEvaluate({
+            val jetifyLibs = it.tasks.findByName(JetifyLibsTask.TASK_NAME)
+            val jetifyGlobal = it.tasks.findByName(JetifyGlobalTask.TASK_NAME)
+
+            if (jetifyLibs == null && jetifyGlobal == null) {
+                return@afterEvaluate
+            }
+
+            if (jetifyLibs != null && jetifyGlobal != null) {
+                jetifyGlobal.dependsOn(jetifyLibs)
+            }
+
+            val preBuildTask = it.tasks.findByName("preBuild")
+            if (preBuildTask == null) {
+                Log.e("TAG", "Failed to hook jetifier tasks. PreBuild task was not found.")
+                return@afterEvaluate
+            }
+
+            if (jetifyGlobal != null) {
+                preBuildTask.dependsOn(jetifyGlobal)
+            } else {
+                preBuildTask.dependsOn(jetifyLibs)
+            }
+        })
+    }
 }
\ No newline at end of file
diff --git a/leanback/Android.mk b/leanback/Android.mk
index d98abf6..e39261f 100644
--- a/leanback/Android.mk
+++ b/leanback/Android.mk
@@ -25,6 +25,7 @@
 # in their makefiles to include the resources and their dependencies in their package.
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
+LOCAL_AAPT2_ONLY := true
 LOCAL_MODULE := android-support-v17-leanback
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := \
@@ -34,13 +35,14 @@
     $(call all-java-files-under, api21) \
     $(call all-java-files-under, src)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-v7-recyclerview \
     android-support-compat \
     android-support-core-ui \
     android-support-media-compat \
-    android-support-fragment \
-    android-support-annotations
+    android-support-fragment
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/leanback/build.gradle b/leanback/build.gradle
index 036f08f..05a91df 100644
--- a/leanback/build.gradle
+++ b/leanback/build.gradle
@@ -20,10 +20,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 17
-    }
-
     sourceSets {
         main.java.srcDirs = [
                 'common',
@@ -44,4 +40,5 @@
     inceptionYear = "2014"
     description = "Android Support Leanback v17"
     legacySourceLocation = true
+    minSdkVersion = 17
 }
diff --git a/leanback/res/values-mr/strings.xml b/leanback/res/values-mr/strings.xml
index 8629ef1..1fcb920 100644
--- a/leanback/res/values-mr/strings.xml
+++ b/leanback/res/values-mr/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">"चित्र मोडमध्ये चित्र एंटर करा"</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/lifecycle/common-java8/build.gradle b/lifecycle/common-java8/build.gradle
index 137ea32..bee8b9c 100644
--- a/lifecycle/common-java8/build.gradle
+++ b/lifecycle/common-java8/build.gradle
@@ -24,10 +24,11 @@
 }
 
 dependencies {
+    compile(project(":lifecycle:common"))
+    compile(SUPPORT_ANNOTATIONS)
+
     testCompile(JUNIT)
     testCompile(MOCKITO_CORE)
-    compile(project(":lifecycle:common"))
-    compile libs.support.annotations
 }
 
 supportLibrary {
diff --git a/lifecycle/common/build.gradle b/lifecycle/common/build.gradle
index bc46d17..866a656 100644
--- a/lifecycle/common/build.gradle
+++ b/lifecycle/common/build.gradle
@@ -26,7 +26,7 @@
 dependencies {
     testCompile(JUNIT)
     testCompile(MOCKITO_CORE)
-    compile libs.support.annotations
+    compile(SUPPORT_ANNOTATIONS)
 }
 
 supportLibrary {
diff --git a/lifecycle/extensions/build.gradle b/lifecycle/extensions/build.gradle
index 38640b6..070394d 100644
--- a/lifecycle/extensions/build.gradle
+++ b/lifecycle/extensions/build.gradle
@@ -24,10 +24,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-
     buildTypes.all {
         consumerProguardFiles 'proguard-rules.pro'
     }
@@ -37,7 +33,7 @@
     api(project(":lifecycle:runtime"))
     api(project(":arch:common"))
     api(project(":arch:runtime"))
-    api libs.support.fragments, libs.support_exclude_config
+    api(SUPPORT_FRAGMENTS, libs.support_exclude_config)
     api(project(":lifecycle:common"))
 
     testImplementation(project(":arch:core-testing"))
@@ -46,7 +42,7 @@
 
     androidTestImplementation(TEST_RUNNER)
     androidTestImplementation(ESPRESSO_CORE)
-    androidTestImplementation libs.support.app_compat, libs.support_exclude_config
+    androidTestImplementation(SUPPORT_APPCOMPAT, libs.support_exclude_config)
 }
 
 supportLibrary {
diff --git a/lifecycle/gradle/wrapper/gradle-wrapper.properties b/lifecycle/gradle/wrapper/gradle-wrapper.properties
index 6051ae0..b519e0a 100644
--- a/lifecycle/gradle/wrapper/gradle-wrapper.properties
+++ b/lifecycle/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.4-bin.zip
diff --git a/lifecycle/integration-tests/testapp/build.gradle b/lifecycle/integration-tests/testapp/build.gradle
index 19d556b..9f970a5 100644
--- a/lifecycle/integration-tests/testapp/build.gradle
+++ b/lifecycle/integration-tests/testapp/build.gradle
@@ -18,8 +18,6 @@
 
 apply plugin: 'com.android.application'
 
-project.ext.noDocs = true
-
 android {
     compileSdkVersion tools.current_sdk
     buildToolsVersion tools.build_tools_version
diff --git a/lifecycle/reactivestreams/build.gradle b/lifecycle/reactivestreams/build.gradle
index 511ad7a..fbbc82f 100644
--- a/lifecycle/reactivestreams/build.gradle
+++ b/lifecycle/reactivestreams/build.gradle
@@ -23,25 +23,19 @@
     id("SupportAndroidLibraryPlugin")
 }
 
-android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-}
-
 dependencies {
     api(project(":arch:common"))
     api(project(":lifecycle:common"))
     api(project(":lifecycle:extensions"))
     api(project(":lifecycle:runtime"))
-    api libs.support.annotations
+    api(SUPPORT_ANNOTATIONS)
     api(REACTIVE_STREAMS)
 
     testImplementation(JUNIT)
     testImplementation(RX_JAVA)
     testImplementation(TEST_RUNNER)
 
-    androidTestImplementation libs.support.app_compat, libs.support_exclude_config
+    androidTestImplementation(SUPPORT_APPCOMPAT, libs.support_exclude_config)
 }
 
 supportLibrary {
diff --git a/lifecycle/runtime/build.gradle b/lifecycle/runtime/build.gradle
index 44e992b..aee73c0 100644
--- a/lifecycle/runtime/build.gradle
+++ b/lifecycle/runtime/build.gradle
@@ -8,10 +8,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-
     buildTypes.all {
         consumerProguardFiles 'proguard-rules.pro'
     }
@@ -21,7 +17,7 @@
     api(project(":lifecycle:common"))
     api(project(":arch:common"))
     // necessary for IJ to resolve dependencies.
-    api libs.support.annotations
+    api(SUPPORT_ANNOTATIONS)
 
     testImplementation(JUNIT)
     testImplementation(MOCKITO_CORE)
diff --git a/media-compat/Android.mk b/media-compat/Android.mk
index 4a4cd02..8538752 100644
--- a/media-compat/Android.mk
+++ b/media-compat/Android.mk
@@ -36,9 +36,10 @@
     $(call all-java-files-under,java) \
     $(call all-Iaidl-files-under,java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-compat \
+LOCAL_JAVA_LIBRARIES := \
     android-support-annotations
+LOCAL_SHARED_ANDROID_LIBRARIES := \
+    android-support-compat
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/media-compat/build.gradle b/media-compat/build.gradle
index 18ff5a3..ffa6e93 100644
--- a/media-compat/build.gradle
+++ b/media-compat/build.gradle
@@ -18,10 +18,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.java.srcDirs = [
                 'api21',
diff --git a/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java b/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java
index d7634b0..3b06125 100644
--- a/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java
+++ b/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java
@@ -24,6 +24,7 @@
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.support.annotation.IntDef;
+import android.support.annotation.LongDef;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.text.TextUtils;
@@ -45,7 +46,7 @@
      * @hide
      */
     @RestrictTo(LIBRARY_GROUP)
-    @IntDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
+    @LongDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
             ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING,
             ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH,
             ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE,
@@ -58,7 +59,7 @@
      * @hide
      */
     @RestrictTo(LIBRARY_GROUP)
-    @IntDef({ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND, ACTION_SKIP_TO_PREVIOUS,
+    @LongDef({ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND, ACTION_SKIP_TO_PREVIOUS,
             ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_PLAY_PAUSE})
     @Retention(RetentionPolicy.SOURCE)
     public @interface MediaKeyAction {}
diff --git a/media-compat/version-compat-tests/current/client/build.gradle b/media-compat/version-compat-tests/current/client/build.gradle
index aeb82c1..9c4f879 100644
--- a/media-compat/version-compat-tests/current/client/build.gradle
+++ b/media-compat/version-compat-tests/current/client/build.gradle
@@ -27,12 +27,6 @@
     androidTestImplementation(TEST_RUNNER)
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-}
-
 supportLibrary {
     legacySourceLocation = true
 }
\ No newline at end of file
diff --git a/media-compat/version-compat-tests/current/client/lint-baseline.xml b/media-compat/version-compat-tests/current/client/lint-baseline.xml
deleted file mode 100644
index ed7ade1..0000000
--- a/media-compat/version-compat-tests/current/client/lint-baseline.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Copyright 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.
--->
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/media-compat/version-compat-tests/current/service/build.gradle b/media-compat/version-compat-tests/current/service/build.gradle
index cf82918..3cb3a49 100644
--- a/media-compat/version-compat-tests/current/service/build.gradle
+++ b/media-compat/version-compat-tests/current/service/build.gradle
@@ -27,12 +27,6 @@
     androidTestImplementation(TEST_RUNNER)
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-}
-
 supportLibrary {
     legacySourceLocation = true
 }
diff --git a/media-compat/version-compat-tests/current/service/lint-baseline.xml b/media-compat/version-compat-tests/current/service/lint-baseline.xml
deleted file mode 100644
index ed7ade1..0000000
--- a/media-compat/version-compat-tests/current/service/lint-baseline.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Copyright 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.
--->
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/media-compat/version-compat-tests/lib/lint-baseline.xml b/media-compat/version-compat-tests/lib/lint-baseline.xml
deleted file mode 100644
index 4dd17af..0000000
--- a/media-compat/version-compat-tests/lib/lint-baseline.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Copyright 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.
--->
-<issues format="4" by="lint 3.0.0">
-
-</issues>
diff --git a/media-compat/version-compat-tests/previous/client/lint-baseline.xml b/media-compat/version-compat-tests/previous/client/lint-baseline.xml
deleted file mode 100644
index ed7ade1..0000000
--- a/media-compat/version-compat-tests/previous/client/lint-baseline.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Copyright 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.
--->
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/media-compat/version-compat-tests/previous/service/lint-baseline.xml b/media-compat/version-compat-tests/previous/service/lint-baseline.xml
deleted file mode 100644
index ed7ade1..0000000
--- a/media-compat/version-compat-tests/previous/service/lint-baseline.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Copyright 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.
--->
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/paging/common/build.gradle b/paging/common/build.gradle
index fc9964e..dbe6b06 100644
--- a/paging/common/build.gradle
+++ b/paging/common/build.gradle
@@ -25,7 +25,7 @@
 }
 
 dependencies {
-    compile libs.support.annotations
+    compile(SUPPORT_ANNOTATIONS)
     compile(project(":arch:common"))
 
     testCompile(JUNIT)
diff --git a/paging/integration-tests/testapp/build.gradle b/paging/integration-tests/testapp/build.gradle
index 91312a3..5bb3443 100644
--- a/paging/integration-tests/testapp/build.gradle
+++ b/paging/integration-tests/testapp/build.gradle
@@ -13,9 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-apply plugin: 'com.android.application'
 
-project.ext.noDocs = true
+import static android.support.dependencies.DependenciesKt.*
+
+apply plugin: 'com.android.application'
 
 android {
     compileSdkVersion tools.current_sdk
@@ -52,10 +53,9 @@
     implementation(project(":lifecycle:runtime"))
     implementation(project(":lifecycle:common"))
     implementation(project(":paging:runtime"))
-    implementation 'com.android.support:multidex:1.0.1'
-
-    implementation libs.support.recyclerview, libs.support_exclude_config
-    implementation libs.support.app_compat, libs.support_exclude_config
+    implementation(MULTIDEX)
+    implementation(SUPPORT_RECYCLERVIEW, libs.support_exclude_config)
+    implementation(SUPPORT_APPCOMPAT, libs.support_exclude_config)
 }
 
 tasks['check'].dependsOn(tasks['connectedCheck'])
diff --git a/paging/runtime/build.gradle b/paging/runtime/build.gradle
index 1a2bd2d..180e399 100644
--- a/paging/runtime/build.gradle
+++ b/paging/runtime/build.gradle
@@ -24,19 +24,13 @@
     id("kotlin-android")
 }
 
-android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-}
-
 dependencies {
     api(project(":arch:runtime"))
     api(project(":paging:common"))
     api(project(":lifecycle:runtime"))
     api(project(":lifecycle:extensions"))
 
-    api libs.support.recyclerview, libs.support_exclude_config
+    api(SUPPORT_RECYCLERVIEW, libs.support_exclude_config)
 
     androidTestImplementation(JUNIT)
     androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
diff --git a/percent/build.gradle b/percent/build.gradle
index 7d5a651..951a0e0 100644
--- a/percent/build.gradle
+++ b/percent/build.gradle
@@ -14,10 +14,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.res.srcDir 'res'
     }
diff --git a/persistence/db-framework/build.gradle b/persistence/db-framework/build.gradle
index 6ce2b94..bae3d02 100644
--- a/persistence/db-framework/build.gradle
+++ b/persistence/db-framework/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -22,14 +23,8 @@
     id("SupportAndroidLibraryPlugin")
 }
 
-android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-}
-
 dependencies {
-    api libs.support.annotations
+    api(SUPPORT_ANNOTATIONS)
     api(project(":persistence:db"))
 }
 
diff --git a/persistence/db/build.gradle b/persistence/db/build.gradle
index 6f5c7f5..657ef1e 100644
--- a/persistence/db/build.gradle
+++ b/persistence/db/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -22,14 +23,8 @@
     id("SupportAndroidLibraryPlugin")
 }
 
-android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-}
-
 dependencies {
-    api libs.support.annotations
+    api(SUPPORT_ANNOTATIONS)
 }
 
 // Used by testCompile in room-compiler
diff --git a/preference-leanback/Android.mk b/preference-leanback/Android.mk
index 263d334..e2ad1de 100644
--- a/preference-leanback/Android.mk
+++ b/preference-leanback/Android.mk
@@ -29,20 +29,22 @@
 # in their makefiles to include the resources in their package.
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
+LOCAL_AAPT2_ONLY := true
 LOCAL_MODULE := android-support-v17-preference-leanback
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := \
     $(call all-java-files-under,api21) \
     $(call all-java-files-under,src)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-v17-leanback \
     android-support-v14-preference \
     android-support-v7-preference \
     android-support-v7-appcompat \
     android-support-v7-recyclerview \
-    android-support-v4 \
-    android-support-annotations
+    android-support-v4
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/preference-leanback/build.gradle b/preference-leanback/build.gradle
index f4d2fd6..c5fb9f5 100644
--- a/preference-leanback/build.gradle
+++ b/preference-leanback/build.gradle
@@ -15,10 +15,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 17
-    }
-
     sourceSets {
         main.java.srcDirs = [
                 'api21',
@@ -36,4 +32,5 @@
     inceptionYear = "2015"
     description = "Android Support Leanback Preference v17"
     legacySourceLocation = true
+    minSdkVersion = 17
 }
\ No newline at end of file
diff --git a/recommendation/Android.mk b/recommendation/Android.mk
index ea819e9..6249df7 100644
--- a/recommendation/Android.mk
+++ b/recommendation/Android.mk
@@ -27,9 +27,10 @@
 LOCAL_SDK_VERSION := current
 LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-v4 \
+LOCAL_JAVA_LIBRARIES := \
     android-support-annotations
+LOCAL_SHARED_ANDROID_LIBRARIES := \
+    android-support-v4
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/recommendation/build.gradle b/recommendation/build.gradle
index 83fa375..bf2265d 100644
--- a/recommendation/build.gradle
+++ b/recommendation/build.gradle
@@ -9,12 +9,6 @@
     api(project(":support-annotations"))
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 21
-    }
-}
-
 supportLibrary {
     name = "Android Support Recommendation"
     publish = true
@@ -23,4 +17,5 @@
     inceptionYear = "2015"
     description = "Android Support Recommendation"
     legacySourceLocation = true
+    minSdkVersion = 21
 }
diff --git a/recyclerview-selection/Android.mk b/recyclerview-selection/Android.mk
index ed93fa2..511806f 100644
--- a/recyclerview-selection/Android.mk
+++ b/recyclerview-selection/Android.mk
@@ -20,10 +20,11 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-v7-recyclerview \
-    android-support-compat \
-    android-support-annotations
+    android-support-compat
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/room/common/build.gradle b/room/common/build.gradle
index 05b63c9..9457308 100644
--- a/room/common/build.gradle
+++ b/room/common/build.gradle
@@ -24,7 +24,7 @@
 }
 
 dependencies {
-    compile libs.support.annotations
+    compile(SUPPORT_ANNOTATIONS)
     testCompile(JUNIT)
     testCompile(MOCKITO_CORE)
 }
diff --git a/room/compiler/build.gradle b/room/compiler/build.gradle
index 2b35032..57ff63f 100644
--- a/room/compiler/build.gradle
+++ b/room/compiler/build.gradle
@@ -27,7 +27,6 @@
     test.java.srcDirs += 'src/tests/kotlin'
     main.java.srcDirs += antlrOut
 }
-project.ext.noDocs = true
 
 // Temporary hack to stop AS to adding two guavas into test's classpath
 configurations.all {
@@ -80,6 +79,7 @@
 supportLibrary {
     name = "Android Room Compiler"
     publish = true
+    generateDocs = false
     mavenVersion = LibraryVersions.ROOM
     mavenGroup = LibraryGroups.ROOM
     inceptionYear = "2017"
diff --git a/room/gradle/wrapper/gradle-wrapper.properties b/room/gradle/wrapper/gradle-wrapper.properties
index 383477d..2f8bf03 100644
--- a/room/gradle/wrapper/gradle-wrapper.properties
+++ b/room/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.4-bin.zip
diff --git a/room/integration-tests/kotlintestapp/build.gradle b/room/integration-tests/kotlintestapp/build.gradle
index da8116b..06cec35 100644
--- a/room/integration-tests/kotlintestapp/build.gradle
+++ b/room/integration-tests/kotlintestapp/build.gradle
@@ -20,8 +20,6 @@
 apply plugin: 'kotlin-kapt'
 apply plugin: 'kotlin-android'
 
-project.ext.noDocs = true
-
 android {
     compileSdkVersion tools.current_sdk
     buildToolsVersion tools.build_tools_version
@@ -66,7 +64,7 @@
     implementation(project(":room:runtime"))
     implementation(project(":arch:runtime"))
 
-    implementation libs.support.app_compat, libs.support_exclude_config
+    implementation(SUPPORT_APPCOMPAT, libs.support_exclude_config)
     kapt project(":room:compiler")
     kaptAndroidTest project(":room:compiler")
 
diff --git a/room/integration-tests/testapp/build.gradle b/room/integration-tests/testapp/build.gradle
index d4d4893..355de3c 100644
--- a/room/integration-tests/testapp/build.gradle
+++ b/room/integration-tests/testapp/build.gradle
@@ -18,8 +18,6 @@
 
 apply plugin: 'com.android.application'
 
-project.ext.noDocs = true
-
 android {
     compileSdkVersion tools.current_sdk
     buildToolsVersion tools.build_tools_version
@@ -71,8 +69,8 @@
     implementation(project(":room:rxjava2"))
     implementation(project(":paging:runtime"))
 
-    implementation libs.support.recyclerview, libs.support_exclude_config
-    implementation libs.support.app_compat, libs.support_exclude_config
+    implementation(SUPPORT_RECYCLERVIEW, libs.support_exclude_config)
+    implementation(SUPPORT_APPCOMPAT, libs.support_exclude_config)
     annotationProcessor project(":room:compiler")
     androidTestAnnotationProcessor project(":room:compiler")
 
diff --git a/room/runtime/build.gradle b/room/runtime/build.gradle
index 8a91ac7..1022616 100644
--- a/room/runtime/build.gradle
+++ b/room/runtime/build.gradle
@@ -24,10 +24,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-
     buildTypes.all {
         consumerProguardFiles 'proguard-rules.pro'
     }
@@ -41,7 +37,7 @@
     compileOnly project(":paging:common")
     compileOnly project(":lifecycle:runtime")
     compileOnly project(":lifecycle:extensions")
-    api libs.support.core_utils, libs.support_exclude_config
+    api(SUPPORT_CORE_UTILS, libs.support_exclude_config)
 
     testImplementation(project(":arch:core-testing"))
     testImplementation(JUNIT)
diff --git a/room/rxjava2/build.gradle b/room/rxjava2/build.gradle
index 1b012dd..d3d7bc9 100644
--- a/room/rxjava2/build.gradle
+++ b/room/rxjava2/build.gradle
@@ -23,17 +23,11 @@
     id("SupportAndroidLibraryPlugin")
 }
 
-android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-}
-
 dependencies {
     api(project(":room:common"))
     api(project(":room:runtime"))
     api(project(":arch:runtime"))
-    api libs.support.core_utils, libs.support_exclude_config
+    api(SUPPORT_CORE_UTILS, libs.support_exclude_config)
     api(RX_JAVA)
     testImplementation(JUNIT)
     testImplementation(MOCKITO_CORE)
diff --git a/room/testing/build.gradle b/room/testing/build.gradle
index b71c8bc..d584b54 100644
--- a/room/testing/build.gradle
+++ b/room/testing/build.gradle
@@ -23,12 +23,6 @@
     id("SupportAndroidLibraryPlugin")
 }
 
-android {
-    defaultConfig {
-        minSdkVersion flatfoot.min_sdk
-    }
-}
-
 dependencies {
     api(project(":room:common"))
     api(project(":room:runtime"))
@@ -36,7 +30,7 @@
     api(project(":persistence:db-framework"))
     api(project(":room:migration"))
     api(project(":arch:runtime"))
-    api libs.support.core_utils, libs.support_exclude_config
+    api(SUPPORT_CORE_UTILS, libs.support_exclude_config)
     api(JUNIT)
 }
 
diff --git a/samples/SupportLeanbackShowcase/OWNERS b/samples/SupportLeanbackShowcase/OWNERS
deleted file mode 100644
index 063702c..0000000
--- a/samples/SupportLeanbackShowcase/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-dake@google.com
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/.gitignore b/samples/SupportLeanbackShowcase/app/.gitignore
deleted file mode 100644
index 796b96d..0000000
--- a/samples/SupportLeanbackShowcase/app/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
diff --git a/samples/SupportLeanbackShowcase/app/build.gradle b/samples/SupportLeanbackShowcase/app/build.gradle
deleted file mode 100644
index b2ff15b..0000000
--- a/samples/SupportLeanbackShowcase/app/build.gradle
+++ /dev/null
@@ -1,36 +0,0 @@
-apply plugin: 'com.android.application'
-
-android {
-    compileSdkVersion 24
-    buildToolsVersion "24.0.2"
-
-    defaultConfig {
-        applicationId "android.support.v17.leanback.supportleanbackshowcase"
-        minSdkVersion 17
-        targetSdkVersion 24
-        versionCode 1
-        versionName "1.0"
-        multiDexEnabled true
-    }
-    buildTypes {
-        release {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
-        }
-    }
-}
-
-dependencies {
-    compile fileTree(dir: 'libs', include: ['*.jar'])
-    compile "com.android.support:recyclerview-v7:${supportLibVersion}"
-    compile "com.android.support:leanback-v17:${supportLibVersion}"
-    compile "com.android.support:appcompat-v7:${supportLibVersion}"
-
-    compile "com.android.support:preference-v7:${supportLibVersion}"
-    compile "com.android.support:preference-leanback-v17:${supportLibVersion}"
-    compile "com.android.support:preference-v14:${supportLibVersion}"
-
-    compile "com.google.code.gson:gson:1.7.2"
-    compile "com.squareup.picasso:picasso:2.5.2"
-    compile "com.android.support:palette-v7:${supportLibVersion}"
-}
diff --git a/samples/SupportLeanbackShowcase/app/proguard-rules.pro b/samples/SupportLeanbackShowcase/app/proguard-rules.pro
deleted file mode 100644
index cf489a5..0000000
--- a/samples/SupportLeanbackShowcase/app/proguard-rules.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in /Users/hahnr/Library/Android/sdk/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the proguardFiles
-# directive in build.gradle.
-#
-# For more details, see
-#   http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-#   public *;
-#}
diff --git a/samples/SupportLeanbackShowcase/app/src/androidTest/java/android/support/v17/leanback/supportleanbackshowcase/ApplicationTest.java b/samples/SupportLeanbackShowcase/app/src/androidTest/java/android/support/v17/leanback/supportleanbackshowcase/ApplicationTest.java
deleted file mode 100644
index 4d13a4b..0000000
--- a/samples/SupportLeanbackShowcase/app/src/androidTest/java/android/support/v17/leanback/supportleanbackshowcase/ApplicationTest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.supportleanbackshowcase;
-
-import android.app.Application;
-import android.test.ApplicationTestCase;
-
-/**
- * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
- */
-public class ApplicationTest extends ApplicationTestCase<Application> {
-    public ApplicationTest() {
-        super(Application.class);
-    }
-}
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/AndroidManifest.xml b/samples/SupportLeanbackShowcase/app/src/main/AndroidManifest.xml
deleted file mode 100644
index 4e71c40..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<manifest
-    package="android.support.v17.leanback.supportleanbackshowcase"
-    xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="23" />
-    <uses-permission android:name="android.permission.INTERNET"/>
-    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
-
-    <uses-feature
-        android:name="android.hardware.touchscreen"
-        android:required="false"/>
-    <uses-feature
-        android:name="android.software.leanback"
-        android:required="true"/>
-
-    <application
-        android:allowBackup="true"
-        android:icon="@mipmap/app_banner_sample_app"
-        android:label="@string/app_name"
-        android:supportsRtl="true"
-        android:largeHeap="true"
-        android:theme="@style/Theme.Example.LeanbackLauncher">
-        <activity
-            android:name=".app.MainActivity"
-            android:exported="true"
-            android:icon="@mipmap/app_banner_sample_app"
-            android:label="@string/app_name"
-            android:logo="@mipmap/app_banner_sample_app"
-            android:screenOrientation="landscape">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-
-                <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
-            </intent-filter>
-        </activity>
-        <activity
-                android:name=".app.page.PageAndListRowActivity"
-                android:exported="true"
-                android:theme="@style/Theme.Example.Leanback.CustomTitle"/>
-        <activity
-            android:name=".app.wizard.WizardExampleActivity"
-            android:exported="true"
-            android:theme="@style/Theme.Example.LeanbackWizard"></activity>
-        <activity
-            android:name=".app.settings.SettingsExampleActivity"
-            android:exported="true"
-            android:theme="@style/Theme.Example.LeanbackPreferences"></activity>
-        <activity
-            android:name=".app.dialog.DialogExampleActivity"
-            android:exported="true"
-            android:theme="@style/Theme.Example.LeanbackDialog"></activity>
-        <activity
-            android:name=".app.details.DetailViewExampleActivity"
-            android:exported="true"
-            android:theme="@style/Theme.Example.LeanbackDetails"></activity>
-        <activity
-            android:name=".app.cards.CardExampleActivity"
-            android:exported="true"
-            android:theme="@style/Theme.Example.LeanbackBrowse"></activity>
-        <activity
-            android:name=".app.grid.GridExampleActivity"
-            android:exported="true"
-            android:theme="@style/Theme.Example.LeanbackVerticalGrid"></activity>
-        <activity
-            android:name=".app.media.VideoExampleActivity"
-            android:exported="true"
-            android:theme="@style/Theme.Example.Leanback"></activity>
-        <activity
-            android:name=".app.media.MusicExampleActivity"
-            android:exported="true"
-            android:theme="@style/Theme.Example.LeanbackMusic"></activity>
-    </application>
-
-</manifest>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/MainActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/MainActivity.java
deleted file mode 100644
index e84c8cc..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/MainActivity.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.support.v17.leanback.supportleanbackshowcase.app;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.os.Bundle;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-
-/*
- * MainActivity class that loads MainFragment
- */
-public class MainActivity extends Activity {
-
-    /**
-     * Called when the activity is first created.
-     */
-    @Override public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_main);
-        if (savedInstanceState == null) {
-            Fragment fragment = new MainFragment();
-            getFragmentManager().beginTransaction().replace(R.id.fragmentContainer, fragment)
-                                .commit();
-        }
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/MainFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/MainFragment.java
deleted file mode 100644
index 6918539..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/MainFragment.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v17.leanback.app.BrowseFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.app.cards.CardExampleActivity;
-import android.support.v17.leanback.supportleanbackshowcase.app.details.DetailViewExampleActivity;
-import android.support.v17.leanback.supportleanbackshowcase.app.dialog.DialogExampleActivity;
-import android.support.v17.leanback.supportleanbackshowcase.app.grid.GridExampleActivity;
-import android.support.v17.leanback.supportleanbackshowcase.app.media.MusicExampleActivity;
-import android.support.v17.leanback.supportleanbackshowcase.app.media.VideoExampleActivity;
-import android.support.v17.leanback.supportleanbackshowcase.app.page.PageAndListRowActivity;
-import android.support.v17.leanback.supportleanbackshowcase.app.settings.SettingsExampleActivity;
-import android.support.v17.leanback.supportleanbackshowcase.app.wizard.WizardExampleActivity;
-import android.support.v17.leanback.supportleanbackshowcase.cards.presenters.CardPresenterSelector;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.supportleanbackshowcase.models.CardRow;
-import android.support.v17.leanback.supportleanbackshowcase.models.Movie;
-import android.support.v17.leanback.supportleanbackshowcase.utils.Utils;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.ImageCardView;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.OnItemViewClickedListener;
-import android.support.v17.leanback.widget.OnItemViewSelectedListener;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.PresenterSelector;
-import android.support.v17.leanback.widget.Row;
-import android.support.v17.leanback.widget.RowPresenter;
-import android.support.v4.app.ActivityOptionsCompat;
-
-import com.google.gson.Gson;
-
-
-public class MainFragment extends BrowseFragment {
-
-    private ArrayObjectAdapter mRowsAdapter;
-
-    @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-
-        setupUIElements();
-        setupRowAdapter();
-        setupEventListeners();
-    }
-
-    private void setupRowAdapter() {
-        mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
-        createRows();
-        setAdapter(mRowsAdapter);
-    }
-
-    private void createRows() {
-        String json = Utils
-                .inputStreamToString(getResources().openRawResource(R.raw.launcher_cards));
-        CardRow[] rows = new Gson().fromJson(json, CardRow[].class);
-        for (CardRow row : rows) {
-            mRowsAdapter.add(createCardRow(row));
-        }
-    }
-
-    private ListRow createCardRow(CardRow cardRow) {
-        PresenterSelector presenterSelector = new CardPresenterSelector(getActivity());
-        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(presenterSelector);
-        for (Card card : cardRow.getCards()) {
-            listRowAdapter.add(card);
-        }
-        return new ListRow(listRowAdapter);
-    }
-
-    private void setupUIElements() {
-        setTitle(getString(R.string.browse_title));
-        setBadgeDrawable(getResources().getDrawable(R.drawable.title_android_tv, null));
-        setHeadersState(HEADERS_DISABLED);
-        setHeadersTransitionOnBackEnabled(false);
-        setBrandColor(getResources().getColor(R.color.fastlane_background));
-    }
-
-    private void setupEventListeners() {
-        setOnItemViewClickedListener(new ItemViewClickedListener());
-        setOnItemViewSelectedListener(new ItemViewSelectedListener());
-    }
-
-    private final class ItemViewClickedListener implements OnItemViewClickedListener {
-
-        @Override
-        public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
-                                  RowPresenter.ViewHolder rowViewHolder, Row row) {
-            Intent intent = null;
-            Card card = (Card) item;
-            int id = card.getId();
-            switch (id) {
-                case 0: {
-                    intent = new Intent(getActivity().getBaseContext(),
-                            CardExampleActivity.class);
-                    break;
-                }
-                case 1:
-                    intent = new Intent(getActivity().getBaseContext(),
-                            PageAndListRowActivity.class);
-                    break;
-                case 2: {
-                    intent = new Intent(getActivity().getBaseContext(),
-                            GridExampleActivity.class);
-                    break;
-                }
-                case 3: {
-                    intent = new Intent(getActivity().getBaseContext(),
-                            DetailViewExampleActivity.class);
-                    break;
-                }
-                case 4: {
-                    intent = new Intent(getActivity().getBaseContext(),
-                            VideoExampleActivity.class);
-                    break;
-                }
-                case 5: {
-                    intent = new Intent(getActivity().getBaseContext(),
-                            MusicExampleActivity.class);
-                    break;
-                }
-                case 6: {
-                    // Let's create a new Wizard for a given Movie. The movie can come from any sort
-                    // of data source. To simplify this example we decode it from a JSON source
-                    // which might be loaded from a server in a real world example.
-                    intent = new Intent(getActivity().getBaseContext(),
-                            WizardExampleActivity.class);
-
-                    // Prepare extras which contains the Movie and will be passed to the Activity
-                    // which is started through the Intent/.
-                    Bundle extras = new Bundle();
-                    String json = Utils.inputStreamToString(
-                            getResources().openRawResource(R.raw.wizard_example));
-                    Movie movie = new Gson().fromJson(json, Movie.class);
-                    extras.putSerializable("movie", movie);
-                    intent.putExtras(extras);
-
-                    // Finally, start the wizard Activity.
-                    break;
-                }
-                case 7: {
-                    intent = new Intent(getActivity().getBaseContext(),
-                            SettingsExampleActivity.class);
-                    startActivity(intent);
-                    return;
-                }
-                case 8: {
-                    intent = new Intent(getActivity().getBaseContext(),
-                            DialogExampleActivity.class);
-                    break;
-                }
-                default:
-                    break;
-            }
-            if (intent != null) {
-                Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity())
-                        .toBundle();
-                startActivity(intent, bundle);
-            }
-        }
-    }
-
-    private final class ItemViewSelectedListener implements OnItemViewSelectedListener {
-
-        @Override
-        public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
-                                   RowPresenter.ViewHolder rowViewHolder, Row row) {
-        }
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/cards/CardExampleActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/cards/CardExampleActivity.java
deleted file mode 100644
index ecb0c7a..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/cards/CardExampleActivity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.support.v17.leanback.supportleanbackshowcase.app.cards;
-
-import android.app.Activity;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Bundle;
-import android.support.v17.leanback.app.GuidedStepFragment;
-import android.support.v17.leanback.supportleanbackshowcase.app.dialog.DialogExampleFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-
-/**
- * TODO: Javadoc
- */
-public class CardExampleActivity extends Activity {
-
-    @Override public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_cards_example);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/cards/CardExampleFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/cards/CardExampleFragment.java
deleted file mode 100644
index ab683d0..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/cards/CardExampleFragment.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.cards;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v17.leanback.app.BrowseFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.app.details.DetailViewExampleActivity;
-import android.support.v17.leanback.supportleanbackshowcase.app.details.DetailViewExampleFragment;
-import android.support.v17.leanback.supportleanbackshowcase.app.details.ShadowRowPresenterSelector;
-import android.support.v17.leanback.supportleanbackshowcase.cards.presenters.CardPresenterSelector;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.supportleanbackshowcase.models.CardRow;
-import android.support.v17.leanback.supportleanbackshowcase.utils.CardListRow;
-import android.support.v17.leanback.supportleanbackshowcase.utils.Utils;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.HeaderItem;
-import android.support.v17.leanback.widget.ImageCardView;
-import android.support.v17.leanback.widget.DividerRow;
-import android.support.v17.leanback.widget.SectionRow;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.OnItemViewClickedListener;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.PresenterSelector;
-import android.support.v17.leanback.widget.Row;
-import android.support.v17.leanback.widget.RowPresenter;
-import android.support.v17.leanback.widget.SearchOrbView;
-import android.support.v4.app.ActivityOptionsCompat;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.Toast;
-
-import com.google.gson.Gson;
-
-/**
- * This fragment will be shown when the "Card Examples" card is selected at the home menu. It will
- * display multiple card types.
- */
-public class CardExampleFragment extends BrowseFragment {
-
-    private ArrayObjectAdapter mRowsAdapter;
-
-    @Override public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-        setupUi();
-        setupRowAdapter();
-    }
-
-    private void setupUi() {
-        setHeadersState(HEADERS_ENABLED);
-        setHeadersTransitionOnBackEnabled(true);
-        setTitle(getString(R.string.card_examples_title));
-        setOnSearchClickedListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Toast.makeText(getActivity(), getString(R.string.implement_search),
-                        Toast.LENGTH_LONG).show();
-            }
-        });
-        setOnItemViewClickedListener(new OnItemViewClickedListener() {
-
-            @Override
-            public void onItemClicked(Presenter.ViewHolder viewHolder, Object item, RowPresenter.ViewHolder viewHolder1, Row row) {
-                if (!(item instanceof Card)) return;
-                if (!(viewHolder.view instanceof ImageCardView)) return;
-
-                ImageView imageView = ((ImageCardView) viewHolder.view).getMainImageView();
-                Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(),
-                        imageView, DetailViewExampleFragment.TRANSITION_NAME).toBundle();
-                Intent intent = new Intent(getActivity().getBaseContext(),
-                        DetailViewExampleActivity.class);
-                Card card = (Card) item;
-                int imageResId = card.getLocalImageResourceId(getContext());
-                intent.putExtra(DetailViewExampleFragment.EXTRA_CARD, imageResId);
-                startActivity(intent, bundle);
-            }
-
-        });
-
-        prepareEntranceTransition();
-    }
-
-    private void setupRowAdapter() {
-        mRowsAdapter = new ArrayObjectAdapter(new ShadowRowPresenterSelector());
-        setAdapter(mRowsAdapter);
-        new Handler().postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                createRows();
-                startEntranceTransition();
-            }
-        }, 500);
-    }
-
-    private void createRows() {
-        String json = Utils
-                .inputStreamToString(getResources().openRawResource(R.raw.cards_example));
-        CardRow[] rows = new Gson().fromJson(json, CardRow[].class);
-        for (CardRow row : rows) {
-            mRowsAdapter.add(createCardRow(row));
-        }
-    }
-
-    private Row createCardRow(final CardRow cardRow) {
-        switch (cardRow.getType()) {
-            case CardRow.TYPE_SECTION_HEADER:
-                return new SectionRow(new HeaderItem(cardRow.getTitle()));
-            case CardRow.TYPE_DIVIDER:
-                return new DividerRow();
-            case CardRow.TYPE_DEFAULT:
-            default:
-                // Build main row using the ImageCardViewPresenter.
-                PresenterSelector presenterSelector = new CardPresenterSelector(getActivity());
-                ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(presenterSelector);
-                for (Card card : cardRow.getCards()) {
-                    listRowAdapter.add(card);
-                }
-                return new CardListRow(new HeaderItem(cardRow.getTitle()), listRowAdapter, cardRow);
-        }
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/DetailViewExampleActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/DetailViewExampleActivity.java
deleted file mode 100644
index 6b9c143..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/DetailViewExampleActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.details;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v17.leanback.app.DetailsFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-
-/**
- * Contains a {@link DetailsFragment} in order to display more details for a given card.
- */
-public class DetailViewExampleActivity extends Activity {
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_detail_example);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/DetailViewExampleFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/DetailViewExampleFragment.java
deleted file mode 100644
index eed800f..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/DetailViewExampleFragment.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.details;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v17.leanback.app.DetailsFragment;
-import android.support.v17.leanback.supportleanbackshowcase.models.DetailedCard;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.utils.CardListRow;
-import android.support.v17.leanback.supportleanbackshowcase.utils.Utils;
-import android.support.v17.leanback.supportleanbackshowcase.cards.presenters.CardPresenterSelector;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.widget.Action;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.ClassPresenterSelector;
-import android.support.v17.leanback.widget.DetailsOverviewRow;
-import android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter;
-import android.support.v17.leanback.widget.FullWidthDetailsOverviewSharedElementHelper;
-import android.support.v17.leanback.widget.HeaderItem;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.OnItemViewClickedListener;
-import android.support.v17.leanback.widget.OnItemViewSelectedListener;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.Row;
-import android.support.v17.leanback.widget.RowPresenter;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Toast;
-
-import com.google.gson.Gson;
-
-/**
- * Displays a card with more details using a {@link DetailsFragment}.
- */
-public class DetailViewExampleFragment extends DetailsFragment implements OnItemViewClickedListener,
-        OnItemViewSelectedListener {
-
-    public static final String TRANSITION_NAME = "t_for_transition";
-    public static final String EXTRA_CARD = "card";
-
-    private ArrayObjectAdapter mRowsAdapter;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setupUi();
-        setupEventListeners();
-    }
-
-    private void setupUi() {
-        // Load the card we want to display from a JSON resource. This JSON data could come from
-        // anywhere in a real world app, e.g. a server.
-        String json = Utils
-                .inputStreamToString(getResources().openRawResource(R.raw.detail_example));
-        DetailedCard data = new Gson().fromJson(json, DetailedCard.class);
-
-        // Setup fragment
-        setTitle(getString(R.string.detail_view_title));
-
-        FullWidthDetailsOverviewRowPresenter rowPresenter = new FullWidthDetailsOverviewRowPresenter(
-                new DetailsDescriptionPresenter(getActivity())) {
-
-            @Override
-            protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) {
-                // Customize Actionbar and Content by using custom colors.
-                RowPresenter.ViewHolder viewHolder = super.createRowViewHolder(parent);
-
-                View actionsView = viewHolder.view.
-                        findViewById(R.id.details_overview_actions_background);
-                actionsView.setBackgroundColor(getActivity().getResources().
-                        getColor(R.color.detail_view_actionbar_background, null));
-
-                View detailsView = viewHolder.view.findViewById(R.id.details_frame);
-                detailsView.setBackgroundColor(
-                        getResources().getColor(R.color.detail_view_background, null));
-                return viewHolder;
-            }
-        };
-
-        FullWidthDetailsOverviewSharedElementHelper mHelper = new FullWidthDetailsOverviewSharedElementHelper();
-        mHelper.setSharedElementEnterTransition(getActivity(), TRANSITION_NAME);
-        rowPresenter.setListener(mHelper);
-        rowPresenter.setParticipatingEntranceTransition(false);
-        prepareEntranceTransition();
-
-        ListRowPresenter shadowDisabledRowPresenter = new ListRowPresenter();
-        shadowDisabledRowPresenter.setShadowEnabled(false);
-
-        // Setup PresenterSelector to distinguish between the different rows.
-        ClassPresenterSelector rowPresenterSelector = new ClassPresenterSelector();
-        rowPresenterSelector.addClassPresenter(DetailsOverviewRow.class, rowPresenter);
-        rowPresenterSelector.addClassPresenter(CardListRow.class, shadowDisabledRowPresenter);
-        rowPresenterSelector.addClassPresenter(ListRow.class, new ListRowPresenter());
-        mRowsAdapter = new ArrayObjectAdapter(rowPresenterSelector);
-
-        // Setup action and detail row.
-        DetailsOverviewRow detailsOverview = new DetailsOverviewRow(data);
-        int imageResId = data.getLocalImageResourceId(getActivity());
-
-        Bundle extras = getActivity().getIntent().getExtras();
-        if (extras != null && extras.containsKey(EXTRA_CARD)) {
-            imageResId = extras.getInt(EXTRA_CARD, imageResId);
-        }
-        detailsOverview.setImageDrawable(getResources().getDrawable(imageResId, null));
-        ArrayObjectAdapter actionAdapter = new ArrayObjectAdapter();
-        actionAdapter.add(new Action(1, getString(R.string.action_buy) + data.getPrice()));
-        actionAdapter.add(new Action(2, getString(R.string.action_wishlist)));
-        actionAdapter.add(new Action(3, getString(R.string.action_related)));
-        detailsOverview.setActionsAdapter(actionAdapter);
-        mRowsAdapter.add(detailsOverview);
-
-        // Setup related row.
-        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
-                new CardPresenterSelector(getActivity()));
-        for (Card characterCard : data.getCharacters()) listRowAdapter.add(characterCard);
-        HeaderItem header = new HeaderItem(0, getString(R.string.header_related));
-        mRowsAdapter.add(new CardListRow(header, listRowAdapter, null));
-
-        // Setup recommended row.
-        listRowAdapter = new ArrayObjectAdapter(new CardPresenterSelector(getActivity()));
-        for (Card card : data.getRecommended()) listRowAdapter.add(card);
-        header = new HeaderItem(1, getString(R.string.header_recommended));
-        mRowsAdapter.add(new ListRow(header, listRowAdapter));
-
-        setAdapter(mRowsAdapter);
-        new Handler().postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                startEntranceTransition();
-            }
-        }, 500);
-    }
-
-    private void setupEventListeners() {
-        setOnItemViewSelectedListener(this);
-        setOnItemViewClickedListener(this);
-    }
-
-    @Override
-    public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
-                              RowPresenter.ViewHolder rowViewHolder, Row row) {
-        if (!(item instanceof Action)) return;
-        Action action = (Action) item;
-        if (action.getId() == 3) {
-            setSelectedPosition(1);
-        } else {
-            Toast.makeText(getActivity(), getString(R.string.action_cicked), Toast.LENGTH_LONG)
-                    .show();
-        }
-    }
-
-    @Override
-    public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
-                               RowPresenter.ViewHolder rowViewHolder, Row row) {
-        if (mRowsAdapter.indexOf(row) > 0) {
-            int backgroundColor = getResources().getColor(R.color.detail_view_related_background,
-                    null);
-            getView().setBackgroundColor(backgroundColor);
-        } else {
-            getView().setBackground(null);
-        }
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/DetailsDescriptionPresenter.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/DetailsDescriptionPresenter.java
deleted file mode 100644
index b8488a1..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/DetailsDescriptionPresenter.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.details;
-
-import android.content.Context;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.models.DetailedCard;
-import android.support.v17.leanback.supportleanbackshowcase.utils.ResourceCache;
-import android.support.v17.leanback.widget.Presenter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-/**
- * This presenter is used to render a {@link DetailedCard} in the {@link
- * DetailViewExampleFragment}.
- */
-public class DetailsDescriptionPresenter extends Presenter {
-
-    private ResourceCache mResourceCache = new ResourceCache();
-    private Context mContext;
-
-    public DetailsDescriptionPresenter(Context context) {
-        mContext = context;
-    }
-
-    @Override public ViewHolder onCreateViewHolder(ViewGroup parent) {
-        View view = LayoutInflater.from(mContext).inflate(R.layout.detail_view_content, null);
-        return new ViewHolder(view);
-    }
-
-    @Override public void onBindViewHolder(ViewHolder viewHolder, Object item) {
-        TextView primaryText = mResourceCache.getViewById(viewHolder.view, R.id.primary_text);
-        TextView sndText1 = mResourceCache.getViewById(viewHolder.view, R.id.secondary_text_first);
-        TextView sndText2 = mResourceCache.getViewById(viewHolder.view, R.id.secondary_text_second);
-        TextView extraText = mResourceCache.getViewById(viewHolder.view, R.id.extra_text);
-
-        DetailedCard card = (DetailedCard) item;
-        primaryText.setText(card.getTitle());
-        sndText1.setText(card.getDescription());
-        sndText2.setText(card.getYear() + "");
-        extraText.setText(card.getText());
-    }
-
-    @Override public void onUnbindViewHolder(ViewHolder viewHolder) {
-        // Nothing to do here.
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/ShadowRowPresenterSelector.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/ShadowRowPresenterSelector.java
deleted file mode 100644
index 7df3bf8..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/details/ShadowRowPresenterSelector.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.details;
-
-import android.support.v17.leanback.supportleanbackshowcase.models.CardRow;
-import android.support.v17.leanback.supportleanbackshowcase.utils.CardListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.PresenterSelector;
-
-/**
- * This {@link PresenterSelector} will return a {@link ListRowPresenter} which has shadow support
- * enabled or not depending on {@link CardRow#useShadow()} for a given row.
- */
-public class ShadowRowPresenterSelector extends PresenterSelector {
-
-    private ListRowPresenter mShadowEnabledRowPresenter = new ListRowPresenter();
-    private ListRowPresenter mShadowDisabledRowPresenter = new ListRowPresenter();
-
-    public ShadowRowPresenterSelector() {
-        mShadowDisabledRowPresenter.setShadowEnabled(false);
-    }
-
-    @Override public Presenter getPresenter(Object item) {
-        if (!(item instanceof CardListRow)) return mShadowDisabledRowPresenter;
-        CardListRow listRow = (CardListRow) item;
-        CardRow row = listRow.getCardRow();
-        if (row.useShadow()) return mShadowEnabledRowPresenter;
-        return mShadowDisabledRowPresenter;
-    }
-
-    @Override
-    public Presenter[] getPresenters() {
-        return new Presenter [] {
-                mShadowDisabledRowPresenter,
-                mShadowEnabledRowPresenter
-        };
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/dialog/DialogExampleActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/dialog/DialogExampleActivity.java
deleted file mode 100644
index 0c71739..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/dialog/DialogExampleActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.support.v17.leanback.supportleanbackshowcase.app.dialog;
-
-import android.app.Activity;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Bundle;
-import android.support.v17.leanback.app.GuidedStepFragment;
-
-/**
- * TODO: Javadoc
- */
-public class DialogExampleActivity extends Activity {
-
-    @Override public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        getWindow().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#21272A")));
-
-        if (savedInstanceState == null) {
-            GuidedStepFragment fragment = new DialogExampleFragment();
-            GuidedStepFragment.addAsRoot(this, fragment, android.R.id.content);
-        }
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/dialog/DialogExampleFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/dialog/DialogExampleFragment.java
deleted file mode 100644
index 80b22a9..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/dialog/DialogExampleFragment.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.dialog;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v17.leanback.app.GuidedStepFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
-import android.support.v17.leanback.widget.GuidedAction;
-import android.widget.Toast;
-
-import java.util.List;
-
-/**
- * TODO: Javadoc
- */
-public class DialogExampleFragment extends GuidedStepFragment {
-
-    private static final int ACTION_ID_POSITIVE = 1;
-    private static final int ACTION_ID_NEGATIVE = ACTION_ID_POSITIVE + 1;
-
-    @NonNull
-    @Override
-    public Guidance onCreateGuidance(Bundle savedInstanceState) {
-        Guidance guidance = new Guidance(getString(R.string.dialog_example_title),
-                getString(R.string.dialog_example_description),
-                "", null);
-        return guidance;
-    }
-
-    @Override
-    public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
-        GuidedAction action = new GuidedAction.Builder()
-                .id(ACTION_ID_POSITIVE)
-                .title(getString(R.string.dialog_example_button_positive)).build();
-        actions.add(action);
-        action = new GuidedAction.Builder()
-                .id(ACTION_ID_NEGATIVE)
-                .title(getString(R.string.dialog_example_button_negative)).build();
-        actions.add(action);
-    }
-
-    @Override
-    public void onGuidedActionClicked(GuidedAction action) {
-        if (ACTION_ID_POSITIVE == action.getId()) {
-            Toast.makeText(getActivity(), R.string.dialog_example_button_toast_positive_clicked,
-                    Toast.LENGTH_SHORT).show();
-        } else {
-            Toast.makeText(getActivity(), R.string.dialog_example_button_toast_negative_clicked,
-                    Toast.LENGTH_SHORT).show();
-        }
-        getActivity().finish();
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/grid/GridExampleActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/grid/GridExampleActivity.java
deleted file mode 100644
index e2d0887..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/grid/GridExampleActivity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.support.v17.leanback.supportleanbackshowcase.app.grid;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-
-/**
- * TODO: Javadoc
- */
-public class GridExampleActivity extends Activity {
-
-    @Override public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_grid_example);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/grid/GridExampleFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/grid/GridExampleFragment.java
deleted file mode 100644
index 6640b51..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/grid/GridExampleFragment.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.grid;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v17.leanback.app.VerticalGridFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.utils.Utils;
-import android.support.v17.leanback.supportleanbackshowcase.models.CardRow;
-import android.support.v17.leanback.supportleanbackshowcase.cards.presenters.CardPresenterSelector;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.FocusHighlight;
-import android.support.v17.leanback.widget.PresenterSelector;
-import android.support.v17.leanback.widget.VerticalGridPresenter;
-
-import com.google.gson.Gson;
-
-/**
- * An example how to use leanback's {@link VerticalGridFragment}.
- */
-public class GridExampleFragment extends VerticalGridFragment {
-
-    private static final int COLUMNS = 4;
-    private static final int ZOOM_FACTOR = FocusHighlight.ZOOM_FACTOR_MEDIUM;
-
-    private ArrayObjectAdapter mAdapter;
-
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setTitle(getString(R.string.grid_example_title));
-        setupRowAdapter();
-    }
-
-    private void setupRowAdapter() {
-        VerticalGridPresenter gridPresenter = new VerticalGridPresenter(ZOOM_FACTOR);
-        gridPresenter.setNumberOfColumns(COLUMNS);
-        setGridPresenter(gridPresenter);
-
-        PresenterSelector cardPresenterSelector = new CardPresenterSelector(getActivity());
-        mAdapter = new ArrayObjectAdapter(cardPresenterSelector);
-        setAdapter(mAdapter);
-
-        prepareEntranceTransition();
-        new Handler().postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                createRows();
-                startEntranceTransition();
-            }
-        }, 1000);
-    }
-
-    private void createRows() {
-        String json = Utils.inputStreamToString(getResources()
-                .openRawResource(R.raw.grid_example));
-        CardRow row = new Gson().fromJson(json, CardRow.class);
-        mAdapter.addAll(0, row.getCards());
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/MediaPlayerGlue.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/MediaPlayerGlue.java
deleted file mode 100644
index f64899e..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/MediaPlayerGlue.java
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.media;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.net.Uri;
-import android.os.Handler;
-import android.support.v17.leanback.app.PlaybackControlGlue;
-import android.support.v17.leanback.app.PlaybackOverlayFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.widget.Action;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.ControlButtonPresenterSelector;
-import android.support.v17.leanback.widget.OnItemViewSelectedListener;
-import android.support.v17.leanback.widget.PlaybackControlsRow;
-import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.Row;
-import android.support.v17.leanback.widget.RowPresenter;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.SurfaceHolder;
-import android.view.View;
-
-import java.io.IOException;
-
-/**
- * This glue extends the {@link PlaybackControlGlue} with a {@link MediaPlayer} synchronization. It
- * supports 7 actions: <ul> <li>{@link android.support.v17.leanback.widget.PlaybackControlsRow.FastForwardAction}</li>
- * <li>{@link android.support.v17.leanback.widget.PlaybackControlsRow.RewindAction}</li> <li>{@link
- * android.support.v17.leanback.widget.PlaybackControlsRow.PlayPauseAction}</li> <li>{@link
- * android.support.v17.leanback.widget.PlaybackControlsRow.ShuffleAction}</li> <li>{@link
- * android.support.v17.leanback.widget.PlaybackControlsRow.RepeatAction}</li> <li>{@link
- * android.support.v17.leanback.widget.PlaybackControlsRow.ThumbsDownAction}</li> <li>{@link
- * android.support.v17.leanback.widget.PlaybackControlsRow.ThumbsUpAction}</li> </ul>
- * <p/>
- */
-public abstract class MediaPlayerGlue extends PlaybackControlGlue implements
-        OnItemViewSelectedListener {
-
-    public static final int FAST_FORWARD_REWIND_STEP = 10 * 1000; // in milliseconds
-    public static final int FAST_FORWARD_REWIND_REPEAT_DELAY = 200; // in milliseconds
-    private static final String TAG = "MediaPlayerGlue";
-    protected final PlaybackControlsRow.ThumbsDownAction mThumbsDownAction;
-    protected final PlaybackControlsRow.ThumbsUpAction mThumbsUpAction;
-    private final Context mContext;
-    private final MediaPlayer mPlayer = new MediaPlayer();
-    private final PlaybackControlsRow.RepeatAction mRepeatAction;
-    private final PlaybackControlsRow.ShuffleAction mShuffleAction;
-    private PlaybackControlsRow mControlsRow;
-    private Runnable mRunnable;
-    private Handler mHandler = new Handler();
-    private boolean mInitialized = false; // true when the MediaPlayer is prepared/initialized
-    private OnMediaFileFinishedPlayingListener mMediaFileFinishedPlayingListener;
-    private Action mSelectedAction; // the action which is currently selected by the user
-    private long mLastKeyDownEvent = 0L; // timestamp when the last DPAD_CENTER KEY_DOWN occurred
-    private MetaData mMetaData;
-    private Uri mMediaSourceUri = null;
-    private String mMediaSourcePath = null;
-
-    public MediaPlayerGlue(Context context, PlaybackOverlayFragment fragment) {
-        super(context, fragment, new int[]{1});
-        mContext = context;
-
-        // Instantiate secondary actions
-        mShuffleAction = new PlaybackControlsRow.ShuffleAction(mContext);
-        mRepeatAction = new PlaybackControlsRow.RepeatAction(mContext);
-        mThumbsDownAction = new PlaybackControlsRow.ThumbsDownAction(mContext);
-        mThumbsUpAction = new PlaybackControlsRow.ThumbsUpAction(mContext);
-        mThumbsDownAction.setIndex(PlaybackControlsRow.ThumbsAction.OUTLINE);
-        mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsAction.OUTLINE);
-
-        // Register selected listener such that we know what action the user currently has focused.
-        fragment.setOnItemViewSelectedListener(this);
-    }
-
-    /**
-     * Will reset the {@link MediaPlayer} and the glue such that a new file can be played. You are
-     * not required to call this method before playing the first file. However you have to call it
-     * before playing a second one.
-     */
-    void reset() {
-        mInitialized = false;
-        mPlayer.reset();
-    }
-
-    public void setOnMediaFileFinishedPlayingListener(OnMediaFileFinishedPlayingListener listener) {
-        mMediaFileFinishedPlayingListener = listener;
-    }
-
-    /**
-     * Override this method in case you need to add different secondary actions.
-     *
-     * @param secondaryActionsAdapter The adapter you need to add the {@link Action}s to.
-     */
-    protected void addSecondaryActions(ArrayObjectAdapter secondaryActionsAdapter) {
-        secondaryActionsAdapter.add(mShuffleAction);
-        secondaryActionsAdapter.add(mRepeatAction);
-        secondaryActionsAdapter.add(mThumbsDownAction);
-        secondaryActionsAdapter.add(mThumbsUpAction);
-    }
-
-    /**
-     * @see MediaPlayer#setDisplay(SurfaceHolder)
-     */
-    public void setDisplay(SurfaceHolder surfaceHolder) {
-        mPlayer.setDisplay(surfaceHolder);
-    }
-
-    /**
-     * Use this method to setup the {@link PlaybackControlsRowPresenter}. It'll be called
-     * <u>after</u> the {@link PlaybackControlsRowPresenter} has been created and the primary and
-     * secondary actions have been added.
-     *
-     * @param presenter The PlaybackControlsRowPresenter used to display the controls.
-     */
-    public void setupControlsRowPresenter(PlaybackControlsRowPresenter presenter) {
-        // TODO: hahnr@ move into resources
-        presenter.setProgressColor(getContext().getResources().getColor(
-                R.color.player_progress_color));
-        presenter.setBackgroundColor(getContext().getResources().getColor(
-                R.color.player_background_color));
-    }
-
-    @Override public PlaybackControlsRowPresenter createControlsRowAndPresenter() {
-        PlaybackControlsRowPresenter presenter = super.createControlsRowAndPresenter();
-        mControlsRow = getControlsRow();
-
-        // Add secondary actions and change the control row color.
-        ArrayObjectAdapter secondaryActions = new ArrayObjectAdapter(
-                new ControlButtonPresenterSelector());
-        mControlsRow.setSecondaryActionsAdapter(secondaryActions);
-        addSecondaryActions(secondaryActions);
-        setupControlsRowPresenter(presenter);
-        return presenter;
-    }
-
-    @Override public void enableProgressUpdating(final boolean enabled) {
-        if (!enabled) {
-            if (mRunnable != null) mHandler.removeCallbacks(mRunnable);
-            return;
-        }
-        mRunnable = new Runnable() {
-            @Override public void run() {
-                updateProgress();
-                Log.d(TAG, "enableProgressUpdating(boolean)");
-                mHandler.postDelayed(this, getUpdatePeriod());
-            }
-        };
-        mHandler.postDelayed(mRunnable, getUpdatePeriod());
-    }
-
-    @Override public void onActionClicked(Action action) {
-        // If either 'Shuffle' or 'Repeat' has been clicked we need to make sure the acitons index
-        // is incremented and the UI updated such that we can display the new state.
-        super.onActionClicked(action);
-        if (action instanceof PlaybackControlsRow.ShuffleAction) {
-            mShuffleAction.nextIndex();
-        } else if (action instanceof PlaybackControlsRow.RepeatAction) {
-            mRepeatAction.nextIndex();
-        } else if (action instanceof PlaybackControlsRow.ThumbsUpAction) {
-            if (mThumbsUpAction.getIndex() == PlaybackControlsRow.ThumbsAction.SOLID) {
-                mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsAction.OUTLINE);
-            } else {
-                mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsAction.SOLID);
-                mThumbsDownAction.setIndex(PlaybackControlsRow.ThumbsAction.OUTLINE);
-            }
-        } else if (action instanceof PlaybackControlsRow.ThumbsDownAction) {
-            if (mThumbsDownAction.getIndex() == PlaybackControlsRow.ThumbsAction.SOLID) {
-                mThumbsDownAction.setIndex(PlaybackControlsRow.ThumbsAction.OUTLINE);
-            } else {
-                mThumbsDownAction.setIndex(PlaybackControlsRow.ThumbsAction.SOLID);
-                mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsAction.OUTLINE);
-            }
-        }
-        onMetadataChanged();
-    }
-
-    @Override public boolean onKey(View v, int keyCode, KeyEvent event) {
-        // This method is overridden in order to make implement fast forwarding and rewinding when
-        // the user keeps the corresponding action pressed.
-        // We only consume DPAD_CENTER Action_DOWN events on the Fast-Forward and Rewind action and
-        // only if it has not been pressed in the last X milliseconds.
-        boolean consume = mSelectedAction instanceof PlaybackControlsRow.RewindAction;
-        consume = consume || mSelectedAction instanceof PlaybackControlsRow.FastForwardAction;
-        consume = consume && mInitialized;
-        consume = consume && event.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER;
-        consume = consume && event.getAction() == KeyEvent.ACTION_DOWN;
-        consume = consume && System
-                .currentTimeMillis() - mLastKeyDownEvent > FAST_FORWARD_REWIND_REPEAT_DELAY;
-        if (consume) {
-            mLastKeyDownEvent = System.currentTimeMillis();
-            int newPosition = getCurrentPosition() + FAST_FORWARD_REWIND_STEP;
-            if (mSelectedAction instanceof PlaybackControlsRow.RewindAction) {
-                newPosition = getCurrentPosition() - FAST_FORWARD_REWIND_STEP;
-            }
-            // Make sure the new calculated duration is in the range 0 >= X >= MediaDuration
-            if (newPosition < 0) newPosition = 0;
-            if (newPosition > getMediaDuration()) newPosition = getMediaDuration();
-            seekTo(newPosition);
-            return true;
-        }
-        return super.onKey(v, keyCode, event);
-    }
-
-    @Override public boolean hasValidMedia() {
-        return mMetaData != null;
-    }
-
-    @Override public boolean isMediaPlaying() {
-        return mPlayer.isPlaying();
-    }
-
-    @Override public CharSequence getMediaTitle() {
-        return hasValidMedia() ? mMetaData.getTitle() : "N/a";
-    }
-
-    @Override public CharSequence getMediaSubtitle() {
-        return hasValidMedia() ? mMetaData.getArtist() : "N/a";
-    }
-
-    @Override public int getMediaDuration() {
-        return mInitialized ? mPlayer.getDuration() : 0;
-    }
-
-    @Override public Drawable getMediaArt() {
-        return hasValidMedia() ? mMetaData.getCover() : null;
-    }
-
-    @Override public long getSupportedActions() {
-        return PlaybackControlGlue.ACTION_PLAY_PAUSE | PlaybackControlGlue.ACTION_FAST_FORWARD | PlaybackControlGlue.ACTION_REWIND;
-    }
-
-    @Override public int getCurrentSpeedId() {
-        // 0 = Pause, 1 = Normal Playback Speed
-        return mPlayer.isPlaying() ? 1 : 0;
-    }
-
-    @Override public int getCurrentPosition() {
-        return mInitialized ? mPlayer.getCurrentPosition() : 0;
-    }
-
-    @Override protected void startPlayback(int speed) throws IllegalStateException {
-        mPlayer.start();
-    }
-
-    @Override protected void pausePlayback() {
-        if (mPlayer.isPlaying()) {
-            mPlayer.pause();
-        }
-    }
-
-    @Override protected void skipToNext() {
-        // Not supported.
-    }
-
-    @Override protected void skipToPrevious() {
-        // Not supported.
-    }
-
-    /**
-     * Called whenever the user presses fast-forward/rewind or when the user keeps the corresponding
-     * action pressed.
-     *
-     * @param newPosition The new position of the media track in milliseconds.
-     */
-    protected void seekTo(int newPosition) {
-        mPlayer.seekTo(newPosition);
-    }
-
-    /**
-     * Sets the media source of the player witha given URI.
-     * @see MediaPlayer#setDataSource(String)
-     * @return Returns <code>true</code> if uri represents a new media; <code>false</code>
-     * otherwise.
-     */
-    public boolean setMediaSource(Uri uri) {
-        if (mMediaSourceUri != null && mMediaSourceUri.equals(uri)) {
-            return false;
-        }
-        mMediaSourceUri = uri;
-        return true;
-    }
-
-    /**
-     * Sets the media source of the player with a String path URL.
-     * @see MediaPlayer#setDataSource(String)
-     * @return Returns <code>true</code> if path represents a new media; <code>false</code>
-     * otherwise.
-     */
-    public boolean setMediaSource(String path) {
-        if (mMediaSourcePath != null && mMediaSourcePath.equals(mMediaSourcePath)) {
-            return false;
-        }
-        mMediaSourcePath = path;
-        return true;
-    }
-
-    public void prepareMediaForPlaying() {
-        reset();
-        try {
-            if (mMediaSourceUri != null) mPlayer.setDataSource(getContext(), mMediaSourceUri);
-            else mPlayer.setDataSource(mMediaSourcePath);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
-        mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
-            @Override public void onPrepared(MediaPlayer mp) {
-                mInitialized = true;
-                mPlayer.start();
-                onMetadataChanged();
-                onStateChanged();
-                updateProgress();
-            }
-        });
-        mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
-            @Override public void onCompletion(MediaPlayer mp) {
-                if (mInitialized && mMediaFileFinishedPlayingListener != null)
-                    mMediaFileFinishedPlayingListener.onMediaFileFinishedPlaying(mMetaData);
-            }
-        });
-        mPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
-            @Override public void onBufferingUpdate(MediaPlayer mp, int percent) {
-                mControlsRow.setBufferedProgress((int) (mp.getDuration() * (percent / 100f)));
-            }
-        });
-        mPlayer.prepareAsync();
-        onStateChanged();
-    }
-
-    /**
-     * Call to <code>startPlayback(1)</code>.
-     *
-     * @throws IllegalStateException See {@link MediaPlayer} for further information about it's
-     * different states when setting a data source and preparing it to be played.
-     */
-    public void startPlayback() throws IllegalStateException {
-        startPlayback(1);
-    }
-
-    /**
-     * @return Returns <code>true</code> iff 'Shuffle' is <code>ON</code>.
-     */
-    public boolean useShuffle() {
-        return mShuffleAction.getIndex() == PlaybackControlsRow.ShuffleAction.ON;
-    }
-
-    /**
-     * @return Returns <code>true</code> iff 'Repeat-One' is <code>ON</code>.
-     */
-    public boolean repeatOne() {
-        return mRepeatAction.getIndex() == PlaybackControlsRow.RepeatAction.ONE;
-    }
-
-    /**
-     * @return Returns <code>true</code> iff 'Repeat-All' is <code>ON</code>.
-     */
-    public boolean repeatAll() {
-        return mRepeatAction.getIndex() == PlaybackControlsRow.RepeatAction.ALL;
-    }
-
-    public void setMetaData(MetaData metaData) {
-        mMetaData = metaData;
-        onMetadataChanged();
-    }
-
-    /**
-     * This is a listener implementation for the {@link OnItemViewSelectedListener} of the {@link
-     * PlaybackOverlayFragment}. This implementation is required in order to detect KEY_DOWN events
-     * on the {@link android.support.v17.leanback.widget.PlaybackControlsRow.FastForwardAction} and
-     * {@link android.support.v17.leanback.widget.PlaybackControlsRow.RewindAction}. Thus you should
-     * <u>NOT</u> set another {@link OnItemViewSelectedListener} on your {@link
-     * PlaybackOverlayFragment}. Instead, override this method and call its super (this)
-     * implementation.
-     *
-     * @see OnItemViewSelectedListener#onItemSelected(Presenter.ViewHolder, Object,
-     * RowPresenter.ViewHolder, Row)
-     */
-    @Override public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
-                                         RowPresenter.ViewHolder rowViewHolder, Row row) {
-        if (item instanceof Action) {
-            mSelectedAction = (Action) item;
-        } else {
-            mSelectedAction = null;
-        }
-    }
-
-    /**
-     * A listener which will be called whenever a track is finished playing.
-     */
-    public interface OnMediaFileFinishedPlayingListener {
-
-        /**
-         * Called when a track is finished playing.
-         *
-         * @param metaData The track's {@link MetaData} which just finished playing.
-         */
-        void onMediaFileFinishedPlaying(MetaData metaData);
-
-    }
-
-    /**
-     * Holds the meta data such as track title, artist and cover art. It'll be used by the {@link
-     * MediaPlayerGlue}.
-     */
-    public static class MetaData {
-
-        private String mTitle;
-        private String mArtist;
-        private Drawable mCover;
-
-        public String getTitle() {
-            return mTitle;
-        }
-
-        public void setTitle(String title) {
-            this.mTitle = title;
-        }
-
-        public String getArtist() {
-            return mArtist;
-        }
-
-        public void setArtist(String artist) {
-            this.mArtist = artist;
-        }
-
-        public Drawable getCover() {
-            return mCover;
-        }
-
-        public void setCover(Drawable cover) {
-            this.mCover = cover;
-        }
-
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/MusicConsumptionExampleFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/MusicConsumptionExampleFragment.java
deleted file mode 100644
index 0650cfc..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/MusicConsumptionExampleFragment.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.media;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v17.leanback.app.PlaybackOverlayFragment;
-import android.support.v17.leanback.supportleanbackshowcase.utils.Constants;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.utils.Utils;
-import android.support.v17.leanback.supportleanbackshowcase.models.Song;
-import android.support.v17.leanback.supportleanbackshowcase.models.SongList;
-import android.support.v17.leanback.widget.*;
-import android.support.v17.leanback.widget.AbstractMediaItemPresenter;
-import android.util.Log;
-
-import com.google.gson.Gson;
-
-import java.util.List;
-
-/**
- * This example shows how to play music files and build a simple track list.
- */
-public class MusicConsumptionExampleFragment extends PlaybackOverlayFragment implements
-        BaseOnItemViewClickedListener, BaseOnItemViewSelectedListener,
-        MediaPlayerGlue.OnMediaFileFinishedPlayingListener {
-
-    private static final String TAG = "MusicConsumptionExampleFragment";
-    private static final int PLAYLIST_ACTION_ID = 0;
-    private static final int FAVORITE_ACTION_ID = 1;
-    private ArrayObjectAdapter mRowsAdapter;
-    private MediaPlayerGlue mGlue;
-    private int mCurrentSongIndex = 0;
-    private List<Song> mSongList;
-    private boolean mAdapterNotified = false;
-
-    @Override public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        if (Constants.LOCAL_LOGD) Log.d(TAG, "onCreate");
-
-        mGlue = new MediaPlayerGlue(getActivity(), this) {
-
-            @Override protected void onRowChanged(PlaybackControlsRow row) {
-                if (mRowsAdapter == null || mAdapterNotified) return;
-                //mAdapterNotified = true;
-                mRowsAdapter.notifyArrayItemRangeChanged(0, 1);
-            }
-        };
-        mGlue.setOnMediaFileFinishedPlayingListener(this);
-
-        String json = Utils.inputStreamToString(
-                getResources().openRawResource(R.raw.music_consumption_example));
-
-
-        mSongList = new Gson().fromJson(json, SongList.class).getSongs();
-
-        Resources res = getActivity().getResources();
-
-        // For each song add a playlist and favorite actions.
-        for(Song song : mSongList) {
-            MultiActionsProvider.MultiAction[] mediaRowActions = new
-                    MultiActionsProvider.MultiAction[2];
-            MultiActionsProvider.MultiAction playlistAction = new
-                    MultiActionsProvider.MultiAction(PLAYLIST_ACTION_ID);
-            Drawable[] playlistActionDrawables = new Drawable[] {
-                    res.getDrawable(R.drawable.ic_playlist_add_white_24dp,
-                            getActivity().getTheme()),
-                    res.getDrawable(R.drawable.ic_playlist_add_filled_24dp,
-                            getActivity().getTheme())};
-            playlistAction.setDrawables(playlistActionDrawables);
-            mediaRowActions[0] = playlistAction;
-
-            MultiActionsProvider.MultiAction favoriteAction = new
-                    MultiActionsProvider.MultiAction(FAVORITE_ACTION_ID);
-            Drawable[] favoriteActionDrawables = new Drawable[] {
-                    res.getDrawable(R.drawable.ic_favorite_border_white_24dp,
-                            getActivity().getTheme()),
-                    res.getDrawable(R.drawable.ic_favorite_filled_24dp,
-                            getActivity().getTheme())};
-            favoriteAction.setDrawables(favoriteActionDrawables);
-            mediaRowActions[1] = favoriteAction;
-            song.setMediaRowActions(mediaRowActions);
-        }
-
-        Song song = mSongList.get(mCurrentSongIndex);
-        MediaPlayerGlue.MetaData metaData = new MediaPlayerGlue.MetaData();
-        metaData.setArtist(song.getDescription());
-        metaData.setTitle(song.getTitle());
-        metaData.setCover(getResources().getDrawable(song.getImageResource(getActivity()), null));
-        Uri uri = Utils.getResourceUri(getActivity(), song.getFileResource(getActivity()));
-        mGlue.setMetaData(metaData);
-        mGlue.setMediaSource(uri);
-        mGlue.prepareMediaForPlaying();
-
-        addPlaybackControlsRow();
-    }
-
-    @Override public void onStart() {
-        super.onStart();
-        mGlue.enableProgressUpdating(mGlue.hasValidMedia() && mGlue.isMediaPlaying());
-    }
-
-    @Override public void onStop() {
-        super.onStop();
-        mGlue.enableProgressUpdating(false);
-        mGlue.reset();
-    }
-
-    static class SongPresenter extends AbstractMediaItemPresenter {
-
-        SongPresenter() {
-            super();
-        }
-
-        SongPresenter(Context context, int themeResId) {
-            super(themeResId);
-            setHasMediaRowSeparator(true);
-        }
-
-        @Override
-        protected void onBindMediaDetails(ViewHolder vh, Object item) {
-
-            int favoriteTextColor =  vh.view.getContext().getResources().getColor(
-                    R.color.song_row_favorite_color);
-            Song song = (Song) item;
-            vh.getMediaItemNumberView().setText("" + song.getNumber());
-
-            String songTitle = song.getTitle() + " / " + song.getDescription();
-            vh.getMediaItemNameView().setText(songTitle);
-
-            vh.getMediaItemDurationView().setText("" + song.getDuration());
-
-            if (song.isFavorite()) {
-                vh.getMediaItemNumberView().setTextColor(favoriteTextColor);
-                vh.getMediaItemNameView().setTextColor(favoriteTextColor);
-                vh.getMediaItemDurationView().setTextColor(favoriteTextColor);
-            } else {
-                Context context = vh.getMediaItemNumberView().getContext();
-                vh.getMediaItemNumberView().setTextAppearance(context,
-                        R.style.TextAppearance_Leanback_PlaybackMediaItemNumber);
-                vh.getMediaItemNameView().setTextAppearance(context,
-                        R.style.TextAppearance_Leanback_PlaybackMediaItemName);
-                vh.getMediaItemDurationView().setTextAppearance(context,
-                        R.style.TextAppearance_Leanback_PlaybackMediaItemDuration);
-            }
-        }
-    };
-
-    static class SongPresenterSelector extends PresenterSelector {
-        Presenter mRegularPresenter;
-        Presenter mFavoritePresenter;
-
-        /**
-         * Adds a presenter to be used for the given class.
-         */
-        public SongPresenterSelector setSongPresenterRegular(Presenter presenter) {
-            mRegularPresenter = presenter;
-            return this;
-        }
-
-        /**
-         * Adds a presenter to be used for the given class.
-         */
-        public SongPresenterSelector setSongPresenterFavorite(Presenter presenter) {
-            mFavoritePresenter = presenter;
-            return this;
-        }
-
-        @Override
-        public Presenter[] getPresenters() {
-            return new Presenter[]{mRegularPresenter, mFavoritePresenter};
-        }
-
-        @Override
-        public Presenter getPresenter(Object item) {
-            return ( (Song) item).isFavorite() ? mFavoritePresenter : mRegularPresenter;
-        }
-
-    }
-
-    static class TrackListHeaderPresenter extends AbstractMediaListHeaderPresenter {
-
-        TrackListHeaderPresenter() {
-            super();
-        }
-
-        @Override
-        protected void onBindMediaListHeaderViewHolder(ViewHolder vh, Object item) {
-            vh.getHeaderView().setText("Tracklist");
-        }
-    };
-
-    private void addPlaybackControlsRow() {
-        mRowsAdapter = new ArrayObjectAdapter(new ClassPresenterSelector()
-                .addClassPresenterSelector(Song.class, new SongPresenterSelector()
-                        .setSongPresenterRegular(new SongPresenter(getActivity(),
-                                R.style.Theme_Example_LeanbackMusic_RegularSongNumbers))
-                        .setSongPresenterFavorite(new SongPresenter(getActivity(),
-                                R.style.Theme_Example_LeanbackMusic_FavoriteSongNumbers)))
-                .addClassPresenter(TrackListHeader.class, new TrackListHeaderPresenter())
-                .addClassPresenter(PlaybackControlsRow.class,
-                        mGlue.createControlsRowAndPresenter()));
-        mRowsAdapter.add(mGlue.getControlsRow());
-        mRowsAdapter.add(new TrackListHeader());
-        mRowsAdapter.addAll(2, mSongList);
-        setAdapter(mRowsAdapter);
-        setOnItemViewClickedListener(this);
-        setOnItemViewSelectedListener(this);
-    }
-
-    public MusicConsumptionExampleFragment() {
-        super();
-    }
-
-
-
-    @Override public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
-                                        RowPresenter.ViewHolder rowViewHolder, Object row) {
-
-        if (item instanceof  Action) {
-            // if the clicked item is a primary or secondary action in the playback controller
-            mGlue.onActionClicked((Action) item);
-        } else if (row instanceof  Song) {
-            // if a media item row is clicked
-            Song clickedSong = (Song) row;
-            AbstractMediaItemPresenter.ViewHolder songRowVh =
-                    (AbstractMediaItemPresenter.ViewHolder) rowViewHolder;
-
-            // if an action within a media item row is clicked
-            if (item instanceof MultiActionsProvider.MultiAction) {
-                if ( ((MultiActionsProvider.MultiAction) item).getId() == FAVORITE_ACTION_ID) {
-                    MultiActionsProvider.MultiAction favoriteAction =
-                            (MultiActionsProvider.MultiAction) item;
-                    MultiActionsProvider.MultiAction playlistAction =
-                            songRowVh.getMediaItemRowActions()[0];
-                    favoriteAction.incrementIndex();
-                    playlistAction.incrementIndex();;
-
-                    clickedSong.setFavorite(!clickedSong.isFavorite());
-                    songRowVh.notifyDetailsChanged();
-                    songRowVh.notifyActionChanged(playlistAction);
-                    songRowVh.notifyActionChanged(favoriteAction);
-                }
-            } else if (item == null){
-                // if a media item details is clicked, start playing that media item
-                onSongDetailsClicked(clickedSong);
-            }
-
-        }
-
-
-    }
-
-    @Override
-    public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
-                               RowPresenter.ViewHolder rowViewHolder, Object row) {
-    }
-
-
-    public void onSongDetailsClicked(Song song) {
-        int nextSongIndex = mSongList.indexOf(song);
-        mCurrentSongIndex = nextSongIndex;
-        startPlayback();
-    }
-
-
-    @Override public void onMediaFileFinishedPlaying(MediaPlayerGlue.MetaData song) {
-        if (mGlue.repeatOne()) {
-        } else if (mGlue.useShuffle()) {
-            mCurrentSongIndex = (int) (Math.random() * mSongList.size());
-        } else {
-            mCurrentSongIndex++;
-            if (mCurrentSongIndex >= mSongList.size()) {
-                mCurrentSongIndex = 0;
-                if (!mGlue.repeatAll()) {
-                    return;
-                }
-            }
-        }
-        startPlayback();
-    }
-
-    private void startPlayback() {
-        Song song = mSongList.get(mCurrentSongIndex);
-        MediaPlayerGlue.MetaData metaData = new MediaPlayerGlue.MetaData();
-        metaData.setArtist(song.getDescription());
-        metaData.setTitle(song.getTitle());
-        metaData.setCover(getResources().getDrawable(song.getImageResource(getActivity()), null));
-
-        Uri uri = Utils.getResourceUri(getActivity(), song.getFileResource(getActivity()));
-        mGlue.setMetaData(metaData);
-
-        if (mGlue.setMediaSource(uri)) {
-            mGlue.prepareMediaForPlaying();
-        }
-        mGlue.startPlayback();
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/MusicExampleActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/MusicExampleActivity.java
deleted file mode 100644
index 3107ed6..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/MusicExampleActivity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.support.v17.leanback.supportleanbackshowcase.app.media;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-
-/**
- * TODO: Javadoc
- */
-public class MusicExampleActivity extends Activity {
-
-    @Override public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_music_example);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/SongListRow.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/SongListRow.java
deleted file mode 100644
index 4096132..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/SongListRow.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.media;
-
-import android.support.v17.leanback.widget.Row;
-
-public class SongListRow extends Row {}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/TrackListHeader.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/TrackListHeader.java
deleted file mode 100644
index 0206748..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/TrackListHeader.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.media;
-
-import android.support.v17.leanback.widget.Row;
-
-public class TrackListHeader extends Row {
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoConsumptionExampleFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoConsumptionExampleFragment.java
deleted file mode 100644
index ca33b42..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoConsumptionExampleFragment.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.media;
-
-import android.app.Fragment;
-import android.os.Bundle;
-import android.support.v17.leanback.app.PlaybackOverlayFragment;
-import android.support.v17.leanback.widget.Action;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.OnItemViewClickedListener;
-import android.support.v17.leanback.widget.PlaybackControlsRow;
-import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.Row;
-import android.support.v17.leanback.widget.RowPresenter;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-
-
-public class VideoConsumptionExampleFragment extends PlaybackOverlayFragment implements
-        OnItemViewClickedListener, MediaPlayerGlue.OnMediaFileFinishedPlayingListener {
-
-    private static final String URL = "http://techslides.com/demos/sample-videos/small.mp4";
-    public static final String TAG = "VideoConsumptionExampleFragment";
-    private ArrayObjectAdapter mRowsAdapter;
-    private MediaPlayerGlue mGlue;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mGlue = new VideoMediaPlayerGlue(getActivity(), this) {
-
-            @Override
-            protected void onRowChanged(PlaybackControlsRow row) {
-                if (mRowsAdapter == null) return;
-                mRowsAdapter.notifyArrayItemRangeChanged(0, 1);
-            }
-        };
-        mGlue.setOnMediaFileFinishedPlayingListener(this);
-        MediaPlayerGlue.MetaData metaData = new MediaPlayerGlue.MetaData();
-        metaData.setArtist("A Googler");
-        metaData.setTitle("Diving with Sharks");
-        mGlue.setMetaData(metaData);
-        mGlue.setMediaSource(URL);
-        mGlue.prepareMediaForPlaying();
-
-
-        Fragment videoSurfaceFragment = getFragmentManager()
-                .findFragmentByTag(VideoSurfaceFragment.TAG);
-
-        SurfaceView surface = (SurfaceView) videoSurfaceFragment.getView();
-        surface.getHolder().addCallback(new SurfaceHolder.Callback() {
-            @Override
-            public void surfaceCreated(SurfaceHolder holder) {
-                mGlue.setDisplay(holder);
-            }
-
-            @Override
-            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-                // Nothing to do
-            }
-
-            @Override
-            public void surfaceDestroyed(SurfaceHolder holder) {
-            }
-        });
-
-        setBackgroundType(PlaybackOverlayFragment.BG_LIGHT);
-        addPlaybackControlsRow();
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        mGlue.enableProgressUpdating(mGlue.hasValidMedia() && mGlue.isMediaPlaying());
-    }
-
-    @Override
-    public void onStop() {
-        super.onStop();
-        mGlue.enableProgressUpdating(false);
-        mGlue.reset();
-    }
-
-    private void addPlaybackControlsRow() {
-        final PlaybackControlsRowPresenter controlsPresenter = mGlue
-                .createControlsRowAndPresenter();
-        mRowsAdapter = new ArrayObjectAdapter(controlsPresenter);
-        mRowsAdapter.add(mGlue.getControlsRow());
-        setAdapter(mRowsAdapter);
-        setOnItemViewClickedListener(this);
-    }
-
-    @Override
-    public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
-                              RowPresenter.ViewHolder rowViewHolder, Row row) {
-        if (!(item instanceof Action)) return;
-        mGlue.onActionClicked((Action) item);
-    }
-
-
-    @Override
-    public void onMediaFileFinishedPlaying(MediaPlayerGlue.MetaData metaData) {
-        mGlue.startPlayback();
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoExampleActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoExampleActivity.java
deleted file mode 100644
index 2e87654..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoExampleActivity.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.support.v17.leanback.supportleanbackshowcase.app.media;
-
-import android.app.Activity;
-import android.app.FragmentTransaction;
-import android.os.Bundle;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-
-/**
- * TODO: Javadoc
- */
-public class VideoExampleActivity extends Activity {
-
-    public static final String TAG = "VideoExampleActivity";
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_video_example);
-
-        FragmentTransaction ft1 = getFragmentManager().beginTransaction();
-        ft1.replace(R.id.videoFragment, new VideoSurfaceFragment(), VideoSurfaceFragment.TAG);
-        ft1.commit();
-
-        FragmentTransaction ft2 = getFragmentManager().beginTransaction();
-        ft2.add(R.id.videoFragment, new VideoConsumptionExampleFragment(), VideoConsumptionExampleFragment.TAG);
-        ft2.commit();
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoMediaPlayerGlue.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoMediaPlayerGlue.java
deleted file mode 100644
index 52ab09f..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoMediaPlayerGlue.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.media;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.support.v17.leanback.app.PlaybackOverlayFragment;
-import android.support.v17.leanback.supportleanbackshowcase.app.media.MediaPlayerGlue;
-import android.support.v17.leanback.widget.Action;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.PlaybackControlsRow;
-import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
-
-public abstract class VideoMediaPlayerGlue extends MediaPlayerGlue {
-
-    private final PlaybackControlsRow.ClosedCaptioningAction mClosedCaptioningAction;
-
-    public VideoMediaPlayerGlue(Context context, PlaybackOverlayFragment fragment) {
-        super(context, fragment);
-
-        // Instantiate secondary actions
-        mClosedCaptioningAction = new PlaybackControlsRow.ClosedCaptioningAction(context);
-        setFadingEnabled(true);
-    }
-
-    @Override protected void addSecondaryActions(ArrayObjectAdapter secondaryActionsAdapter) {
-        secondaryActionsAdapter.add(mClosedCaptioningAction);
-        secondaryActionsAdapter.add(mThumbsDownAction);
-        secondaryActionsAdapter.add(mThumbsUpAction);
-    }
-
-    @Override public void onActionClicked(Action action) {
-        super.onActionClicked(action);
-        if (action == mClosedCaptioningAction) {
-            mClosedCaptioningAction.nextIndex();
-        }
-    }
-
-    public void setupControlsRowPresenter(PlaybackControlsRowPresenter presenter) {
-        // TODO: hahnr@ move into resources
-        presenter.setProgressColor(Color.parseColor("#EEFF41"));
-        presenter.setBackgroundColor(Color.parseColor("#007236"));
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoSurfaceFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoSurfaceFragment.java
deleted file mode 100644
index 569309d..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/media/VideoSurfaceFragment.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.media;
-
-import android.app.Fragment;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-
-public class VideoSurfaceFragment extends Fragment {
-
-    public static final String TAG = "VideoSurfaceFragment";
-
-    @Override public void onCreate(Bundle savedInstanceState) {
-        Log.d(TAG, "onCreate started");
-        super.onCreate(savedInstanceState);
-
-    }
-
-    @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                                                 Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.video_surface_fragment, null);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/CustomTitleView.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/CustomTitleView.java
deleted file mode 100644
index 10ca3e9..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/CustomTitleView.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.page;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.widget.TitleViewAdapter;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-/**
- * Custom title view to be used in {@link android.support.v17.leanback.app.BrowseFragment}.
- */
-public class CustomTitleView extends RelativeLayout implements TitleViewAdapter.Provider {
-    private final TextView mTitleView;
-    private final ImageView mBadgeView;
-
-    private final TitleViewAdapter mTitleViewAdapter = new TitleViewAdapter() {
-        @Override
-        public View getSearchAffordanceView() {
-            return null;
-        }
-
-        @Override
-        public void setTitle(CharSequence titleText) {
-            CustomTitleView.this.setTitle(titleText);
-        }
-
-        @Override
-        public void setBadgeDrawable(Drawable drawable) {
-            CustomTitleView.this.setBadgeDrawable(drawable);
-        }
-    };
-
-    public CustomTitleView(Context context) {
-        this(context, null);
-    }
-
-    public CustomTitleView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public CustomTitleView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        View root  = LayoutInflater.from(context).inflate(R.layout.custom_titleview, this);
-        mTitleView = (TextView) root.findViewById(R.id.title_tv);
-        mBadgeView = (ImageView)root.findViewById(R.id.title_badge_iv);
-    }
-
-    public void setTitle(CharSequence title) {
-        if (title != null) {
-            mTitleView.setText(title);
-            mTitleView.setVisibility(View.VISIBLE);
-            mBadgeView.setVisibility(View.GONE);
-        }
-    }
-
-
-    public void setBadgeDrawable(Drawable drawable) {
-        if (drawable != null) {
-            mTitleView.setVisibility(View.GONE);
-            mBadgeView.setImageDrawable(drawable);
-            mBadgeView.setVisibility(View.VISIBLE);
-        }
-    }
-
-    @Override
-    public TitleViewAdapter getTitleViewAdapter() {
-        return mTitleViewAdapter;
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/GridFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/GridFragment.java
deleted file mode 100644
index a1a25a5..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/GridFragment.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.page;
-
-import android.app.Fragment;
-import android.os.Bundle;
-import android.support.v17.leanback.app.BrowseFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.transition.TransitionHelper;
-import android.support.v17.leanback.widget.ObjectAdapter;
-import android.support.v17.leanback.widget.OnChildLaidOutListener;
-import android.support.v17.leanback.widget.OnItemViewClickedListener;
-import android.support.v17.leanback.widget.OnItemViewSelectedListener;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.Row;
-import android.support.v17.leanback.widget.RowPresenter;
-import android.support.v17.leanback.widget.VerticalGridPresenter;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * A fragment for rendering items in a vertical grids.
- */
-public class GridFragment extends Fragment implements BrowseFragment.MainFragmentAdapterProvider {
-    private static final String TAG = "VerticalGridFragment";
-    private static boolean DEBUG = false;
-
-    private ObjectAdapter mAdapter;
-    private VerticalGridPresenter mGridPresenter;
-    private VerticalGridPresenter.ViewHolder mGridViewHolder;
-    private OnItemViewSelectedListener mOnItemViewSelectedListener;
-    private OnItemViewClickedListener mOnItemViewClickedListener;
-    private Object mSceneAfterEntranceTransition;
-    private int mSelectedPosition = -1;
-    private BrowseFragment.MainFragmentAdapter mMainFragmentAdapter =
-            new BrowseFragment.MainFragmentAdapter(this) {
-                @Override
-                public void setEntranceTransitionState(boolean state) {
-                    GridFragment.this.setEntranceTransitionState(state);
-                }
-            };
-    /**
-     * Sets the grid presenter.
-     */
-    public void setGridPresenter(VerticalGridPresenter gridPresenter) {
-        if (gridPresenter == null) {
-            throw new IllegalArgumentException("Grid presenter may not be null");
-        }
-        mGridPresenter = gridPresenter;
-        mGridPresenter.setOnItemViewSelectedListener(mViewSelectedListener);
-        if (mOnItemViewClickedListener != null) {
-            mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener);
-        }
-    }
-
-    /**
-     * Returns the grid presenter.
-     */
-    public VerticalGridPresenter getGridPresenter() {
-        return mGridPresenter;
-    }
-
-    /**
-     * Sets the object adapter for the fragment.
-     */
-    public void setAdapter(ObjectAdapter adapter) {
-        mAdapter = adapter;
-        updateAdapter();
-    }
-
-    /**
-     * Returns the object adapter.
-     */
-    public ObjectAdapter getAdapter() {
-        return mAdapter;
-    }
-
-    final private OnItemViewSelectedListener mViewSelectedListener =
-            new OnItemViewSelectedListener() {
-                @Override
-                public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
-                                           RowPresenter.ViewHolder rowViewHolder, Row row) {
-                    int position = mGridViewHolder.getGridView().getSelectedPosition();
-                    if (DEBUG) Log.v(TAG, "grid selected position " + position);
-                    gridOnItemSelected(position);
-                    if (mOnItemViewSelectedListener != null) {
-                        mOnItemViewSelectedListener.onItemSelected(itemViewHolder, item,
-                                rowViewHolder, row);
-                    }
-                }
-            };
-
-    final private OnChildLaidOutListener mChildLaidOutListener =
-            new OnChildLaidOutListener() {
-                @Override
-                public void onChildLaidOut(ViewGroup parent, View view, int position, long id) {
-                    if (position == 0) {
-                        showOrHideTitle();
-                    }
-                }
-            };
-
-    /**
-     * Sets an item selection listener.
-     */
-    public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
-        mOnItemViewSelectedListener = listener;
-    }
-
-    private void gridOnItemSelected(int position) {
-        if (position != mSelectedPosition) {
-            mSelectedPosition = position;
-            showOrHideTitle();
-        }
-    }
-
-    private void showOrHideTitle() {
-        if (mGridViewHolder.getGridView().findViewHolderForAdapterPosition(mSelectedPosition)
-                == null) {
-            return;
-        }
-        if (!mGridViewHolder.getGridView().hasPreviousViewInSameRow(mSelectedPosition)) {
-            mMainFragmentAdapter.getFragmentHost().showTitleView(true);
-        } else {
-            mMainFragmentAdapter.getFragmentHost().showTitleView(false);
-        }
-    }
-
-    /**
-     * Sets an item clicked listener.
-     */
-    public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
-        mOnItemViewClickedListener = listener;
-        if (mGridPresenter != null) {
-            mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener);
-        }
-    }
-
-    /**
-     * Returns the item clicked listener.
-     */
-    public OnItemViewClickedListener getOnItemViewClickedListener() {
-        return mOnItemViewClickedListener;
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                             Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.grid_fragment, container, false);
-    }
-
-    @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        ViewGroup gridDock = (ViewGroup) view.findViewById(R.id.browse_grid_dock);
-        mGridViewHolder = mGridPresenter.onCreateViewHolder(gridDock);
-        gridDock.addView(mGridViewHolder.view);
-        mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener);
-
-        mSceneAfterEntranceTransition = TransitionHelper.createScene(gridDock, new Runnable() {
-            @Override
-            public void run() {
-                setEntranceTransitionState(true);
-            }
-        });
-
-        getMainFragmentAdapter().getFragmentHost().notifyViewCreated(mMainFragmentAdapter);
-        updateAdapter();
-
-    }
-
-    @Override
-    public void onDestroyView() {
-        super.onDestroyView();
-        mGridViewHolder = null;
-    }
-
-    @Override
-    public BrowseFragment.MainFragmentAdapter getMainFragmentAdapter() {
-        return mMainFragmentAdapter;
-    }
-
-    /**
-     * Sets the selected item position.
-     */
-    public void setSelectedPosition(int position) {
-        mSelectedPosition = position;
-        if(mGridViewHolder != null && mGridViewHolder.getGridView().getAdapter() != null) {
-            mGridViewHolder.getGridView().setSelectedPositionSmooth(position);
-        }
-    }
-
-    private void updateAdapter() {
-        if (mGridViewHolder != null) {
-            mGridPresenter.onBindViewHolder(mGridViewHolder, mAdapter);
-            if (mSelectedPosition != -1) {
-                mGridViewHolder.getGridView().setSelectedPosition(mSelectedPosition);
-            }
-        }
-    }
-
-    void setEntranceTransitionState(boolean afterTransition) {
-        mGridPresenter.setEntranceTransitionState(mGridViewHolder, afterTransition);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/PageAndListRowActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/PageAndListRowActivity.java
deleted file mode 100644
index 4d5b309..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/PageAndListRowActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.page;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-
-/**
- * Activity showcasing the use of {@link android.support.v17.leanback.widget.PageRow} and
- * {@link android.support.v17.leanback.widget.ListRow}.
- */
-public class PageAndListRowActivity extends Activity {
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.page_list_row);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/PageAndListRowFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/PageAndListRowFragment.java
deleted file mode 100644
index 3f08a59..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/PageAndListRowFragment.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.page;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v17.leanback.app.BackgroundManager;
-import android.support.v17.leanback.app.BrowseFragment;
-import android.support.v17.leanback.app.RowsFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.app.details.ShadowRowPresenterSelector;
-import android.support.v17.leanback.supportleanbackshowcase.cards.presenters.CardPresenterSelector;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.supportleanbackshowcase.models.CardRow;
-import android.support.v17.leanback.supportleanbackshowcase.utils.CardListRow;
-import android.support.v17.leanback.supportleanbackshowcase.utils.Utils;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.FocusHighlight;
-import android.support.v17.leanback.widget.HeaderItem;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.OnItemViewClickedListener;
-import android.support.v17.leanback.widget.PageRow;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.PresenterSelector;
-import android.support.v17.leanback.widget.Row;
-import android.support.v17.leanback.widget.RowPresenter;
-import android.support.v17.leanback.widget.VerticalGridPresenter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.FrameLayout;
-import android.widget.Toast;
-import com.google.gson.Gson;
-
-/**
- * Sample {@link BrowseFragment} implementation showcasing the use of {@link PageRow} and
- * {@link ListRow}.
- */
-public class PageAndListRowFragment extends BrowseFragment {
-    private static final long HEADER_ID_1 = 1;
-    private static final String HEADER_NAME_1 = "Page Fragment";
-    private static final long HEADER_ID_2 = 2;
-    private static final String HEADER_NAME_2 = "Rows Fragment";
-    private static final long HEADER_ID_3 = 3;
-    private static final String HEADER_NAME_3 = "Settings Fragment";
-    private static final long HEADER_ID_4 = 4;
-    private static final String HEADER_NAME_4 = "User agreement Fragment";
-    private BackgroundManager mBackgroundManager;
-
-    private ArrayObjectAdapter mRowsAdapter;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setupUi();
-        loadData();
-        mBackgroundManager = BackgroundManager.getInstance(getActivity());
-        mBackgroundManager.attach(getActivity().getWindow());
-        getMainFragmentRegistry().registerFragment(PageRow.class,
-                new PageRowFragmentFactory(mBackgroundManager));
-    }
-
-    private void setupUi() {
-        setHeadersState(HEADERS_ENABLED);
-        setHeadersTransitionOnBackEnabled(true);
-        setBrandColor(getResources().getColor(R.color.fastlane_background));
-        setTitle("Title goes here");
-        setOnSearchClickedListener(new View.OnClickListener() {
-
-            @Override
-            public void onClick(View view) {
-                Toast.makeText(
-                        getActivity(), getString(R.string.implement_search), Toast.LENGTH_SHORT)
-                        .show();
-            }
-        });
-
-        prepareEntranceTransition();
-    }
-
-    private void loadData() {
-        mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
-        setAdapter(mRowsAdapter);
-
-        new Handler().postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                createRows();
-                startEntranceTransition();
-            }
-        }, 2000);
-    }
-
-    private void createRows() {
-        HeaderItem headerItem1 = new HeaderItem(HEADER_ID_1, HEADER_NAME_1);
-        PageRow pageRow1 = new PageRow(headerItem1);
-        mRowsAdapter.add(pageRow1);
-
-        HeaderItem headerItem2 = new HeaderItem(HEADER_ID_2, HEADER_NAME_2);
-        PageRow pageRow2 = new PageRow(headerItem2);
-        mRowsAdapter.add(pageRow2);
-
-        HeaderItem headerItem3 = new HeaderItem(HEADER_ID_3, HEADER_NAME_3);
-        PageRow pageRow3 = new PageRow(headerItem3);
-        mRowsAdapter.add(pageRow3);
-
-        HeaderItem headerItem4 = new HeaderItem(HEADER_ID_4, HEADER_NAME_4);
-        PageRow pageRow4 = new PageRow(headerItem4);
-        mRowsAdapter.add(pageRow4);
-    }
-
-    private static class PageRowFragmentFactory extends BrowseFragment.FragmentFactory {
-        private final BackgroundManager mBackgroundManager;
-
-        PageRowFragmentFactory(BackgroundManager backgroundManager) {
-            this.mBackgroundManager = backgroundManager;
-        }
-
-        @Override
-        public Fragment createFragment(Object rowObj) {
-            Row row = (Row)rowObj;
-            mBackgroundManager.setDrawable(null);
-            if (row.getHeaderItem().getId() == HEADER_ID_1) {
-                return new SampleFragmentA();
-            } else if (row.getHeaderItem().getId() == HEADER_ID_2) {
-                return new SampleFragmentB();
-            } else if (row.getHeaderItem().getId() == HEADER_ID_3) {
-                return new SettingsFragment();
-            } else if (row.getHeaderItem().getId() == HEADER_ID_4) {
-                return new WebViewFragment();
-            }
-
-            throw new IllegalArgumentException(String.format("Invalid row %s", rowObj));
-        }
-    }
-
-    public static class PageFragmentAdapterImpl extends MainFragmentAdapter<SampleFragmentA> {
-
-        public PageFragmentAdapterImpl(SampleFragmentA fragment) {
-            super(fragment);
-        }
-    }
-
-    /**
-     * Simple page fragment implementation.
-     */
-    public static class SampleFragmentA extends GridFragment {
-        private static final int COLUMNS = 4;
-        private final int ZOOM_FACTOR = FocusHighlight.ZOOM_FACTOR_SMALL;
-        private ArrayObjectAdapter mAdapter;
-
-        @Override
-        public void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            setupAdapter();
-            loadData();
-            getMainFragmentAdapter().getFragmentHost().notifyDataReady(getMainFragmentAdapter());
-        }
-
-
-        private void setupAdapter() {
-            VerticalGridPresenter presenter = new VerticalGridPresenter(ZOOM_FACTOR);
-            presenter.setNumberOfColumns(COLUMNS);
-            setGridPresenter(presenter);
-
-            CardPresenterSelector cardPresenter = new CardPresenterSelector(getActivity());
-            mAdapter = new ArrayObjectAdapter(cardPresenter);
-            setAdapter(mAdapter);
-
-            setOnItemViewClickedListener(new OnItemViewClickedListener() {
-                @Override
-                public void onItemClicked(
-                        Presenter.ViewHolder itemViewHolder,
-                        Object item,
-                        RowPresenter.ViewHolder rowViewHolder,
-                        Row row) {
-                    Card card = (Card)item;
-                    Toast.makeText(getActivity(),
-                            "Clicked on "+card.getTitle(),
-                            Toast.LENGTH_SHORT).show();
-                }
-            });
-        }
-
-        private void loadData() {
-            String json = Utils.inputStreamToString(getResources().openRawResource(
-                    R.raw.grid_example));
-            CardRow cardRow = new Gson().fromJson(json, CardRow.class);
-            mAdapter.addAll(0, cardRow.getCards());
-        }
-    }
-
-    /**
-     * Page fragment embeds a rows fragment.
-     */
-    public static class SampleFragmentB extends RowsFragment {
-        private final ArrayObjectAdapter mRowsAdapter;
-
-        public SampleFragmentB() {
-            mRowsAdapter = new ArrayObjectAdapter(new ShadowRowPresenterSelector());
-
-            setAdapter(mRowsAdapter);
-            setOnItemViewClickedListener(new OnItemViewClickedListener() {
-                @Override
-                public void onItemClicked(
-                        Presenter.ViewHolder itemViewHolder,
-                        Object item,
-                        RowPresenter.ViewHolder rowViewHolder,
-                        Row row) {
-                    Toast.makeText(getActivity(), "Implement click handler", Toast.LENGTH_SHORT)
-                            .show();
-                }
-            });
-        }
-
-        @Override
-        public void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            createRows();
-            getMainFragmentAdapter().getFragmentHost().notifyDataReady(getMainFragmentAdapter());
-        }
-
-        private void createRows() {
-                String json = Utils.inputStreamToString(getResources().openRawResource(
-                        R.raw.page_row_example));
-                CardRow[] rows = new Gson().fromJson(json, CardRow[].class);
-                for (CardRow row : rows) {
-                    if (row.getType() == CardRow.TYPE_DEFAULT) {
-                        mRowsAdapter.add(createCardRow(row));
-                    }
-                }
-        }
-
-        private Row createCardRow(CardRow cardRow) {
-            PresenterSelector presenterSelector = new CardPresenterSelector(getActivity());
-            ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
-            for (Card card : cardRow.getCards()) {
-                adapter.add(card);
-            }
-
-            HeaderItem headerItem = new HeaderItem(cardRow.getTitle());
-            return new CardListRow(headerItem, adapter, cardRow);
-        }
-    }
-
-    public static class SettingsFragment extends RowsFragment {
-        private final ArrayObjectAdapter mRowsAdapter;
-
-        public SettingsFragment() {
-            ListRowPresenter selector = new ListRowPresenter();
-            selector.setNumRows(2);
-            mRowsAdapter = new ArrayObjectAdapter(selector);
-            setAdapter(mRowsAdapter);
-        }
-
-        @Override
-        public void onAttach(Activity activity) {
-            super.onAttach(activity);
-            new Handler().postDelayed(new Runnable() {
-                @Override
-                public void run() {
-                    loadData();
-                }
-            }, 200);
-        }
-
-        private void loadData() {
-            if (isAdded()) {
-                String json = Utils.inputStreamToString(getResources().openRawResource(
-                        R.raw.icon_example));
-                CardRow cardRow = new Gson().fromJson(json, CardRow.class);
-                mRowsAdapter.add(createCardRow(cardRow));
-                getMainFragmentAdapter().getFragmentHost().notifyDataReady(
-                        getMainFragmentAdapter());
-            }
-        }
-
-        private ListRow createCardRow(CardRow cardRow) {
-            SettingsIconPresenter iconCardPresenter = new SettingsIconPresenter(getActivity());
-            ArrayObjectAdapter adapter = new ArrayObjectAdapter(iconCardPresenter);
-            for(Card card : cardRow.getCards()) {
-                adapter.add(card);
-            }
-
-            HeaderItem headerItem = new HeaderItem(cardRow.getTitle());
-            return new CardListRow(headerItem, adapter, cardRow);
-        }
-    }
-
-    public static class WebViewFragment extends Fragment implements MainFragmentAdapterProvider {
-        private MainFragmentAdapter mMainFragmentAdapter = new MainFragmentAdapter(this);
-        private WebView mWebview;
-
-        @Override
-        public MainFragmentAdapter getMainFragmentAdapter() {
-            return mMainFragmentAdapter;
-        }
-
-        @Override
-        public View onCreateView(
-                LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-            FrameLayout root = new FrameLayout(getActivity());
-            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
-                    FrameLayout.LayoutParams.MATCH_PARENT,
-                    FrameLayout.LayoutParams.MATCH_PARENT);
-            lp.setMarginStart(32);
-            mWebview = new WebView(getActivity());
-            mWebview.setWebViewClient(new WebViewClient());
-            mWebview.getSettings().setJavaScriptEnabled(true);
-            root.addView(mWebview, lp);
-            return root;
-        }
-
-        @Override
-        public void onResume() {
-            super.onResume();
-            mWebview.loadUrl("https://www.google.com/policies/terms");
-            getMainFragmentAdapter().getFragmentHost().notifyDataReady(getMainFragmentAdapter());
-        }
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/SettingsIconPresenter.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/SettingsIconPresenter.java
deleted file mode 100644
index cdc8447..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/page/SettingsIconPresenter.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.page;
-
-import android.content.Context;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.cards.presenters.ImageCardViewPresenter;
-import android.support.v17.leanback.widget.ImageCardView;
-import android.view.View;
-import android.widget.ImageView;
-
-/**
- * Simple presenter implementation to represent settings icon as cards.
- */
-public class SettingsIconPresenter extends ImageCardViewPresenter {
-
-    public SettingsIconPresenter(Context context) {
-        super(context, R.style.IconCardTheme);
-    }
-
-    @Override
-    protected ImageCardView onCreateView() {
-        final ImageCardView imageCardView = super.onCreateView();
-        imageCardView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
-            @Override
-            public void onFocusChange(View v, boolean hasFocus) {
-                if (hasFocus) {
-                    setImageBackground(imageCardView, R.color.settings_card_background_focussed);
-                } else {
-                    setImageBackground(imageCardView, R.color.settings_card_background);
-                }
-            }
-        });
-        setImageBackground(imageCardView, R.color.settings_card_background);
-        return imageCardView;
-    }
-
-    private void setImageBackground(ImageCardView imageCardView, int colorId) {
-        imageCardView.setBackgroundColor(getContext().getResources().getColor(colorId));
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/settings/SettingsExampleActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/settings/SettingsExampleActivity.java
deleted file mode 100644
index 01963ca..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/settings/SettingsExampleActivity.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.settings;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.os.Bundle;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-
-/*
- * TODO: Javadoc
- */
-public class SettingsExampleActivity extends Activity {
-
-    @Override public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_settings_example);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/settings/SettingsExampleFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/settings/SettingsExampleFragment.java
deleted file mode 100644
index 0276d53..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/settings/SettingsExampleFragment.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.settings;
-
-import android.app.Fragment;
-import android.content.Context;
-import android.os.Bundle;
-import android.support.v14.preference.PreferenceFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.preference.LeanbackPreferenceFragment;
-import android.support.v17.preference.LeanbackSettingsFragment;
-import android.support.v7.preference.DialogPreference;
-import android.support.v7.preference.ListPreference;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
-import android.widget.Toast;
-
-import java.util.Arrays;
-import java.util.Stack;
-
-public class SettingsExampleFragment extends LeanbackSettingsFragment {
-
-    @Override
-    public void onPreferenceStartInitialScreen() {
-        startPreferenceFragment(buildPreferenceFragment(R.xml.prefs, null));
-    }
-
-    @Override
-    public boolean onPreferenceStartFragment(PreferenceFragment preferenceFragment,
-                                             Preference preference) {
-        return false;
-    }
-
-    @Override
-    public boolean onPreferenceStartScreen(PreferenceFragment preferenceFragment,
-                                           PreferenceScreen preferenceScreen) {
-        PreferenceFragment frag = buildPreferenceFragment(R.xml.prefs, preferenceScreen.getKey());
-        startPreferenceFragment(frag);
-        return true;
-    }
-
-    private PreferenceFragment buildPreferenceFragment(int preferenceResId, String root) {
-        PreferenceFragment fragment = new PrefFragment();
-        Bundle args = new Bundle();
-        args.putInt("preferenceResource", preferenceResId);
-        args.putString("root", root);
-        fragment.setArguments(args);
-        return fragment;
-    }
-
-    public static class PrefFragment extends LeanbackPreferenceFragment {
-
-        @Override
-        public void onCreatePreferences(Bundle bundle, String s) {
-            String root = getArguments().getString("root", null);
-            int prefResId = getArguments().getInt("preferenceResource");
-            if (root == null) {
-                addPreferencesFromResource(prefResId);
-            } else {
-                setPreferencesFromResource(prefResId, root);
-            }
-        }
-
-        @Override
-        public boolean onPreferenceTreeClick(Preference preference) {
-            final String[] keys = {"prefs_wifi_connect_wps", "prefs_date", "prefs_time",
-                    "prefs_date_time_use_timezone", "app_banner_sample_app", "pref_force_stop",
-                    "pref_uninstall", "pref_more_info"};
-            if (Arrays.asList(keys).contains(preference.getKey())) {
-                Toast.makeText(getActivity(), "Implement your own action handler.", Toast.LENGTH_SHORT).show();
-                return true;
-            }
-            return super.onPreferenceTreeClick(preference);
-        }
-
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample1stStepFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample1stStepFragment.java
deleted file mode 100644
index cbfa868..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample1stStepFragment.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.wizard;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v17.leanback.app.GuidedStepFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.widget.GuidanceStylist;
-import android.support.v17.leanback.widget.GuidedAction;
-
-import java.util.List;
-
-/**
- * The first screen of the rental wizard. Gives the user the choice between renting the movie in SD
- * or HD quality.
- */
-public class WizardExample1stStepFragment extends WizardExampleBaseStepFragment {
-
-    private static final int ACTION_ID_BUY_HD = 1;
-    private static final int ACTION_ID_BUY_SD = ACTION_ID_BUY_HD + 1;
-
-    @NonNull
-    @Override
-    public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
-        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(mMovie.getTitle(),
-                getString(R.string.wizard_example_choose_rent_options),
-                mMovie.getBreadcrump(), null);
-        return guidance;
-    }
-
-    @Override
-    public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
-        GuidedAction action = new GuidedAction.Builder(getActivity())
-                .id(ACTION_ID_BUY_HD)
-                .title(R.string.wizard_example_rent_hd)
-                .editable(false)
-                .description(mMovie.getPriceHd() + " " +
-                        getString(R.string.wizard_example_watch_hd))
-                .build();
-        actions.add(action);
-        action = new GuidedAction.Builder(getActivity())
-                .id(ACTION_ID_BUY_SD)
-                .title(getString(R.string.wizard_example_rent_sd))
-                .editable(false)
-                .description(mMovie.getPriceSd() + " " +
-                        getString(R.string.wizard_example_watch_sd))
-                .build();
-        actions.add(action);
-    }
-
-    @Override
-    public void onGuidedActionClicked(GuidedAction action) {
-        boolean rentHd = ACTION_ID_BUY_HD == action.getId();
-        GuidedStepFragment fragment = WizardExample2ndStepFragment.build(rentHd, this);
-        add(getFragmentManager(), fragment);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample2ndStepFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample2ndStepFragment.java
deleted file mode 100644
index f630d59..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample2ndStepFragment.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.wizard;
-
-import android.app.FragmentManager;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v17.leanback.app.GuidedStepFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.widget.GuidanceStylist;
-import android.support.v17.leanback.widget.GuidedAction;
-import android.support.v17.leanback.widget.GuidedActionsStylist;
-import android.widget.Toast;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Displays the second screen of the rental wizard which requires the user to confirm his purchase.
- */
-public class WizardExample2ndStepFragment extends WizardExampleBaseStepFragment {
-
-    private static final String ARG_HD = "hd";
-    private static final int ACTION_ID_CONFIRM = 1;
-    private static final int ACTION_ID_PAYMENT_METHOD = ACTION_ID_CONFIRM + 1;
-    private static final int ACTION_ID_NEW_PAYMENT = ACTION_ID_PAYMENT_METHOD + 1;
-
-    protected static ArrayList<String> sCards = new ArrayList();
-    protected static int sSelectedCard = -1;
-
-    static {
-        sCards.add("Visa-1234");
-        sCards.add("Master-4321");
-    }
-
-
-    public static GuidedStepFragment build(boolean hd, WizardExampleBaseStepFragment previousFragment) {
-        GuidedStepFragment fragment = new WizardExample2ndStepFragment();
-        // Reuse the same arguments this fragment was given.
-        Bundle args = previousFragment.getArguments();
-        args.putBoolean(ARG_HD, hd);
-        fragment.setArguments(args);
-        return fragment;
-    }
-
-    @NonNull
-    @Override
-    public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
-        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(mMovie.getTitle(),
-                getString(R.string.wizard_example_rental_period),
-                mMovie.getBreadcrump(), null);
-        return guidance;
-
-    }
-
-    @Override
-    public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
-        boolean rentHighDefinition = getArguments().getBoolean(ARG_HD);
-
-        GuidedAction action = new GuidedAction.Builder(getActivity())
-                .id(ACTION_ID_CONFIRM)
-                .title(R.string.wizard_example_rent)
-                .description(rentHighDefinition ? mMovie.getPriceHd() : mMovie.getPriceSd())
-                .editable(false)
-                .build();
-        action.setEnabled(false);
-        actions.add(action);
-        List<GuidedAction> subActions = new ArrayList();
-        action = new GuidedAction.Builder(getActivity())
-                .id(ACTION_ID_PAYMENT_METHOD)
-                .title(R.string.wizard_example_payment_method)
-                .editTitle("")
-                .description(R.string.wizard_example_input_credit)
-                .subActions(subActions)
-                .build();
-        actions.add(action);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        GuidedAction payment = findActionById(ACTION_ID_PAYMENT_METHOD);
-
-        List<GuidedAction> paymentSubActions = payment.getSubActions();
-        paymentSubActions.clear();
-        for (int i = 0; i < sCards.size(); i++) {
-            paymentSubActions.add(new GuidedAction.Builder(getActivity())
-                            .title(sCards.get(i))
-                            .description("")
-                            .checkSetId(GuidedAction.DEFAULT_CHECK_SET_ID)
-                            .build()
-            );
-        }
-        paymentSubActions.add(new GuidedAction.Builder(getActivity())
-                .id(ACTION_ID_NEW_PAYMENT)
-                .title("Add New Card")
-                .description("")
-                .editable(false)
-                .build()
-        );
-        if ( sSelectedCard >= 0 && sSelectedCard < sCards.size() ) {
-            payment.setDescription(sCards.get(sSelectedCard));
-            findActionById(ACTION_ID_CONFIRM).setEnabled(true);
-        } else
-            findActionById(ACTION_ID_CONFIRM).setEnabled(false);
-        notifyActionChanged(findActionPositionById(ACTION_ID_CONFIRM));
-    }
-
-    @Override
-    public boolean onSubGuidedActionClicked(GuidedAction action) {
-
-        if (action.isChecked()) {
-            String payment = action.getTitle().toString();
-            if ( (sSelectedCard = sCards.indexOf(payment)) != -1 ) {
-                findActionById(ACTION_ID_PAYMENT_METHOD).setDescription(payment);
-                notifyActionChanged(findActionPositionById(ACTION_ID_PAYMENT_METHOD));
-                findActionById(ACTION_ID_CONFIRM).setEnabled(true);
-                notifyActionChanged(findActionPositionById(ACTION_ID_CONFIRM));
-            }
-            return true;
-        } else {
-            FragmentManager fm = getFragmentManager();
-            GuidedStepFragment fragment = new WizardNewPaymentStepFragment();
-            fragment.setArguments(getArguments());
-            add(fm, fragment);
-            return false;
-        }
-    }
-
-    @Override
-    public void onGuidedActionClicked(GuidedAction action) {
-        if (ACTION_ID_CONFIRM == action.getId()) {
-            GuidedStepFragment fragment = new WizardExample3rdStepFragment();
-            fragment.setArguments(getArguments());
-            add(getFragmentManager(), fragment);
-        }
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample3rdStepFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample3rdStepFragment.java
deleted file mode 100644
index 9a2ec39..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample3rdStepFragment.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.wizard;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.annotation.NonNull;
-import android.support.v17.leanback.app.GuidedStepFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.widget.GuidanceStylist;
-import android.support.v17.leanback.widget.GuidedAction;
-import android.support.v17.leanback.widget.GuidedActionsStylist;
-
-import java.util.List;
-
-/**
- * This is the third screen of the rental wizard which will display a progressbar while waiting for
- * the server to process the rental. The server communication is faked for the sake of this example
- * by waiting four seconds until continuing.
- */
-public class WizardExample3rdStepFragment extends WizardExampleBaseStepFragment {
-
-    private static final int ACTION_ID_PROCESSING = 1;
-    private final Handler mFakeHttpHandler = new Handler();
-
-    @Override
-    public void onStart() {
-        super.onStart();
-
-        // Fake Http call by creating some sort of delay.
-        mFakeHttpHandler.postDelayed(fakeHttpRequestRunnable, 4000L);
-    }
-
-    @Override
-    public GuidedActionsStylist onCreateActionsStylist() {
-        GuidedActionsStylist stylist = new GuidedActionsStylist() {
-            @Override
-            public int onProvideItemLayoutId() {
-                return R.layout.wizard_progress_action_item;
-            }
-
-        };
-        return stylist;
-    }
-
-    @Override
-    public int onProvideTheme() {
-        return R.style.Theme_Example_LeanbackWizard_NoSelector;
-    }
-
-    @Override
-    public void onStop() {
-        super.onStop();
-
-        // Make sure to cancel the execution of the Runnable in case the fragment is stopped.
-        mFakeHttpHandler.removeCallbacks(fakeHttpRequestRunnable);
-    }
-
-    @NonNull
-    @Override
-    public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
-        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(mMovie.getTitle(),
-                getString(R.string.wizard_example_just_a_second),
-                mMovie.getBreadcrump(), null);
-        return guidance;
-    }
-
-    @Override
-    public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
-        GuidedAction action = new GuidedAction.Builder(getActivity())
-                .id(ACTION_ID_PROCESSING)
-                .title(R.string.wizard_example_processing)
-                .infoOnly(true)
-                .build();
-        actions.add(action);
-    }
-
-    private final Runnable fakeHttpRequestRunnable = new Runnable() {
-        @Override
-        public void run() {
-            GuidedStepFragment fragment = new WizardExample4thStepFragment();
-            fragment.setArguments(getArguments());
-            add(getFragmentManager(), fragment);
-        }
-    };
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample4thStepFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample4thStepFragment.java
deleted file mode 100644
index b0cb9aa..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample4thStepFragment.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.wizard;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.app.media.VideoExampleActivity;
-import android.support.v17.leanback.widget.GuidanceStylist;
-import android.support.v17.leanback.widget.GuidedAction;
-import android.support.v4.app.ActivityOptionsCompat;
-import android.widget.Toast;
-
-import java.util.List;
-
-/**
- * The last screen of the Wizard gives to options to either watch the rented movie now or later. Due
- * to keep this example simple and focused on the usage of the GuidedStepFragment, clicking on
- * either action will end the wizard. You might however start a new Activity playing the movie.
- */
-public class WizardExample4thStepFragment extends WizardExampleBaseStepFragment {
-
-    private static final int ACTION_ID_WATCH = 1;
-    private static final int ACTION_ID_LATER = ACTION_ID_WATCH + 1;
-
-    @NonNull
-    @Override
-    public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
-        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(mMovie.getTitle(),
-                getString(R.string.wizard_example_rental_period),
-                mMovie.getBreadcrump(), null);
-        return guidance;
-    }
-
-    @Override
-    public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
-        GuidedAction action = new GuidedAction.Builder(getActivity())
-                .id(ACTION_ID_WATCH)
-                .editable(false)
-                .title(R.string.wizard_example_watch_now)
-                .build();
-        actions.add(action);
-        action = new GuidedAction.Builder(getActivity())
-                .id(ACTION_ID_LATER)
-                .editable(false)
-                .title(R.string.wizard_example_later)
-                .build();
-        actions.add(action);
-    }
-
-    @Override
-    public void onGuidedActionClicked(GuidedAction action) {
-        if (action.getId() == ACTION_ID_WATCH) {
-            finishGuidedStepFragments();
-            Intent intent = new Intent(getActivity().getBaseContext(),
-                    VideoExampleActivity.class);
-            startActivity(intent);
-        } else if (action.getId() == ACTION_ID_LATER) {
-            Toast.makeText(getActivity(), getString(R.string.wizard_example_later_clicked),
-                    Toast.LENGTH_SHORT).show();
-            finishGuidedStepFragments();
-        }
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExampleActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExampleActivity.java
deleted file mode 100644
index 96f71f8..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExampleActivity.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.support.v17.leanback.supportleanbackshowcase.app.wizard;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.os.PersistableBundle;
-import android.support.v17.leanback.app.GuidedStepFragment;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-
-/**
- * An Activity displaying a wizard for renting a movie.
- */
-public class WizardExampleActivity extends Activity {
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        getWindow().setBackgroundDrawableResource(R.drawable.wizard_background_blackned);
-
-        GuidedStepFragment fragment = new WizardExample1stStepFragment();
-        fragment.setArguments(getIntent().getExtras()); // Delegate Movie to first step.
-        GuidedStepFragment.addAsRoot(this, fragment, android.R.id.content);
-    }
-
-    @Override
-    public void onBackPressed() {
-        if (GuidedStepFragment.getCurrentGuidedStepFragment(getFragmentManager())
-                instanceof WizardExample4thStepFragment) {
-            // The user 'bought' the product. When he presses 'Back' the Wizard will be closed and
-            // he will not be send back to 'Processing Payment...'-Screen.
-            finish();
-        } else super.onBackPressed();
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExampleBaseStepFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExampleBaseStepFragment.java
deleted file mode 100644
index 8fd5981..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExampleBaseStepFragment.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.wizard;
-
-import android.os.Bundle;
-import android.support.v17.leanback.app.GuidedStepFragment;
-import android.support.v17.leanback.supportleanbackshowcase.models.Movie;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-
-/**
- * A base class which provides all it's implementations with a method #getWizardActivity(). It also
- * makes sure that the wizard is using the correct theme.
- */
-public abstract class WizardExampleBaseStepFragment extends GuidedStepFragment {
-
-    protected Movie mMovie;
-
-    @Override
-    public int onProvideTheme() {
-        return R.style.Theme_Example_LeanbackWizard;
-    }
-
-    WizardExampleActivity getWizardActivity() {
-        if (!(getActivity() instanceof WizardExampleActivity)) {
-            throw new IllegalStateException(WizardExampleActivity.class.getName() + " expected.");
-        }
-        return (WizardExampleActivity) getActivity();
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        mMovie = (Movie) getArguments().getSerializable("movie");
-        super.onCreate(savedInstanceState);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardNewPaymentStepFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardNewPaymentStepFragment.java
deleted file mode 100644
index a42ab9e..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardNewPaymentStepFragment.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.supportleanbackshowcase.app.wizard;
-
-import android.app.FragmentManager;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.widget.GuidanceStylist;
-import android.support.v17.leanback.widget.GuidedAction;
-import android.support.v17.leanback.widget.GuidedDatePickerAction;
-import android.text.TextUtils;
-
-import java.util.Calendar;
-import java.util.List;
-
-/**
- * A fragment for allowing users to enter a new payment information.
- */
-public class WizardNewPaymentStepFragment extends WizardExampleBaseStepFragment {
-
-    private static final int ACTION_ID_CARD_NUMBER = 1;
-    private static final int ACTION_ID_PAYMENT_EXP = ACTION_ID_CARD_NUMBER + 1;
-
-    @NonNull
-    @Override
-    public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
-        String title = getString(R.string.wizard_example_new_payment_guidance_title);
-        String description = getString(R.string.wizard_example_new_payment_guidance_description);
-        String breadcrumb = mMovie.getBreadcrump();
-
-        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
-                breadcrumb, null);
-        return guidance;
-    }
-
-    @Override
-    public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
-        actions.add(new GuidedAction.Builder(getActivity())
-                        .id(ACTION_ID_CARD_NUMBER)
-                        .title(R.string.wizard_example_input_card)
-                        .editTitle("")
-                        .description(R.string.wizard_example_input_card)
-                        .editDescription("Card number")
-                        .editable(true)
-                        .build()
-        );
-
-        actions.add(new GuidedDatePickerAction.Builder(getActivity())
-                        .id(ACTION_ID_PAYMENT_EXP)
-                        .title(R.string.wizard_example_expiration_date)
-                        .datePickerFormat("MY")
-                        .build()
-        );
-    }
-
-    @Override
-    public void onCreateButtonActions(@NonNull List<GuidedAction> actions,
-                                      Bundle savedInstanceState) {
-        actions.add(new GuidedAction.Builder(getActivity())
-                        .clickAction(GuidedAction.ACTION_ID_OK)
-                        .build()
-        );
-        actions.get(actions.size() - 1).setEnabled(false);
-    }
-
-    @Override
-    public void onGuidedActionClicked(GuidedAction action) {
-        if (action.getId() == GuidedAction.ACTION_ID_OK) {
-            CharSequence cardNumber = findActionById(ACTION_ID_CARD_NUMBER).getDescription();
-            WizardExample2ndStepFragment.sSelectedCard = WizardExample2ndStepFragment.sCards.size();
-            WizardExample2ndStepFragment.sCards.add(cardNumber.toString());
-            popBackStackToGuidedStepFragment(WizardNewPaymentStepFragment.class,
-                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
-        }
-    }
-
-    @Override
-    public long onGuidedActionEditedAndProceed(GuidedAction action) {
-
-        boolean cardNumberCheck = false;
-        boolean expDateCheck = false;
-
-        if (action.getId() == ACTION_ID_CARD_NUMBER) {
-            CharSequence cardNumber = action.getEditTitle();
-            cardNumberCheck = isCardNumberValid(cardNumber);
-            expDateCheck = isExpDateValid(findActionById(ACTION_ID_PAYMENT_EXP));
-            updateOkButton(cardNumberCheck && expDateCheck);
-
-            if (cardNumberCheck) {
-                String last4Digits = cardNumber.subSequence(cardNumber.length() - 4,
-                        cardNumber.length()).toString();
-
-                if ( (Integer.parseInt(last4Digits) & 1) == 0 )
-                    action.setDescription(getString(R.string.wizard_example_visa,
-                            last4Digits));
-                else
-                    action.setDescription(getString(R.string.wizard_example_master,
-                            last4Digits));
-
-                return GuidedAction.ACTION_ID_NEXT;
-            } else if (cardNumber.length() == 0) {
-                action.setDescription(getString(R.string.wizard_example_input_card));
-                return GuidedAction.ACTION_ID_CURRENT;
-            } else {
-                action.setDescription(getString(R.string.wizard_example_input_credit_wrong));
-                return GuidedAction.ACTION_ID_CURRENT;
-            }
-
-        } else if (action.getId() == ACTION_ID_PAYMENT_EXP) {
-            expDateCheck = isExpDateValid(action);
-            cardNumberCheck = isCardNumberValid(findActionById(ACTION_ID_CARD_NUMBER)
-                    .getEditTitle());
-            updateOkButton(cardNumberCheck && expDateCheck);
-            if (expDateCheck) {
-                return GuidedAction.ACTION_ID_NEXT;
-            }
-        }
-        return GuidedAction.ACTION_ID_CURRENT;
-    }
-
-    private void updateOkButton(boolean enabled) {
-        findButtonActionById(GuidedAction.ACTION_ID_OK).setEnabled(enabled);
-        notifyButtonActionChanged(findButtonActionPositionById(GuidedAction.ACTION_ID_OK));
-    }
-
-    private static boolean isCardNumberValid(CharSequence number) {
-        return (TextUtils.isDigitsOnly(number) && number.length() == 16);
-    }
-
-    private static boolean isExpDateValid(GuidedAction dateAction) {
-        long date = ((GuidedDatePickerAction) dateAction).getDate();
-        Calendar c = Calendar.getInstance();
-        c.setTimeInMillis(date);
-        return Calendar.getInstance().before(c);
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/CharacterCardView.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/CharacterCardView.java
deleted file mode 100644
index 89117b5..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/CharacterCardView.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.supportleanbackshowcase.cards;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.widget.BaseCardView;
-import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
-import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-public class CharacterCardView extends BaseCardView {
-
-    public CharacterCardView(Context context) {
-        super(context, null, R.style.CharacterCardStyle);
-        LayoutInflater.from(getContext()).inflate(R.layout.character_card, this);
-        setOnFocusChangeListener(new View.OnFocusChangeListener() {
-            @Override
-            public void onFocusChange(View v, boolean hasFocus) {
-                ImageView mainImage = findViewById(R.id.main_image);
-                View container = findViewById(R.id.container);
-                if (hasFocus) {
-                    container.setBackgroundResource(R.drawable.character_focused);
-                    mainImage.setBackgroundResource(R.drawable.character_focused);
-                } else {
-                    container.setBackgroundResource(R.drawable.character_not_focused_padding);
-                    mainImage.setBackgroundResource(R.drawable.character_not_focused);
-                }
-            }
-        });
-        setFocusable(true);
-    }
-
-    public void updateUi(Card card) {
-        TextView primaryText = findViewById(R.id.primary_text);
-        final ImageView imageView = findViewById(R.id.main_image);
-
-        primaryText.setText(card.getTitle());
-        if (card.getLocalImageResourceName() != null) {
-            int resourceId = card.getLocalImageResourceId(getContext());
-            Bitmap bitmap = BitmapFactory
-                    .decodeResource(getContext().getResources(), resourceId);
-            RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(getContext().getResources(), bitmap);
-            drawable.setAntiAlias(true);
-            drawable.setCornerRadius(Math.max(bitmap.getWidth(), bitmap.getHeight()) / 2.0f);
-            imageView.setImageDrawable(drawable);
-        }
-    }
-
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/TextCardView.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/TextCardView.java
deleted file mode 100644
index 8f94e2a..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/TextCardView.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.supportleanbackshowcase.cards;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.widget.BaseCardView;
-import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
-import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
-import android.view.LayoutInflater;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-public class TextCardView extends BaseCardView {
-
-    public TextCardView(Context context) {
-        super(context, null, R.style.TextCardStyle);
-        LayoutInflater.from(getContext()).inflate(R.layout.text_icon_card, this);
-        setFocusable(true);
-    }
-
-    public void updateUi(Card card) {
-        TextView extraText = findViewById(R.id.extra_text);
-        TextView primaryText = findViewById(R.id.primary_text);
-        final ImageView imageView = findViewById(R.id.main_image);
-
-        extraText.setText(card.getExtraText());
-        primaryText.setText(card.getTitle());
-
-        // Create a rounded drawable.
-        int resourceId = card.getLocalImageResourceId(getContext());
-        Bitmap bitmap = BitmapFactory
-                .decodeResource(getContext().getResources(), resourceId);
-        RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(getContext().getResources(), bitmap);
-        drawable.setAntiAlias(true);
-        drawable.setCornerRadius(
-                Math.max(bitmap.getWidth(), bitmap.getHeight()) / 2.0f);
-        imageView.setImageDrawable(drawable);
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/AbstractCardPresenter.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/AbstractCardPresenter.java
deleted file mode 100644
index fe7541b..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/AbstractCardPresenter.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.supportleanbackshowcase.cards.presenters;
-
-import android.content.Context;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.widget.BaseCardView;
-import android.support.v17.leanback.widget.Presenter;
-import android.view.ViewGroup;
-
-/**
- * This abstract, generic class will create and manage the
- * ViewHolder and will provide typed Presenter callbacks such that you do not have to perform casts
- * on your own.
- *
- * @param <T> View type for the card.
- */
-public abstract class AbstractCardPresenter<T extends BaseCardView> extends Presenter {
-
-    private static final String TAG = "AbstractCardPresenter";
-    private final Context mContext;
-
-    /**
-     * @param context The current context.
-     */
-    public AbstractCardPresenter(Context context) {
-        mContext = context;
-    }
-
-    public Context getContext() {
-        return mContext;
-    }
-
-    @Override public final ViewHolder onCreateViewHolder(ViewGroup parent) {
-        T cardView = onCreateView();
-        return new ViewHolder(cardView);
-    }
-
-    @Override public final void onBindViewHolder(ViewHolder viewHolder, Object item) {
-        Card card = (Card) item;
-        onBindViewHolder(card, (T) viewHolder.view);
-    }
-
-    @Override public final void onUnbindViewHolder(ViewHolder viewHolder) {
-        onUnbindViewHolder((T) viewHolder.view);
-    }
-
-    public void onUnbindViewHolder(T cardView) {
-        // Nothing to clean up. Override if necessary.
-    }
-
-    /**
-     * Invoked when a new view is created.
-     *
-     * @return Returns the newly created view.
-     */
-    protected abstract T onCreateView();
-
-    /**
-     * Implement this method to update your card's view with the data bound to it.
-     *
-     * @param card The model containing the data for the card.
-     * @param cardView The view the card is bound to.
-     * @see Presenter#onBindViewHolder(Presenter.ViewHolder, Object)
-     */
-    public abstract void onBindViewHolder(Card card, T cardView);
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/CardPresenterSelector.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/CardPresenterSelector.java
deleted file mode 100644
index d4e8283..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/CardPresenterSelector.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.supportleanbackshowcase.cards.presenters;
-
-import android.content.Context;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.PresenterSelector;
-
-import java.util.HashMap;
-
-/**
- * This PresenterSelector will decide what Presenter to use depending on a given card's type.
- */
-public class CardPresenterSelector extends PresenterSelector {
-
-    private final Context mContext;
-    private final HashMap<Card.Type, Presenter> presenters = new HashMap<Card.Type, Presenter>();
-
-    public CardPresenterSelector(Context context) {
-        mContext = context;
-    }
-
-    @Override
-    public Presenter getPresenter(Object item) {
-        if (!(item instanceof Card)) throw new RuntimeException(
-                String.format("The PresenterSelector only supports data items of type '%s'",
-                        Card.class.getName()));
-        Card card = (Card) item;
-        Presenter presenter = presenters.get(card.getType());
-        if (presenter == null) {
-            switch (card.getType()) {
-                case SINGLE_LINE:
-                    presenter = new SingleLineCardPresenter(mContext);
-                    break;
-                case MOVIE:
-                case MOVIE_BASE:
-                case MOVIE_COMPLETE:
-                case SQUARE_BIG:
-                case GRID_SQUARE:
-                case GAME: {
-                    int themeResId = R.style.MovieCardSimpleTheme;
-                    if (card.getType() == Card.Type.MOVIE_BASE) {
-                        themeResId = R.style.MovieCardBasicTheme;
-                    } else if (card.getType() == Card.Type.MOVIE_COMPLETE) {
-                        themeResId = R.style.MovieCardCompleteTheme;
-                    } else if (card.getType() == Card.Type.SQUARE_BIG) {
-                        themeResId = R.style.SquareBigCardTheme;
-                    } else if (card.getType() == Card.Type.GRID_SQUARE) {
-                        themeResId = R.style.GridCardTheme;
-                    } else if (card.getType() == Card.Type.GAME) {
-                        themeResId = R.style.GameCardTheme;
-                    }
-                    presenter = new ImageCardViewPresenter(mContext, themeResId);
-                    break;
-                }
-                case SIDE_INFO:
-                    presenter = new SideInfoCardPresenter(mContext);
-                    break;
-                case TEXT:
-                    presenter = new TextCardPresenter(mContext);
-                    break;
-                case ICON:
-                    presenter = new IconCardPresenter(mContext);
-                    break;
-                case CHARACTER:
-                    presenter = new CharacterCardPresenter(mContext);
-                    break;
-                default:
-                    presenter = new ImageCardViewPresenter(mContext);
-                    break;
-            }
-        }
-        presenters.put(card.getType(), presenter);
-        return presenter;
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/CharacterCardPresenter.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/CharacterCardPresenter.java
deleted file mode 100644
index 35a42a9..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/CharacterCardPresenter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.supportleanbackshowcase.cards.presenters;
-
-import android.content.Context;
-import android.support.v17.leanback.supportleanbackshowcase.cards.CharacterCardView;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-
-/**
- * This Presenter is used to display the characters card row in the DetailView examples.
- */
-public class CharacterCardPresenter extends AbstractCardPresenter<CharacterCardView> {
-
-    public CharacterCardPresenter(Context context) {
-        super(context);
-    }
-
-    @Override
-    protected CharacterCardView onCreateView() {
-        return new CharacterCardView(getContext());
-    }
-
-    @Override
-    public void onBindViewHolder(Card card, CharacterCardView cardView) {
-        cardView.updateUi(card);
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/IconCardPresenter.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/IconCardPresenter.java
deleted file mode 100644
index c628988..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/IconCardPresenter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.supportleanbackshowcase.cards.presenters;
-
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.widget.ImageCardView;
-import android.view.View;
-import android.widget.ImageView;
-
-/**
- * This Presenter will display cards which consists of a single icon which will be highlighted by a
- * surrounding circle when the card is focused. AndroidTV uses these cards for entering settings
- * menu.
- */
-public class IconCardPresenter extends ImageCardViewPresenter {
-    private static final int ANIMATION_DURATION = 200;
-
-    public IconCardPresenter(Context context) {
-        super(context, R.style.IconCardTheme);
-    }
-
-    @Override
-    protected ImageCardView onCreateView() {
-        final ImageCardView imageCardView = super.onCreateView();
-        final ImageView image = imageCardView.getMainImageView();
-        image.setBackgroundResource(R.drawable.icon_focused);
-        image.getBackground().setAlpha(0);
-        imageCardView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
-            @Override
-            public void onFocusChange(View v, boolean hasFocus) {
-                animateIconBackground(image.getBackground(), hasFocus);
-            }
-        });
-        return imageCardView;
-    }
-
-    private void animateIconBackground(Drawable drawable, boolean hasFocus) {
-        if (hasFocus) {
-            ObjectAnimator.ofInt(drawable, "alpha", 0, 255).setDuration(ANIMATION_DURATION).start();
-        } else {
-            ObjectAnimator.ofInt(drawable, "alpha", 255, 0).setDuration(ANIMATION_DURATION).start();
-        }
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/ImageCardViewPresenter.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/ImageCardViewPresenter.java
deleted file mode 100644
index f0b75f1..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/ImageCardViewPresenter.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.supportleanbackshowcase.cards.presenters;
-
-import android.content.Context;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.widget.ImageCardView;
-import android.view.ContextThemeWrapper;
-
-import android.view.View;
-import android.widget.Toast;
-import com.squareup.picasso.Picasso;
-
-/**
- * A very basic {@link ImageCardView} {@link android.support.v17.leanback.widget.Presenter}.You can
- * pass a custom style for the ImageCardView in the constructor. Use the default constructor to
- * create a Presenter with a default ImageCardView style.
- */
-public class ImageCardViewPresenter extends AbstractCardPresenter<ImageCardView> {
-
-    public ImageCardViewPresenter(Context context, int cardThemeResId) {
-        super(new ContextThemeWrapper(context, cardThemeResId));
-    }
-
-    public ImageCardViewPresenter(Context context) {
-        this(context, R.style.DefaultCardTheme);
-    }
-
-    @Override
-    protected ImageCardView onCreateView() {
-        ImageCardView imageCardView = new ImageCardView(getContext());
-        imageCardView.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Toast.makeText(getContext(), "Clicked on ImageCardView", Toast.LENGTH_SHORT).show();
-            }
-        });
-        return imageCardView;
-    }
-
-    @Override
-    public void onBindViewHolder(Card card, final ImageCardView cardView) {
-        cardView.setTag(card);
-        cardView.setTitleText(card.getTitle());
-        cardView.setContentText(card.getDescription());
-        if (card.getLocalImageResourceName() != null) {
-            int resourceId = getContext().getResources()
-                    .getIdentifier(card.getLocalImageResourceName(),
-                            "drawable", getContext().getPackageName());
-            Picasso.with(getContext()).load(resourceId).into(cardView.getMainImageView());
-        }
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/SideInfoCardPresenter.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/SideInfoCardPresenter.java
deleted file mode 100644
index b9f44fc..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/SideInfoCardPresenter.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.supportleanbackshowcase.cards.presenters;
-
-import android.content.Context;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.widget.BaseCardView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.squareup.picasso.Picasso;
-
-/**
- * This Presenter will display a card consisting of an image on the left side of the card followed
- * by text on the right side. The image and text have equal width. The text will work like a info
- * box, thus it will be hidden if the parent row is inactive. This behavior is unique to this card
- * and requires a special focus handler.
- */
-public class SideInfoCardPresenter extends AbstractCardPresenter<BaseCardView> {
-
-    public SideInfoCardPresenter(Context context) {
-        super(context);
-    }
-
-    @Override
-    protected BaseCardView onCreateView() {
-        final BaseCardView cardView = new BaseCardView(getContext(), null,
-                R.style.SideInfoCardStyle);
-        cardView.setFocusable(true);
-        cardView.addView(LayoutInflater.from(getContext()).inflate(R.layout.side_info_card, null));
-        return cardView;
-    }
-
-    @Override
-    public void onBindViewHolder(Card card, BaseCardView cardView) {
-        ImageView imageView = (ImageView) cardView.findViewById(R.id.main_image);
-        if (card.getLocalImageResourceName() != null) {
-            int width = (int) getContext().getResources()
-                    .getDimension(R.dimen.sidetext_image_card_width);
-            int height = (int) getContext().getResources()
-                    .getDimension(R.dimen.sidetext_image_card_height);
-            int resourceId = getContext().getResources()
-                    .getIdentifier(card.getLocalImageResourceName(),
-                            "drawable", getContext().getPackageName());
-            Picasso.with(getContext()).load(resourceId).resize(width, height).centerCrop()
-                    .into(imageView);
-        }
-
-        TextView primaryText = (TextView) cardView.findViewById(R.id.primary_text);
-        primaryText.setText(card.getTitle());
-
-        TextView secondaryText = (TextView) cardView.findViewById(R.id.secondary_text);
-        secondaryText.setText(card.getDescription());
-
-        TextView extraText = (TextView) cardView.findViewById(R.id.extra_text);
-        extraText.setText(card.getExtraText());
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/SingleLineCardPresenter.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/SingleLineCardPresenter.java
deleted file mode 100644
index a823993..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/SingleLineCardPresenter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.supportleanbackshowcase.cards.presenters;
-
-import android.content.Context;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-import android.support.v17.leanback.widget.ImageCardView;
-
-/**
- * This Presenter will display a card which consists of a big image followed by a colored footer.
- * Not only the colored footer is unique to this card, but also it's footer (info) will be visible
- * even when its parent row is inactive.
- */
-public class SingleLineCardPresenter extends ImageCardViewPresenter {
-
-    public SingleLineCardPresenter(Context context) {
-        super(context, R.style.SingleLineCardTheme);
-    }
-
-    @Override public void onBindViewHolder(Card card, ImageCardView cardView) {
-        super.onBindViewHolder(card, cardView);
-        cardView.setInfoAreaBackgroundColor(card.getFooterColor());
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/TextCardPresenter.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/TextCardPresenter.java
deleted file mode 100644
index 7e65f0f..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/cards/presenters/TextCardPresenter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.supportleanbackshowcase.cards.presenters;
-
-import android.content.Context;
-import android.support.v17.leanback.supportleanbackshowcase.cards.TextCardView;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-
-/**
- * The Presenter displays a card consisting of text as a replacement for a big image. The footer is
- * also quite unique since it does contain two images rather than one or non.
- */
-public class TextCardPresenter extends AbstractCardPresenter<TextCardView> {
-
-    public TextCardPresenter(Context context) {
-        super(context);
-    }
-
-    @Override
-    protected TextCardView onCreateView() {
-        return new TextCardView(getContext());
-    }
-
-    @Override
-    public void onBindViewHolder(Card card, TextCardView cardView) {
-        cardView.updateUi(card);
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/Card.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/Card.java
deleted file mode 100644
index ccaaf72..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/Card.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.support.v17.leanback.supportleanbackshowcase.models;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.util.Log;
-
-import com.google.gson.annotations.SerializedName;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-/**
- * This is a generic example of a custom data object, containing info we might want to keep with
- * each card on the home screen
- */
-public class Card {
-
-    @SerializedName("title") private String mTitle = "";
-    @SerializedName("description") private String mDescription = "";
-    @SerializedName("extraText") private String mExtraText = "";
-    @SerializedName("imageUrl") private String mImageUrl;
-    @SerializedName("footerColor") private String mFooterColor = null;
-    @SerializedName("selectedColor") private String mSelectedColor = null;
-    @SerializedName("localImageResource") private String mLocalImageResource = null;
-    @SerializedName("footerIconLocalImageResource") private String mFooterResource = null;
-    @SerializedName("type") private Card.Type mType;
-    @SerializedName("id") private int mId;
-    @SerializedName("width") private int mWidth;
-    @SerializedName("height") private int mHeight;
-
-    public String getTitle() {
-        return mTitle;
-    }
-
-    public int getWidth() {
-        return mWidth;
-    }
-
-    public int getHeight() {
-        return mHeight;
-    }
-
-    public int getId() {
-        return mId;
-    }
-
-    public Card.Type getType() {
-        return mType;
-    }
-
-    public String getDescription() {
-        return mDescription;
-    }
-
-    public String getExtraText() {
-        return mExtraText;
-    }
-
-    public int getFooterColor() {
-        if (mFooterColor == null) return -1;
-        return Color.parseColor(mFooterColor);
-    }
-
-    public int getSelectedColor() {
-        if (mSelectedColor == null) return -1;
-        return Color.parseColor(mSelectedColor);
-    }
-
-    public String getImageUrl() {
-        return mImageUrl;
-    }
-
-    public URI getImageURI() {
-        if (getImageUrl() == null) return null;
-        try {
-            return new URI(getImageUrl());
-        } catch (URISyntaxException e) {
-            Log.d("URI exception: ", getImageUrl());
-            return null;
-        }
-    }
-
-    public int getLocalImageResourceId(Context context) {
-        return context.getResources().getIdentifier(getLocalImageResourceName(), "drawable",
-                                                    context.getPackageName());
-    }
-
-    public String getLocalImageResourceName() {
-        return mLocalImageResource;
-    }
-
-    public String getFooterLocalImageResourceName() {
-        return mFooterResource;
-    }
-
-    public enum Type {
-
-        MOVIE_COMPLETE,
-        MOVIE,
-        MOVIE_BASE,
-        ICON,
-        SQUARE_BIG,
-        SINGLE_LINE,
-        GAME,
-        SQUARE_SMALL,
-        DEFAULT,
-        SIDE_INFO,
-        SIDE_INFO_TEST_1,
-        TEXT,
-        CHARACTER,
-        GRID_SQUARE
-
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/CardRow.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/CardRow.java
deleted file mode 100644
index ffc5001..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/CardRow.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.supportleanbackshowcase.models;
-
-import com.google.gson.annotations.SerializedName;
-
-import java.util.List;
-
-/**
- * This class represents a row of cards. In a real world application you might want to store more
- * data than in this example.
- */
-public class CardRow {
-
-    // default is a list of cards
-    public static final int TYPE_DEFAULT = 0;
-    // section header
-    public static final int TYPE_SECTION_HEADER = 1;
-    // divider
-    public static final int TYPE_DIVIDER = 2;
-
-    @SerializedName("type") private int mType = TYPE_DEFAULT;
-    // Used to determine whether the row shall use shadows when displaying its cards or not.
-    @SerializedName("shadow") private boolean mShadow = true;
-    @SerializedName("title") private String mTitle;
-    @SerializedName("cards") private List<Card> mCards;
-
-    public int getType() {
-        return mType;
-    }
-
-    public String getTitle() {
-        return mTitle;
-    }
-
-    public boolean useShadow() {
-        return mShadow;
-    }
-
-    public List<Card> getCards() {
-        return mCards;
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/DetailedCard.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/DetailedCard.java
deleted file mode 100644
index 8727a40..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/DetailedCard.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.supportleanbackshowcase.models;
-
-import android.content.Context;
-import android.support.v17.leanback.supportleanbackshowcase.models.Card;
-
-import com.google.gson.annotations.SerializedName;
-
-public class DetailedCard {
-
-    @SerializedName("title") private String mTitle = "";
-    @SerializedName("description") private String mDescription = "";
-    @SerializedName("text") private String mText = "";
-    @SerializedName("localImageResource") private String mLocalImageResource = null;
-    @SerializedName("price") private String mPrice = null;
-    @SerializedName("characters") private Card[] mCharacters = null;
-    @SerializedName("recommended") private Card[] mRecommended = null;
-    @SerializedName("year") private int mYear = 0;
-
-
-    public String getPrice() {
-        return mPrice;
-    }
-
-    public int getYear() {
-        return mYear;
-    }
-
-    public String getLocalImageResource() {
-        return mLocalImageResource;
-    }
-
-    public String getText() {
-        return mText;
-    }
-
-    public String getDescription() {
-        return mDescription;
-    }
-
-    public String getTitle() {
-        return mTitle;
-    }
-
-    public Card[] getCharacters() {
-        return mCharacters;
-    }
-
-    public Card[] getRecommended() {
-        return mRecommended;
-    }
-
-    public int getLocalImageResourceId(Context context) {
-        return context.getResources()
-                      .getIdentifier(getLocalImageResource(), "drawable", context.getPackageName());
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/Movie.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/Movie.java
deleted file mode 100644
index 83912b3..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/Movie.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.supportleanbackshowcase.models;
-
-import com.google.gson.annotations.SerializedName;
-
-import java.io.Serializable;
-
-public class Movie implements Serializable {
-
-    private static final long serialVersionUID = 133742L;
-
-    @SerializedName("title")
-    private String mTitle = "";
-    @SerializedName("price_hd")
-    private String mPriceHd = "n/a";
-    @SerializedName("price_sd")
-    private String mPriceSd = "n/a";
-    @SerializedName("breadcrump")
-    private String mBreadcrump = "";
-
-    public String getTitle() {
-        return mTitle;
-    }
-
-    public String getBreadcrump() {
-        return mBreadcrump;
-    }
-
-    public String getPriceHd() {
-        return mPriceHd;
-    }
-
-    public String getPriceSd() {
-        return mPriceSd;
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/Song.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/Song.java
deleted file mode 100644
index 1ba29ca..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/Song.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.supportleanbackshowcase.models;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.support.v17.leanback.supportleanbackshowcase.R;
-import android.support.v17.leanback.widget.BaseOnItemViewSelectedListener;
-import android.support.v17.leanback.widget.MultiActionsProvider;
-import android.support.v17.leanback.widget.Row;
-import android.support.v17.leanback.widget.RowPresenter;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import com.google.gson.Gson;
-import com.google.gson.annotations.SerializedName;
-
-public class Song implements MultiActionsProvider {
-
-    @SerializedName("title") private String mTitle = "";
-    @SerializedName("description") private String mDescription = "";
-    @SerializedName("text") private String mText = "";
-    @SerializedName("image") private String mImage = null;
-    @SerializedName("file") private String mFile = null;
-    @SerializedName("duration") private String mDuration = null;
-    @SerializedName("number") private int mNumber = 0;
-    @SerializedName("favorite") private boolean mFavorite = false;
-
-    private MultiAction[] mMediaRowActions;
-
-
-    public void setMediaRowActions(MultiAction[] mediaRowActions) {
-        mMediaRowActions = mediaRowActions;
-    }
-
-    public MultiAction[] getMediaRowActions() {
-        return mMediaRowActions;
-    }
-
-    public String getDuration() {
-        return mDuration;
-    }
-
-    public void setDuration(String duration) {
-        mDuration = duration;
-    }
-
-    public int getNumber() {
-        return mNumber;
-    }
-
-    public String getText() {
-        return mText;
-    }
-
-    public String getDescription() {
-        return mDescription;
-    }
-
-    public void setDescription(String description) {
-        mDescription = description;
-    }
-
-    public String getTitle() {
-        return mTitle;
-    }
-
-    public void setTitle(String title) {
-        mTitle = title;
-    }
-
-    public boolean isFavorite() {
-        return mFavorite;
-    }
-
-    public void setFavorite(boolean favorite) {
-        mFavorite = favorite;
-    }
-
-    public int getFileResource(Context context) {
-        return context.getResources()
-                      .getIdentifier(mFile, "raw", context.getPackageName());
-    }
-
-    public int getImageResource(Context context) {
-        return context.getResources()
-                      .getIdentifier(mImage, "drawable", context.getPackageName());
-    }
-
-    @Override
-    public MultiAction[] getActions() {
-        return mMediaRowActions;
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/SongList.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/SongList.java
deleted file mode 100644
index 034ae19..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/models/SongList.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.supportleanbackshowcase.models;
-
-import com.google.gson.annotations.SerializedName;
-
-import java.util.List;
-
-/**
- */
-public class SongList {
-
-    @SerializedName("songs") private List<Song> mSongs;
-
-    public List<Song> getSongs() {
-        return mSongs;
-    }
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/CardListRow.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/CardListRow.java
deleted file mode 100644
index 19f2437..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/CardListRow.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.supportleanbackshowcase.utils;
-
-import android.support.v17.leanback.supportleanbackshowcase.app.details.ShadowRowPresenterSelector;
-import android.support.v17.leanback.supportleanbackshowcase.models.CardRow;
-import android.support.v17.leanback.widget.HeaderItem;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ObjectAdapter;
-
-/**
- * The {@link CardListRow} allows the {@link ShadowRowPresenterSelector} to access the {@link CardRow}
- * held by the row and determine whether to use a {@link android.support.v17.leanback.widget.Presenter}
- * with or without a shadow.
- */
-public class CardListRow extends ListRow {
-
-    private CardRow mCardRow;
-
-    public CardListRow(HeaderItem header, ObjectAdapter adapter, CardRow cardRow) {
-        super(header, adapter);
-        setCardRow(cardRow);
-    }
-
-    public CardRow getCardRow() {
-        return mCardRow;
-    }
-
-    public void setCardRow(CardRow cardRow) {
-        this.mCardRow = cardRow;
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/Constants.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/Constants.java
deleted file mode 100644
index 1c9dd9c..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/Constants.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * 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.supportleanbackshowcase.utils;
-
-public class Constants {
-
-    public static final boolean LOCAL_LOGD = true;
-
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/PicassoBackgroundManagerTarget.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/PicassoBackgroundManagerTarget.java
deleted file mode 100644
index 2723d0b..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/PicassoBackgroundManagerTarget.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.support.v17.leanback.supportleanbackshowcase.utils;
-
-import android.graphics.Bitmap;
-import android.graphics.drawable.Drawable;
-import android.support.v17.leanback.app.BackgroundManager;
-
-import com.squareup.picasso.Picasso;
-import com.squareup.picasso.Target;
-
-/**
- * Picasso target for updating default_background images
- */
-public class PicassoBackgroundManagerTarget implements Target {
-
-    private BackgroundManager mBackgroundManager;
-
-    public PicassoBackgroundManagerTarget(BackgroundManager backgroundManager) {
-        this.mBackgroundManager = backgroundManager;
-    }
-
-    @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
-        this.mBackgroundManager.setBitmap(bitmap);
-    }
-
-    @Override public void onBitmapFailed(Drawable drawable) {
-        this.mBackgroundManager.setDrawable(drawable);
-    }
-
-    @Override public void onPrepareLoad(Drawable drawable) {
-        // Do nothing, default_background manager has its own transitions
-    }
-
-    @Override public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        PicassoBackgroundManagerTarget that = (PicassoBackgroundManagerTarget) o;
-
-        if (!mBackgroundManager.equals(that.mBackgroundManager)) return false;
-
-        return true;
-    }
-
-    @Override public int hashCode() {
-        return mBackgroundManager.hashCode();
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/ResourceCache.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/ResourceCache.java
deleted file mode 100644
index 09a1965..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/ResourceCache.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.supportleanbackshowcase.utils;
-
-import android.util.SparseArray;
-import android.view.View;
-
-/**
- * ResourceCache allows retrieving children from a given view and caches the resulting views in
- * order to prevent future lookups.
- */
-public class ResourceCache {
-
-    private final SparseArray<View> mCachedViews = new SparseArray<View>();
-
-    public <ViewType extends View> ViewType getViewById(View view, int resId) {
-        View child = mCachedViews.get(resId, null);
-        if (child == null) {
-            child = view.findViewById(resId);
-            mCachedViews.put(resId, child);
-        }
-        return (ViewType) child;
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/Utils.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/Utils.java
deleted file mode 100644
index 4416cbe..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/utils/Utils.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.support.v17.leanback.supportleanbackshowcase.utils;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.net.Uri;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A collection of utility methods, all static.
- */
-public class Utils {
-
-    public static int convertDpToPixel(Context ctx, int dp) {
-        float density = ctx.getResources().getDisplayMetrics().density;
-        return Math.round((float) dp * density);
-    }
-
-    /**
-     * Will read the content from a given {@link InputStream} and return it as a {@link String}.
-     *
-     * @param inputStream The {@link InputStream} which should be read.
-     * @return Returns <code>null</code> if the the {@link InputStream} could not be read. Else
-     * returns the content of the {@link InputStream} as {@link String}.
-     */
-    public static String inputStreamToString(InputStream inputStream) {
-        try {
-            byte[] bytes = new byte[inputStream.available()];
-            inputStream.read(bytes, 0, bytes.length);
-            String json = new String(bytes);
-            return json;
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    public static Uri getResourceUri(Context context, int resID) {
-        return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
-                                 context.getResources().getResourcePackageName(resID) + '/' +
-                                 context.getResources().getResourceTypeName(resID) + '/' +
-                                 context.getResources().getResourceEntryName(resID));
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-v21/song_row_background_focused.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-v21/song_row_background_focused.xml
deleted file mode 100644
index 34e2bd7..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-v21/song_row_background_focused.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item>
-        <color android:color="#384248"></color>
-    </item>
-    <item>
-        <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-                android:color="?android:attr/colorControlHighlight">
-            <item android:id="@android:id/mask">
-                <shape android:shape="rectangle">
-                    <corners android:radius="2dp"/>
-                    <solid android:color="#FFFFFF"/>
-                </shape>
-            </item>
-
-        </ripple>
-    </item>
-
-</layer-list>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/background_canyon.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/background_canyon.jpg
deleted file mode 100644
index 0f77261..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/background_canyon.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/background_food.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/background_food.jpg
deleted file mode 100644
index cbe05f8..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/background_food.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/background_sax.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/background_sax.jpg
deleted file mode 100644
index 20fec8c..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/background_sax.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_dummy_16_9_l.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_dummy_16_9_l.png
deleted file mode 100644
index 6088150..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_dummy_16_9_l.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_01.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_01.jpg
deleted file mode 100644
index df42850..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_01.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_02.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_02.jpg
deleted file mode 100644
index f633b04..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_02.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_03.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_03.jpg
deleted file mode 100644
index 52a6b01..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_03.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_04.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_04.jpg
deleted file mode 100644
index 428e6bf..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_04.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_05.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_05.jpg
deleted file mode 100644
index a816fe8..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_05.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_06.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_06.jpg
deleted file mode 100644
index 8746fd9..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_06.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_07.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_07.jpg
deleted file mode 100644
index 770f22e..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_07.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_08.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_08.jpg
deleted file mode 100644
index cf83f9f..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_08.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_09.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_09.jpg
deleted file mode 100644
index 2622893..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_movie_09.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_01.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_01.jpg
deleted file mode 100644
index d604a50..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_01.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_02.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_02.jpg
deleted file mode 100644
index cdcee88..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_02.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_03.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_03.jpg
deleted file mode 100644
index 229f0c4..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_03.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_04.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_04.jpg
deleted file mode 100644
index b7bbe9c..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_04.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_05.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_05.jpg
deleted file mode 100644
index bfa1389..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_05.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_06.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_06.jpg
deleted file mode 100644
index 033d60e..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_06.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_07.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_07.jpg
deleted file mode 100644
index 784d0e9..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_07.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_08.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_08.jpg
deleted file mode 100644
index 040e222..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_08.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_09.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_09.jpg
deleted file mode 100644
index 2a9f136..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/card_image_music_09.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_action.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_action.png
deleted file mode 100755
index f3cb7af..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_action.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_animation.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_animation.png
deleted file mode 100755
index a1d9f40..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_animation.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_classics.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_classics.png
deleted file mode 100755
index 17c1580..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_classics.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_comedy.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_comedy.png
deleted file mode 100755
index 5a23e6e..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_comedy.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_crime.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_crime.png
deleted file mode 100755
index 52450a6..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_crime.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_documentary.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_documentary.png
deleted file mode 100755
index afb2b61..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_documentary.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_drama.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_drama.png
deleted file mode 100755
index 79e1b57..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/category_drama.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_01.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_01.png
deleted file mode 100755
index 9fb73f7..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_01.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_02.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_02.png
deleted file mode 100755
index 9e0abfe..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_02.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_03.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_03.png
deleted file mode 100755
index cd78b71..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_03.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_04.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_04.png
deleted file mode 100755
index bf7561c..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_04.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_05.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_05.png
deleted file mode 100755
index eae5338..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_05.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_06.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_06.png
deleted file mode 100755
index b1feda0..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_06.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_07.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_07.png
deleted file mode 100755
index 0f7dd21..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_07.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_08.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_08.png
deleted file mode 100755
index b904137..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/coffee_and_tea_08.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_01.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_01.png
deleted file mode 100755
index b4757a8..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_01.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_02.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_02.png
deleted file mode 100755
index 0d746d3..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_02.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_03.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_03.png
deleted file mode 100755
index ddde1ef..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_03.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_04.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_04.png
deleted file mode 100755
index ca09156..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_04.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_05.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_05.png
deleted file mode 100755
index 8c4d7e6..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_05.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_06.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_06.png
deleted file mode 100755
index d81ad8c..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_06.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_07.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_07.png
deleted file mode 100755
index a0f381d..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_07.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_08.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_08.png
deleted file mode 100755
index c377d27..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_08.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_09.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_09.png
deleted file mode 100755
index de5a207..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_09.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_10.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_10.png
deleted file mode 100755
index 958f47e..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_10.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_11.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_11.png
deleted file mode 100755
index 36a8007..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_11.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_12.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_12.png
deleted file mode 100755
index 4d60e8e..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_12.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_13.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_13.png
deleted file mode 100755
index b4a8837..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_13.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_14.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_14.png
deleted file mode 100755
index ae3d40b..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/food_14.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_crazy_one.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_crazy_one.jpg
deleted file mode 100644
index 9bb47c1..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_crazy_one.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_cursed.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_cursed.jpg
deleted file mode 100644
index 7d4b45a..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_cursed.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_fairy.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_fairy.jpg
deleted file mode 100644
index c1658e9..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_fairy.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_hear_the_roar.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_hear_the_roar.jpg
deleted file mode 100644
index 78003b2..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_hear_the_roar.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_silence.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_silence.jpg
deleted file mode 100644
index 1672536..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/game_silence.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/google_map.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/google_map.jpg
deleted file mode 100644
index 447de09..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/google_map.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_cc.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_cc.png
deleted file mode 100644
index 4615394..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_cc.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_installed.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_installed.png
deleted file mode 100644
index 190f6ba..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_installed.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_apps.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_apps.png
deleted file mode 100755
index ed92603..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_apps.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_more.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_more.png
deleted file mode 100755
index 5307576..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_more.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_parental_control.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_parental_control.png
deleted file mode 100755
index d541c6a..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_parental_control.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_settings.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_settings.png
deleted file mode 100755
index f2eaa45..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_settings.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_time.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_time.png
deleted file mode 100755
index 72899ae..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_time.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_wifi_3_bar.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_wifi_3_bar.png
deleted file mode 100755
index f9abb6c..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_wifi_3_bar.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_wifi_4_bar.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_wifi_4_bar.png
deleted file mode 100755
index dcd2088..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_settings_wifi_4_bar.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_star_off.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_star_off.png
deleted file mode 100644
index cbee75a..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_star_off.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_star_on_yellow.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_star_on_yellow.png
deleted file mode 100644
index 28cd07a..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/ic_star_on_yellow.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/movie_poster_01.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/movie_poster_01.png
deleted file mode 100644
index e09af32..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/movie_poster_01.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/stars_red.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/stars_red.png
deleted file mode 100644
index e4c6056..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/stars_red.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/stars_white.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/stars_white.png
deleted file mode 100644
index 83e7c8b..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/stars_white.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_browse.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_browse.png
deleted file mode 100755
index 374f357..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_browse.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_cards.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_cards.png
deleted file mode 100755
index 1ddadfa..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_cards.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_custom_01.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_custom_01.png
deleted file mode 100755
index f73b9b7..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_custom_01.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_detail.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_detail.png
deleted file mode 100755
index aa881b8..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_detail.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_dialog.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_dialog.png
deleted file mode 100755
index 6508d08..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_dialog.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_grid.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_grid.png
deleted file mode 100755
index 686566f..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_grid.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_music_consumption.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_music_consumption.png
deleted file mode 100755
index ffc653d..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_music_consumption.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_settings.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_settings.png
deleted file mode 100755
index 8337b92..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_settings.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_video_consumption.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_video_consumption.png
deleted file mode 100755
index a0a9d95..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_video_consumption.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_wizard.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_wizard.png
deleted file mode 100755
index 4338d30..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/thumbnail_example_wizard.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/title_android_tv.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/title_android_tv.png
deleted file mode 100644
index 8d1e241..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable-xhdpi/title_android_tv.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/app_icon_your_company.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/app_icon_your_company.png
deleted file mode 100644
index 0a47b01..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/app_icon_your_company.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/bg_living_room.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/bg_living_room.jpg
deleted file mode 100644
index 47e8851..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/bg_living_room.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/bg_living_room_wide.jpg b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/bg_living_room_wide.jpg
deleted file mode 100644
index 156d55c..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/bg_living_room_wide.jpg
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/character_focused.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/character_focused.xml
deleted file mode 100644
index 5c2570d..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/character_focused.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval">
-    <padding
-        android:bottom="4dp"
-        android:left="4dp"
-        android:right="4dp"
-        android:top="4dp"></padding>
-    <solid android:color="#FFEEEEEE"></solid>
-</shape>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/character_not_focused.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/character_not_focused.xml
deleted file mode 100644
index db4cf9c..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/character_not_focused.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval">
-    <padding
-        android:bottom="4dp"
-        android:left="4dp"
-        android:right="4dp"
-        android:top="4dp"></padding>
-    <solid android:color="#FFCCCCCC"></solid>
-</shape>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/character_not_focused_padding.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/character_not_focused_padding.xml
deleted file mode 100644
index 8da3812..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/character_not_focused_padding.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval">
-    <padding
-        android:bottom="4dp"
-        android:left="4dp"
-        android:right="4dp"
-        android:top="4dp"></padding>
-    <solid android:color="#00CCCCCC"></solid>
-</shape>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/default_background.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/default_background.xml
deleted file mode 100644
index d9fa80b..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/default_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle">
-    <gradient
-        android:angle="-270"
-        android:endColor="@color/background_gradient_end"
-        android:startColor="@color/background_gradient_start"/>
-</shape>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_01.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_01.png
deleted file mode 100755
index d5b2900..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_01.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_02.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_02.png
deleted file mode 100755
index ced0a7c..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_02.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_03.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_03.png
deleted file mode 100755
index 276cacf..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_03.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_04.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_04.png
deleted file mode 100755
index e90487d..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_04.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_05.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_05.png
deleted file mode 100755
index f048ecb..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_05.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_06.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_06.png
deleted file mode 100755
index f4d15eb..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_06.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_07.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_07.png
deleted file mode 100755
index 7ac0af3..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_07.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_08.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_08.png
deleted file mode 100755
index e6fc51e..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/face_08.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_favorite_border_white_24dp.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_favorite_border_white_24dp.xml
deleted file mode 100644
index 03e16ad..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_favorite_border_white_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3 4.42,3 2,5.42 2,8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5 22,5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1 -0.1,-0.1C7.14,14.24 4,11.39 4,8.5 4,6.5 5.5,5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5 0,2.89 -3.14,5.74 -7.9,10.05z"
-        android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_favorite_filled_24dp.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_favorite_filled_24dp.xml
deleted file mode 100644
index bce1999..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_favorite_filled_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"
-        android:fillColor="@color/song_row_favorite_color"/>
-</vector>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_playlist_add_filled_24dp.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_playlist_add_filled_24dp.xml
deleted file mode 100644
index ac5d3f3..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_playlist_add_filled_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M14,10L2,10v2h12v-2zM14,6L2,6v2h12L14,6zM18,14v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM2,16h8v-2L2,14v2z"
-        android:fillColor="@color/song_row_favorite_color"/>
-</vector>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_playlist_add_white_24dp.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_playlist_add_white_24dp.xml
deleted file mode 100644
index 4147e81..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/ic_playlist_add_white_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M14,10L2,10v2h12v-2zM14,6L2,6v2h12L14,6zM18,14v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM2,16h8v-2L2,14v2z"
-        android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_01.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_01.png
deleted file mode 100644
index 6fdb583..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_01.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_02.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_02.png
deleted file mode 100644
index 8728c6f..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_02.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_03.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_03.png
deleted file mode 100644
index 2364de9..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_03.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_04.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_04.png
deleted file mode 100644
index 9c4fa52..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_04.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_05.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_05.png
deleted file mode 100644
index c56828c..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_05.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_06.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_06.png
deleted file mode 100644
index b9f34f4..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_06.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_07.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_07.png
deleted file mode 100644
index 76ea4f6..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_07.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_08.png b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_08.png
deleted file mode 100644
index 4b1ddb9..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_08.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_focused.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_focused.xml
deleted file mode 100644
index bab1cc6..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/icon_focused.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="oval">
-    <solid android:color="#4DEEEEEE"></solid>
-    <size
-        android:width="96dp"
-        android:height="96dp"/>
-</shape>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/song_row_background_focused.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/song_row_background_focused.xml
deleted file mode 100644
index 152e7e6..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/song_row_background_focused.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?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.
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item>
-        <color android:color="#384248"></color>
-    </item>
-    <item>
-        <color android:color="#1AFFFFFF"></color>
-    </item>
-</layer-list>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_background_blackned.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_background_blackned.xml
deleted file mode 100644
index bea8d66..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_background_blackned.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-     <item android:drawable="@drawable/background_canyon"></item>
-     <item android:drawable="@drawable/overlay_black"></item>
-</layer-list>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background.xml
deleted file mode 100644
index b4fd39e..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/wizard_important_action_item_background_focused" android:state_focused="true"></item>
-    <item android:drawable="@drawable/wizard_important_action_item_background_not_focused"></item>
-</selector>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_not_focused.xml b/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_not_focused.xml
deleted file mode 100644
index 74cccd0..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_not_focused.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="#B2FFFFFF"></solid>
-</shape>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_cards_example.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_cards_example.xml
deleted file mode 100644
index 45b5505..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_cards_example.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
-
-    <fragment
-        android:id="@+id/cardsFragment"
-        android:name="android.support.v17.leanback.supportleanbackshowcase.app.cards.CardExampleFragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"></fragment>
-</RelativeLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_detail_example.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_detail_example.xml
deleted file mode 100644
index 1dd92d8..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_detail_example.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
-    <fragment
-        android:id="@+id/detailsFragment"
-        android:name="android.support.v17.leanback.supportleanbackshowcase.app.details.DetailViewExampleFragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"></fragment>
-</RelativeLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_grid_example.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_grid_example.xml
deleted file mode 100644
index f3fcdea..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_grid_example.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
-
-    <fragment
-        android:id="@+id/cardsFragment"
-        android:name="android.support.v17.leanback.supportleanbackshowcase.app.grid.GridExampleFragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"></fragment>
-</RelativeLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_music_example.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_music_example.xml
deleted file mode 100644
index 9eef61a..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_music_example.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
-
-    <fragment
-        android:id="@+id/musicFragment"
-        android:name="android.support.v17.leanback.supportleanbackshowcase.app.media.MusicConsumptionExampleFragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"></fragment>
-</RelativeLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_settings_example.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_settings_example.xml
deleted file mode 100644
index c6c81a3..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_settings_example.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
-    <fragment
-        android:id="@+id/settingsFragment"
-        android:name="android.support.v17.leanback.supportleanbackshowcase.app.settings.SettingsExampleFragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"></fragment>
-</RelativeLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/character_card.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/character_card.xml
deleted file mode 100644
index dee09a8..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/character_card.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             xmlns:lb="http://schemas.android.com/apk/res-auto"
-             android:layout_width="match_parent"
-             android:layout_height="match_parent"
-             lb:cardBackground="@null"
-             lb:layout_viewType="main">
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
-
-        <FrameLayout
-            android:id="@+id/container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:background="@drawable/character_not_focused_padding">
-
-            <ImageView
-                android:id="@+id/main_image"
-                android:layout_width="@dimen/character_image_card_width"
-                android:layout_height="@dimen/character_image_card_height"
-                android:background="@drawable/character_not_focused"
-                android:src="@drawable/face_08"/>
-        </FrameLayout>
-
-        <TextView
-            android:id="@+id/primary_text"
-            style="@style/Widget.Leanback.ImageCardView.TitleStyle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="7dp"
-            android:fontFamily="sans-serif-condensed"
-            android:gravity="center"/>
-    </LinearLayout>
-</FrameLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/custom_titleview.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/custom_titleview.xml
deleted file mode 100644
index f3ac0df..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/custom_titleview.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-
-    <!--<android.support.v17.leanback.widget.SearchOrbView-->
-        <!--android:id="@+id/search_orb"-->
-        <!--android:layout_height="wrap_content"-->
-        <!--android:layout_width="wrap_content"-->
-        <!--android:transitionGroup="true"-->
-        <!--android:layout_gravity="center_vertical|start"-->
-        <!--android:layout_marginStart="56dp" />-->
-
-    <AnalogClock
-            android:id="@+id/clock"
-            android:layout_width="80dp"
-            android:layout_height="80dp"
-            android:padding="6dp"
-            android:layout_alignParentEnd="true"
-            android:layout_centerVertical="true"
-            android:layout_marginEnd="24dp" />
-
-    <ImageView
-            android:id="@+id/title_badge_iv"
-            android:layout_width="wrap_content"
-            android:layout_height="224dp"
-            android:adjustViewBounds="true"
-            android:layout_gravity="center_vertical|end"
-            android:layout_toStartOf="@id/clock"
-            android:src="@null"
-            android:layout_centerVertical="true"
-            android:visibility="gone" />
-
-    <TextView
-            android:id="@+id/title_tv"
-            android:textAppearance="@android:style/TextAppearance.Large"
-            android:visibility="gone"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginEnd="24dp"
-            android:layout_centerVertical="true"
-            android:layout_toStartOf="@id/clock" />
-
-</merge>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/detail_view_content.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/detail_view_content.xml
deleted file mode 100644
index 5140ed7..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/detail_view_content.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent"
-              android:orientation="vertical">
-
-    <TextView
-        android:id="@+id/primary_text"
-        style="@style/Widget.Leanback.DetailsDescriptionTitleStyle"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="3dp"
-        android:layout_marginTop="15dp"
-        android:fontFamily="sans-serif-light"
-        android:text="Title Text"/>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="14dp"
-        android:gravity="center_vertical"
-        android:orientation="horizontal">
-
-        <TextView
-            android:id="@+id/secondary_text_first"
-            style="@style/Widget.Leanback.DetailsDescriptionSubtitleStyle"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginRight="16dp"
-            android:fontFamily="sans-serif-condensed"
-            android:text="Secondary Text Area"/>
-
-        <TextView
-            android:id="@+id/secondary_text_second"
-            style="@style/Widget.Leanback.DetailsDescriptionSubtitleStyle"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginRight="16dp"
-            android:fontFamily="sans-serif-condensed"
-            android:text="With Icons"/>
-
-        <ImageView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginRight="16dp"
-            android:src="@drawable/ic_cc"/>
-
-        <ImageView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:src="@drawable/ic_star_on_yellow"/>
-
-        <ImageView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:src="@drawable/ic_star_on_yellow"/>
-
-        <ImageView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:src="@drawable/ic_star_on_yellow"/>
-
-        <ImageView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:src="@drawable/ic_star_off"/>
-
-        <ImageView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:src="@drawable/ic_star_off"/>
-    </LinearLayout>
-
-    <TextView
-        android:id="@+id/extra_text"
-        style="@style/Widget.Leanback.DetailsDescriptionBodyStyle"
-        android:layout_width="match_parent"
-        android:fontFamily="sans-serif-regular"
-        android:layout_height="wrap_content"
-        android:text="Filmmaker Guillermo del Toro teas up with Legendary Pictures to bring audiences a unique take on the monster film with this sci/fi production."/>
-</LinearLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/grid_fragment.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/grid_fragment.xml
deleted file mode 100644
index 4e67908..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/grid_fragment.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             android:id="@+id/browse_dummy"
-             android:layout_width="match_parent"
-             android:layout_height="match_parent" >
-
-    <android.support.v17.leanback.widget.BrowseFrameLayout
-            android:id="@+id/grid_frame"
-            android:focusable="true"
-            android:focusableInTouchMode="true"
-            android:descendantFocusability="afterDescendants"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent" >
-
-        <FrameLayout
-                android:id="@+id/browse_grid_dock"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent" />
-
-    </android.support.v17.leanback.widget.BrowseFrameLayout>
-</FrameLayout>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/page_fragment.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/page_fragment.xml
deleted file mode 100644
index 3419b66..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/page_fragment.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:id="@+id/container_list"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
-
-    <LinearLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:layout_alignParentRight="true"
-            android:layout_marginRight="128dp"
-            android:layout_centerVertical="true">
-
-        <EditText
-                android:id="@+id/tv1"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="Header 1"
-                android:layout_margin="16dp"
-                android:focusable="true"
-                android:textAppearance="@android:style/TextAppearance.DeviceDefault.Large" />
-
-        <EditText
-                android:id="@+id/tv2"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="Header 2"
-                android:layout_margin="16dp"
-                android:focusable="true"
-                android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium" />
-
-        <EditText
-                android:id="@+id/tv3"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="Header 3"
-                android:layout_margin="16dp"
-                android:focusable="true"
-                android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small" />
-
-    </LinearLayout>
-</RelativeLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/page_list_row.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/page_list_row.xml
deleted file mode 100644
index 6b3cb6b..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/page_list_row.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent">
-
-    <fragment
-        android:id="@+id/page_list_fragment"
-        android:name="android.support.v17.leanback.supportleanbackshowcase.app.page.PageAndListRowFragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-</FrameLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/side_info_card.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/side_info_card.xml
deleted file mode 100644
index 725af09..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/side_info_card.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:lb="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/container"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:orientation="horizontal">
-
-    <ImageView
-        android:id="@+id/main_image"
-        android:layout_width="144dp"
-        android:layout_height="144dp"
-        lb:layout_viewType="main"
-        />
-
-    <LinearLayout
-        android:id="@+id/info"
-        android:layout_width="144dp"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:paddingLeft="11dp"
-        android:paddingRight="11dp"
-        android:paddingTop="7dp"
-        android:background="@color/default_card_footer_background_color">
-
-        <TextView
-            android:id="@+id/primary_text"
-            style="@style/Widget.Leanback.ImageCardView.TitleStyle"
-            android:fontFamily="sans-serif-condensed"
-            android:maxLines="2"
-            android:textSize="16sp"/>
-
-        <TextView
-            android:id="@+id/secondary_text"
-            style="@style/Widget.Leanback.ImageCardView.ContentStyle"
-            android:layout_marginTop="4dp"
-            android:fontFamily="sans-serif-condensed"
-            android:maxLines="1"
-            android:textColor="#EEEEEE"/>
-
-        <TextView
-            android:id="@+id/extra_text"
-            style="@style/Widget.Leanback.ImageCardView.ContentStyle"
-            android:layout_marginTop="6dp"
-            android:fontFamily="sans-serif-condensed"
-            android:maxLines="5"/>
-    </LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/text_icon_card.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/text_icon_card.xml
deleted file mode 100644
index 339549a..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/text_icon_card.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
-       xmlns:lb="http://schemas.android.com/apk/res-auto"
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content">
-
-    <TextView
-        android:id="@+id/extra_text"
-        style="@style/Widget.Leanback.ImageCardView.ContentStyle"
-        android:layout_width="256dp"
-        android:layout_height="wrap_content"
-        android:background="@color/default_card_background_color"
-        android:fontFamily="sans-serif-condensed"
-        android:lines="7"
-        android:maxLines="7"
-        android:paddingBottom="14dp"
-        android:paddingLeft="15dp"
-        android:paddingRight="15dp"
-        android:paddingTop="12dp"
-        lb:layout_viewType="main"/>
-
-    <android.support.v17.leanback.widget.NonOverlappingRelativeLayout
-        android:layout_width="256dp"
-        android:layout_height="36dp"
-        android:background="@color/default_card_footer_background_color"
-        android:gravity="left"
-        android:orientation="horizontal"
-        android:paddingBottom="7dp"
-        android:paddingLeft="12dp"
-        android:paddingRight="12dp"
-        android:paddingTop="7dp">
-
-        <ImageView
-            android:id="@+id/main_image"
-            android:layout_width="36dp"
-            android:layout_height="36dp"
-            android:layout_centerVertical="true"
-            android:layout_gravity="center_vertical"
-            android:layout_marginRight="8dp"
-            android:adjustViewBounds="true"/>
-
-        <TextView
-            android:id="@+id/primary_text"
-            style="@style/Widget.Leanback.ImageCardView.TitleStyle"
-            android:layout_width="match_parent"
-            android:layout_centerVertical="true"
-            android:layout_gravity="left"
-            android:layout_toRightOf="@+id/main_image"
-            android:fontFamily="sans-serif-condensed"
-            android:maxLines="1"
-            />
-
-        <ImageView
-            android:id="@+id/footer_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="32dp"
-            android:layout_alignParentEnd="true"
-            android:layout_centerVertical="true"
-            android:layout_gravity="center_vertical"
-            android:adjustViewBounds="true"
-            android:src="@drawable/stars_white"/>
-
-    </android.support.v17.leanback.widget.NonOverlappingRelativeLayout>
-</merge>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/titleview.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/titleview.xml
deleted file mode 100644
index a5de787..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/titleview.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<android.support.v17.leanback.supportleanbackshowcase.app.page.CustomTitleView
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/browse_title_group"
-        android:padding="16dp"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/video_surface_fragment.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/video_surface_fragment.xml
deleted file mode 100644
index ff5be69..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/video_surface_fragment.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
-           android:layout_width="match_parent"
-           android:layout_height="match_parent">
-</SurfaceView>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/wizard_progress_action_item.xml b/samples/SupportLeanbackShowcase/app/src/main/res/layout/wizard_progress_action_item.xml
deleted file mode 100644
index 9051f38..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/wizard_progress_action_item.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<android.support.v17.leanback.widget.NonOverlappingLinearLayout
-    style="?attr/guidedActionItemContainerStyle"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <ProgressBar
-        android:id="@+id/progressBar"
-        style="?android:attr/progressBarStyle"
-        android:indeterminateTintMode="src_in"
-        android:indeterminateTint="#FFAB91"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginRight="10dp"
-        android:indeterminate="false"/>
-
-    <android.support.v17.leanback.widget.NonOverlappingLinearLayout
-        android:id="@+id/guidedactions_item_content"
-        style="?attr/guidedActionItemContentStyle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content">
-
-        <TextView
-            android:id="@+id/guidedactions_item_title"
-            style="?attr/guidedActionItemTitleStyle"
-            android:text="Processing..."
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
-    </android.support.v17.leanback.widget.NonOverlappingLinearLayout>
-
-</android.support.v17.leanback.widget.NonOverlappingLinearLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/mipmap-xhdpi/app_banner_sample_app.png b/samples/SupportLeanbackShowcase/app/src/main/res/mipmap-xhdpi/app_banner_sample_app.png
deleted file mode 100644
index 222c1e5..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/mipmap-xhdpi/app_banner_sample_app.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/cards_example.json b/samples/SupportLeanbackShowcase/app/src/main/res/raw/cards_example.json
deleted file mode 100644
index 4fc4672..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/cards_example.json
+++ /dev/null
@@ -1,517 +0,0 @@
-[
-  {
-    "type" : 1,
-    "title": "ImageCardView Examples"
-  },
-  {
-    "title": "One Line Title",
-    "cards": [
-      {
-        "type": "MOVIE",
-        "title": "Deep Into The Deep Sleep",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_01"
-      },
-      {
-        "type": "MOVIE",
-        "title": "We",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_02"
-      },
-      {
-        "type": "MOVIE",
-        "title": "The Fairy Story Of A Legend",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_03"
-      },
-      {
-        "type": "MOVIE",
-        "title": "Cursed",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_04"
-      },
-      {
-        "type": "MOVIE",
-        "title": "My Crazy One",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_05"
-      },
-      {
-        "type": "MOVIE",
-        "title": "Gone",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_06"
-      },
-      {
-        "type": "MOVIE",
-        "title": "A Cold Night To Stay",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_07"
-      },
-      {
-        "type": "MOVIE",
-        "title": "The Silence",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_08"
-      },
-      {
-        "type": "MOVIE",
-        "title": "Hear The Roar",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_09"
-      }
-    ]
-  },
-  {
-    "title": "Two Line Title + Icon",
-    "cards": [
-      {
-        "type": "MOVIE_BASE",
-        "title": "Deep Into The Deep Sleep",
-        "localImageResource": "card_image_movie_01"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "We",
-        "localImageResource": "card_image_movie_02"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "The Fairy Story Of A Legend",
-        "localImageResource": "card_image_movie_03"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "Cursed",
-        "localImageResource": "card_image_movie_04"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "My Crazy One",
-        "localImageResource": "card_image_movie_05"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "Gone",
-        "localImageResource": "card_image_movie_06"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "A Cold Night To Stay",
-        "localImageResource": "card_image_movie_07"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "The Silence",
-        "localImageResource": "card_image_movie_08"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "Hear The Roar",
-        "localImageResource": "card_image_movie_09"
-      }
-    ]
-  },
-  {
-    "title": "Two Line Title + Description + Icon",
-    "cards": [
-      {
-        "type": "MOVIE_COMPLETE",
-        "description": "$3.99",
-        "title": "Deep Into The Deep Sleep",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_01"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "We",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_02"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "The Fairy",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_03"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "Cursed",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_04"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "My Crazy One",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_05"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "Gone",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_06"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "A Cold Night To Stay",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_07"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "description": "$3.99",
-        "title": "The Silence",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_08"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "Hear The Roar",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_09"
-      }
-    ]
-  },
-  {
-    "title": "Title + Description",
-    "cards": [
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#bf360C",
-        "localImageResource": "card_image_music_02"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#b93221",
-        "localImageResource": "card_image_music_03"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#311b92",
-        "localImageResource": "card_image_music_04"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#33691e",
-        "localImageResource": "card_image_music_05"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#37474f",
-        "localImageResource": "card_image_music_06"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#3e2723",
-        "localImageResource": "card_image_music_08"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#01579B",
-        "localImageResource": "card_image_music_09"
-      }
-    ]
-  },
-  {
-    "title": "Title + Description + Icon",
-    "cards": [
-      {
-        "type": "GAME",
-        "title": "Crazy One",
-        "description": "Purchased",
-        "localImageResource": "game_crazy_one",
-        "footerIconLocalImageResource": "ic_installed"
-      },
-      {
-        "type": "GAME",
-        "title": "Cursed",
-        "description": "Purchased",
-        "localImageResource": "game_cursed",
-        "footerIconLocalImageResource": "ic_installed"
-      },
-      {
-        "type": "GAME",
-        "title": "fairy",
-        "description": "Purchased",
-        "localImageResource": "game_fairy",
-        "footerIconLocalImageResource": "ic_installed"
-      },
-      {
-        "type": "GAME",
-        "title": "Hear The Roar",
-        "description": "Purchased",
-        "localImageResource": "game_hear_the_roar",
-        "footerIconLocalImageResource": "ic_installed"
-      },
-      {
-        "type": "GAME",
-        "title": "Silence",
-        "description": "Purchased",
-        "localImageResource": "game_silence",
-        "footerIconLocalImageResource": "ic_installed"
-      }
-    ]
-  },
-  {
-    "title": "Title + Description (Wide)",
-    "cards": [
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_01"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_02"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_03"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_04"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_05"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_06"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_07"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_08"
-      }
-    ]
-  },
-  {
-    "type" : 2
-  },
-  {
-    "type" : 1,
-    "title": "Advanced Examples"
-  },
-  {
-    "title": "BaseCardView Info On The Right",
-    "cards": [
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_02"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_03"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_04"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_05"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_06"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_07"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_08"
-      }
-    ]
-  },
-  {
-    "title": "BaseCardView using TextView",
-    "cards": [
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_01"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_02"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_03"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_04"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_05"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_06"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_07"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_08"
-      }
-    ]
-  },
-  {
-    "title": "ImageCardView Customize Style",
-    "cards": [
-      {
-        "type": "SINGLE_LINE",
-        "title": "Action & Adventure",
-        "footerColor": "#dd004e",
-        "localImageResource": "category_action"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Animation",
-        "footerColor": "#c51162",
-        "localImageResource": "category_animation"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Classics",
-        "footerColor": "#9c27b0",
-        "localImageResource": "category_classics"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Comedy",
-        "footerColor": "#cf4900",
-        "localImageResource": "category_comedy"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Crime",
-        "footerColor": "#3f51b5",
-        "localImageResource": "category_crime"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Documentary",
-        "footerColor": "#02639b",
-        "localImageResource": "category_documentary"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Drama",
-        "footerColor": "#2a56c6",
-        "localImageResource": "category_drama"
-      }
-    ]
-  },
-  {
-    "title": "ImageCardView with onFocusChange listener",
-    "shadow": false,
-    "cards": [
-      {
-        "type": "ICON",
-        "title": "Settings",
-        "localImageResource": "ic_settings_settings"
-      },
-      {
-        "type": "ICON",
-        "title": "WiFi",
-        "localImageResource": "ic_settings_wifi_3_bar"
-      },
-      {
-        "type": "ICON",
-        "title": "Parental Control",
-        "localImageResource": "ic_settings_parental_control"
-      },
-      {
-        "type": "ICON",
-        "title": "Time",
-        "localImageResource": "ic_settings_time"
-      }
-    ]
-  }
-]
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/detail_example.json b/samples/SupportLeanbackShowcase/app/src/main/res/raw/detail_example.json
deleted file mode 100644
index b6d06e2..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/detail_example.json
+++ /dev/null
@@ -1,106 +0,0 @@
-{
-  "title": "A Summer in a Canyon",
-  "description": "Kate Douglas Smith Wiggin",
-  "year": 1914,
-  "text": "It was nine o’clock one sunny California morning, and Geoffrey Strong stood under the live-oak trees in Las Flores Cañon, with a pot of black paint in one hand and a huge brush in the other.  He could have handled these implements to better purpose and with better grace had not his arms been firmly held by three laughing girls, who pulled not wisely, but too well.  He was further incommoded by the presence of a small urchin who lay on the dusty ground beneath his feet, fastening an upward clutch on the legs of his trousers.\n\nThere were three large canvas tents directly in front of them, yet no one of these seemed to be the object of dissension, but rather a redwood board, some three feet in length, which was nailed on a tree near by. twitch of her cousin’s sleeve.",
-  "localImageResource": "movie_poster_01",
-  "price": "$9.99",
-  "characters": [
-    {
-      "type": "CHARACTER",
-      "title": "Leonardo Di Caprio",
-      "localImageResource": "face_01"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Gerald Butler",
-      "localImageResource": "face_08"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Russle Crow",
-      "localImageResource": "face_02"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Emma Stone",
-      "localImageResource": "face_03"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Natalie Portman",
-      "localImageResource": "face_04"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Jack Gyllanhall",
-      "localImageResource": "face_05"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Ryan Gossling",
-      "localImageResource": "face_06"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Olivia Wilde",
-      "localImageResource": "face_07"
-    }
-  ],
-  "recommended": [
-    {
-      "type": "MOVIE",
-      "title": "The Amazing Spuder-Man",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_01"
-    },
-    {
-      "type": "MOVIE",
-      "title": "American Psycho",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_02"
-    },
-    {
-      "type": "MOVIE",
-      "title": "Big Hero 6",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_03"
-    },
-    {
-      "type": "MOVIE",
-      "title": "Edge of Tomorrow",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_04"
-    },
-    {
-      "type": "MOVIE",
-      "title": "The Hobbit: The Desolation of Smaug",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_05"
-    },
-    {
-      "type": "MOVIE",
-      "title": "Interstellar",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_06"
-    },
-    {
-      "type": "MOVIE",
-      "title": "Jurassic Park",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_07"
-    },
-    {
-      "type": "MOVIE",
-      "title": "The Hunger Games: Mockingjay Part I",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_08"
-    },
-    {
-      "type": "MOVIE",
-      "title": "Planes",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_09"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/grid_example.json b/samples/SupportLeanbackShowcase/app/src/main/res/raw/grid_example.json
deleted file mode 100644
index 56da5db..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/grid_example.json
+++ /dev/null
@@ -1,88 +0,0 @@
-{
-  "cards": [
-    {
-      "type": "GRID_SQUARE",
-      "title": "Nüsse",
-      "description": "$3.99/lb",
-      "localImageResource": "food_01"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Undefinierbar",
-      "description": "$3.99/lb",
-      "localImageResource": "food_02"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Brocoli",
-      "description": "$3.99/lb",
-      "localImageResource": "food_03"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Salat",
-      "description": "$3.99/lb",
-      "localImageResource": "food_04"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Große Radischen",
-      "description": "$3.99/lb",
-      "localImageResource": "food_05"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Rote Zwiebeln",
-      "description": "$3.99/lb",
-      "localImageResource": "food_06"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Lauch",
-      "description": "$3.99/lb",
-      "localImageResource": "food_07"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Exotisches Zeugs",
-      "description": "$3.99/lb",
-      "localImageResource": "food_08"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Zitronen",
-      "description": "$3.99/lb",
-      "localImageResource": "food_09"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Meerirgendwas",
-      "description": "$3.99/lb",
-      "localImageResource": "food_10"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Irgendein Kohl",
-      "description": "$3.99/lb",
-      "localImageResource": "food_11"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Apfel",
-      "description": "$3.99/lb",
-      "localImageResource": "food_12"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Mehr Äpfel",
-      "description": "$3.99/lb",
-      "localImageResource": "food_13"
-    },
-    {
-      "type": "GRID_SQUARE",
-      "title": "Tomaten",
-      "description": "$3.99/lb",
-      "localImageResource": "food_14"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/icon_example.json b/samples/SupportLeanbackShowcase/app/src/main/res/raw/icon_example.json
deleted file mode 100644
index 2fdfef5..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/icon_example.json
+++ /dev/null
@@ -1,65 +0,0 @@
-{
-  "title": "Icon",
-  "cards": [
-      {
-        "type": "ICON",
-        "title": "Settings",
-        "localImageResource": "ic_settings_settings"
-      },
-      {
-        "type": "ICON",
-        "title": "WiFi",
-        "localImageResource": "ic_settings_wifi_3_bar"
-      },
-      {
-        "type": "ICON",
-        "title": "Parental Control",
-        "localImageResource": "ic_settings_parental_control"
-      },
-      {
-        "type": "ICON",
-        "title": "Time",
-        "localImageResource": "ic_settings_time"
-      },
-      {
-        "type": "ICON",
-        "title": "Input connection",
-        "localImageResource": "icon_01"
-      },
-      {
-        "type": "ICON",
-        "title": "Hdmi",
-        "localImageResource": "icon_02"
-      },
-      {
-        "type": "ICON",
-        "title": "Overscan",
-        "localImageResource": "icon_03"
-      },
-      {
-        "type": "ICON",
-        "title": "Remote",
-        "localImageResource": "icon_04"
-      },
-      {
-        "type": "ICON",
-        "title": "Ethernet",
-        "localImageResource": "icon_05"
-      },
-      {
-        "type": "ICON",
-        "title": "Voice",
-        "localImageResource": "icon_06"
-      },
-      {
-        "type": "ICON",
-        "title": "Brightness",
-        "localImageResource": "icon_07"
-      },
-      {
-        "type": "ICON",
-        "title": "Antenna",
-        "localImageResource": "icon_08"
-      }
-    ]
-}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/launcher_cards.json b/samples/SupportLeanbackShowcase/app/src/main/res/raw/launcher_cards.json
deleted file mode 100644
index 7508d97..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/launcher_cards.json
+++ /dev/null
@@ -1,70 +0,0 @@
-[
-  {
-    "title": "",
-    "cards": [
-      {
-        "id": 0,
-        "type": "DEFAULT",
-        "title": "Card Examples",
-        "localImageResource": "thumbnail_example_cards",
-        "description": "Showcase of various card design and layouts"
-      },
-      {
-        "id": 1,
-        "type": "DEFAULT",
-        "title": "Page/Row fragment Examples",
-        "localImageResource": "thumbnail_example_browse",
-        "description": "Showcase usage of page/rows fragment"
-      },
-      {
-        "id": 2,
-        "type": "DEFAULT",
-        "title": "Grid Examples",
-        "localImageResource": "thumbnail_example_grid",
-        "description": "Showcase of various card design and layouts"
-      },
-      {
-        "id": 3,
-        "type": "DEFAULT",
-        "title": "Detail Examples",
-        "localImageResource": "thumbnail_example_detail",
-        "description": "Showcase of various card design and layouts"
-      },
-      {
-        "id": 4,
-        "type": "DEFAULT",
-        "title": "Video consumption Examples",
-        "localImageResource": "thumbnail_example_video_consumption",
-        "description": "Showcase of various card design and layouts"
-      },
-      {
-        "id": 5,
-        "type": "DEFAULT",
-        "title": "Music consumption Examples",
-        "localImageResource": "thumbnail_example_music_consumption",
-        "description": "Showcase of various card design and layouts"
-      },
-      {
-        "id": 6,
-        "type": "DEFAULT",
-        "title": "Wizard Examples",
-        "localImageResource": "thumbnail_example_wizard",
-        "description": "Showcase of various card design and layouts"
-      },
-      {
-        "id": 7,
-        "type": "DEFAULT",
-        "title": "Settings Examples",
-        "localImageResource": "thumbnail_example_settings",
-        "description": "Showcase of various card design and layouts"
-      },
-      {
-        "id": 8,
-        "type": "DEFAULT",
-        "title": "Dialog Examples",
-        "localImageResource": "thumbnail_example_dialog",
-        "description": "Showcase of various card design and layouts"
-      }
-    ]
-  }
-]
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/music_consumption_example.json b/samples/SupportLeanbackShowcase/app/src/main/res/raw/music_consumption_example.json
deleted file mode 100644
index 23eb239..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/music_consumption_example.json
+++ /dev/null
@@ -1,76 +0,0 @@
-{
-  "songs": [
-    {
-      "number": 1,
-      "duration": "1:38",
-      "title": "Thump and Jump",
-      "description": "Jimmy Fontanez/Media Right Production",
-      "image": "card_image_music_01",
-      "file": "track_01"
-    },
-    {
-      "number": 2,
-      "duration": "1:42",
-      "title": "Give",
-      "description": "Silent Partner",
-      "image": "card_image_music_02",
-      "file": "track_02"
-    },
-    {
-      "number": 3,
-      "duration": "1:21",
-      "title": "Dusty Road",
-      "description": "Jingle Punks",
-      "image": "card_image_music_03",
-      "file": "track_03"
-    },
-    {
-      "number": 4,
-      "duration": "2:06",
-      "title": "Light The Torch",
-      "description": "Silent Partner",
-      "image": "card_image_music_04",
-      "file": "track_04"
-    },
-    {
-      "number": 5,
-      "duration": "2:43",
-      "title": "Blue Skies",
-      "description": "Silent Partner",
-      "image": "card_image_music_05",
-      "file": "track_05"
-    },
-    {
-      "number": 6,
-      "duration": "0:05",
-      "title": "In the Land of Rhinoplasty(Sting)",
-      "description": "Jingle Punks",
-      "image": "card_image_music_06",
-      "file": "track_06"
-    },
-    {
-      "number": 7,
-      "duration": "2:54",
-      "title": "Ice Crystals",
-      "description": "Everet Almond",
-      "image": "card_image_music_07",
-      "file": "track_07"
-    },
-    {
-      "number": 8,
-      "duration": "2:38",
-      "title": "Shoulder Closures",
-      "description": "Gunnar Olsen",
-      "image": "card_image_music_08",
-      "file": "track_08"
-    },
-    {
-      "number": 9,
-      "duration": "2:40",
-      "title": "The Coldest Shoulder",
-      "description": "The 126ers",
-      "image": "card_image_music_09",
-      "file": "track_09"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/music_example.json b/samples/SupportLeanbackShowcase/app/src/main/res/raw/music_example.json
deleted file mode 100644
index b01a2d4..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/music_example.json
+++ /dev/null
@@ -1,106 +0,0 @@
-{
-  "title": "A Summer in a Canyon",
-  "description": "Kate Douglas Smith Wiggin",
-  "year": 1914,
-  "text": "It was nine o’clock one sunny California morning, and Geoffrey Strong stood under the live-oak trees in Las Flores Cañon, with a pot of black paint in one hand and a huge brush in the other.  He could have handled these implements to better purpose and with better grace had not his arms been firmly held by three laughing girls, who pulled not wisely, but too well.  He was further incommoded by the presence of a small urchin who lay on the dusty ground beneath his feet, fastening an upward clutch on the legs of his trousers.\n\nThere were three large canvas tents directly in front of them, yet no one of these seemed to be the object of dissension, but rather a redwood board, some three feet in length, which was nailed on a tree near by. twitch of her cousin’s sleeve.",
-  "localImageResource": "movie_poster_01",
-  "price": "$9.99",
-  "characters": [
-    {
-      "type": "CHARACTER",
-      "title": "Leonardo Di Caprio",
-      "localImageResource": "face_01"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Gerald Butler",
-      "localImageResource": "face_08"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Russle Crow",
-      "localImageResource": "face_02"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Emma Stone",
-      "localImageResource": "face_03"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Natalie Portman",
-      "localImageResource": "face_04"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Jack Gyllanhall",
-      "localImageResource": "face_05"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Ryan Gossling",
-      "localImageResource": "face_06"
-    },
-    {
-      "type": "CHARACTER",
-      "title": "Olivia Wilde",
-      "localImageResource": "face_07"
-    }
-  ],
-  "recommended": [
-    {
-      "type": "THIN",
-      "title": "The Amazing Spuder-Man",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_01"
-    },
-    {
-      "type": "THIN",
-      "title": "American Psycho",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_02"
-    },
-    {
-      "type": "THIN",
-      "title": "Big Hero 6",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_03"
-    },
-    {
-      "type": "THIN",
-      "title": "Edge of Tomorrow",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_04"
-    },
-    {
-      "type": "THIN",
-      "title": "The Hobbit: The Desolation of Smaug",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_05"
-    },
-    {
-      "type": "THIN",
-      "title": "Interstellar",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_06"
-    },
-    {
-      "type": "THIN",
-      "title": "Jurassic Park",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_07"
-    },
-    {
-      "type": "THIN",
-      "title": "The Hunger Games: Mockingjay Part I",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_08"
-    },
-    {
-      "type": "THIN",
-      "title": "Planes",
-      "description": "$3.99",
-      "localImageResource": "card_image_movie_09"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/page_row_example.json b/samples/SupportLeanbackShowcase/app/src/main/res/raw/page_row_example.json
deleted file mode 100644
index 5e686d7..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/page_row_example.json
+++ /dev/null
@@ -1,515 +0,0 @@
-[
-  {
-    "title": "One Line Title",
-    "cards": [
-      {
-        "type": "MOVIE",
-        "title": "Deep Into The Deep Sleep",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_01"
-      },
-      {
-        "type": "MOVIE",
-        "title": "We",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_02"
-      },
-      {
-        "type": "MOVIE",
-        "title": "The Fairy Story Of A Legend",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_03"
-      },
-      {
-        "type": "MOVIE",
-        "title": "Cursed",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_04"
-      },
-      {
-        "type": "MOVIE",
-        "title": "My Crazy One",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_05"
-      },
-      {
-        "type": "MOVIE",
-        "title": "Gone",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_06"
-      },
-      {
-        "type": "MOVIE",
-        "title": "A Cold Night To Stay",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_07"
-      },
-      {
-        "type": "MOVIE",
-        "title": "The Silence",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_08"
-      },
-      {
-        "type": "MOVIE",
-        "title": "Hear The Roar",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_09"
-      }
-    ]
-  },
-  {
-    "title": "Two Line Title",
-    "cards": [
-      {
-        "type": "MOVIE_BASE",
-        "title": "Deep Into The Deep Sleep",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_01"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "We",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_02"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "The Fairy Story Of A Legend",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_03"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "Cursed",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_04"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "My Crazy One",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_05"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "Gone",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_06"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "A Cold Night To Stay",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_07"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "The Silence",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_08"
-      },
-      {
-        "type": "MOVIE_BASE",
-        "title": "Hear The Roar",
-        "description": "$3.99",
-        "localImageResource": "card_image_movie_09"
-      }
-    ]
-  },
-  {
-    "title": "Two Line Title + Icon",
-    "cards": [
-      {
-        "type": "MOVIE_COMPLETE",
-        "description": "$3.99",
-        "title": "Deep Into The Deep Sleep",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_01"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "We",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_02"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "The Fairy",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_03"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "Cursed",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_04"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "My Crazy One",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_05"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "Gone",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_06"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "A Cold Night To Stay",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_07"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "description": "$3.99",
-        "title": "The Silence",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_08"
-      },
-      {
-        "type": "MOVIE_COMPLETE",
-        "title": "Hear The Roar",
-        "description": "$3.99",
-        "footerIconLocalImageResource": "stars_red",
-        "localImageResource": "card_image_movie_09"
-      }
-    ]
-  },
-  {
-    "title": "Title + Description",
-    "cards": [
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#bf360C",
-        "localImageResource": "card_image_music_02"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#b93221",
-        "localImageResource": "card_image_music_03"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#311b92",
-        "localImageResource": "card_image_music_04"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#33691e",
-        "localImageResource": "card_image_music_05"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#37474f",
-        "localImageResource": "card_image_music_06"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#3e2723",
-        "localImageResource": "card_image_music_08"
-      },
-      {
-        "type": "SQUARE_BIG",
-        "title": "Blue in Green",
-        "description": "Miles Davis",
-        "footerColor": "#01579B",
-        "localImageResource": "card_image_music_09"
-      }
-    ]
-  },
-  {
-    "title": "Title + Description + Icon",
-    "cards": [
-      {
-        "type": "GAME",
-        "title": "Crazy One",
-        "description": "Purchased",
-        "localImageResource": "game_crazy_one",
-        "footerIconLocalImageResource": "ic_installed"
-      },
-      {
-        "type": "GAME",
-        "title": "Cursed",
-        "description": "Purchased",
-        "localImageResource": "game_cursed",
-        "footerIconLocalImageResource": "ic_installed"
-      },
-      {
-        "type": "GAME",
-        "title": "fairy",
-        "description": "Purchased",
-        "localImageResource": "game_fairy",
-        "footerIconLocalImageResource": "ic_installed"
-      },
-      {
-        "type": "GAME",
-        "title": "Hear The Roar",
-        "description": "Purchased",
-        "localImageResource": "game_hear_the_roar",
-        "footerIconLocalImageResource": "ic_installed"
-      },
-      {
-        "type": "GAME",
-        "title": "Silence",
-        "description": "Purchased",
-        "localImageResource": "game_silence",
-        "footerIconLocalImageResource": "ic_installed"
-      }
-    ]
-  },
-  {
-    "title": "Title + Description (Wide)",
-    "cards": [
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_01"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_02"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_03"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_04"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_05"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_06"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_07"
-      },
-      {
-        "type": "DEFAULT",
-        "title": "Marseille sea food tour",
-        "description": "9,089 views   3 years ago   by ADELAIDE",
-        "localImageResource": "coffee_and_tea_08"
-      }
-    ]
-  },
-  {
-    "title": "BaseCardView Info On The Right",
-    "cards": [
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_02"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_03"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_04"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_05"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_06"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_07"
-      },
-      {
-        "type": "SIDE_INFO",
-        "title": "The Life Aquatic",
-        "description": "Seu Jorge",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "card_image_music_08"
-      }
-    ]
-  },
-  {
-    "title": "BaseCardView using TextView",
-    "cards": [
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_01"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_02"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_03"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_04"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_05"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_06"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_07"
-      },
-      {
-        "type": "TEXT",
-        "title": "Jonathan Max",
-        "extraText": "Bacon ipsum dolor amet bresaola kevin tenderloin swine shoulder strip steak t-bone picanha turducken beef. Ribeye turkey t-bone pastrami meatball corned beef. Pork belly landjaeger short ribs ground round cupim, brisket ham tri-tip. Pig pork loin hamburger picanha ribeye, pork belly meatball chicken ham boudin sirloin corned beef frankfurter ham hock.",
-        "localImageResource": "face_08"
-      }
-    ]
-  },
-  {
-    "title": "ImageCardView Customize Style",
-    "cards": [
-      {
-        "type": "SINGLE_LINE",
-        "title": "Action & Adventure",
-        "footerColor": "#dd004e",
-        "localImageResource": "category_action"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Animation",
-        "footerColor": "#c51162",
-        "localImageResource": "category_animation"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Classics",
-        "footerColor": "#9c27b0",
-        "localImageResource": "category_classics"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Comedy",
-        "footerColor": "#cf4900",
-        "localImageResource": "category_comedy"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Crime",
-        "footerColor": "#3f51b5",
-        "localImageResource": "category_crime"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Documentary",
-        "footerColor": "#02639b",
-        "localImageResource": "category_documentary"
-      },
-      {
-        "type": "SINGLE_LINE",
-        "title": "Drama",
-        "footerColor": "#2a56c6",
-        "localImageResource": "category_drama"
-      }
-    ]
-  },
-  {
-    "title": "ImageCardView with onFocusChange listener",
-    "shadow": false,
-    "cards": [
-      {
-        "type": "ICON",
-        "title": "Settings",
-        "localImageResource": "ic_settings_settings"
-      },
-      {
-        "type": "ICON",
-        "title": "WiFi",
-        "localImageResource": "ic_settings_wifi_3_bar"
-      },
-      {
-        "type": "ICON",
-        "title": "Parental Control",
-        "localImageResource": "ic_settings_parental_control"
-      },
-      {
-        "type": "ICON",
-        "title": "Time",
-        "localImageResource": "ic_settings_time"
-      }
-    ]
-  }
-]
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_01.mp3 b/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_01.mp3
deleted file mode 100755
index 9762383..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_01.mp3
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_02.mp3 b/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_02.mp3
deleted file mode 100755
index 82f4c8a..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_02.mp3
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_03.mp3 b/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_03.mp3
deleted file mode 100755
index 7faaeea..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_03.mp3
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_04.mp3 b/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_04.mp3
deleted file mode 100755
index 90a5310..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_04.mp3
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_05.mp3 b/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_05.mp3
deleted file mode 100755
index ec65400..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_05.mp3
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_06.mp3 b/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_06.mp3
deleted file mode 100755
index fe84974..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_06.mp3
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_07.mp3 b/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_07.mp3
deleted file mode 100755
index 9f876c0..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_07.mp3
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_08.mp3 b/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_08.mp3
deleted file mode 100755
index 33c8af8..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_08.mp3
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_09.mp3 b/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_09.mp3
deleted file mode 100755
index aaed617..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/track_09.mp3
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/raw/wizard_example.json b/samples/SupportLeanbackShowcase/app/src/main/res/raw/wizard_example.json
deleted file mode 100644
index f46b856..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/raw/wizard_example.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "title": "Androidify! The Movie",
-  "breadcrump": "Android TV",
-  "price_hd": "$4.99",
-  "price_sd": "$2.99"
-}
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/values/arrays.xml b/samples/SupportLeanbackShowcase/app/src/main/res/values/arrays.xml
deleted file mode 100644
index 9933ba7..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/values/arrays.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2015 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
-  ~ in compliance with the License. You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software distributed under the License
-  ~ is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-  ~ or implied. See the License for the specific language governing permissions and limitations under
-  ~ the License.
-  ~
-  -->
-
-<resources>
-    <array name="pref_parent_control_entries">
-        <item>Everyone</item>
-        <item>Low maturity</item>
-        <item>Medium maturity</item>
-        <item>High maturity</item>
-    </array>
-    <array name="pref_parent_control_entries_values">
-        <item>everyone</item>
-        <item>low</item>
-        <item>medium</item>
-        <item>high</item>
-    </array>
-    <array name="pref_parent_control_entries_summaries">
-        <item>This description becomes visible only on focus.</item>
-        <item>This description becomes visible only on focus.</item>
-        <item>This description becomes visible only on focus.</item>
-        <item>This description becomes visible only on focus.</item>
-    </array>
-    <array name="pref_wifi_networks">
-        <item>Wi-Fi network 1</item>
-        <item>Wi-Fi network 2</item>
-        <item>Wi-Fi network 3</item>
-        <item>Wi-Fi network 4</item>
-        <item>Wi-Fi network 5</item>
-        <item>Wi-Fi network 6</item>
-    </array>
-</resources>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/values/colors.xml b/samples/SupportLeanbackShowcase/app/src/main/res/values/colors.xml
deleted file mode 100644
index 8526c76..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2015 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
-  ~ in compliance with the License. You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software distributed under the License
-  ~ is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-  ~ or implied. See the License for the specific language governing permissions and limitations under
-  ~ the License.
-  ~
-  -->
-<resources>
-    <color name="background_gradient_start">#FFFFFF</color>
-    <color name="background_gradient_end">#DDDDDD</color>
-    <color name="fastlane_background">#06838f</color>
-    <color name="fastlane_teal_background">#00796B</color>
-    <color name="search_opaque">#ffaa3f</color>
-    <color name="search_color">#FFEB3B</color>
-    <color name="search_bright_color">#FFEB3B</color>
-    <color name="search_icon_color">#222222</color>
-    <color name="accent">#80D3FB</color>
-    <color name="settings_background">#00695C</color>
-
-    <color name="default_background">#3d3d3d</color>
-
-    <color name="default_card_background_color">#263238</color>
-    <color name="default_card_footer_background_color">#37474F</color>
-    <color name="selected_card_footer_background_color">#F0F</color>
-
-    <color name="lb_default_brand_color">#FF455A64</color>
-    <color name="card_primary_text">#EEEEEE</color>
-    <color name="card_secondary_text">#99EEEEEE</color>
-
-    <color name="loading_error_card_background">#86c739</color>
-
-    <color name="card_examples_background">#222222</color>
-
-    <color name="detail_view_actionbar_background">#04549D</color>
-    <color name="detail_view_background">#0374BF</color>
-    <color name="detail_view_related_background">#022A4E</color>
-    <color name="song_row_favorite_color">#FF6E40</color>
-
-    <color name="app_guidedstep_actions_background">#C03800</color>
-    <color name="app_guidedstep_subactions_background">#732200</color>
-    <color name="app_guidedstep_dialog_actions_background">#263238</color>
-    <color name="settings_card_background">#0277BD</color>
-    <color name="settings_card_background_focussed">#01579B</color>
-
-    <color name="player_progress_color">#feab91</color>
-    <color name="player_background_color">#db2a0f</color>
-
-</resources>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/values/dims.xml b/samples/SupportLeanbackShowcase/app/src/main/res/values/dims.xml
deleted file mode 100644
index 07c8027..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/values/dims.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2015 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
-  ~ in compliance with the License. You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software distributed under the License
-  ~ is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-  ~ or implied. See the License for the specific language governing permissions and limitations under
-  ~ the License.
-  ~
-  -->
-<resources>
-    <dimen name="default_image_card_width">224dp</dimen>
-    <dimen name="default_image_card_height">126dp</dimen>
-
-    <dimen name="movie_image_card_width">120dp</dimen>
-    <dimen name="movie_image_card_height">172dp</dimen>
-
-    <dimen name="icon_image_card_width">224dp</dimen>
-    <dimen name="icon_image_card_height">109dp</dimen>
-
-    <dimen name="big_square_image_card_width">144dp</dimen>
-    <dimen name="big_square_image_card_height">144dp</dimen>
-
-    <dimen name="square_image_card_width">128dp</dimen>
-    <dimen name="square_image_card_height">128dp</dimen>
-
-    <dimen name="small_square_image_card_width">96dp</dimen>
-    <dimen name="small_square_image_card_height">96dp</dimen>
-
-    <dimen name="sidetext_image_card_width">144dp</dimen>
-    <dimen name="sidetext_image_card_height">144dp</dimen>
-
-    <dimen name="wide_short_image_card_width">224dp</dimen>
-    <dimen name="wide_short_image_card_height">109dp</dimen>
-
-    <dimen name="character_image_card_width">120dp</dimen>
-    <dimen name="character_image_card_height">120dp</dimen>
-
-    <dimen name="grid_card_width">200dp</dimen>
-    <dimen name="grid_card_height">200dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/values/strings.xml b/samples/SupportLeanbackShowcase/app/src/main/res/values/strings.xml
deleted file mode 100644
index 0921d66..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2015 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
-  ~ in compliance with the License. You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software distributed under the License
-  ~ is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-  ~ or implied. See the License for the specific language governing permissions and limitations under
-  ~ the License.
-  ~
-  -->
-<resources>
-    <string name="app_name">ShowcaseApp</string>
-    <string name="browse_title"><![CDATA[androidTV]]></string>
-
-    <!-- Error messages -->
-    <string name="implement_search">Implement your own in-app search.</string>
-    <string name="card_examples_title">Card Examples</string>
-    <string name="detail_view_title">DetailView Example</string>
-    <string name="action_cicked">Action clicked. Implement your own handler.</string>
-    <string name="grid_example_title">Grid Example</string>
-    <string name="action_buy">Buy </string>
-    <string name="action_wishlist">Add to wishlist</string>
-    <string name="action_related">Related</string>
-    <string name="header_related">Related Items</string>
-    <string name="header_recommended">Recommended</string>
-
-    <!-- Page/List Row -->
-    <string name="page_list_row_title">Page and List Row</string>
-
-    <!-- Dialog example -->
-    <string name="dialog_example_title">Use Google\'s location service?</string>
-    <string name="dialog_example_description">Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.</string>
-    <string name="dialog_example_button_positive">Agree</string>
-    <string name="dialog_example_button_negative">Disagree</string>
-    <string name="dialog_example_button_toast_positive_clicked">\'Agree\' clicked.</string>
-    <string name="dialog_example_button_toast_negative_clicked">\'Disagree\' clicked.</string>
-
-    <!-- Wizard example -->
-    <string name="wizard_example_choose_rent_options">Choose rent options</string>
-    <string name="wizard_example_watch_hd">Watch in HD on supported devices</string>
-    <string name="wizard_example_watch_sd">Watch in standard definition on the web and supported devices</string>
-    <string name="wizard_example_rental_period">Rental period: start within 30 days,\nfinish within 24 hours</string>
-    <string name="wizard_example_input_card">Enter credit card number</string>
-    <string name="wizard_example_expiration_date">Exp Date</string>
-    <string name="wizard_example_payment_method">Payment Method</string>
-    <string name="wizard_example_toast_payment_method_clicked">\'Payment Method\' clicked.</string>
-    <string name="wizard_example_rent">Rent</string>
-    <string name="wizard_example_rent_hd">Rent HD</string>
-    <string name="wizard_example_rent_sd">Rent SD</string>
-    <string name="wizard_example_processing">Processinig...</string>
-    <string name="wizard_example_watch_now">Watch now</string>
-    <string name="wizard_example_later">Later</string>
-    <string name="wizard_example_watch_now_clicked">\'Watch now\' clicked.</string>
-    <string name="wizard_example_later_clicked">\'Later\' clicked.</string>
-    <string name="wizard_example_new_payment_guidance_title">New credit card</string>
-    <string name="wizard_example_new_payment_guidance_description">Enter new credit card information here</string>
-    <string name="wizard_example_input_credit">Input Payment Type</string>
-    <string name="wizard_example_visa">Visa-%s</string>
-    <string name="wizard_example_master">Master-%s</string>
-    <string name="wizard_example_input_credit_wrong">Error: invalid credit card number</string>
-    <string name="wizard_example_just_a_second">Just a second...</string>
-</resources>
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/values/styles.xml b/samples/SupportLeanbackShowcase/app/src/main/res/values/styles.xml
deleted file mode 100644
index 4f624d8..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,271 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2015 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
-  ~ in compliance with the License. You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software distributed under the License
-  ~ is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-  ~ or implied. See the License for the specific language governing permissions and limitations under
-  ~ the License.
-  ~
-  -->
-<resources>
-
-    <style name="AppTheme" parent="@style/Theme.Leanback">
-    </style>
-
-    <!-- Various movie card styles. Used in cards example. -->
-    <style name="MovieCardBadgeStyle" parent="Widget.Leanback.ImageCardView.BadgeStyle">
-        <item name="android:src">@drawable/stars_red</item>
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:scaleType">center</item>
-    </style>
-
-    <style name="MovieCardTitleTwoLineStyle" parent="Widget.Leanback.ImageCardView.TitleStyle">
-        <item name="android:maxLines">2</item>
-        <item name="android:minLines">2</item>
-    </style>
-
-    <style name="MovieCardContentGoneStyle" parent="Widget.Leanback.ImageCardView.ContentStyle">
-        <item name="android:visibility">invisible</item>
-    </style>
-
-    <style name="MovieCardContentStyle" parent="Widget.Leanback.ImageCardView.ContentStyle">
-        <item name="android:gravity">right</item>
-    </style>
-
-    <style name="MovieCardImageStyle" parent="Widget.Leanback.ImageCardView.ImageStyle">
-        <item name="android:layout_width">@dimen/movie_image_card_width</item>
-        <item name="android:layout_height">@dimen/movie_image_card_height</item>
-    </style>
-
-
-    <style name="MovieCardTitleOnlyStyle" parent="Widget.Leanback.ImageCardViewStyle">
-        <item name="lbImageCardViewType">Title</item>
-        <item name="cardBackground">@null</item>
-    </style>
-
-    <!-- Theme corresponding to the MovieCardSimpleStyle -->
-    <style name="MovieCardSimpleTheme" parent="Theme.Leanback">
-        <item name="imageCardViewStyle"> @style/MovieCardTitleOnlyStyle </item>
-        <item name="imageCardViewImageStyle">@style/MovieCardImageStyle</item>
-    </style>
-
-    <style name="MovieCardCompleteStyle" parent="MovieCardTitleOnlyStyle">
-        <item name="lbImageCardViewType">Title|Content|IconOnLeft</item>
-    </style>
-
-    <!-- Theme corresponding to the MovieCardCompleteStyle -->
-    <style name="MovieCardCompleteTheme" parent="Theme.Leanback">
-        <item name="imageCardViewStyle"> @style/MovieCardCompleteStyle </item>
-        <item name="imageCardViewImageStyle">@style/MovieCardImageStyle</item>
-        <item name="imageCardViewTitleStyle">@style/MovieCardTitleTwoLineStyle</item>
-        <item name="imageCardViewBadgeStyle">@style/MovieCardBadgeStyle</item>
-        <item name="imageCardViewContentStyle">@style/MovieCardContentStyle</item>
-    </style>
-
-    <!-- Theme corresponding to the MovieCardBasicStyle -->
-    <style name="MovieCardBasicTheme" parent="MovieCardCompleteTheme">
-        <item name="imageCardViewContentStyle">@style/MovieCardContentGoneStyle</item>
-    </style>
-
-    <!-- Squared Title/Content card style. Used in cards example. -->
-    <style name="SquareBigCardImageStyle" parent="Widget.Leanback.ImageCardView.ImageStyle">
-        <item name="android:layout_width">@dimen/big_square_image_card_width</item>
-        <item name="android:layout_height">@dimen/big_square_image_card_height</item>
-    </style>
-
-    <style name="SquareBigCard" parent="Widget.Leanback.ImageCardViewStyle">
-        <item name="cardBackground">@null</item>
-    </style>
-
-    <!-- Theme corresponding to the SquareBigCard -->
-    <style name="SquareBigCardTheme" parent="Theme.Leanback">
-        <item name="imageCardViewStyle"> @style/SquareBigCard </item>
-        <item name="imageCardViewImageStyle">@style/SquareBigCardImageStyle</item>
-    </style>
-
-    <!-- SideInfo. used in cards example -->
-    <style name="SideInfoCardStyle" parent="Widget.Leanback.BaseCardViewStyle">
-        <item name="cardType">mainOnly</item>
-        <item name="cardBackground">@null</item>
-    </style>
-
-    <!-- TextCardView. used in cards example -->
-    <style name="TextCardStyle" parent="Widget.Leanback.BaseCardViewStyle">
-        <item name="cardBackground">@null</item>
-    </style>
-
-    <!-- CharacterCardView. used in details example -->
-    <style name="CharacterCardStyle" parent="Widget.Leanback.BaseCardViewStyle">
-        <item name="cardBackground">@null</item>
-    </style>
-
-    <!-- Grid card style. Used by Grid example. -->
-    <style name="GridCardImageStyle" parent="Widget.Leanback.ImageCardView.ImageStyle">
-        <item name="android:layout_width">@dimen/grid_card_width</item>
-        <item name="android:layout_height">@dimen/grid_card_height</item>
-    </style>
-
-    <style name="GridCardStyle" parent="Widget.Leanback.ImageCardViewStyle">
-        <item name="cardBackground">@null</item>
-    </style>
-
-    <!-- Theme corresponding to the GridCardTheme -->
-    <style name="GridCardTheme" parent="Theme.Leanback">
-        <item name="imageCardViewStyle"> @style/GridCardStyle </item>
-        <item name="imageCardViewImageStyle">@style/GridCardImageStyle</item>
-    </style>
-
-    <!-- A default card style. Used in cards example. -->
-    <style name="DefaultCardImageStyle" parent="Widget.Leanback.ImageCardView.ImageStyle">
-        <item name="android:layout_width">@dimen/default_image_card_width</item>
-        <item name="android:layout_height">@dimen/default_image_card_height</item>
-    </style>
-
-    <style name="DefaultCardStyle" parent="Widget.Leanback.ImageCardViewStyle">
-        <item name="cardBackground">@null</item>
-    </style>
-
-    <style name="DefaultCardTheme" parent="Theme.Leanback">
-        <item name="imageCardViewStyle"> @style/DefaultCardStyle </item>
-        <item name="imageCardViewImageStyle">@style/DefaultCardImageStyle</item>
-    </style>
-
-    <!-- Game card styles with custom Badge icon. Used in cards example. -->
-    <style name="GameCardContentStyle" parent="Widget.Leanback.ImageCardView.ContentStyle">
-        <item name="android:textColor">#80c349</item>
-    </style>
-
-    <style name="GameCardBadgeStyle" parent="Widget.Leanback.ImageCardView.BadgeStyle">
-        <item name="android:src">@drawable/ic_installed</item>
-    </style>
-
-    <style name="GameCardStyle" parent="DefaultCardStyle">
-        <item name="lbImageCardViewType">Title|Content|IconOnRight</item>
-    </style>
-
-    <!-- Theme corresponding to the GameCardStyle -->
-    <style name="GameCardTheme" parent="Theme.Leanback">
-        <item name="imageCardViewStyle"> @style/GameCardStyle </item>
-        <item name="imageCardViewContentStyle">@style/GameCardContentStyle</item>
-        <item name="imageCardViewBadgeStyle">@style/GameCardBadgeStyle</item>
-        <item name="imageCardViewImageStyle">@style/DefaultCardImageStyle</item>
-    </style>
-
-    <!-- Squared single line card with colored footer style. Used in cards example. -->
-    <style name="SingleLineCardTitleStyle" parent="Widget.Leanback.ImageCardView.TitleStyle">
-        <item name="android:textAlignment">center</item>
-        <item name="android:gravity">center</item>
-    </style>
-
-    <style name="SingleLineCardInfoAreaStyle" parent="Widget.Leanback.ImageCardView.InfoAreaStyle">
-        <item name="android:layout_width">@dimen/square_image_card_width</item>
-        <item name="layout_viewType">main</item>
-    </style>
-
-    <style name="SingleLineCardImageStyle" parent="Widget.Leanback.ImageCardView.ImageStyle">
-        <item name="android:layout_width">@dimen/square_image_card_width</item>
-        <item name="android:layout_height">@dimen/square_image_card_height</item>
-    </style>
-
-    <style name="SingleLineCardStyle" parent="DefaultCardStyle">
-        <item name="lbImageCardViewType">Title</item>
-    </style>
-
-    <!-- Theme corresponding to the SingleLineCardStyle -->
-    <style name="SingleLineCardTheme" parent="Theme.Leanback">
-        <item name="imageCardViewStyle"> @style/SingleLineCardStyle </item>
-        <item name="imageCardViewTitleStyle">@style/SingleLineCardTitleStyle</item>
-        <item name="imageCardViewImageStyle">@style/SingleLineCardImageStyle</item>
-        <item name="imageCardViewInfoAreaStyle">@style/SingleLineCardInfoAreaStyle</item>
-    </style>
-
-
-    <!-- Icon card style with custom focus handler. Used in cards example. -->
-    <style name="IconCardViewStyle" parent="DefaultCardStyle">
-        <item name="lbImageCardViewType">Title</item>
-    </style>
-
-    <style name="IconCardImageStyle" parent="Widget.Leanback.ImageCardView.ImageStyle">
-        <item name="android:layout_width">96dp</item>
-        <item name="android:layout_height">96dp</item>
-        <item name="android:padding">16dp</item>
-    </style>
-
-    <style name="IconCardTitleStyle" parent="Widget.Leanback.ImageCardView.TitleStyle">
-        <item name="android:maxLines">2</item>
-        <item name="android:minLines">2</item>
-        <item name="android:gravity">center</item>
-    </style>
-
-    <style name="IconCardInfoAreaStyle" parent="Widget.Leanback.ImageCardView.InfoAreaStyle">
-        <item name="android:layout_width">96dp</item>
-        <item name="android:background">@null</item>
-        <item name="layout_viewType">main</item>
-    </style>
-
-    <!-- Theme corresponding to the IconCardStyle -->
-    <style name="IconCardTheme" parent="Theme.Leanback">
-        <item name="imageCardViewStyle"> @style/IconCardViewStyle </item>
-        <item name="imageCardViewTitleStyle">@style/IconCardTitleStyle</item>
-        <item name="imageCardViewImageStyle">@style/IconCardImageStyle</item>
-        <item name="imageCardViewInfoAreaStyle">@style/IconCardInfoAreaStyle</item>
-    </style>
-
-
-    <style name="MediaListHeaderStyle" parent="Widget.Leanback.PlaybackMediaListHeaderStyle">
-        <item name="android:background">#282248</item>
-    </style>
-
-    <style name="SharedMediaItemRowStyle" parent="Widget.Leanback.PlaybackMediaItemRowStyle">
-        <item name="android:background">#282248</item>
-    </style>
-
-    <style name="RegularMediaItemTextStyle" parent="TextAppearance.Leanback.PlaybackMediaItemNumber">
-        <item name="android:textColor">#FF6255</item>
-        <item name="android:textSize">18sp</item>
-        <item name="android:fontFamily">sans-serif-light</item>
-    </style>
-
-
-    <style name="RegularMediaItemNumberStyle" parent="Widget.Leanback.PlaybackMediaItemNumberStyle">
-        <item name="android:visibility">visible</item>
-        <!--<item name="android:textAppearance">@style/OddMediaItemNumberTextStyle</item>-->
-    </style>
-
-    <style name="RegularMediaItemNameStyle" parent="Widget.Leanback.PlaybackMediaItemNameStyle">
-        <!--<item name="android:textAppearance">@style/OddMediaItemNumberTextStyle</item>-->
-    </style>
-
-    <style name="RegularMediaItemDurationStyle" parent="Widget.Leanback.PlaybackMediaItemDurationStyle">
-        <item name="android:visibility">visible</item>
-        <!--<item name="android:textAppearance">@style/OddMediaItemNumberTextStyle</item>-->
-    </style>
-
-
-    <style name="FavoriteMediaItemTextStyle" parent="TextAppearance.Leanback.PlaybackMediaItemNumber">
-        <item name="android:textColor">#FF6E40</item>
-        <item name="android:textSize">18sp</item>
-        <item name="android:fontFamily">sans-serif-medium</item>
-    </style>
-
-    <style name="FavoriteMediaItemNumberStyle" parent="Widget.Leanback.PlaybackMediaItemNumberStyle">
-        <item name="android:visibility">visible</item>
-        <item name="android:textAppearance">@style/FavoriteMediaItemTextStyle</item>
-    </style>
-
-    <style name="FavoriteMediaItemNameStyle" parent="Widget.Leanback.PlaybackMediaItemNameStyle">
-        <item name="android:textAppearance">@style/FavoriteMediaItemTextStyle</item>
-    </style>
-
-    <style name="FavoriteMediaItemDurationStyle" parent="Widget.Leanback.PlaybackMediaItemDurationStyle">
-        <item name="android:visibility">visible</item>
-        <item name="android:textAppearance">@style/FavoriteMediaItemTextStyle</item>
-    </style>
-
-</resources>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/values/themes.xml b/samples/SupportLeanbackShowcase/app/src/main/res/values/themes.xml
deleted file mode 100644
index 4aa06f6..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/values/themes.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2015 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
-  ~ in compliance with the License. You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software distributed under the License
-  ~ is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-  ~ or implied. See the License for the specific language governing permissions and limitations under
-  ~ the License.
-  ~
-  -->
-<resources>
-
-    <style name="Theme.Example.Leanback" parent="Theme.Leanback">
-        <item name="android:colorPrimary">#00A2B8</item>
-        <item name="android:colorAccent">@color/accent</item>
-        <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14</item>
-    </style>
-
-    <style name="Theme.Example.LeanbackLauncher" parent="Theme.Example.Leanback">
-        <item name="android:windowBackground">@drawable/bg_living_room_wide</item>
-        <item name="browseRowsMarginTop">275dp</item>
-    </style>
-
-    <style name="Theme.Example.LeanbackBrowse" parent="Theme.Leanback.Browse">
-        <item name="android:windowBackground">@color/card_examples_background</item>
-        <item name="defaultBrandColor">@color/fastlane_background</item>
-        <item name="defaultSearchColor">@color/search_color</item>
-        <item name="defaultSearchIconColor">@color/search_icon_color</item>
-        <item name="defaultSearchBrightColor">@color/search_bright_color</item>
-    </style>
-
-    <style name="Theme.Example.Leanback.CustomTitle" parent="Theme.Example.LeanbackBrowse">
-        <item name="browseTitleViewLayout">@layout/titleview</item>
-        <item name="browseRowsMarginTop">120dp</item>
-    </style>
-
-    <style name="Theme.Example.LeanbackVerticalGrid" parent="Theme.Leanback.VerticalGrid">
-        <item name="android:windowBackground">@drawable/background_food</item>
-    </style>
-
-    <style name="Theme.Example.LeanbackWizard" parent="Theme.Leanback.GuidedStep">
-        <item name="guidedActionsBackground">@color/app_guidedstep_actions_background</item>
-        <item name="guidedActionsBackgroundDark">@color/app_guidedstep_subactions_background</item>
-    </style>
-
-    <style name="Theme.Example.LeanbackWizard.NoSelector">
-        <item name="guidedActionsSelectorDrawable">@null</item>
-    </style>
-
-    <style name="Theme.Example.LeanbackDialog" parent="Theme.Leanback.GuidedStep">
-        <item name="guidedActionsBackground">@color/app_guidedstep_dialog_actions_background</item>
-    </style>
-
-    <style name="Theme.Example.LeanbackPreferences" parent="Theme.Leanback">
-        <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Leanback</item>
-        <item name="android:windowIsTranslucent">true</item>
-        <item name="android:windowBackground">@android:color/transparent</item>
-        <item name="android:backgroundDimEnabled">true</item>
-        <item name="android:colorPrimary">@color/settings_background</item>
-    </style>
-
-    <style name="Theme.Example.LeanbackDetails" parent="Theme.Leanback.Details">
-        <item name="android:colorPrimary">@color/detail_view_actionbar_background</item>
-        <item name="android:windowBackground">@drawable/background_canyon</item>
-     </style>
-
-    <style name="Theme.Example.LeanbackMusic" parent="Theme.Example.Leanback">
-        <item name="android:windowBackground">@drawable/background_sax</item>
-     </style>
-
-    <style name="Theme.Example.LeanbackMusic.RegularSongNumbers">
-        <!--<item name="playbackMediaItemRowStyle">@style/SharedMediaItemRowStyle</item>-->
-        <item name="playbackMediaItemNumberStyle">@style/RegularMediaItemNumberStyle</item>
-        <item name="playbackMediaItemNameStyle">@style/RegularMediaItemNameStyle</item>
-        <item name="playbackMediaItemDurationStyle">@style/RegularMediaItemDurationStyle</item>
-    </style>
-
-    <style name="Theme.Example.LeanbackMusic.FavoriteSongNumbers">
-        <!--<item name="playbackMediaItemRowStyle">@style/SharedMediaItemRowStyle</item>-->
-        <item name="playbackMediaItemNumberStyle">@style/FavoriteMediaItemNumberStyle</item>
-        <item name="playbackMediaItemNameStyle">@style/FavoriteMediaItemNameStyle</item>
-        <item name="playbackMediaItemDurationStyle">@style/FavoriteMediaItemDurationStyle</item>
-    </style>
-
-    <style name="Theme.Example.LeanbackMusic.TrackListHeader">
-        <item name="playbackMediaListHeaderStyle">@style/MediaListHeaderStyle</item>
-    </style>
-
-</resources>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/xml/prefs.xml b/samples/SupportLeanbackShowcase/app/src/main/res/xml/prefs.xml
deleted file mode 100644
index f0edd0e..0000000
--- a/samples/SupportLeanbackShowcase/app/src/main/res/xml/prefs.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-                  xmlns:app="http://schemas.android.com/apk/res-auto"
-                  android:summary="This is a dummy activitiy only to show case how to build a settings in an application. Changing configurations in this example doesn't affect anything."
-                  android:title="Settings Example">
-    <PreferenceScreen
-        android:icon="@drawable/ic_settings_wifi_4_bar"
-        android:key="prefs_wifi_screen_key"
-        android:title="Wi-Fi">
-        <PreferenceCategory
-            android:key="prefs_wifi_networks_key"
-            android:title="Available Wi-Fi networks">
-            <ListPreference
-                android:defaultValue="-1"
-                android:entries="@array/pref_wifi_networks"
-                android:entryValues="@array/pref_wifi_networks"
-                android:title="Available Wi-Fi networks"
-                android:key="prefs_wifi_key">
-            </ListPreference>
-        </PreferenceCategory>
-        <PreferenceCategory
-            android:key="prefs_wifi_others_key"
-            android:title="Other options">
-            <Preference
-                android:title="Connect via WPS"
-                android:key="prefs_wifi_connect_wps"><!-- You can use Intents here -->
-            </Preference>
-        </PreferenceCategory>
-    </PreferenceScreen>
-    <PreferenceScreen
-        android:icon="@drawable/ic_settings_time"
-        android:key="prefs_date_time_screen_key"
-        android:title="Date &amp; time">
-        <CheckBoxPreference
-            android:defaultValue="true"
-            android:disableDependentsState="true"
-            android:key="prefs_date_time_automatic"
-            android:summaryOff="On"
-            android:summaryOn="Off"
-            android:title="Automatic date  &amp; time"></CheckBoxPreference>
-        <Preference
-            android:dependency="prefs_date_time_automatic"
-            android:key="prefs_date"
-            android:summary="01/01/1970"
-            android:title="Date"></Preference>
-        <Preference
-            android:dependency="prefs_date_time_automatic"
-            android:key="prefs_time"
-            android:summary="00:43 PM"
-            android:title="Time"></Preference>
-        <CheckBoxPreference
-            android:defaultValue="true"
-            android:disableDependentsState="true"
-            android:key="prefs_date_time_use_timezone"
-            android:summary="Use network provided time zone"
-            android:title="Automatic time zone"></CheckBoxPreference>
-        <Preference
-            android:dependency="prefs_date_time_use_timezone"
-            android:summary="GMT 07:00 Pacific Daylight Time"
-            android:title="Time zone"></Preference>
-    </PreferenceScreen>
-    <ListPreference
-        android:defaultValue="everyone"
-        android:icon="@drawable/ic_settings_parental_control"
-        android:entries="@array/pref_parent_control_entries"
-        android:entryValues="@array/pref_parent_control_entries_values"
-        android:key="prefs_parental_control_level_key"
-        android:dialogMessage="Allow contents rated for"
-        android:title="Parental Control">
-    </ListPreference>
-    <PreferenceScreen
-        android:icon="@drawable/ic_settings_apps"
-        android:key="prefs_apps_screen_key"
-        android:title="Apps">
-        <PreferenceCategory
-            android:key="prefs_app_settings_category"
-            android:title="Apps settings">
-            <PreferenceScreen
-                android:key="prefs_app_settings_screen_key"
-                android:summary="Lorem ipsum dolor sit amet consectur adipiscing."
-                android:title="App permissions">
-                <Preference
-                    android:icon="@mipmap/app_banner_sample_app"
-                    android:summary="45.5 MB"
-                    android:selectable="false"
-                    android:title="Application A"></Preference>
-                <Preference
-                    android:selectable="false"
-                    android:summary="Hier steht ein voelligst sinnfreier Text den ja sowieso niemandhier lesen kann. Deshalb macht es auch keinen Unterschied ob hier sinnvolles und nicht so sinnvolles Zeug steht. Hm... Sasha, du kannst das vielleicht lesen und denkst dir jetzt auch, dass ich voll haengen geblieben bin, oder?... ^_^"></Preference>
-                <SwitchPreference
-                    android:title="Notifications"
-                    android:key="pref_force_stop"><!-- Start an Intent --></SwitchPreference>
-                <Preference
-                    android:title="Uninstall"
-                    android:key="pref_uninstall"><!-- Start an Intent --></Preference>
-                <Preference
-                    android:title="More Information"
-                    android:key="pref_more_info"></Preference>
-            </PreferenceScreen>
-        </PreferenceCategory>
-        <PreferenceCategory
-            android:key="prefs_app_downloaded_apps_category"
-            android:title="Downloaded Apps">
-            <ListPreference
-                android:defaultValue="everyone"
-                android:entries="@array/pref_parent_control_entries"
-                android:entryValues="@array/pref_parent_control_entries_values"
-                android:key="prefs_parental_control_level_key"
-                android:title="Downloaded Apps">
-            </ListPreference>
-        </PreferenceCategory>
-    </PreferenceScreen>
-</PreferenceScreen>
diff --git a/samples/SupportLeanbackShowcase/build-local.py b/samples/SupportLeanbackShowcase/build-local.py
deleted file mode 100644
index 2677f3a..0000000
--- a/samples/SupportLeanbackShowcase/build-local.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# BUILDING SupportLeanbackShowcase app using local library.
-import sys
-import subprocess
-import os
-import fileinput
-import re
-
-# Does an inplace substitution of the pattern with newVal in inputFile
-def replace(inputFile, pattern, newVal, ):
-  print 'About to replace repo path to {0} in {1}'.format(newVal, inputFile)
-  replaced = False
-  if os.path.exists(inputFile):
-    for line in fileinput.input(inputFile, inplace = 1):
-      if re.match(pattern, line, re.I|re.M):
-        line = re.sub(pattern, newVal, line)
-        replaced = True
-      print line,
-
-  if not replaced:
-    file = open(inputFile, "a")
-    file.write(newVal + "\n")
-
-# Finds the local leanback library version based on leanback-v17/maven-metadata.xml
-def lookup_local_library_version(repo_path):
-  leanback_maven_metadata_path = repo_path + "/out/host/gradle/frameworks/support/build/support_repo/com/android/support/leanback-v17/maven-metadata.xml"
-  if not os.path.exists(leanback_maven_metadata_path):
-    print "ERROR: Missing leanback-v17 library {} in local repo".format(leanback_maven_metadata_path)
-
-  file = open(leanback_maven_metadata_path, "r")
-  for line in file:
-    matchObj = re.match(r'\s*<version>(.*)</version>', line)
-    if matchObj:
-      return matchObj.group(1).strip(' \t\n\r')
-
-# Get repo path
-current_path = os.getcwd()
-index = current_path.find("frameworks/support/samples/SupportLeanbackShowcase")
-if index < 0:
-  print "ERROR: Invalid repo {0}".format(current_path)
-  exit(0)
-
-repo_path = current_path[:index]
-support_frameworks_path = repo_path + "/frameworks/support"
-if not (os.path.isdir(repo_path) or os.path.isdir(support_frameworks_path)):
-  print 'ERROR : Repo "{0}" does not exist'.format(repo_path)
-  print 'Please run gradlew uploadArchives inside frameworks/support'
-  exit(0)
-
-# Substitute LIBRARY_VERSION/LOCAL_REPO in local.properties
-library_version = lookup_local_library_version(repo_path)
-replace(os.getcwd()+"/local.properties", r'(.*)LOCAL_REPO(.*)', 'LOCAL_REPO='+repo_path)
-replace(os.getcwd()+"/local.properties", r'(.*)LIBRARY_VERSION(.*)', 'LIBRARY_VERSION='+library_version)
-
-# Build
-print "Building SupportLeanbackShowcase app..."
-subprocess.call(["./gradlew", "assembleDebug"])
-
-#Install apk
-print "Installing SupportLeanbackShowcase..."
-subprocess.call(["adb", "install", "-r", "./app/build/outputs/apk/app-debug.apk"])
-
-print "Finished installing SupportLeanbackShowcase app."
-
diff --git a/samples/SupportLeanbackShowcase/build-release.py b/samples/SupportLeanbackShowcase/build-release.py
deleted file mode 100644
index 1ee4ef3..0000000
--- a/samples/SupportLeanbackShowcase/build-release.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# BUILDING SupportLeanbackShowcase app using local library.
-import sys
-import subprocess
-import os
-import fileinput
-import re
-
-# Does an inplace substitution of the pattern with newVal in inputFile
-def replace(inputFile, pattern, newVal, ):
-  print 'About to replace repo path to {0} in {1}'.format(newVal, inputFile)
-  replaced = False
-  if os.path.exists(inputFile):
-    for line in fileinput.input(inputFile, inplace = 1):
-      if re.match(pattern, line, re.I|re.M):
-        line = re.sub(pattern, newVal, line)
-        replaced = True
-      print line,
-
-  if not replaced:
-    file = open(inputFile, "a")
-    file.write(newVal + "\n")
-
-# Substitute LIBRARY_VERSION/LOCAL_REPO in local.properties
-# It will use default values in build.gradle
-replace(os.getcwd()+"/local.properties", r'(.*)LOCAL_REPO(.*)', 'LOCAL_REPO=')
-replace(os.getcwd()+"/local.properties", r'(.*)LIBRARY_VERSION(.*)', 'LIBRARY_VERSION=')
-
-# Build
-print "Building SupportLeanbackShowcase app..."
-subprocess.call(["./gradlew", "assembleDebug"])
-
-#Install apk
-print "Installing SupportLeanbackShowcase..."
-subprocess.call(["adb", "install", "-r", "./app/build/outputs/apk/app-debug.apk"])
-
-print "Finished installing SupportLeanbackShowcase app."
-
diff --git a/samples/SupportLeanbackShowcase/build.gradle b/samples/SupportLeanbackShowcase/build.gradle
deleted file mode 100644
index 287a234..0000000
--- a/samples/SupportLeanbackShowcase/build.gradle
+++ /dev/null
@@ -1,33 +0,0 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-ext {
-  // This will be set by local.properties file. By default it
-  // will use the public release version (24.0.0). You can run
-  // python build-local.py to build the local verison. That script will
-  // figure out the local library version based on maven metadata for leanback
-  // library and update local.properties file. Gradle build file in turn
-  // will pick up the settings from local.properties.
-  Properties properties = new Properties()
-  properties.load(project.rootProject.file('local.properties').newDataInputStream())
-  supportLibVersion = properties.getProperty('LIBRARY_VERSION')
-  supportLibVersion = supportLibVersion ? supportLibVersion : "24.0.0"
-  localRepo = properties.getProperty('LOCAL_REPO')
-}
-
-buildscript {
-    repositories {
-        jcenter()
-    }
-    dependencies {
-        classpath 'com.android.tools.build:gradle:3.0.0-rc1'
-
-        // NOTE: Do not place your application dependencies here; they belong
-        // in the individual module build.gradle files
-    }
-}
-
-allprojects {
-    repositories {
-        maven { url "${localRepo}/out/host/gradle/frameworks/support/build/support_repo/"}
-        jcenter()
-    }
-}
diff --git a/samples/SupportLeanbackShowcase/gradle.properties b/samples/SupportLeanbackShowcase/gradle.properties
deleted file mode 100644
index 1d3591c..0000000
--- a/samples/SupportLeanbackShowcase/gradle.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-# Project-wide Gradle settings.
-
-# IDE (e.g. Android Studio) users:
-# Gradle settings configured through the IDE *will override*
-# any settings specified in this file.
-
-# For more details on how to configure your build environment visit
-# http://www.gradle.org/docs/current/userguide/build_environment.html
-
-# Specifies the JVM arguments used for the daemon process.
-# The setting is particularly useful for tweaking memory settings.
-# Default value: -Xmx10248m -XX:MaxPermSize=256m
-# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
-
-# When configured, Gradle will run in incubating parallel mode.
-# This option should only be used with decoupled projects. More details, visit
-# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
-# org.gradle.parallel=true
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/gradle/wrapper/gradle-wrapper.jar b/samples/SupportLeanbackShowcase/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 8c0fb64..0000000
--- a/samples/SupportLeanbackShowcase/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/gradle/wrapper/gradle-wrapper.properties b/samples/SupportLeanbackShowcase/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 5686dee..0000000
--- a/samples/SupportLeanbackShowcase/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-#Thu Sep 01 17:18:32 PDT 2016
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
diff --git a/samples/SupportLeanbackShowcase/gradlew b/samples/SupportLeanbackShowcase/gradlew
deleted file mode 100755
index 91a7e26..0000000
--- a/samples/SupportLeanbackShowcase/gradlew
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/env bash
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn ( ) {
-    echo "$*"
-}
-
-die ( ) {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-esac
-
-# For Cygwin, ensure paths are in UNIX format before anything is touched.
-if $cygwin ; then
-    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
-fi
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >&-
-APP_HOME="`pwd -P`"
-cd "$SAVED" >&-
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
-    JVM_OPTS=("$@")
-}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
-
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/samples/SupportLeanbackShowcase/gradlew.bat b/samples/SupportLeanbackShowcase/gradlew.bat
deleted file mode 100644
index aec9973..0000000
--- a/samples/SupportLeanbackShowcase/gradlew.bat
+++ /dev/null
@@ -1,90 +0,0 @@
-@if "%DEBUG%" == "" @echo off

-@rem ##########################################################################

-@rem

-@rem  Gradle startup script for Windows

-@rem

-@rem ##########################################################################

-

-@rem Set local scope for the variables with windows NT shell

-if "%OS%"=="Windows_NT" setlocal

-

-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.

-set DEFAULT_JVM_OPTS=

-

-set DIRNAME=%~dp0

-if "%DIRNAME%" == "" set DIRNAME=.

-set APP_BASE_NAME=%~n0

-set APP_HOME=%DIRNAME%

-

-@rem Find java.exe

-if defined JAVA_HOME goto findJavaFromJavaHome

-

-set JAVA_EXE=java.exe

-%JAVA_EXE% -version >NUL 2>&1

-if "%ERRORLEVEL%" == "0" goto init

-

-echo.

-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

-echo.

-echo Please set the JAVA_HOME variable in your environment to match the

-echo location of your Java installation.

-

-goto fail

-

-:findJavaFromJavaHome

-set JAVA_HOME=%JAVA_HOME:"=%

-set JAVA_EXE=%JAVA_HOME%/bin/java.exe

-

-if exist "%JAVA_EXE%" goto init

-

-echo.

-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%

-echo.

-echo Please set the JAVA_HOME variable in your environment to match the

-echo location of your Java installation.

-

-goto fail

-

-:init

-@rem Get command-line arguments, handling Windowz variants

-

-if not "%OS%" == "Windows_NT" goto win9xME_args

-if "%@eval[2+2]" == "4" goto 4NT_args

-

-:win9xME_args

-@rem Slurp the command line arguments.

-set CMD_LINE_ARGS=

-set _SKIP=2

-

-:win9xME_args_slurp

-if "x%~1" == "x" goto execute

-

-set CMD_LINE_ARGS=%*

-goto execute

-

-:4NT_args

-@rem Get arguments from the 4NT Shell from JP Software

-set CMD_LINE_ARGS=%$

-

-:execute

-@rem Setup the command line

-

-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

-

-@rem Execute Gradle

-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

-

-:end

-@rem End local scope for the variables with windows NT shell

-if "%ERRORLEVEL%"=="0" goto mainEnd

-

-:fail

-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of

-rem the _cmd.exe /c_ return code!

-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1

-exit /b 1

-

-:mainEnd

-if "%OS%"=="Windows_NT" endlocal

-

-:omega

diff --git a/samples/SupportLeanbackShowcase/libs/gson-1.7.2.jar b/samples/SupportLeanbackShowcase/libs/gson-1.7.2.jar
deleted file mode 100644
index 99e7afc..0000000
--- a/samples/SupportLeanbackShowcase/libs/gson-1.7.2.jar
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/libs/picasso-2.5.2.jar b/samples/SupportLeanbackShowcase/libs/picasso-2.5.2.jar
deleted file mode 100644
index 6acbaa1..0000000
--- a/samples/SupportLeanbackShowcase/libs/picasso-2.5.2.jar
+++ /dev/null
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/settings.gradle b/samples/SupportLeanbackShowcase/settings.gradle
deleted file mode 100644
index e7b4def..0000000
--- a/samples/SupportLeanbackShowcase/settings.gradle
+++ /dev/null
@@ -1 +0,0 @@
-include ':app'
diff --git a/samples/SupportPreferenceDemos/src/main/res/xml/preferences.xml b/samples/SupportPreferenceDemos/src/main/res/xml/preferences.xml
index f469af2..4d1dca7 100644
--- a/samples/SupportPreferenceDemos/src/main/res/xml/preferences.xml
+++ b/samples/SupportPreferenceDemos/src/main/res/xml/preferences.xml
@@ -31,6 +31,12 @@
         android:title="@string/title_stylish_preference"
         android:summary="@string/summary_stylish_preference" />
 
+    <Preference
+        android:key="preference_with_icon"
+        android:title="Preference with icon"
+        android:summary="This preference has an icon"
+        android:icon="@android:drawable/ic_menu_camera" />
+
     <PreferenceCategory
         android:title="@string/inline_preferences">
 
@@ -39,6 +45,11 @@
             android:title="@string/title_checkbox_preference"
             android:summary="@string/summary_checkbox_preference" />
 
+        <SwitchPreference
+            android:key="switch_preference"
+            android:title="Switch preference"
+            android:summary="This is a switch" />
+
         <DropDownPreference
             android:key="dropdown_preference"
             android:title="@string/title_dropdown_preference"
diff --git a/samples/SupportSliceDemos/OWNERS b/samples/SupportSliceDemos/OWNERS
new file mode 100644
index 0000000..921a517
--- /dev/null
+++ b/samples/SupportSliceDemos/OWNERS
@@ -0,0 +1,2 @@
+jmonk@google.com
+madym@google.com
diff --git a/samples/SupportSliceDemos/build.gradle b/samples/SupportSliceDemos/build.gradle
new file mode 100644
index 0000000..be89a66
--- /dev/null
+++ b/samples/SupportSliceDemos/build.gradle
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+import static android.support.dependencies.DependenciesKt.*
+
+apply plugin: 'com.android.application'
+
+dependencies {
+    implementation(project(":slices-view"))
+    implementation(project(":slices-builders"))
+    implementation(project(":slices-core"))
+    implementation(project(":design"))
+    implementation(project(":appcompat-v7"))
+    implementation(project(":cardview-v7"))
+    api(ARCH_LIFECYCLE_EXTENSIONS, libs.exclude_annotations_transitive)
+}
+
+android {
+    compileSdkVersion project.ext.currentSdk
+
+    defaultConfig {
+        applicationId "com.example.androidx.slice.demos"
+        minSdkVersion 26
+        targetSdkVersion project.ext.currentSdk
+    }
+
+    signingConfigs {
+        debug {
+            // Use a local debug keystore to avoid build server issues.
+            storeFile project.rootProject.init.debugKeystore
+        }
+    }
+
+    lintOptions {
+        abortOnError true
+        disable "SetTextI18n", "AppCompatResource", "WrongConstant", "AllowBackup",
+                "GoogleAppIndexingWarning", "AlwaysShowAction"
+    }
+    compileOptions {
+        targetCompatibility 1.8
+        sourceCompatibility 1.8
+    }
+}
diff --git a/samples/SupportSliceDemos/src/main/AndroidManifest.xml b/samples/SupportSliceDemos/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..5285c34
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/AndroidManifest.xml
@@ -0,0 +1,67 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="com.example.androidx.slice.demos">
+
+    <uses-sdk tools:overrideLibrary="androidx.app.slice.view, androidx.app.slice.builders, androidx.app.slice.core" />
+
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.BIND_SLICE" />
+
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
+        <activity
+            android:name=".SliceBrowser"
+            android:label="@string/app_name"
+            android:theme="@style/AppTheme.NoActionBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+            <intent-filter>
+                <action android:name="androidx.intent.SLICE_ACTION"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+
+        <provider android:authorities="com.example.androidx.slice.demos"
+                  android:name=".SampleSliceProvider"
+                  android:grantUriPermissions="true">
+            <intent-filter>
+                <action android:name="androidx.intent.SLICE_ACTION"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </provider>
+
+        <receiver
+            android:name=".SliceBroadcastReceiver"
+            android:exported="true" >
+            <intent-filter>
+                <action android:name="com.example.androidx.slice.action.*"/>
+            </intent-filter>
+        </receiver>
+    </application>
+
+</manifest>
diff --git a/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
new file mode 100644
index 0000000..2f2a1c3
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright 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.androidx.slice.demos;
+
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.net.wifi.WifiManager;
+import android.provider.Settings;
+import android.support.annotation.NonNull;
+import android.text.format.DateUtils;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceProvider;
+import androidx.app.slice.builders.ListBuilder;
+import androidx.app.slice.builders.MessagingSliceBuilder;
+
+/**
+ * Examples of using slice template builders.
+ */
+public class SampleSliceProvider extends SliceProvider {
+
+    public static final String ACTION_WIFI_CHANGED =
+            "com.example.androidx.slice.action.WIFI_CHANGED";
+    public static final String ACTION_TOAST =
+            "com.example.androidx.slice.action.TOAST";
+    public static final String EXTRA_TOAST_MESSAGE = "com.example.androidx.extra.TOAST_MESSAGE";
+
+    public static final String[] URI_PATHS = { "message", "wifi", "note", "ride", "toggle"};
+
+    /**
+     * @return Uri with the provided path
+     */
+    public static Uri getUri(String path, Context context) {
+        return new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(context.getPackageName())
+                .appendPath(path)
+                .build();
+    }
+
+    @Override
+    public boolean onCreateSliceProvider() {
+        return true;
+    }
+
+    @NonNull
+    @Override
+    public Uri onMapIntentToUri(Intent intent) {
+        return getUri("wifi", getContext());
+    }
+
+    @Override
+    public Slice onBindSlice(Uri sliceUri) {
+        String path = sliceUri.getPath();
+        switch (path) {
+            case "/message":
+                return createMessagingSlice(sliceUri);
+            case "/wifi":
+                return createWifiSlice(sliceUri);
+            case "/note":
+                return createNoteSlice(sliceUri);
+            case "/ride":
+                return createRideSlice(sliceUri);
+            case "/toggle":
+                return createCustomToggleSlice(sliceUri);
+        }
+        throw new IllegalArgumentException("Unknown uri " + sliceUri);
+    }
+
+    private Slice createMessagingSlice(Uri sliceUri) {
+        // TODO: Remote input.
+        return new MessagingSliceBuilder(sliceUri)
+                .add(b -> b
+                        .addText("yo home \uD83C\uDF55, I emailed you the info")
+                        .addTimestamp(System.currentTimeMillis() - 20 * DateUtils.MINUTE_IN_MILLIS)
+                        .addSource(Icon.createWithResource(getContext(), R.drawable.mady)))
+                .add(b -> b
+                        .addText("just bought my tickets")
+                        .addTimestamp(System.currentTimeMillis() - 10 * DateUtils.MINUTE_IN_MILLIS))
+                .add(b -> b
+                        .addText("yay! can't wait for getContext() weekend!\n"
+                                + "\uD83D\uDE00")
+                        .addTimestamp(System.currentTimeMillis() - 5 * DateUtils.MINUTE_IN_MILLIS)
+                        .addSource(Icon.createWithResource(getContext(), R.drawable.mady)))
+                .build();
+
+    }
+
+    private Slice createNoteSlice(Uri sliceUri) {
+        return new ListBuilder(sliceUri)
+                .setColor(0xfff4b400)
+                .add(b -> b
+                    .setTitle("Create new note")
+                    .setSubtitle("with this note taking app")
+                    .addEndItem(getBroadcastIntent(ACTION_TOAST, "create note"),
+                            Icon.createWithResource(getContext(), R.drawable.ic_create))
+                    .addEndItem(getBroadcastIntent(ACTION_TOAST, "voice note"),
+                            Icon.createWithResource(getContext(), R.drawable.ic_voice))
+                    .addEndItem(getIntent("android.media.action.IMAGE_CAPTURE"),
+                            Icon.createWithResource(getContext(), R.drawable.ic_camera)))
+                .build();
+    }
+
+    private Slice createRideSlice(Uri sliceUri) {
+        return new ListBuilder(sliceUri)
+                .setColor(0xff1b5e20)
+                .add(b -> b
+                    .setContentIntent(getBroadcastIntent(ACTION_TOAST, "work"))
+                    .setTitle("Work")
+                    .setSubtitle("2 min")
+                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_work)))
+                .add(b -> b
+                    .setContentIntent(getBroadcastIntent(ACTION_TOAST, "home"))
+                    .setTitle("Home")
+                    .setSubtitle("2 hours 33 min via 101")
+                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_home))
+                    .setIsHeader(true))
+                .add(b -> b
+                    .setContentIntent(getBroadcastIntent(ACTION_TOAST, "book ride"))
+                    .setTitle("Book ride")
+                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_car)))
+                .build();
+    }
+
+    private Slice createCustomToggleSlice(Uri sliceUri) {
+        return new ListBuilder(sliceUri)
+                .setColor(0xffff4081)
+                .add(b -> b
+                    .setTitle("Custom toggle")
+                    .setSubtitle("It can support two states")
+                    .addToggle(getBroadcastIntent(ACTION_TOAST, "start toggled"),
+                            Icon.createWithResource(getContext(), R.drawable.toggle_star),
+                            true /* isChecked */))
+                .build();
+    }
+
+    private Slice createWifiSlice(Uri sliceUri) {
+        // Get wifi state
+        WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
+        int wifiState = wifiManager.getWifiState();
+        boolean wifiEnabled = false;
+        String state;
+        switch (wifiState) {
+            case WifiManager.WIFI_STATE_DISABLED:
+            case WifiManager.WIFI_STATE_DISABLING:
+                state = "disconnected";
+                break;
+            case WifiManager.WIFI_STATE_ENABLED:
+            case WifiManager.WIFI_STATE_ENABLING:
+                state = wifiManager.getConnectionInfo().getSSID();
+                wifiEnabled = true;
+                break;
+            case WifiManager.WIFI_STATE_UNKNOWN:
+            default:
+                state = ""; // just don't show anything?
+                break;
+        }
+        boolean finalWifiEnabled = wifiEnabled;
+        return new ListBuilder(sliceUri)
+                .setColor(0xff4285f4)
+                .add(b -> b
+                    .setTitle("Wi-fi")
+                    .setTitleItem(Icon.createWithResource(getContext(), R.drawable.ic_wifi))
+                    .setSubtitle(state)
+                    .addToggle(getBroadcastIntent(ACTION_WIFI_CHANGED, null), finalWifiEnabled)
+                    .setContentIntent(getIntent(Settings.ACTION_WIFI_SETTINGS)))
+            .build();
+    }
+
+    private PendingIntent getIntent(String action) {
+        Intent intent = new Intent(action);
+        PendingIntent pi = PendingIntent.getActivity(getContext(), 0, intent, 0);
+        return pi;
+    }
+
+    private PendingIntent getBroadcastIntent(String action, String message) {
+        Intent intent = new Intent(action);
+        if (message != null) {
+            intent.putExtra(EXTRA_TOAST_MESSAGE, message);
+        }
+        intent.setClass(getContext(), SliceBroadcastReceiver.class);
+        return PendingIntent.getBroadcast(getContext(), 0, intent,
+                PendingIntent.FLAG_CANCEL_CURRENT);
+    }
+}
diff --git a/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SliceBroadcastReceiver.java b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SliceBroadcastReceiver.java
new file mode 100644
index 0000000..05f0820
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SliceBroadcastReceiver.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 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.androidx.slice.demos;
+
+import static com.example.androidx.slice.demos.SampleSliceProvider.getUri;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.widget.Toast;
+
+import androidx.app.slice.core.SliceHints;
+
+/**
+ * Responds to actions performed on slices and notifies slices of updates in state changes.
+ */
+public class SliceBroadcastReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(Context context, Intent i) {
+        String action = i.getAction();
+        switch (action) {
+            case SampleSliceProvider.ACTION_WIFI_CHANGED:
+                WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+                boolean newState = i.getBooleanExtra(SliceHints.EXTRA_TOGGLE_STATE,
+                        wm.isWifiEnabled());
+                wm.setWifiEnabled(newState);
+                // Wait a bit for wifi to update (TODO: is there a better way to do this?)
+                Handler h = new Handler();
+                h.postDelayed(() -> {
+                    context.getContentResolver().notifyChange(getUri("wifi", context), null);
+                }, 1000);
+                break;
+            case SampleSliceProvider.ACTION_TOAST:
+                String message = i.getExtras().getString(SampleSliceProvider.EXTRA_TOAST_MESSAGE,
+                        "no message");
+                Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
+                break;
+        }
+    }
+}
diff --git a/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SliceBrowser.java b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SliceBrowser.java
new file mode 100644
index 0000000..82804fd
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SliceBrowser.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright 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.androidx.slice.demos;
+
+import static com.example.androidx.slice.demos.SampleSliceProvider.URI_PATHS;
+import static com.example.androidx.slice.demos.SampleSliceProvider.getUri;
+
+import android.arch.lifecycle.LiveData;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.BaseColumns;
+import android.support.annotation.RequiresApi;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.SubMenu;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.SearchView;
+import android.widget.SimpleCursorAdapter;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.widget.SliceLiveData;
+import androidx.app.slice.widget.SliceView;
+
+/**
+ * Example use of SliceView. Uses a search bar to select/auto-complete a slice uri which is
+ * then displayed in the selected mode with SliceView.
+ */
+@RequiresApi(api = 28)
+public class SliceBrowser extends AppCompatActivity {
+
+    private static final String TAG = "SlicePresenter";
+
+    private static final String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
+    private static final boolean TEST_INTENT = false;
+
+    private ArrayList<Uri> mSliceUris = new ArrayList<Uri>();
+    private int mSelectedMode;
+    private ViewGroup mContainer;
+    private SearchView mSearchView;
+    private SimpleCursorAdapter mAdapter;
+    private SubMenu mTypeMenu;
+    private LiveData<Slice> mSliceLiveData;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_layout);
+
+        Toolbar toolbar = findViewById(R.id.search_toolbar);
+        setSupportActionBar(toolbar);
+
+        // Shows the slice
+        mContainer = findViewById(R.id.slice_preview);
+        mSearchView = findViewById(R.id.search_view);
+
+        final String[] from = new String[]{"uri"};
+        final int[] to = new int[]{android.R.id.text1};
+        mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1,
+                null, from, to, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
+        mSearchView.setSuggestionsAdapter(mAdapter);
+        mSearchView.setIconifiedByDefault(false);
+        mSearchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
+            @Override
+            public boolean onSuggestionClick(int position) {
+                mSearchView.setQuery(((Cursor) mAdapter.getItem(position)).getString(1), true);
+                return true;
+            }
+
+            @Override
+            public boolean onSuggestionSelect(int position) {
+                mSearchView.setQuery(((Cursor) mAdapter.getItem(position)).getString(1), true);
+                return true;
+            }
+        });
+        mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+            @Override
+            public boolean onQueryTextSubmit(String s) {
+                addSlice(Uri.parse(s));
+                mSearchView.clearFocus();
+                return false;
+            }
+
+            @Override
+            public boolean onQueryTextChange(String s) {
+                populateAdapter(s);
+                return false;
+            }
+        });
+
+        mSelectedMode = (savedInstanceState != null)
+                ? savedInstanceState.getInt("SELECTED_MODE", SliceView.MODE_SHORTCUT)
+                : SliceView.MODE_SHORTCUT;
+        if (savedInstanceState != null) {
+            mSearchView.setQuery(savedInstanceState.getString("SELECTED_QUERY"), true);
+        }
+
+        // TODO: Listen for changes.
+        updateAvailableSlices();
+        if (TEST_INTENT) {
+            addSlice(new Intent("androidx.intent.SLICE_ACTION").setPackage(getPackageName()));
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        mTypeMenu = menu.addSubMenu("Type");
+        mTypeMenu.setIcon(R.drawable.ic_shortcut);
+        mTypeMenu.getItem().setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+        mTypeMenu.add("Shortcut");
+        mTypeMenu.add("Small");
+        mTypeMenu.add("Large");
+        menu.add("Auth");
+        super.onCreateOptionsMenu(menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getTitle().toString()) {
+            case "Auth":
+                authAllSlices();
+                return true;
+            case "Shortcut":
+                mTypeMenu.setIcon(R.drawable.ic_shortcut);
+                mSelectedMode = SliceView.MODE_SHORTCUT;
+                updateSliceModes();
+                return true;
+            case "Small":
+                mTypeMenu.setIcon(R.drawable.ic_small);
+                mSelectedMode = SliceView.MODE_SMALL;
+                updateSliceModes();
+                return true;
+            case "Large":
+                mTypeMenu.setIcon(R.drawable.ic_large);
+                mSelectedMode = SliceView.MODE_LARGE;
+                updateSliceModes();
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putInt("SELECTED_MODE", mSelectedMode);
+        outState.putString("SELECTED_QUERY", mSearchView.getQuery().toString());
+    }
+
+    private void authAllSlices() {
+        List<ApplicationInfo> packages = getPackageManager().getInstalledApplications(0);
+        packages.forEach(info -> {
+            for (int i = 0; i < URI_PATHS.length; i++) {
+                grantUriPermission(info.packageName, getUri(URI_PATHS[i], getApplicationContext()),
+                        Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+                                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+            }
+        });
+    }
+
+    private void updateAvailableSlices() {
+        mSliceUris.clear();
+        List<PackageInfo> packageInfos = getPackageManager()
+                .getInstalledPackages(PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
+        for (PackageInfo pi : packageInfos) {
+            ActivityInfo[] activityInfos = pi.activities;
+            if (activityInfos != null) {
+                for (ActivityInfo ai : activityInfos) {
+                    if (ai.metaData != null) {
+                        String sliceUri = ai.metaData.getString(SLICE_METADATA_KEY);
+                        if (sliceUri != null) {
+                            mSliceUris.add(Uri.parse(sliceUri));
+                        }
+                    }
+                }
+            }
+        }
+        for (int i = 0; i < URI_PATHS.length; i++) {
+            mSliceUris.add(getUri(URI_PATHS[i], getApplicationContext()));
+        }
+        populateAdapter(String.valueOf(mSearchView.getQuery()));
+    }
+
+    private void addSlice(Intent intent) {
+        SliceView v = new SliceView(getApplicationContext());
+        v.setTag(intent);
+        if (mSliceLiveData != null) {
+            mSliceLiveData.removeObservers(this);
+        }
+        mContainer.removeAllViews();
+        mContainer.addView(v);
+        mSliceLiveData = SliceLiveData.fromIntent(this, intent);
+        v.setMode(mSelectedMode);
+        mSliceLiveData.observe(this, v);
+    }
+
+    private void addSlice(Uri uri) {
+        if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+            SliceView v = new SliceView(getApplicationContext());
+            v.setTag(uri);
+            if (mSliceLiveData != null) {
+                mSliceLiveData.removeObservers(this);
+            }
+            mContainer.removeAllViews();
+            mContainer.addView(v);
+            mSliceLiveData = SliceLiveData.fromUri(this, uri);
+            v.setMode(mSelectedMode);
+            mSliceLiveData.observe(this, v);
+        } else {
+            Log.w(TAG, "Invalid uri, skipping slice: " + uri);
+        }
+    }
+
+    private void updateSliceModes() {
+        final int count = mContainer.getChildCount();
+        for (int i = 0; i < count; i++) {
+            ((SliceView) mContainer.getChildAt(i)).setMode(mSelectedMode);
+        }
+    }
+
+    private void populateAdapter(String query) {
+        final MatrixCursor c = new MatrixCursor(new String[]{BaseColumns._ID, "uri"});
+        ArrayMap<String, Integer> ranking = new ArrayMap<>();
+        ArrayList<String> suggestions = new ArrayList();
+        mSliceUris.forEach(uri -> {
+            String uriString = uri.toString();
+            if (uriString.contains(query)) {
+                ranking.put(uriString, uriString.indexOf(query));
+                suggestions.add(uriString);
+            }
+        });
+        suggestions.sort(new Comparator<String>() {
+            @Override
+            public int compare(String o1, String o2) {
+                return Integer.compare(ranking.get(o1), ranking.get(o2));
+            }
+        });
+        for (int i = 0; i < suggestions.size(); i++) {
+            c.addRow(new Object[]{i, suggestions.get(i)});
+        }
+        mAdapter.changeCursor(c);
+    }
+}
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_camera.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_camera.xml
new file mode 100644
index 0000000..74b6bf9
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_camera.xml
@@ -0,0 +1,32 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 12 8.8 C 13.7673111995 8.8 15.2 10.2326888005 15.2 12 C 15.2 13.7673111995 13.7673111995 15.2 12 15.2 C 10.2326888005 15.2 8.8 13.7673111995 8.8 12 C 8.8 10.2326888005 10.2326888005 8.8 12 8.8 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1 .9 2 2 2h16c1.1 0 2-.9
+2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5
+5-2.24 5-5 5z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_car.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_car.xml
new file mode 100644
index 0000000..6bab660
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_car.xml
@@ -0,0 +1,31 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21 .42 -1.42 1.01L3 12v8c0
+.55 .45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55 .45 1 1 1h1c.55 0 1-.45
+1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5 .67 1.5
+1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5 .67 1.5
+1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_create.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_create.xml
new file mode 100644
index 0000000..d1666a8
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_create.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
+</vector>
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_home.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_home.xml
new file mode 100644
index 0000000..b278230
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_home.xml
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_large.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_large.xml
new file mode 100644
index 0000000..79ac590
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_large.xml
@@ -0,0 +1,28 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48.0dp"
+        android:height="48.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M34.0,2.02L14.0,2.0c-2.21,0.0 -4.0,1.79 -4.0,4.0l0.0,36.0c0.0,2.21 1.79,4.0 4.0,4.0l20.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L38.0,6.0c0.0,-2.21 -1.79,-3.98 -4.0,-3.98zM34.0,38.0L14.0,38.0L14.0,10.0l20.0,0.0l0.0,28.0z"/>
+    <path
+        android:strokeColor="#FF000000"
+        android:strokeWidth="2"
+        android:pathData="M16,18 l16,0 l0,10 l-16,0z"/>
+</vector>
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_shortcut.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_shortcut.xml
new file mode 100644
index 0000000..bf9572a
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_shortcut.xml
@@ -0,0 +1,34 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="48.0dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="48.0dp">
+    <path
+        android:fillColor="#e2e2e2"
+        android:pathData="M24.0,24.0m-19.0,0.0a19.0,19.0 0.0,1.0 1.0,38.0 0.0a19.0,19.0 0.0,1.0 1.0,-38.0 0.0"/>
+    <group
+        android:scaleX=".7"
+        android:scaleY=".7"
+        android:translateX="7.2"
+        android:translateY="7.2">
+
+        <path
+            android:fillColor="#ff000000"
+            android:pathData="M12.0,36.0c0.0,1.0 0.9,2.0 2.0,2.0l2.0,0.0l0.0,7.0c0.0,1.66 1.34,3.0 3.0,3.0s3.0,-1.34 3.0,-3.0l0.0,-7.0l4.0,0.0l0.0,7.0c0.0,1.66 1.34,3.0 3.0,3.0s3.0,-1.34 3.0,-3.0l0.0,-7.0l2.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L36.0,16.0L12.0,16.0l0.0,20.0zM7.0,16.0c-1.66,0.0 -3.0,1.34 -3.0,3.0l0.0,14.0c0.0,1.66 1.34,3.0 3.0,3.0s3.0,-1.34 3.0,-3.0L10.0,19.0c0.0,-1.66 -1.34,-3.0 -3.0,-3.0zm34.0,0.0c-1.66,0.0 -3.0,1.34 -3.0,3.0l0.0,14.0c0.0,1.66 1.34,3.0 3.0,3.0s3.0,-1.34 3.0,-3.0L44.0,19.0c0.0,-1.66 -1.34,-3.0 -3.0,-3.0zM31.06,4.32l2.61,-2.61c0.39,-0.3 0.39,-1.02 0.0,-1.41 -0.39,-0.39 -1.02,-0.39 -1.41,0.0L29.3,3.25C27.7,2.46 25.91,2.0 24.0,2.0c-1.92,0.0 -3.7,0.46 -5.33,1.26L15.0,0.29c-0.39,-0.39 -1.02,-0.39 -1.41,0.0 -0.3,0.39 -0.39,1.02 0.0,1.41l2.62,2.62C13.94,6.51 12.0,10.03 12.0,14.0l24.0,0.0c0.0,-3.98 -1.95,-7.5 -4.94,-9.68zM20.0,10.0l-2.0,0.0L18.0,8.0l2.0,0.0l0.0,2.0zm10.0,0.0l-2.0,0.0L28.0,8.0l2.0,0.0l0.0,2.0z"/>
+    </group>
+</vector>
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_small.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_small.xml
new file mode 100644
index 0000000..8fd43df
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_small.xml
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48.0dp"
+        android:height="48.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M34.0,2.02L14.0,2.0c-2.21,0.0 -4.0,1.79 -4.0,4.0l0.0,36.0c0.0,2.21 1.79,4.0 4.0,4.0l20.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L38.0,6.0c0.0,-2.21 -1.79,-3.98 -4.0,-3.98zM34.0,38.0L14.0,38.0L14.0,10.0l20.0,0.0l0.0,28.0z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M16,18 l16,0 l0,4 l-16,0z"/>
+</vector>
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_star_off.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_star_off.xml
new file mode 100644
index 0000000..7f023b3
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_star_off.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
+</vector>
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_star_on.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_star_on.xml
new file mode 100644
index 0000000..f3ca086
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_star_on.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
+</vector>
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_voice.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_voice.xml
new file mode 100644
index 0000000..8f465bb
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_voice.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12,15c1.66,0 2.99,-1.34 2.99,-3L15,6c0,-1.66 -1.34,-3 -3,-3S9,4.34 9,6v6c0,1.66 1.34,3 3,3zM17.3,12c0,3 -2.54,5.1 -5.3,5.1S6.7,15 6.7,12L5,12c0,3.42 2.72,6.23 6,6.72L11,22h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"/>
+</vector>
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_wifi.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_wifi.xml
new file mode 100644
index 0000000..4fbfd60
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_wifi.xml
@@ -0,0 +1,28 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12.01,21.49L23.64,7c-0.45,-0.34 -4.93,-4 -11.64,-4C5.28,3 0.81,6.66 0.36,7l11.63,14.49 0.01,0.01 0.01,-0.01z"
+        android:fillAlpha=".3"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M3.53,10.95l8.46,10.54 0.01,0.01 0.01,-0.01 8.46,-10.54C20.04,10.62 16.81,8 12,8c-4.81,0 -8.04,2.62 -8.47,2.95z"/>
+</vector>
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_work.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_work.xml
new file mode 100644
index 0000000..6806402
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_work.xml
@@ -0,0 +1,28 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:pathData="M0 0h24v24H0z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20 6h-4V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H4c-1.11 0-1.99 .89 -1.99 2L2
+19c0 1.11 .89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-6 0h-4V4h4v2z" />
+</vector>
\ No newline at end of file
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/mady.jpg b/samples/SupportSliceDemos/src/main/res/drawable/mady.jpg
new file mode 100644
index 0000000..8b61f1b
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/mady.jpg
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/song_row_background.xml b/samples/SupportSliceDemos/src/main/res/drawable/toggle_star.xml
similarity index 71%
rename from samples/SupportLeanbackShowcase/app/src/main/res/drawable/song_row_background.xml
rename to samples/SupportSliceDemos/src/main/res/drawable/toggle_star.xml
index 0329874e..e964925 100644
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/song_row_background.xml
+++ b/samples/SupportSliceDemos/src/main/res/drawable/toggle_star.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -15,8 +14,11 @@
      limitations under the License.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/song_row_background_focused" android:state_focused="true"></item>
-    <item>
-        <color android:color="#384248"></color>
-    </item>
+    <item
+        android:id="@+id/on"
+        android:state_checked="true"
+        android:drawable="@drawable/ic_star_on" />
+    <item
+        android:id="@+id/off"
+        android:drawable="@drawable/ic_star_off" />
 </selector>
\ No newline at end of file
diff --git a/samples/SupportSliceDemos/src/main/res/layout/activity_demo.xml b/samples/SupportSliceDemos/src/main/res/layout/activity_demo.xml
new file mode 100644
index 0000000..f557f40
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/layout/activity_demo.xml
@@ -0,0 +1,40 @@
+<?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.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="com.example.android.support.content.demos.ContentPagerDemoActivity">
+
+    <android.support.v7.widget.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize"
+        android:background="?attr/colorPrimary"
+        android:theme="@style/AppTheme.AppBarOverlay"
+        app:popupTheme="@style/AppTheme.PopupOverlay"/>
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</LinearLayout>
diff --git a/samples/SupportSliceDemos/src/main/res/layout/activity_layout.xml b/samples/SupportSliceDemos/src/main/res/layout/activity_layout.xml
new file mode 100644
index 0000000..6a087a3
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/layout/activity_layout.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="top"
+    android:orientation="vertical" >
+
+    <FrameLayout
+        android:id="@+id/search_bar_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="#f2f2f2">
+        <android.support.v7.widget.CardView
+            android:id="@+id/search_bar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_margin="8dp"
+            app:cardCornerRadius="2dp"
+            app:cardBackgroundColor="?android:attr/colorBackground"
+            app:cardElevation="2dp">
+            <android.support.v7.widget.Toolbar
+                android:id="@+id/search_toolbar"
+                android:layout_width="match_parent"
+                android:layout_height="48dp"
+                android:background="?android:attr/selectableItemBackground"
+                android:contentInsetStart="0dp"
+                android:contentInsetStartWithNavigation="0dp"
+                android:theme="?android:attr/actionBarTheme">
+                <SearchView
+                    android:id="@+id/search_view"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:iconifiedByDefault="false"
+                    android:imeOptions="actionSearch|flagNoExtractUi"
+                    android:queryHint="content://..."
+                    android:searchIcon="@null"/>
+            </android.support.v7.widget.Toolbar>
+        </android.support.v7.widget.CardView>
+    </FrameLayout>
+
+
+    <ScrollView
+        android:id="@+id/container"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" >
+
+        <FrameLayout
+            android:id="@+id/slice_preview"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_margin="8dp"
+            android:orientation="vertical"
+            android:background="?android:attr/colorBackground"
+            android:elevation="10dp" />
+    </ScrollView>
+
+</LinearLayout>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/mipmap-hdpi/ic_launcher.png b/samples/SupportSliceDemos/src/main/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from samples/SupportLeanbackShowcase/app/src/main/res/mipmap-hdpi/ic_launcher.png
rename to samples/SupportSliceDemos/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/SupportSliceDemos/src/main/res/mipmap-hdpi/ic_launcher_round.png b/samples/SupportSliceDemos/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..9a078e3
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/mipmap-hdpi/ic_launcher_round.png
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/mipmap-mdpi/ic_launcher.png b/samples/SupportSliceDemos/src/main/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from samples/SupportLeanbackShowcase/app/src/main/res/mipmap-mdpi/ic_launcher.png
rename to samples/SupportSliceDemos/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/SupportSliceDemos/src/main/res/mipmap-mdpi/ic_launcher_round.png b/samples/SupportSliceDemos/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..efc028a
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/mipmap-mdpi/ic_launcher_round.png
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/samples/SupportSliceDemos/src/main/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from samples/SupportLeanbackShowcase/app/src/main/res/mipmap-xhdpi/ic_launcher.png
rename to samples/SupportSliceDemos/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/SupportSliceDemos/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/samples/SupportSliceDemos/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..3af2608
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/samples/SupportSliceDemos/src/main/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from samples/SupportLeanbackShowcase/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
rename to samples/SupportSliceDemos/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/SupportSliceDemos/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/samples/SupportSliceDemos/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..9bec2e6
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/samples/SupportSliceDemos/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/samples/SupportSliceDemos/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/SupportSliceDemos/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/samples/SupportSliceDemos/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..34947cd
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/samples/SupportSliceDemos/src/main/res/values/colors.xml b/samples/SupportSliceDemos/src/main/res/values/colors.xml
new file mode 100644
index 0000000..86b4304
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/values/colors.xml
@@ -0,0 +1,22 @@
+<?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.
+  -->
+
+<resources>
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+</resources>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/overlay_black.xml b/samples/SupportSliceDemos/src/main/res/values/strings.xml
similarity index 76%
rename from samples/SupportLeanbackShowcase/app/src/main/res/drawable/overlay_black.xml
rename to samples/SupportSliceDemos/src/main/res/values/strings.xml
index 9fccc24..89583bd 100644
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/overlay_black.xml
+++ b/samples/SupportSliceDemos/src/main/res/values/strings.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,6 +13,6 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#E6000000"></solid>
-</shape>
\ No newline at end of file
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">Slice Browser</string>
+</resources>
diff --git a/samples/SupportSliceDemos/src/main/res/values/styles.xml b/samples/SupportSliceDemos/src/main/res/values/styles.xml
new file mode 100644
index 0000000..afb6bad
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/values/styles.xml
@@ -0,0 +1,34 @@
+<?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.
+  -->
+
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+    </style>
+    <style name="AppTheme.NoActionBar">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+    </style>
+    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
+    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
+
+</resources>
diff --git a/samples/ViewPager2Demos/build.gradle b/samples/ViewPager2Demos/build.gradle
new file mode 100644
index 0000000..04b831a
--- /dev/null
+++ b/samples/ViewPager2Demos/build.gradle
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+apply plugin: 'com.android.application'
+
+dependencies {
+    implementation(project(":viewpager2"))
+}
+
+android {
+    compileSdkVersion project.ext.currentSdk
+
+    defaultConfig {
+        minSdkVersion 14
+        targetSdkVersion project.ext.currentSdk
+    }
+
+    signingConfigs {
+        debug {
+            // Use a local debug keystore to avoid build server issues.
+            storeFile project.rootProject.init.debugKeystore
+        }
+    }
+
+    lintOptions {
+        abortOnError true
+        check 'NewApi'
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+}
diff --git a/samples/ViewPager2Demos/src/main/AndroidManifest.xml b/samples/ViewPager2Demos/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..57e52d3
--- /dev/null
+++ b/samples/ViewPager2Demos/src/main/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.androidx.widget.viewpager2">
+
+    <application
+        android:icon="@drawable/app_sample_code"
+        android:label="@string/activity_sample_code"
+        android:supportsRtl="true"
+        android:theme="@style/android:Theme.Holo.Light">
+
+        <activity android:name=".CardActivity" android:label="CardsDemo">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.SAMPLE_CODE"/>
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".BrowseActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/BrowseActivity.java b/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/BrowseActivity.java
new file mode 100644
index 0000000..6c36994
--- /dev/null
+++ b/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/BrowseActivity.java
@@ -0,0 +1,154 @@
+/*
+ * 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.androidx.widget.viewpager2;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This activity lists all the activities in this application.
+ *
+ * TODO: consider pulling out into a common test / demo library (a few forks of this class around)
+ */
+public class BrowseActivity extends ListActivity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Intent intent = getIntent();
+        String path = intent.getStringExtra("com.example.androidx.widget.viewpager2");
+
+        if (path == null) {
+            path = "";
+        }
+
+        setListAdapter(new SimpleAdapter(this, getData(path),
+                android.R.layout.simple_list_item_1, new String[]{"title"},
+                new int[]{android.R.id.text1}));
+        getListView().setTextFilterEnabled(true);
+    }
+
+    protected List<Map<String, Object>> getData(String prefix) {
+        List<Map<String, Object>> myData = new ArrayList<>();
+
+        Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+        mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);
+
+        PackageManager pm = getPackageManager();
+        List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
+
+        if (null == list) {
+            return myData;
+        }
+
+        String[] prefixPath;
+        String prefixWithSlash = prefix;
+
+        if (prefix.equals("")) {
+            prefixPath = null;
+        } else {
+            prefixPath = prefix.split("/");
+            prefixWithSlash = prefix + "/";
+        }
+
+        int len = list.size();
+
+        Map<String, Boolean> entries = new HashMap<>();
+
+        for (int i = 0; i < len; i++) {
+            ResolveInfo info = list.get(i);
+            CharSequence labelSeq = info.loadLabel(pm);
+            String label = labelSeq != null ? labelSeq.toString() : info.activityInfo.name;
+
+            if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) {
+
+                String[] labelPath = label.split("/");
+
+                String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];
+
+                if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
+                    addItem(myData, nextLabel, activityIntent(
+                            info.activityInfo.applicationInfo.packageName,
+                            info.activityInfo.name));
+                } else {
+                    if (entries.get(nextLabel) == null) {
+                        addItem(myData, nextLabel, browseIntent(prefix.equals("")
+                                ? nextLabel : prefix + "/" + nextLabel));
+                        entries.put(nextLabel, true);
+                    }
+                }
+            }
+        }
+
+        Collections.sort(myData, sDisplayNameComparator);
+        return myData;
+    }
+
+    private static final Comparator<Map<String, Object>> sDisplayNameComparator =
+            new Comparator<Map<String, Object>>() {
+                final Collator mCollator = Collator.getInstance();
+
+                public int compare(Map<String, Object> map1, Map<String, Object> map2) {
+                    return mCollator.compare(map1.get("title"), map2.get("title"));
+                }
+            };
+
+    protected Intent activityIntent(String pkg, String componentName) {
+        Intent result = new Intent();
+        result.setClassName(pkg, componentName);
+        return result;
+    }
+
+    protected Intent browseIntent(String path) {
+        Intent result = new Intent();
+        result.setClass(this, BrowseActivity.class);
+        result.putExtra("com.example.androidx.widget.viewpager2", path);
+        return result;
+    }
+
+    protected void addItem(List<Map<String, Object>> data, String name, Intent intent) {
+        Map<String, Object> temp = new HashMap<>();
+        temp.put("title", name);
+        temp.put("intent", intent);
+        data.add(temp);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+        Map<String, Object> map = (Map<String, Object>) l.getItemAtPosition(position);
+
+        Intent intent = new Intent((Intent) map.get("intent"));
+        intent.addCategory(Intent.CATEGORY_SAMPLE_CODE);
+        startActivity(intent);
+    }
+}
diff --git a/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/CardActivity.java b/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/CardActivity.java
new file mode 100644
index 0000000..7484389
--- /dev/null
+++ b/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/CardActivity.java
@@ -0,0 +1,49 @@
+/*
+ * 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.androidx.widget.viewpager2;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableList;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.example.androidx.widget.viewpager2.cards.Card;
+import com.example.androidx.widget.viewpager2.cards.CardDataAdapter;
+
+import java.util.List;
+
+import androidx.widget.ViewPager2;
+
+/** @inheritDoc */
+public class CardActivity extends Activity {
+    private static final List<Card> sCards = unmodifiableList(asList(
+            new Card('♦', 'A'),
+            new Card('♣', 'K'),
+            new Card('♥', 'J'),
+            new Card('♠', '9'),
+            new Card('♦', '2')));
+
+    @Override
+    public void onCreate(Bundle bundle) {
+        super.onCreate(bundle);
+        setContentView(R.layout.activity_card_layout);
+
+        this.<ViewPager2>findViewById(R.id.view_pager).setAdapter(
+                new CardDataAdapter(getLayoutInflater(), sCards));
+    }
+}
diff --git a/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/cards/Card.java b/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/cards/Card.java
new file mode 100644
index 0000000..02f3271
--- /dev/null
+++ b/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/cards/Card.java
@@ -0,0 +1,56 @@
+/*
+ * 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.androidx.widget.viewpager2.cards;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableSet;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Playing card
+ */
+public class Card {
+    private static final Set<Character> SUITS = unmodifiableSet(new LinkedHashSet<>(
+            asList('♦', /* diamonds*/ '♣', /*, clubs*/ '♥', /* hearts*/ '♠' /*spades*/)));
+    private static final Set<Character> VALUES = unmodifiableSet(new LinkedHashSet<>(
+            asList('2', '3', '4', '5', '6', '7', '8', '9', '⒑', 'J', 'Q', 'K', 'A')));
+
+    private final char mSuit;
+    private final char mValue;
+
+    public Card(char suit, char value) {
+        this.mSuit = checkValidValue(suit, SUITS);
+        this.mValue = checkValidValue(value, VALUES);
+    }
+
+    public char getSuit() {
+        return mSuit;
+    }
+
+    public String getCornerLabel() {
+        return mValue + "\n" + mSuit;
+    }
+
+    private static char checkValidValue(char value, Set<Character> allowed) {
+        if (allowed.contains(value)) {
+            return value;
+        }
+        throw new IllegalArgumentException("Illegal argument: " + value);
+    }
+}
diff --git a/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/cards/CardDataAdapter.java b/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/cards/CardDataAdapter.java
new file mode 100644
index 0000000..7f69e1b
--- /dev/null
+++ b/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/cards/CardDataAdapter.java
@@ -0,0 +1,56 @@
+/*
+ * 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.androidx.widget.viewpager2.cards;
+
+import android.support.annotation.NonNull;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.example.androidx.widget.viewpager2.R;
+
+import java.util.List;
+
+/** @inheritDoc */
+public class CardDataAdapter extends RecyclerView.Adapter<CardViewHolder> {
+    private final List<Card> mCards;
+    private final LayoutInflater mLayoutInflater;
+
+    public CardDataAdapter(LayoutInflater layoutInflater, List<Card> cards) {
+        mLayoutInflater = layoutInflater;
+        mCards = cards;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    @NonNull
+    public CardViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        return new CardViewHolder(
+                mLayoutInflater.inflate(R.layout.item_card_layout, parent, false));
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull CardViewHolder holder, int position) {
+        holder.apply(mCards.get(position));
+    }
+
+    @Override
+    public int getItemCount() {
+        return mCards.size();
+    }
+}
diff --git a/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/cards/CardViewHolder.java b/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/cards/CardViewHolder.java
new file mode 100644
index 0000000..8fd0477
--- /dev/null
+++ b/samples/ViewPager2Demos/src/main/java/com/example/androidx/widget/viewpager2/cards/CardViewHolder.java
@@ -0,0 +1,49 @@
+/*
+ * 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.androidx.widget.viewpager2.cards;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.TextView;
+
+import com.example.androidx.widget.viewpager2.R;
+
+/** @inheritDoc */
+public class CardViewHolder extends RecyclerView.ViewHolder {
+    private final TextView mTextSuite;
+    private final TextView mTextCorner1;
+    private final TextView mTextCorner2;
+
+    public CardViewHolder(View itemView) {
+        super(itemView);
+        mTextSuite = itemView.findViewById(R.id.label_center);
+        mTextCorner1 = itemView.findViewById(R.id.label_top);
+        mTextCorner2 = itemView.findViewById(R.id.label_bottom);
+    }
+
+    /**
+     * Updates the view to represent the passed in card
+     */
+    public void apply(Card card) {
+        mTextSuite.setText(Character.toString(card.getSuit()));
+
+        String cornerLabel = card.getCornerLabel();
+        mTextCorner1.setText(cornerLabel);
+        mTextCorner2.setText(cornerLabel);
+        mTextCorner2.setRotation(180);
+    }
+}
diff --git a/samples/ViewPager2Demos/src/main/res/drawable-hdpi/app_sample_code.png b/samples/ViewPager2Demos/src/main/res/drawable-hdpi/app_sample_code.png
new file mode 100755
index 0000000..66a1984
--- /dev/null
+++ b/samples/ViewPager2Demos/src/main/res/drawable-hdpi/app_sample_code.png
Binary files differ
diff --git a/samples/ViewPager2Demos/src/main/res/drawable-mdpi/app_sample_code.png b/samples/ViewPager2Demos/src/main/res/drawable-mdpi/app_sample_code.png
new file mode 100644
index 0000000..5ae7701
--- /dev/null
+++ b/samples/ViewPager2Demos/src/main/res/drawable-mdpi/app_sample_code.png
Binary files differ
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_main.xml b/samples/ViewPager2Demos/src/main/res/layout/activity_card_layout.xml
similarity index 74%
rename from samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_main.xml
rename to samples/ViewPager2Demos/src/main/res/layout/activity_card_layout.xml
index 9d2eda6..3037029 100644
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_main.xml
+++ b/samples/ViewPager2Demos/src/main/res/layout/activity_card_layout.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,12 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<RelativeLayout
-    android:id="@+id/fragmentContainer"
+
+<androidx.widget.ViewPager2
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/view_pager"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:deviceIds="tv"
-    tools:ignore="MergeRootFrame">
-</RelativeLayout>
+    android:background="#FFF"
+    android:padding="16dp"/>
diff --git a/samples/ViewPager2Demos/src/main/res/layout/item_card_layout.xml b/samples/ViewPager2Demos/src/main/res/layout/item_card_layout.xml
new file mode 100644
index 0000000..90a0404
--- /dev/null
+++ b/samples/ViewPager2Demos/src/main/res/layout/item_card_layout.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#FEFEFE"
+    android:padding="16dp">
+
+    <TextView
+        android:id="@+id/label_top"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top|start"
+        android:textAppearance="@android:style/TextAppearance.Medium"/>
+
+    <TextView
+        android:id="@+id/label_center"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:textAppearance="@android:style/TextAppearance.Large"/>
+
+    <TextView
+        android:id="@+id/label_bottom"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom|end"
+        android:textAppearance="@android:style/TextAppearance.Medium"/>
+</FrameLayout>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/overlay_black.xml b/samples/ViewPager2Demos/src/main/res/values/strings.xml
similarity index 76%
copy from samples/SupportLeanbackShowcase/app/src/main/res/drawable/overlay_black.xml
copy to samples/ViewPager2Demos/src/main/res/values/strings.xml
index 9fccc24..85b9151 100644
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/overlay_black.xml
+++ b/samples/ViewPager2Demos/src/main/res/values/strings.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,6 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#E6000000"></solid>
-</shape>
\ No newline at end of file
+
+<resources>
+    <string name="activity_sample_code">ViewPager2 Demos</string>
+</resources>
diff --git a/settings.gradle b/settings.gradle
index 1eccbcf..97c5353 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -85,6 +85,9 @@
 include ':support-dynamic-animation'
 project(':support-dynamic-animation').projectDir = new File(rootDir, 'dynamic-animation')
 
+include ':viewpager2'
+project(':viewpager2').projectDir = new File(rootDir, 'viewpager2')
+
 include ':exifinterface'
 project(':exifinterface').projectDir = new File(rootDir, 'exifinterface')
 
@@ -112,6 +115,15 @@
 include ':webkit'
 project(':webkit').projectDir = new File(rootDir, 'webkit')
 
+include ':slices-core'
+project(':slices-core').projectDir = new File(rootDir, 'slices/core')
+
+include ':slices-view'
+project(':slices-view').projectDir = new File(rootDir, 'slices/view')
+
+include ':slices-builders'
+project(':slices-builders').projectDir = new File(rootDir, 'slices/builders')
+
 /////////////////////////////
 //
 // Samples
@@ -156,6 +168,9 @@
 include ':support-animation-demos'
 project(':support-animation-demos').projectDir = new File(samplesRoot, 'SupportAnimationDemos')
 
+include ':viewpager2-demos'
+project(':viewpager2-demos').projectDir = new File(samplesRoot, 'ViewPager2Demos')
+
 include ':support-wear-demos'
 project(':support-wear-demos').projectDir = new File(samplesRoot, 'SupportWearDemos')
 
@@ -167,6 +182,10 @@
 
 include ':support-car-demos'
 project(':support-car-demos').projectDir = new File(samplesRoot, 'SupportCarDemos')
+
+include ':support-slices-demos'
+project(':support-slices-demos').projectDir = new File(samplesRoot, 'SupportSliceDemos')
+
 /////////////////////////////
 //
 // Testing libraries
diff --git a/slices/Android.mk b/slices/Android.mk
new file mode 100644
index 0000000..b622eed
--- /dev/null
+++ b/slices/Android.mk
@@ -0,0 +1,18 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+# Build all slices libraries
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/slices/OWNERS b/slices/OWNERS
new file mode 100644
index 0000000..921a517
--- /dev/null
+++ b/slices/OWNERS
@@ -0,0 +1,2 @@
+jmonk@google.com
+madym@google.com
diff --git a/slices/builders/Android.mk b/slices/builders/Android.mk
new file mode 100644
index 0000000..ca66cbe
--- /dev/null
+++ b/slices/builders/Android.mk
@@ -0,0 +1,38 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# Here is the final static library that apps can link against.
+# Applications that use this library must specify
+#
+#   LOCAL_STATIC_ANDROID_LIBRARIES := \
+#       android-slices-core \
+#       android-slices-builders
+#
+# in their makefiles to include the resources and their dependencies in their package.
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_MODULE := android-slices-builders
+LOCAL_MANIFEST_FILE := src/main/AndroidManifest.xml
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under,src/main/java) \
+    $(call all-Iaidl-files-under,src/main/java)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/src/main/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations \
+    android-slices-core
+LOCAL_JAR_EXCLUDE_FILES := none
+LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/slices/builders/api/current.txt b/slices/builders/api/current.txt
new file mode 100644
index 0000000..52f30c8
--- /dev/null
+++ b/slices/builders/api/current.txt
@@ -0,0 +1,47 @@
+package androidx.app.slice.builders {
+
+  public class ListBuilder extends androidx.app.slice.builders.TemplateSliceBuilder {
+    ctor public ListBuilder(android.net.Uri);
+    method public androidx.app.slice.builders.ListBuilder add(androidx.app.slice.builders.RowBuilder);
+    method public androidx.app.slice.builders.ListBuilder add(java.util.function.Consumer<androidx.app.slice.builders.RowBuilder>);
+  }
+
+  public class MessagingSliceBuilder extends androidx.app.slice.builders.TemplateSliceBuilder {
+    ctor public MessagingSliceBuilder(android.net.Uri);
+    method public androidx.app.slice.builders.MessagingSliceBuilder add(androidx.app.slice.builders.MessagingSliceBuilder.MessageBuilder);
+    method public androidx.app.slice.builders.MessagingSliceBuilder add(java.util.function.Consumer<androidx.app.slice.builders.MessagingSliceBuilder.MessageBuilder>);
+    field public static final int MAXIMUM_RETAINED_MESSAGES = 50; // 0x32
+  }
+
+  public static final class MessagingSliceBuilder.MessageBuilder extends androidx.app.slice.builders.TemplateSliceBuilder {
+    method public androidx.app.slice.builders.MessagingSliceBuilder.MessageBuilder addSource(android.graphics.drawable.Icon);
+    method public androidx.app.slice.builders.MessagingSliceBuilder.MessageBuilder addText(java.lang.CharSequence);
+    method public androidx.app.slice.builders.MessagingSliceBuilder.MessageBuilder addTimestamp(long);
+    method public void apply(androidx.app.slice.Slice.Builder);
+  }
+
+  public class RowBuilder extends androidx.app.slice.builders.TemplateSliceBuilder {
+    ctor public RowBuilder(androidx.app.slice.builders.ListBuilder);
+    ctor public RowBuilder(android.net.Uri);
+    method public androidx.app.slice.builders.RowBuilder addEndItem(long);
+    method public androidx.app.slice.builders.RowBuilder addEndItem(android.graphics.drawable.Icon);
+    method public androidx.app.slice.builders.RowBuilder addEndItem(android.app.PendingIntent, android.graphics.drawable.Icon);
+    method public androidx.app.slice.builders.RowBuilder addToggle(android.app.PendingIntent, boolean);
+    method public androidx.app.slice.builders.RowBuilder addToggle(android.app.PendingIntent, android.graphics.drawable.Icon, boolean);
+    method public void apply(androidx.app.slice.Slice.Builder);
+    method public androidx.app.slice.builders.RowBuilder setContentIntent(android.app.PendingIntent);
+    method public androidx.app.slice.builders.RowBuilder setIsHeader(boolean);
+    method public androidx.app.slice.builders.RowBuilder setSubtitle(java.lang.CharSequence);
+    method public androidx.app.slice.builders.RowBuilder setTitle(java.lang.CharSequence);
+    method public androidx.app.slice.builders.RowBuilder setTitleItem(long);
+    method public androidx.app.slice.builders.RowBuilder setTitleItem(android.graphics.drawable.Icon);
+    method public androidx.app.slice.builders.RowBuilder setTitleItem(android.app.PendingIntent, android.graphics.drawable.Icon);
+  }
+
+  public abstract class TemplateSliceBuilder {
+    ctor public TemplateSliceBuilder(android.net.Uri);
+    method public androidx.app.slice.Slice build();
+  }
+
+}
+
diff --git a/slices/builders/build.gradle b/slices/builders/build.gradle
new file mode 100644
index 0000000..2816600
--- /dev/null
+++ b/slices/builders/build.gradle
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+import static android.support.dependencies.DependenciesKt.*
+import android.support.LibraryVersions
+import android.support.LibraryGroups
+
+plugins {
+    id("SupportAndroidLibraryPlugin")
+}
+
+dependencies {
+    implementation(project(":slices-core"))
+    implementation project(":support-annotations")
+}
+
+supportLibrary {
+    name = "Slice builders"
+    publish = true
+    mavenVersion = LibraryVersions.SUPPORT_LIBRARY
+    mavenGroup = LibraryGroups.SLICES
+    inceptionYear = "2017"
+    description = "A set of builders to create templates using SliceProvider APIs"
+    minSdkVersion = 19
+}
diff --git a/slices/builders/lint-baseline.xml b/slices/builders/lint-baseline.xml
new file mode 100644
index 0000000..2cadde1
--- /dev/null
+++ b/slices/builders/lint-baseline.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="4" by="lint 3.0.0">
+
+</issues>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml b/slices/builders/src/main/AndroidManifest.xml
similarity index 72%
copy from samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml
copy to slices/builders/src/main/AndroidManifest.xml
index d6a1023..75e31f1 100644
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml
+++ b/slices/builders/src/main/AndroidManifest.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,8 +13,7 @@
      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">
-    <solid android:color="#FFFFFF"></solid>
-</shape>
\ No newline at end of file
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="androidx.app.slice.builders">
+    <uses-sdk android:minSdkVersion="28"/>
+</manifest>
diff --git a/slices/builders/src/main/java/androidx/app/slice/builders/ListBuilder.java b/slices/builders/src/main/java/androidx/app/slice/builders/ListBuilder.java
new file mode 100644
index 0000000..cd644d5
--- /dev/null
+++ b/slices/builders/src/main/java/androidx/app/slice/builders/ListBuilder.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 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 androidx.app.slice.builders;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.net.Uri;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.RestrictTo;
+
+import java.util.function.Consumer;
+
+/**
+ * Builder to construct slice content.
+ * <p>
+ * Use this builder for showing rows of content which is composed of text, images, and actions. For
+ * more details {@see RowBuilder}.
+ * </p>
+ * <p>
+ * Slices can be displayed in different formats:
+ * <ul>
+ *     <li>Shortcut - The slice is displayed as an icon with a text label.</li>
+ *     <li>Small - Only a single row of content is displayed in small format, to specify which
+ *         row to display in small format see {@link RowBuilder#setIsHeader(boolean)}.</li>
+ *     <li>Large - As many rows of content are shown as possible. If the presenter of the slice
+ *         allows scrolling then all rows of content will be displayed in a scrollable view.</li>
+ * </ul>
+ * </p>
+ *
+ * @see RowBuilder
+ */
+public class ListBuilder extends TemplateSliceBuilder {
+
+    public ListBuilder(@NonNull Uri uri) {
+        super(uri);
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    @Override
+    public void apply(androidx.app.slice.Slice.Builder builder) {
+
+    }
+
+    /**
+     * Add a subslice to this builder.
+     */
+    public ListBuilder add(RowBuilder builder) {
+        getBuilder().addSubSlice(builder.build());
+        return this;
+    }
+
+    /**
+     * Add a subslice to this builder.
+     */
+    @RequiresApi(api = Build.VERSION_CODES.N)
+    public ListBuilder add(Consumer<RowBuilder> c) {
+        RowBuilder b = new RowBuilder(this);
+        c.accept(b);
+        return add(b);
+    }
+
+    /**
+     * Sets the color to tint items displayed by this template (e.g. icons).
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    public ListBuilder setColor(int color) {
+        getBuilder().addColor(color, null);
+        return this;
+    }
+}
diff --git a/slices/builders/src/main/java/androidx/app/slice/builders/MessagingSliceBuilder.java b/slices/builders/src/main/java/androidx/app/slice/builders/MessagingSliceBuilder.java
new file mode 100644
index 0000000..66bb345
--- /dev/null
+++ b/slices/builders/src/main/java/androidx/app/slice/builders/MessagingSliceBuilder.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 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 androidx.app.slice.builders;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.RestrictTo;
+
+import java.util.function.Consumer;
+
+import androidx.app.slice.Slice;
+
+/**
+ * Builder to construct slice content in a messaging format.
+ */
+public class MessagingSliceBuilder extends TemplateSliceBuilder {
+
+    /**
+     * The maximum number of messages that will be retained in the Slice itself (the
+     * number displayed is up to the platform).
+     */
+    public static final int MAXIMUM_RETAINED_MESSAGES = 50;
+
+    public MessagingSliceBuilder(@NonNull Uri uri) {
+        super(uri);
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    @Override
+    public void apply(androidx.app.slice.Slice.Builder builder) {
+
+    }
+
+    /**
+     * Add a subslice to this builder.
+     */
+    public MessagingSliceBuilder add(MessageBuilder builder) {
+        getBuilder().addSubSlice(builder.build());
+        return this;
+    }
+
+    /**
+     * Add a subslice to this builder.
+     */
+    @RequiresApi(api = Build.VERSION_CODES.N)
+    public MessagingSliceBuilder add(Consumer<MessageBuilder> c) {
+        MessageBuilder b = new MessageBuilder(this);
+        c.accept(b);
+        return add(b);
+    }
+
+    /**
+     * Builder for adding a message to {@link MessagingSliceBuilder}.
+     */
+    public static final class MessageBuilder extends TemplateSliceBuilder {
+        /**
+         * @hide
+         */
+        @RestrictTo(RestrictTo.Scope.LIBRARY)
+        public MessageBuilder(MessagingSliceBuilder parent) {
+            super(parent.createChildBuilder());
+        }
+
+        /**
+         * Add the icon used to display contact in the messaging experience
+         */
+        public MessageBuilder addSource(Icon source) {
+            getBuilder().addIcon(source, android.app.slice.Slice.SUBTYPE_SOURCE);
+            return this;
+        }
+
+        /**
+         * Add the text to be used for this message.
+         */
+        public MessageBuilder addText(CharSequence text) {
+            getBuilder().addText(text, null);
+            return this;
+        }
+
+        /**
+         * Add the time at which this message arrived in ms since Unix epoch
+         */
+        public MessageBuilder addTimestamp(long timestamp) {
+            getBuilder().addTimestamp(timestamp, null);
+            return this;
+        }
+
+        @Override
+        public void apply(Slice.Builder builder) {
+        }
+    }
+}
diff --git a/slices/builders/src/main/java/androidx/app/slice/builders/RowBuilder.java b/slices/builders/src/main/java/androidx/app/slice/builders/RowBuilder.java
new file mode 100644
index 0000000..f2e57ba
--- /dev/null
+++ b/slices/builders/src/main/java/androidx/app/slice/builders/RowBuilder.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 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 androidx.app.slice.builders;
+
+import static android.app.slice.Slice.HINT_LARGE;
+import static android.app.slice.Slice.HINT_LIST_ITEM;
+import static android.app.slice.Slice.HINT_NO_TINT;
+import static android.app.slice.Slice.HINT_SELECTED;
+import static android.app.slice.Slice.HINT_TITLE;
+import static android.app.slice.SliceItem.FORMAT_ACTION;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
+
+import static androidx.app.slice.core.SliceHints.SUBTYPE_TOGGLE;
+
+import android.app.PendingIntent;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+
+import java.util.ArrayList;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceItem;
+import androidx.app.slice.core.SliceHints;
+
+/**
+ * Sub-builder to construct a row of slice content.
+ * <p>
+ * Row content can have:
+ * <ul>
+ *     <li>Title item - This is only displayed if this is a list item in a large template, it
+ *     will not be shown if this template is being used for small format. The item appears at the
+ *     start of the template. There can only be one title item displayed, and it could be a
+ *     timestamp, image, or a tappable icon.</li>
+ *     <li>Title - Formatted as a title.</li>
+ *     <li>Subtitle - Appears below the title (if one exists) and is formatted as normal text.</li>
+ *     <li>End item -  Appears at the end of the template, there can be multiple end items but they
+ *     are only shown if there's enough space. End items can be a timestamp, image, or a
+ *     tappable icon.</li>
+ * </ul>
+ * </p>
+ *
+ * @see ListBuilder
+ */
+public class RowBuilder extends TemplateSliceBuilder {
+
+    private boolean mIsHeader;
+    private PendingIntent mContentIntent;
+    private SliceItem mTitleItem;
+    private SliceItem mSubtitleItem;
+    private SliceItem mStartItem;
+    private ArrayList<SliceItem> mEndItems = new ArrayList<>();
+
+    public RowBuilder(ListBuilder parent) {
+        super(parent.createChildBuilder());
+    }
+
+    public RowBuilder(Uri uri) {
+        super(new Slice.Builder(uri));
+    }
+
+    /**
+     * Sets this row to be considered the header of the slice. This means that when the slice is
+     * requested to be show in small format, it will display only the contents specified in this
+     * row. If a slice has no header specified, the first row item will be used in the small format.
+     */
+    public RowBuilder setIsHeader(boolean isHeader) {
+        mIsHeader = isHeader;
+        return this;
+    }
+
+    /**
+     * Sets the title item to be the provided timestamp.
+     * <p>
+     * There can only be one title item, this will replace any other title
+     * items that may have been set.
+     */
+    public RowBuilder setTitleItem(long timeStamp) {
+        mStartItem = new SliceItem(timeStamp, FORMAT_TIMESTAMP, null, new String[0]);
+        return this;
+    }
+
+    /**
+     * Sets the title item to be the provided icon.
+     * <p>
+     * There can only be one title item, this will replace any other title
+     * items that may have been set.
+     */
+    public RowBuilder setTitleItem(Icon icon) {
+        mStartItem = new SliceItem(icon, FORMAT_IMAGE, null, new String[0]);
+        return this;
+    }
+
+    /**
+     * Sets the title item to be a tappable icon.
+     * <p>
+     * There can only be one title item, this will replace any other title
+     * items that may have been set.
+     */
+    public RowBuilder setTitleItem(@NonNull PendingIntent action, @NonNull Icon icon) {
+        Slice actionSlice = new Slice.Builder(getBuilder()).addIcon(icon, null).build();
+        mStartItem = new SliceItem(action, actionSlice, FORMAT_ACTION, null, new String[0]);
+        return this;
+    }
+
+    /**
+     * Sets the action to be invoked if the user taps on the main content of the template.
+     */
+    public RowBuilder setContentIntent(@NonNull PendingIntent action) {
+        mContentIntent = action;
+        return this;
+    }
+
+    /**
+     * Sets the title text.
+     */
+    public RowBuilder setTitle(CharSequence title) {
+        mTitleItem = new SliceItem(title, FORMAT_TEXT, null, new String[] {HINT_TITLE});
+        return this;
+    }
+
+    /**
+     * Sets the subtitle text.
+     */
+    public RowBuilder setSubtitle(CharSequence subtitle) {
+        mSubtitleItem = new SliceItem(subtitle, FORMAT_TEXT, null, new String[0]);
+        return this;
+    }
+
+    /**
+     * Adds a timestamp to be displayed at the end of the row.
+     */
+    public RowBuilder addEndItem(long timeStamp) {
+        // TODO -- should multiple timestamps be allowed at the end of the row?
+        mEndItems.add(new SliceItem(timeStamp, FORMAT_TIMESTAMP, null, new String[0]));
+        return this;
+    }
+
+    /**
+     * Adds an icon to be displayed at the end of the row.
+     */
+    public RowBuilder addEndItem(Icon icon) {
+        mEndItems.add(new SliceItem(icon, FORMAT_IMAGE, null,
+                new String[] {HINT_NO_TINT, HINT_LARGE}));
+        return this;
+    }
+
+    /**
+     * Adds a tappable icon to be displayed at the end of the row.
+     */
+    public RowBuilder addEndItem(@NonNull PendingIntent action, @NonNull Icon icon) {
+        Slice actionSlice = new Slice.Builder(getBuilder()).addIcon(icon, null).build();
+        mEndItems.add(new SliceItem(action, actionSlice, FORMAT_ACTION, null, new String[0]));
+        return this;
+    }
+
+    /**
+     * Adds a toggle action to the template. If there is a toggle to display, any end items
+     * that were added will not be shown.
+     */
+    public RowBuilder addToggle(@NonNull PendingIntent action, boolean isChecked) {
+        @Slice.SliceHint String[] hints = isChecked
+                ? new String[] {SUBTYPE_TOGGLE, HINT_SELECTED}
+                : new String[] {SUBTYPE_TOGGLE};
+        Slice s = new Slice.Builder(getBuilder()).addHints(hints).build();
+        mEndItems.add(0, new SliceItem(action, s, FORMAT_ACTION, null, hints));
+        return this;
+    }
+
+    /**
+     * Adds a toggle action to the template with custom icons to represent checked and unchecked
+     * state. If there is a toggle to display, any end items that were added will not be shown.
+     */
+    public RowBuilder addToggle(@NonNull PendingIntent action, @NonNull Icon icon,
+            boolean isChecked) {
+        @Slice.SliceHint String[] hints = isChecked
+                ? new String[] {SliceHints.SUBTYPE_TOGGLE, HINT_SELECTED}
+                : new String[] {SliceHints.SUBTYPE_TOGGLE};
+        Slice actionSlice = new Slice.Builder(getBuilder())
+                .addIcon(icon, null)
+                .addHints(hints).build();
+        mEndItems.add(0, new SliceItem(action, actionSlice, FORMAT_ACTION, null, hints));
+        return this;
+    }
+
+    @Override
+    public void apply(Slice.Builder b) {
+        Slice.Builder wrapped = b;
+        if (mContentIntent != null) {
+            b = new Slice.Builder(wrapped);
+        }
+        if (mStartItem != null) {
+            b.addItem(mStartItem);
+        }
+        if (mTitleItem != null) {
+            b.addItem(mTitleItem);
+        }
+        if (mSubtitleItem != null) {
+            b.addItem(mSubtitleItem);
+        }
+        for (int i = 0; i < mEndItems.size(); i++) {
+            SliceItem item = mEndItems.get(i);
+            b.addItem(item);
+        }
+        if (mContentIntent != null) {
+            wrapped.addAction(mContentIntent, b.build(), null);
+        }
+        wrapped.addHints(mIsHeader ? null : HINT_LIST_ITEM);
+    }
+}
diff --git a/slices/builders/src/main/java/androidx/app/slice/builders/TemplateSliceBuilder.java b/slices/builders/src/main/java/androidx/app/slice/builders/TemplateSliceBuilder.java
new file mode 100644
index 0000000..464f940
--- /dev/null
+++ b/slices/builders/src/main/java/androidx/app/slice/builders/TemplateSliceBuilder.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 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 androidx.app.slice.builders;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY;
+
+import android.net.Uri;
+import android.support.annotation.RestrictTo;
+
+import androidx.app.slice.Slice;
+
+/**
+ * Base class of builders of various template types.
+ */
+public abstract class TemplateSliceBuilder {
+
+    private final Slice.Builder mSliceBuilder;
+
+    public TemplateSliceBuilder(Uri uri) {
+        mSliceBuilder = new Slice.Builder(uri);
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(LIBRARY)
+    protected TemplateSliceBuilder(Slice.Builder b) {
+        mSliceBuilder = b;
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(LIBRARY)
+    public Slice.Builder getBuilder() {
+        return mSliceBuilder;
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(LIBRARY)
+    public Slice.Builder createChildBuilder() {
+        return new Slice.Builder(mSliceBuilder);
+    }
+
+    /**
+     * Construct the slice.
+     */
+    public Slice build() {
+        apply(mSliceBuilder);
+        return mSliceBuilder.build();
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(LIBRARY)
+    public abstract void apply(Slice.Builder builder);
+}
diff --git a/slices/core/Android.mk b/slices/core/Android.mk
new file mode 100644
index 0000000..cd3a353
--- /dev/null
+++ b/slices/core/Android.mk
@@ -0,0 +1,37 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# Here is the final static library that apps can link against.
+# Applications that use this library must specify
+#
+#   LOCAL_STATIC_ANDROID_LIBRARIES := \
+#       android-slices-core
+#
+# in their makefiles to include the resources and their dependencies in their package.
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_MODULE := android-slices-core
+LOCAL_MANIFEST_FILE := src/main/AndroidManifest.xml
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under,src/main/java) \
+    $(call all-Iaidl-files-under,src/main/java)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/src/main/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-compat \
+    android-support-annotations
+LOCAL_JAR_EXCLUDE_FILES := none
+LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/slices/core/api/current.txt b/slices/core/api/current.txt
new file mode 100644
index 0000000..cc628d6
--- /dev/null
+++ b/slices/core/api/current.txt
@@ -0,0 +1,60 @@
+package androidx.app.slice {
+
+  public final class Slice {
+    method public static androidx.app.slice.Slice bindSlice(android.content.Context, android.net.Uri);
+    method public static androidx.app.slice.Slice bindSlice(android.content.Context, android.content.Intent);
+    method public java.util.List<java.lang.String> getHints();
+    method public java.util.List<androidx.app.slice.SliceItem> getItems();
+    method public android.net.Uri getUri();
+  }
+
+  public static class Slice.Builder {
+    ctor public Slice.Builder(android.net.Uri);
+    ctor public Slice.Builder(androidx.app.slice.Slice.Builder);
+    method public androidx.app.slice.Slice.Builder addAction(android.app.PendingIntent, androidx.app.slice.Slice, java.lang.String);
+    method public androidx.app.slice.Slice.Builder addColor(int, java.lang.String, java.lang.String...);
+    method public androidx.app.slice.Slice.Builder addColor(int, java.lang.String, java.util.List<java.lang.String>);
+    method public androidx.app.slice.Slice.Builder addHints(java.lang.String...);
+    method public androidx.app.slice.Slice.Builder addHints(java.util.List<java.lang.String>);
+    method public androidx.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.lang.String...);
+    method public androidx.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.util.List<java.lang.String>);
+    method public androidx.app.slice.Slice.Builder addRemoteInput(android.app.RemoteInput, java.lang.String, java.util.List<java.lang.String>);
+    method public androidx.app.slice.Slice.Builder addRemoteInput(android.app.RemoteInput, java.lang.String, java.lang.String...);
+    method public androidx.app.slice.Slice.Builder addSubSlice(androidx.app.slice.Slice);
+    method public androidx.app.slice.Slice.Builder addSubSlice(androidx.app.slice.Slice, java.lang.String);
+    method public androidx.app.slice.Slice.Builder addText(java.lang.CharSequence, java.lang.String, java.lang.String...);
+    method public androidx.app.slice.Slice.Builder addText(java.lang.CharSequence, java.lang.String, java.util.List<java.lang.String>);
+    method public androidx.app.slice.Slice.Builder addTimestamp(long, java.lang.String, java.lang.String...);
+    method public androidx.app.slice.Slice.Builder addTimestamp(long, java.lang.String, java.util.List<java.lang.String>);
+    method public androidx.app.slice.Slice build();
+  }
+
+  public class SliceConvert {
+    ctor public SliceConvert();
+    method public static android.app.slice.Slice unwrap(androidx.app.slice.Slice);
+    method public static androidx.app.slice.Slice wrap(android.app.slice.Slice);
+  }
+
+  public class SliceItem {
+    method public android.app.PendingIntent getAction();
+    method public int getColor();
+    method public java.lang.String getFormat();
+    method public java.util.List<java.lang.String> getHints();
+    method public android.graphics.drawable.Icon getIcon();
+    method public android.app.RemoteInput getRemoteInput();
+    method public androidx.app.slice.Slice getSlice();
+    method public java.lang.String getSubType();
+    method public java.lang.CharSequence getText();
+    method public long getTimestamp();
+    method public boolean hasHint(java.lang.String);
+  }
+
+  public abstract class SliceProvider extends android.content.ContentProvider {
+    ctor public SliceProvider();
+    method public abstract androidx.app.slice.Slice onBindSlice(android.net.Uri);
+    method public abstract boolean onCreateSliceProvider();
+    method public android.net.Uri onMapIntentToUri(android.content.Intent);
+  }
+
+}
+
diff --git a/slices/core/build.gradle b/slices/core/build.gradle
new file mode 100644
index 0000000..4cec017
--- /dev/null
+++ b/slices/core/build.gradle
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+import static android.support.dependencies.DependenciesKt.*
+import android.support.LibraryVersions
+import android.support.LibraryGroups
+
+plugins {
+    id("SupportAndroidLibraryPlugin")
+}
+
+dependencies {
+    implementation project(":support-annotations")
+    implementation project(":appcompat-v7")
+}
+
+android {
+    sourceSets {
+        main.res.srcDirs = [
+                'res',
+                'res-public'
+        ]
+    }
+}
+
+supportLibrary {
+    name = "Common utilities for slices"
+    publish = true
+    mavenVersion = LibraryVersions.SUPPORT_LIBRARY
+    mavenGroup = LibraryGroups.SLICES
+    inceptionYear = "2017"
+    description = "The slices core library provides utilities for the slices view and provider libraries"
+    minSdkVersion = 19
+}
diff --git a/slices/core/lint-baseline.xml b/slices/core/lint-baseline.xml
new file mode 100644
index 0000000..2cadde1
--- /dev/null
+++ b/slices/core/lint-baseline.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="4" by="lint 3.0.0">
+
+</issues>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml b/slices/core/src/main/AndroidManifest.xml
similarity index 72%
copy from samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml
copy to slices/core/src/main/AndroidManifest.xml
index d6a1023..ca86418 100644
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml
+++ b/slices/core/src/main/AndroidManifest.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,8 +13,7 @@
      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">
-    <solid android:color="#FFFFFF"></solid>
-</shape>
\ No newline at end of file
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="androidx.app.slice.core">
+    <uses-sdk android:minSdkVersion="28"/>
+</manifest>
diff --git a/slices/core/src/main/java/androidx/app/slice/ArrayUtils.java b/slices/core/src/main/java/androidx/app/slice/ArrayUtils.java
new file mode 100644
index 0000000..669f66a
--- /dev/null
+++ b/slices/core/src/main/java/androidx/app/slice/ArrayUtils.java
@@ -0,0 +1,75 @@
+/*
+ * 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 androidx.app.slice;
+
+
+import android.support.annotation.RestrictTo;
+import android.support.annotation.RestrictTo.Scope;
+
+import java.lang.reflect.Array;
+import java.util.Objects;
+
+/**
+ * @hide
+ */
+@RestrictTo(Scope.LIBRARY)
+class ArrayUtils {
+
+    public static <T> boolean contains(T[] array, T item) {
+        for (T t : array) {
+            if (Objects.equals(t, item)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static <T> T[] appendElement(Class<T> kind, T[] array, T element) {
+        final T[] result;
+        final int end;
+        if (array != null) {
+            end = array.length;
+            result = (T[]) Array.newInstance(kind, end + 1);
+            System.arraycopy(array, 0, result, 0, end);
+        } else {
+            end = 0;
+            result = (T[]) Array.newInstance(kind, 1);
+        }
+        result[end] = element;
+        return result;
+    }
+
+    public static <T> T[] removeElement(Class<T> kind, T[] array, T element) {
+        if (array != null) {
+            if (!contains(array, element)) {
+                return array;
+            }
+            final int length = array.length;
+            for (int i = 0; i < length; i++) {
+                if (Objects.equals(array[i], element)) {
+                    if (length == 1) {
+                        return null;
+                    }
+                    T[] result = (T[]) Array.newInstance(kind, length - 1);
+                    System.arraycopy(array, 0, result, 0, i);
+                    System.arraycopy(array, i + 1, result, i, length - i - 1);
+                    return result;
+                }
+            }
+        }
+        return array;
+    }
+}
diff --git a/slices/core/src/main/java/androidx/app/slice/Slice.java b/slices/core/src/main/java/androidx/app/slice/Slice.java
new file mode 100644
index 0000000..8033bb7
--- /dev/null
+++ b/slices/core/src/main/java/androidx/app/slice/Slice.java
@@ -0,0 +1,430 @@
+/*
+ * 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 androidx.app.slice;
+
+import static android.app.slice.Slice.HINT_ACTIONS;
+import static android.app.slice.Slice.HINT_HORIZONTAL;
+import static android.app.slice.Slice.HINT_LARGE;
+import static android.app.slice.Slice.HINT_LIST;
+import static android.app.slice.Slice.HINT_LIST_ITEM;
+import static android.app.slice.Slice.HINT_NO_TINT;
+import static android.app.slice.Slice.HINT_PARTIAL;
+import static android.app.slice.Slice.HINT_SELECTED;
+import static android.app.slice.Slice.HINT_TITLE;
+import static android.app.slice.SliceItem.FORMAT_ACTION;
+import static android.app.slice.SliceItem.FORMAT_COLOR;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_REMOTE_INPUT;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
+
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.content.ContentProvider;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.RestrictTo.Scope;
+import android.support.annotation.StringDef;
+import android.support.v4.os.BuildCompat;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import androidx.app.slice.compat.SliceProviderCompat;
+import androidx.app.slice.core.SliceHints;
+import androidx.app.slice.core.SliceSpecs;
+
+/**
+ * A slice is a piece of app content and actions that can be surfaced outside of the app.
+ *
+ * <p>They are constructed using {@link Builder} in a tree structure
+ * that provides the OS some information about how the content should be displayed.
+ */
+public final class Slice {
+
+    private static final String HINTS = "hints";
+    private static final String ITEMS = "items";
+    private static final String URI = "uri";
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    @StringDef({HINT_TITLE, HINT_LIST, HINT_LIST_ITEM, HINT_LARGE, HINT_ACTIONS, HINT_SELECTED,
+            HINT_HORIZONTAL, HINT_NO_TINT, HINT_PARTIAL,
+            SliceHints.HINT_HIDDEN, SliceHints.SUBTYPE_TOGGLE})
+    public @interface SliceHint{ }
+
+    private final SliceItem[] mItems;
+    private final @SliceHint String[] mHints;
+    private Uri mUri;
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    Slice(ArrayList<SliceItem> items, @SliceHint String[] hints, Uri uri) {
+        mHints = hints;
+        mItems = items.toArray(new SliceItem[items.size()]);
+        mUri = uri;
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public Slice(Bundle in) {
+        mHints = in.getStringArray(HINTS);
+        Parcelable[] items = in.getParcelableArray(ITEMS);
+        mItems = new SliceItem[items.length];
+        for (int i = 0; i < mItems.length; i++) {
+            if (items[i] instanceof Bundle) {
+                mItems[i] = new SliceItem((Bundle) items[i]);
+            }
+        }
+        mUri = in.getParcelable(URI);
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public Bundle toBundle() {
+        Bundle b = new Bundle();
+        b.putStringArray(HINTS, mHints);
+        Parcelable[] p = new Parcelable[mItems.length];
+        for (int i = 0; i < mItems.length; i++) {
+            p[i] = mItems[i].toBundle();
+        }
+        b.putParcelableArray(ITEMS, p);
+        b.putParcelable(URI, mUri);
+        return b;
+    }
+
+    /**
+     * @return The Uri that this Slice represents.
+     */
+    public Uri getUri() {
+        return mUri;
+    }
+
+    /**
+     * @return All child {@link SliceItem}s that this Slice contains.
+     */
+    public List<SliceItem> getItems() {
+        return Arrays.asList(mItems);
+    }
+
+    /**
+     * @return All hints associated with this Slice.
+     */
+    public @SliceHint List<String> getHints() {
+        return Arrays.asList(mHints);
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public boolean hasHint(@SliceHint String hint) {
+        return ArrayUtils.contains(mHints, hint);
+    }
+
+    /**
+     * A Builder used to construct {@link Slice}s
+     */
+    public static class Builder {
+
+        private final Uri mUri;
+        private ArrayList<SliceItem> mItems = new ArrayList<>();
+        private @SliceHint ArrayList<String> mHints = new ArrayList<>();
+
+        /**
+         * Create a builder which will construct a {@link Slice} for the Given Uri.
+         * @param uri Uri to tag for this slice.
+         */
+        public Builder(@NonNull Uri uri) {
+            mUri = uri;
+        }
+
+        /**
+         * Create a builder for a {@link Slice} that is a sub-slice of the slice
+         * being constructed by the provided builder.
+         * @param parent The builder constructing the parent slice
+         */
+        public Builder(@NonNull Slice.Builder parent) {
+            mUri = parent.mUri.buildUpon().appendPath("_gen")
+                    .appendPath(String.valueOf(mItems.size())).build();
+        }
+
+        /**
+         * Add hints to the Slice being constructed
+         */
+        public Builder addHints(@SliceHint String... hints) {
+            mHints.addAll(Arrays.asList(hints));
+            return this;
+        }
+
+        /**
+         * Add hints to the Slice being constructed
+         */
+        public Builder addHints(@SliceHint List<String> hints) {
+            return addHints(hints.toArray(new String[hints.size()]));
+        }
+
+        /**
+         * Add a sub-slice to the slice being constructed
+         */
+        public Builder addSubSlice(@NonNull Slice slice) {
+            return addSubSlice(slice, null);
+        }
+
+        /**
+         * Add a sub-slice to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Builder addSubSlice(@NonNull Slice slice, String subType) {
+            mItems.add(new SliceItem(slice, FORMAT_SLICE, subType, slice.getHints().toArray(
+                    new String[slice.getHints().size()])));
+            return this;
+        }
+
+        /**
+         * Add an action to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Slice.Builder addAction(@NonNull PendingIntent action,
+                @NonNull Slice s, @Nullable String subType) {
+            mItems.add(new SliceItem(action, s, FORMAT_ACTION, subType, new String[0]));
+            return this;
+        }
+
+        /**
+         * Add text to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Builder addText(CharSequence text, @Nullable String subType,
+                @SliceHint String... hints) {
+            mItems.add(new SliceItem(text, FORMAT_TEXT, subType, hints));
+            return this;
+        }
+
+        /**
+         * Add text to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Builder addText(CharSequence text, @Nullable String subType,
+                @SliceHint List<String> hints) {
+            return addText(text, subType, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
+         * Add an image to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Builder addIcon(Icon icon, @Nullable String subType,
+                @SliceHint String... hints) {
+            mItems.add(new SliceItem(icon, FORMAT_IMAGE, subType, hints));
+            return this;
+        }
+
+        /**
+         * Add an image to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Builder addIcon(Icon icon, @Nullable String subType,
+                @SliceHint List<String> hints) {
+            return addIcon(icon, subType, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
+         * Add remote input to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Slice.Builder addRemoteInput(RemoteInput remoteInput, @Nullable String subType,
+                @SliceHint List<String> hints) {
+            return addRemoteInput(remoteInput, subType, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
+         * Add remote input to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Slice.Builder addRemoteInput(RemoteInput remoteInput, @Nullable String subType,
+                @SliceHint String... hints) {
+            mItems.add(new SliceItem(remoteInput, FORMAT_REMOTE_INPUT, subType, hints));
+            return this;
+        }
+
+        /**
+         * Add a color to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Builder addColor(int color, @Nullable String subType,
+                @SliceHint String... hints) {
+            mItems.add(new SliceItem(color, FORMAT_COLOR, subType, hints));
+            return this;
+        }
+
+        /**
+         * Add a color to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Builder addColor(int color, @Nullable String subType,
+                @SliceHint List<String> hints) {
+            return addColor(color, subType, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
+         * Add a timestamp to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Slice.Builder addTimestamp(long time, @Nullable String subType,
+                @SliceHint String... hints) {
+            mItems.add(new SliceItem(time, FORMAT_TIMESTAMP, subType, hints));
+            return this;
+        }
+
+        /**
+         * Add a timestamp to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Slice.Builder addTimestamp(long time, @Nullable String subType,
+                @SliceHint List<String> hints) {
+            return addTimestamp(time, subType, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
+         * Add a SliceItem to the slice being constructed.
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY)
+        public Slice.Builder addItem(SliceItem item) {
+            mItems.add(item);
+            return this;
+        }
+
+        /**
+         * Construct the slice.
+         */
+        public Slice build() {
+            return new Slice(mItems, mHints.toArray(new String[mHints.size()]), mUri);
+        }
+    }
+
+    /**
+     * @hide
+     * @return A string representation of this slice.
+     */
+    @RestrictTo(Scope.LIBRARY)
+    @Override
+    public String toString() {
+        return toString("");
+    }
+
+    private String toString(String indent) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < mItems.length; i++) {
+            sb.append(indent);
+            if (FORMAT_SLICE.equals(mItems[i].getFormat())) {
+                sb.append("slice:\n");
+                sb.append(mItems[i].getSlice().toString(indent + "   "));
+            } else if (FORMAT_TEXT.equals(mItems[i].getFormat())) {
+                sb.append("text: ");
+                sb.append(mItems[i].getText());
+                sb.append("\n");
+            } else {
+                sb.append(SliceItem.typeToString(mItems[i].getFormat()));
+                sb.append("\n");
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Turns a slice Uri into slice content.
+     *
+     * @param context Context to be used.
+     * @param uri The URI to a slice provider
+     * @return The Slice provided by the app or null if none is given.
+     * @see Slice
+     */
+    @SuppressWarnings("NewApi")
+    public static @Nullable Slice bindSlice(Context context, @NonNull Uri uri) {
+        if (BuildCompat.isAtLeastP()) {
+            return callBindSlice(context, uri);
+        } else {
+            return SliceProviderCompat.bindSlice(context, uri);
+        }
+    }
+
+    @TargetApi(28)
+    private static Slice callBindSlice(Context context, Uri uri) {
+        return SliceConvert.wrap(android.app.slice.Slice.bindSlice(
+                context.getContentResolver(), uri, SliceSpecs.SUPPORTED_SPECS));
+    }
+
+
+    /**
+     * Turns a slice intent into slice content. Expects an explicit intent. If there is no
+     * {@link ContentProvider} associated with the given intent this will throw
+     * {@link IllegalArgumentException}.
+     *
+     * @param context The context to use.
+     * @param intent The intent associated with a slice.
+     * @return The Slice provided by the app or null if none is given.
+     * @see Slice
+     * @see SliceProvider#onMapIntentToUri(Intent)
+     * @see Intent
+     */
+    @SuppressWarnings("NewApi")
+    public static @Nullable Slice bindSlice(Context context, @NonNull Intent intent) {
+        if (BuildCompat.isAtLeastP()) {
+            return callBindSlice(context, intent);
+        } else {
+            return SliceProviderCompat.bindSlice(context, intent);
+        }
+    }
+
+    @TargetApi(28)
+    private static Slice callBindSlice(Context context, Intent intent) {
+        return SliceConvert.wrap(android.app.slice.Slice.bindSlice(
+                context, intent, SliceSpecs.SUPPORTED_SPECS));
+    }
+}
diff --git a/slices/core/src/main/java/androidx/app/slice/SliceConvert.java b/slices/core/src/main/java/androidx/app/slice/SliceConvert.java
new file mode 100644
index 0000000..edbc293
--- /dev/null
+++ b/slices/core/src/main/java/androidx/app/slice/SliceConvert.java
@@ -0,0 +1,106 @@
+/*
+ * 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 androidx.app.slice;
+
+
+import static android.app.slice.SliceItem.FORMAT_ACTION;
+import static android.app.slice.SliceItem.FORMAT_COLOR;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_REMOTE_INPUT;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
+
+import android.support.annotation.RequiresApi;
+
+/**
+ * Convert between {@link androidx.app.slice.Slice} and {@link android.app.slice.Slice}
+ */
+@RequiresApi(28)
+public class SliceConvert {
+
+    /**
+     * Convert {@link androidx.app.slice.Slice} to {@link android.app.slice.Slice}
+     */
+    public static android.app.slice.Slice unwrap(androidx.app.slice.Slice slice) {
+        android.app.slice.Slice.Builder builder = new android.app.slice.Slice.Builder(
+                slice.getUri());
+        builder.addHints(slice.getHints());
+        for (androidx.app.slice.SliceItem item : slice.getItems()) {
+            switch (item.getFormat()) {
+                case FORMAT_SLICE:
+                    builder.addSubSlice(unwrap(item.getSlice()), item.getSubType());
+                    break;
+                case FORMAT_IMAGE:
+                    builder.addIcon(item.getIcon(), item.getSubType(), item.getHints());
+                    break;
+                case FORMAT_REMOTE_INPUT:
+                    builder.addRemoteInput(item.getRemoteInput(), item.getSubType(),
+                            item.getHints());
+                    break;
+                case FORMAT_ACTION:
+                    builder.addAction(item.getAction(), unwrap(item.getSlice()), item.getSubType());
+                    break;
+                case FORMAT_TEXT:
+                    builder.addText(item.getText(), item.getSubType(), item.getHints());
+                    break;
+                case FORMAT_COLOR:
+                    builder.addColor(item.getColor(), item.getSubType(), item.getHints());
+                    break;
+                case FORMAT_TIMESTAMP:
+                    builder.addTimestamp(item.getTimestamp(), item.getSubType(), item.getHints());
+                    break;
+            }
+        }
+        return builder.build();
+    }
+
+    /**
+     * Convert {@link android.app.slice.Slice} to {@link androidx.app.slice.Slice}
+     */
+    public static androidx.app.slice.Slice wrap(android.app.slice.Slice slice) {
+        androidx.app.slice.Slice.Builder builder = new androidx.app.slice.Slice.Builder(
+                slice.getUri());
+        builder.addHints(slice.getHints());
+        for (android.app.slice.SliceItem item : slice.getItems()) {
+            switch (item.getFormat()) {
+                case FORMAT_SLICE:
+                    builder.addSubSlice(wrap(item.getSlice()), item.getSubType());
+                    break;
+                case FORMAT_IMAGE:
+                    builder.addIcon(item.getIcon(), item.getSubType(), item.getHints());
+                    break;
+                case FORMAT_REMOTE_INPUT:
+                    builder.addRemoteInput(item.getRemoteInput(), item.getSubType(),
+                            item.getHints());
+                    break;
+                case FORMAT_ACTION:
+                    builder.addAction(item.getAction(), wrap(item.getSlice()), item.getSubType());
+                    break;
+                case FORMAT_TEXT:
+                    builder.addText(item.getText(), item.getSubType(), item.getHints());
+                    break;
+                case FORMAT_COLOR:
+                    builder.addColor(item.getColor(), item.getSubType(), item.getHints());
+                    break;
+                case FORMAT_TIMESTAMP:
+                    builder.addTimestamp(item.getTimestamp(), item.getSubType(), item.getHints());
+                    break;
+            }
+        }
+        return builder.build();
+    }
+}
diff --git a/slices/core/src/main/java/androidx/app/slice/SliceItem.java b/slices/core/src/main/java/androidx/app/slice/SliceItem.java
new file mode 100644
index 0000000..e4412d1
--- /dev/null
+++ b/slices/core/src/main/java/androidx/app/slice/SliceItem.java
@@ -0,0 +1,351 @@
+/*
+ * 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 androidx.app.slice;
+
+import static android.app.slice.SliceItem.FORMAT_ACTION;
+import static android.app.slice.SliceItem.FORMAT_COLOR;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_REMOTE_INPUT;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
+
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.RestrictTo.Scope;
+import android.support.annotation.StringDef;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+/**
+ * A SliceItem is a single unit in the tree structure of a {@link Slice}.
+ * <p>
+ * A SliceItem a piece of content and some hints about what that content
+ * means or how it should be displayed. The types of content can be:
+ * <li>{@link android.app.slice.SliceItem#FORMAT_SLICE}</li>
+ * <li>{@link android.app.slice.SliceItem#FORMAT_TEXT}</li>
+ * <li>{@link android.app.slice.SliceItem#FORMAT_IMAGE}</li>
+ * <li>{@link android.app.slice.SliceItem#FORMAT_ACTION}</li>
+ * <li>{@link android.app.slice.SliceItem#FORMAT_COLOR}</li>
+ * <li>{@link android.app.slice.SliceItem#FORMAT_TIMESTAMP}</li>
+ * <li>{@link android.app.slice.SliceItem#FORMAT_REMOTE_INPUT}</li>
+ * <p>
+ * The hints that a {@link SliceItem} are a set of strings which annotate
+ * the content. The hints that are guaranteed to be understood by the system
+ * are defined on {@link Slice}.
+ */
+public class SliceItem {
+
+    private static final String HINTS = "hints";
+    private static final String FORMAT = "format";
+    private static final String SUBTYPE = "subtype";
+    private static final String OBJ = "obj";
+    private static final String OBJ_2 = "obj_2";
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    @StringDef({FORMAT_SLICE, FORMAT_TEXT, FORMAT_IMAGE, FORMAT_ACTION, FORMAT_COLOR,
+            FORMAT_TIMESTAMP, FORMAT_REMOTE_INPUT})
+    public @interface SliceType {
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    protected @Slice.SliceHint String[] mHints;
+    private final String mFormat;
+    private final String mSubType;
+    private final Object mObj;
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public SliceItem(Object obj, @SliceType String format, String subType,
+            @Slice.SliceHint String[] hints) {
+        mHints = hints;
+        mFormat = format;
+        mSubType = subType;
+        mObj = obj;
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public SliceItem(PendingIntent intent, Slice slice, String format, String subType,
+            @Slice.SliceHint String[] hints) {
+        this(new Pair<>(intent, slice), format, subType, hints);
+    }
+
+    /**
+     * Gets all hints associated with this SliceItem.
+     *
+     * @return Array of hints.
+     */
+    public @NonNull @Slice.SliceHint List<String> getHints() {
+        return Arrays.asList(mHints);
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public void addHint(@Slice.SliceHint String hint) {
+        mHints = ArrayUtils.appendElement(String.class, mHints, hint);
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public void removeHint(String hint) {
+        ArrayUtils.removeElement(String.class, mHints, hint);
+    }
+
+    /**
+     * Get the format of this SliceItem.
+     * <p>
+     * The format will be one of the following types supported by the platform:
+     * <li>{@link android.app.slice.SliceItem#FORMAT_SLICE}</li>
+     * <li>{@link android.app.slice.SliceItem#FORMAT_TEXT}</li>
+     * <li>{@link android.app.slice.SliceItem#FORMAT_IMAGE}</li>
+     * <li>{@link android.app.slice.SliceItem#FORMAT_ACTION}</li>
+     * <li>{@link android.app.slice.SliceItem#FORMAT_COLOR}</li>
+     * <li>{@link android.app.slice.SliceItem#FORMAT_TIMESTAMP}</li>
+     * <li>{@link android.app.slice.SliceItem#FORMAT_REMOTE_INPUT}</li>
+     * @see #getSubType() ()
+     */
+    public @SliceType String getFormat() {
+        return mFormat;
+    }
+
+    /**
+     * Get the sub-type of this SliceItem.
+     * <p>
+     * Subtypes provide additional information about the type of this information beyond basic
+     * interpretations inferred by {@link #getFormat()}. For example a slice may contain
+     * many {@link android.app.slice.SliceItem#FORMAT_TEXT} items, but only some of them may be
+     * {@link android.app.slice.Slice#SUBTYPE_MESSAGE}.
+     * @see #getFormat()
+     */
+    public String getSubType() {
+        return mSubType;
+    }
+
+    /**
+     * @return The text held by this {@link android.app.slice.SliceItem#FORMAT_TEXT} SliceItem
+     */
+    public CharSequence getText() {
+        return (CharSequence) mObj;
+    }
+
+    /**
+     * @return The icon held by this {@link android.app.slice.SliceItem#FORMAT_IMAGE} SliceItem
+     */
+    @RequiresApi(23)
+    public Icon getIcon() {
+        return (Icon) mObj;
+    }
+
+    /**
+     * @return The pending intent held by this {@link android.app.slice.SliceItem#FORMAT_ACTION}
+     * SliceItem
+     */
+    public PendingIntent getAction() {
+        return ((Pair<PendingIntent, Slice>) mObj).first;
+    }
+
+    /**
+     * @return The remote input held by this {@link android.app.slice.SliceItem#FORMAT_REMOTE_INPUT}
+     * SliceItem
+     */
+    @RequiresApi(20)
+    public RemoteInput getRemoteInput() {
+        return (RemoteInput) mObj;
+    }
+
+    /**
+     * @return The color held by this {@link android.app.slice.SliceItem#FORMAT_COLOR} SliceItem
+     */
+    public int getColor() {
+        return (Integer) mObj;
+    }
+
+    /**
+     * @return The slice held by this {@link android.app.slice.SliceItem#FORMAT_ACTION} or
+     * {@link android.app.slice.SliceItem#FORMAT_SLICE} SliceItem
+     */
+    public Slice getSlice() {
+        if (FORMAT_ACTION.equals(getFormat())) {
+            return ((Pair<PendingIntent, Slice>) mObj).second;
+        }
+        return (Slice) mObj;
+    }
+
+    /**
+     * @return The timestamp held by this {@link android.app.slice.SliceItem#FORMAT_TIMESTAMP}
+     * SliceItem
+     */
+    public long getTimestamp() {
+        return (Long) mObj;
+    }
+
+    /**
+     * @param hint The hint to check for
+     * @return true if this item contains the given hint
+     */
+    public boolean hasHint(@Slice.SliceHint String hint) {
+        return ArrayUtils.contains(mHints, hint);
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public SliceItem(Bundle in) {
+        mHints = in.getStringArray(HINTS);
+        mFormat = in.getString(FORMAT);
+        mSubType = in.getString(SUBTYPE);
+        mObj = readObj(mFormat, in);
+    }
+
+    /**
+     * @hide
+     * @return
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public Bundle toBundle() {
+        Bundle b = new Bundle();
+        b.putStringArray(HINTS, mHints);
+        b.putString(FORMAT, mFormat);
+        b.putString(SUBTYPE, mSubType);
+        writeObj(b, mObj, mFormat);
+        return b;
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public boolean hasHints(@Slice.SliceHint String[] hints) {
+        if (hints == null) return true;
+        for (String hint : hints) {
+            if (!TextUtils.isEmpty(hint) && !ArrayUtils.contains(mHints, hint)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public boolean hasAnyHints(@Slice.SliceHint String[] hints) {
+        if (hints == null) return false;
+        for (String hint : hints) {
+            if (ArrayUtils.contains(mHints, hint)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void writeObj(Bundle dest, Object obj, String type) {
+        switch (type) {
+            case FORMAT_IMAGE:
+            case FORMAT_REMOTE_INPUT:
+                dest.putParcelable(OBJ, (Parcelable) obj);
+                break;
+            case FORMAT_SLICE:
+                dest.putParcelable(OBJ, ((Slice) obj).toBundle());
+                break;
+            case FORMAT_ACTION:
+                dest.putParcelable(OBJ, ((Pair<PendingIntent, Slice>) obj).first);
+                dest.putBundle(OBJ_2, ((Pair<PendingIntent, Slice>) obj).second.toBundle());
+                break;
+            case FORMAT_TEXT:
+                dest.putCharSequence(OBJ, (CharSequence) obj);
+                break;
+            case FORMAT_COLOR:
+                dest.putInt(OBJ, (Integer) mObj);
+                break;
+            case FORMAT_TIMESTAMP:
+                dest.putLong(OBJ, (Long) mObj);
+                break;
+        }
+    }
+
+    private static Object readObj(String type, Bundle in) {
+        switch (type) {
+            case FORMAT_IMAGE:
+            case FORMAT_REMOTE_INPUT:
+                return in.getParcelable(OBJ);
+            case FORMAT_SLICE:
+                return new Slice(in.getBundle(OBJ));
+            case FORMAT_TEXT:
+                return in.getCharSequence(OBJ);
+            case FORMAT_ACTION:
+                return new Pair<>(
+                        (PendingIntent) in.getParcelable(OBJ),
+                        new Slice(in.getBundle(OBJ_2)));
+            case FORMAT_COLOR:
+                return in.getInt(OBJ);
+            case FORMAT_TIMESTAMP:
+                return in.getLong(OBJ);
+        }
+        throw new RuntimeException("Unsupported type " + type);
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY)
+    public static String typeToString(String format) {
+        switch (format) {
+            case FORMAT_SLICE:
+                return "Slice";
+            case FORMAT_TEXT:
+                return "Text";
+            case FORMAT_IMAGE:
+                return "Image";
+            case FORMAT_ACTION:
+                return "Action";
+            case FORMAT_COLOR:
+                return "Color";
+            case FORMAT_TIMESTAMP:
+                return "Timestamp";
+            case FORMAT_REMOTE_INPUT:
+                return "RemoteInput";
+        }
+        return "Unrecognized format: " + format;
+    }
+}
diff --git a/slices/core/src/main/java/androidx/app/slice/SliceProvider.java b/slices/core/src/main/java/androidx/app/slice/SliceProvider.java
new file mode 100644
index 0000000..a0c12f1
--- /dev/null
+++ b/slices/core/src/main/java/androidx/app/slice/SliceProvider.java
@@ -0,0 +1,130 @@
+/*
+ * 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 androidx.app.slice;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ProviderInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.v4.os.BuildCompat;
+
+import androidx.app.slice.compat.ContentProviderWrapper;
+import androidx.app.slice.compat.SliceProviderCompat;
+import androidx.app.slice.compat.SliceProviderWrapper;
+
+/**
+ * A SliceProvider allows an app to provide content to be displayed in system spaces. This content
+ * is templated and can contain actions, and the behavior of how it is surfaced is specific to the
+ * system surface.
+ * <p>
+ * Slices are not currently live content. They are bound once and shown to the user. If the content
+ * changes due to a callback from user interaction, then
+ * {@link ContentResolver#notifyChange(Uri, ContentObserver)} should be used to notify the system.
+ * </p>
+ * <p>
+ * The provider needs to be declared in the manifest to provide the authority for the app. The
+ * authority for most slices is expected to match the package of the application.
+ * </p>
+ *
+ * <pre class="prettyprint">
+ * {@literal
+ * <provider
+ *     android:name="com.android.mypkg.MySliceProvider"
+ *     android:authorities="com.android.mypkg" />}
+ * </pre>
+ * <p>
+ * Slices can be identified by a Uri or by an Intent. To link an Intent with a slice, the provider
+ * must have an {@link IntentFilter} matching the slice intent. When a slice is being requested via
+ * an intent, {@link #onMapIntentToUri(Intent)} can be called and is expected to return an
+ * appropriate Uri representing the slice.
+ *
+ * <pre class="prettyprint">
+ * {@literal
+ * <provider
+ *     android:name="com.android.mypkg.MySliceProvider"
+ *     android:authorities="com.android.mypkg">
+ *     <intent-filter>
+ *         <action android:name="android.intent.action.MY_SLICE_INTENT" />
+ *     </intent-filter>
+ * </provider>}
+ * </pre>
+ *
+ * @see android.app.slice.Slice
+ */
+public abstract class SliceProvider extends ContentProviderWrapper {
+
+    @Override
+    public void attachInfo(Context context, ProviderInfo info) {
+        ContentProvider impl;
+        if (BuildCompat.isAtLeastP()) {
+            impl = new SliceProviderWrapper(this);
+        } else {
+            impl = new SliceProviderCompat(this);
+        }
+        super.attachInfo(context, info, impl);
+    }
+
+    /**
+     * Implement this to initialize your slice provider on startup.
+     * This method is called for all registered slice providers on the
+     * application main thread at application launch time.  It must not perform
+     * lengthy operations, or application startup will be delayed.
+     *
+     * <p>You should defer nontrivial initialization (such as opening,
+     * upgrading, and scanning databases) until the slice provider is used
+     * (via #onBindSlice, etc).  Deferred initialization
+     * keeps application startup fast, avoids unnecessary work if the provider
+     * turns out not to be needed, and stops database errors (such as a full
+     * disk) from halting application launch.
+     *
+     * @return true if the provider was successfully loaded, false otherwise
+     */
+    public abstract boolean onCreateSliceProvider();
+
+    /**
+     * Implemented to create a slice. Will be called on the main thread.
+     * <p>
+     * onBindSlice should return as quickly as possible so that the UI tied
+     * to this slice can be responsive. No network or other IO will be allowed
+     * during onBindSlice. Any loading that needs to be done should happen
+     * off the main thread with a call to {@link ContentResolver#notifyChange(Uri, ContentObserver)}
+     * when the app is ready to provide the complete data in onBindSlice.
+     * <p>
+     *
+     * @see {@link Slice}.
+     * @see {@link android.app.slice.Slice#HINT_PARTIAL}
+     */
+    // TODO: Provide alternate notifyChange that takes in the slice (i.e. notifyChange(Uri, Slice)).
+    public abstract Slice onBindSlice(Uri sliceUri);
+
+    /**
+     * This method must be overridden if an {@link IntentFilter} is specified on the SliceProvider.
+     * In that case, this method can be called and is expected to return a non-null Uri representing
+     * a slice. Otherwise this will throw {@link UnsupportedOperationException}.
+     *
+     * @return Uri representing the slice associated with the provided intent.
+     * @see {@link android.app.slice.Slice}
+     */
+    public @NonNull Uri onMapIntentToUri(Intent intent) {
+        throw new UnsupportedOperationException(
+                "This provider has not implemented intent to uri mapping");
+    }
+}
diff --git a/slices/core/src/main/java/androidx/app/slice/compat/ContentProviderWrapper.java b/slices/core/src/main/java/androidx/app/slice/compat/ContentProviderWrapper.java
new file mode 100644
index 0000000..9e02b3a
--- /dev/null
+++ b/slices/core/src/main/java/androidx/app/slice/compat/ContentProviderWrapper.java
@@ -0,0 +1,121 @@
+/*
+ * 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 androidx.app.slice.compat;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.RestrictTo.Scope;
+
+/**
+ * @hide
+ */
+// TODO: Remove as soon as we have better systems in place for this.
+@RestrictTo(Scope.LIBRARY)
+public class ContentProviderWrapper extends ContentProvider {
+
+    private ContentProvider mImpl;
+
+    /**
+     * Triggers an attach with the object to wrap.
+     */
+    public void attachInfo(Context context, ProviderInfo info, ContentProvider impl) {
+        mImpl = impl;
+        super.attachInfo(context, info);
+        mImpl.attachInfo(context, info);
+    }
+
+    @Override
+    public final boolean onCreate() {
+        return mImpl.onCreate();
+    }
+
+    @Nullable
+    @Override
+    public final Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs,
+            @Nullable String sortOrder) {
+        return mImpl.query(uri, projection, selection, selectionArgs, sortOrder);
+    }
+
+    @Nullable
+    @Override
+    @RequiresApi(28)
+    public final Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+            @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) {
+        return mImpl.query(uri, projection, queryArgs, cancellationSignal);
+    }
+
+    @Nullable
+    @Override
+    public final Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs,
+            @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) {
+        return mImpl.query(uri, projection, selection, selectionArgs, sortOrder,
+                cancellationSignal);
+    }
+
+    @Nullable
+    @Override
+    public final String getType(@NonNull Uri uri) {
+        return mImpl.getType(uri);
+    }
+
+    @Nullable
+    @Override
+    public final Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+        return mImpl.insert(uri, values);
+    }
+
+    @Override
+    public final int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
+        return mImpl.bulkInsert(uri, values);
+    }
+
+    @Override
+    public final int delete(@NonNull Uri uri, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return mImpl.delete(uri, selection, selectionArgs);
+    }
+
+    @Override
+    public final int update(@NonNull Uri uri, @Nullable ContentValues values,
+            @Nullable String selection, @Nullable String[] selectionArgs) {
+        return mImpl.update(uri, values, selection, selectionArgs);
+    }
+
+    @Nullable
+    @Override
+    public final Bundle call(@NonNull String method, @Nullable String arg,
+            @Nullable Bundle extras) {
+        return mImpl.call(method, arg, extras);
+    }
+
+    @Nullable
+    @Override
+    public final Uri canonicalize(@NonNull Uri url) {
+        return mImpl.canonicalize(url);
+    }
+}
diff --git a/slices/core/src/main/java/androidx/app/slice/compat/SliceProviderCompat.java b/slices/core/src/main/java/androidx/app/slice/compat/SliceProviderCompat.java
new file mode 100644
index 0000000..9fcac1b
--- /dev/null
+++ b/slices/core/src/main/java/androidx/app/slice/compat/SliceProviderCompat.java
@@ -0,0 +1,266 @@
+/*
+ * 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 androidx.app.slice.compat;
+
+import static android.app.slice.SliceProvider.SLICE_TYPE;
+
+import android.Manifest.permission;
+import android.content.ContentProvider;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Parcelable;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.StrictMode;
+import android.os.StrictMode.ThreadPolicy;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.RestrictTo.Scope;
+import android.util.Log;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceProvider;
+
+/**
+ * @hide
+ */
+@RestrictTo(Scope.LIBRARY)
+public class SliceProviderCompat extends ContentProvider {
+
+    private static final String TAG = "SliceProvider";
+
+    public static final String EXTRA_BIND_URI = "slice_uri";
+    public static final String METHOD_SLICE = "bind_slice";
+    public static final String METHOD_MAP_INTENT = "map_slice";
+    public static final String EXTRA_INTENT = "slice_intent";
+    public static final String EXTRA_SLICE = "slice";
+
+    private static final boolean DEBUG = false;
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private SliceProvider mSliceProvider;
+
+    public SliceProviderCompat(SliceProvider provider) {
+        mSliceProvider = provider;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return mSliceProvider.onCreateSliceProvider();
+    }
+
+    @Override
+    public final int update(Uri uri, ContentValues values, String selection,
+            String[] selectionArgs) {
+        if (DEBUG) Log.d(TAG, "update " + uri);
+        return 0;
+    }
+
+    @Override
+    public final int delete(Uri uri, String selection, String[] selectionArgs) {
+        if (DEBUG) Log.d(TAG, "delete " + uri);
+        return 0;
+    }
+
+    @Override
+    public final Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        if (DEBUG) Log.d(TAG, "query " + uri);
+        return null;
+    }
+
+    @Override
+    public final Cursor query(Uri uri, String[] projection, String selection, String[]
+            selectionArgs, String sortOrder, CancellationSignal cancellationSignal) {
+        if (DEBUG) Log.d(TAG, "query " + uri);
+        return null;
+    }
+
+    @Override
+    public final Cursor query(Uri uri, String[] projection, Bundle queryArgs,
+            CancellationSignal cancellationSignal) {
+        if (DEBUG) Log.d(TAG, "query " + uri);
+        return null;
+    }
+
+    @Override
+    public final Uri insert(Uri uri, ContentValues values) {
+        if (DEBUG) Log.d(TAG, "insert " + uri);
+        return null;
+    }
+
+    @Override
+    public final String getType(Uri uri) {
+        if (DEBUG) Log.d(TAG, "getFormat " + uri);
+        return SLICE_TYPE;
+    }
+
+    @Override
+    public Bundle call(String method, String arg, Bundle extras) {
+        if (method.equals(METHOD_SLICE)) {
+            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
+            if (Binder.getCallingUid() != Process.myUid()) {
+                getContext().enforceUriPermission(uri, permission.BIND_SLICE,
+                        permission.BIND_SLICE, Binder.getCallingPid(), Binder.getCallingUid(),
+                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+                        "Slice binding requires the permission BIND_SLICE");
+            }
+
+            Slice s = handleBindSlice(uri);
+            Bundle b = new Bundle();
+            b.putParcelable(EXTRA_SLICE, s.toBundle());
+            return b;
+        } else if (method.equals(METHOD_MAP_INTENT)) {
+            if (Binder.getCallingUid() != Process.myUid()) {
+                getContext().enforceCallingPermission(permission.BIND_SLICE,
+                        "Slice binding requires the permission BIND_SLICE");
+            }
+            Intent intent = extras.getParcelable(EXTRA_INTENT);
+            Uri uri = mSliceProvider.onMapIntentToUri(intent);
+            Bundle b = new Bundle();
+            if (uri != null) {
+                Slice s = handleBindSlice(uri);
+                b.putParcelable(EXTRA_SLICE, s.toBundle());
+            } else {
+                b.putParcelable(EXTRA_SLICE, null);
+            }
+            return b;
+        }
+        return super.call(method, arg, extras);
+    }
+
+    private Slice handleBindSlice(final Uri sliceUri) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
+            return onBindSliceStrict(sliceUri);
+        } else {
+            final CountDownLatch latch = new CountDownLatch(1);
+            final Slice[] output = new Slice[1];
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    output[0] = onBindSliceStrict(sliceUri);
+                    latch.countDown();
+                }
+            });
+            try {
+                latch.await();
+                return output[0];
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    private Slice onBindSliceStrict(Uri sliceUri) {
+        ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
+        try {
+            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+                    .detectAll()
+                    .penaltyDeath()
+                    .build());
+            return mSliceProvider.onBindSlice(sliceUri);
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+    }
+
+    /**
+     * Compat version of {@link Slice#bindSlice(Context, Uri)}.
+     */
+    public static Slice bindSlice(Context context, Uri uri) {
+        ContentProviderClient provider = context.getContentResolver()
+                .acquireContentProviderClient(uri);
+        if (provider == null) {
+            throw new IllegalArgumentException("Unknown URI " + uri);
+        }
+        try {
+            Bundle extras = new Bundle();
+            extras.putParcelable(EXTRA_BIND_URI, uri);
+            final Bundle res = provider.call(METHOD_SLICE, null, extras);
+            if (res == null) {
+                return null;
+            }
+            Parcelable bundle = res.getParcelable(EXTRA_SLICE);
+            if (!(bundle instanceof Bundle)) {
+                return null;
+            }
+            return new Slice((Bundle) bundle);
+        } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+            return null;
+        } finally {
+            provider.close();
+        }
+    }
+
+    /**
+     * Compat version of {@link Slice#bindSlice(Context, Intent)}.
+     */
+    public static Slice bindSlice(Context context, Intent intent) {
+        ContentResolver resolver = context.getContentResolver();
+
+        // Check if the intent has data for the slice uri on it and use that
+        final Uri intentData = intent.getData();
+        if (intentData != null && SLICE_TYPE.equals(resolver.getType(intentData))) {
+            return bindSlice(context, intentData);
+        }
+        // Otherwise ask the app
+        List<ResolveInfo> providers =
+                context.getPackageManager().queryIntentContentProviders(intent, 0);
+        if (providers == null) {
+            throw new IllegalArgumentException("Unable to resolve intent " + intent);
+        }
+        String authority = providers.get(0).providerInfo.authority;
+        Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(authority).build();
+        ContentProviderClient provider = resolver.acquireContentProviderClient(uri);
+        if (provider == null) {
+            throw new IllegalArgumentException("Unknown URI " + uri);
+        }
+        try {
+            Bundle extras = new Bundle();
+            extras.putParcelable(EXTRA_INTENT, intent);
+            final Bundle res = provider.call(METHOD_MAP_INTENT, null, extras);
+            if (res == null) {
+                return null;
+            }
+            Parcelable bundle = res.getParcelable(EXTRA_SLICE);
+            if (!(bundle instanceof Bundle)) {
+                return null;
+            }
+            return new Slice((Bundle) bundle);
+        } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+            return null;
+        } finally {
+            provider.close();
+        }
+    }
+}
diff --git a/slices/core/src/main/java/androidx/app/slice/compat/SliceProviderWrapper.java b/slices/core/src/main/java/androidx/app/slice/compat/SliceProviderWrapper.java
new file mode 100644
index 0000000..3afed2b
--- /dev/null
+++ b/slices/core/src/main/java/androidx/app/slice/compat/SliceProviderWrapper.java
@@ -0,0 +1,62 @@
+/*
+ * 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 androidx.app.slice.compat;
+
+import android.annotation.TargetApi;
+import android.app.slice.Slice;
+import android.app.slice.SliceProvider;
+import android.app.slice.SliceSpec;
+import android.content.Intent;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.RestrictTo.Scope;
+
+import java.util.List;
+
+import androidx.app.slice.SliceConvert;
+
+/**
+ * @hide
+ */
+@RestrictTo(Scope.LIBRARY)
+@TargetApi(28)
+public class SliceProviderWrapper extends SliceProvider {
+
+    private androidx.app.slice.SliceProvider mSliceProvider;
+
+    public SliceProviderWrapper(androidx.app.slice.SliceProvider provider) {
+        mSliceProvider = provider;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return mSliceProvider.onCreateSliceProvider();
+    }
+
+    @Override
+    public Slice onBindSlice(Uri sliceUri, List<SliceSpec> supportedVersions) {
+        return SliceConvert.unwrap(mSliceProvider.onBindSlice(sliceUri));
+    }
+
+    /**
+     * Maps intents to uris.
+     */
+    @Override
+    public @NonNull Uri onMapIntentToUri(Intent intent) {
+        return mSliceProvider.onMapIntentToUri(intent);
+    }
+}
diff --git a/slices/core/src/main/java/androidx/app/slice/core/SliceHints.java b/slices/core/src/main/java/androidx/app/slice/core/SliceHints.java
new file mode 100644
index 0000000..96e2c3f
--- /dev/null
+++ b/slices/core/src/main/java/androidx/app/slice/core/SliceHints.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 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 androidx.app.slice.core;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.app.slice.Slice;
+import android.support.annotation.RestrictTo;
+
+/**
+ * Temporary class to contain hint constants for slices to be used.
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+public class SliceHints {
+    /**
+     * Subtype to indicate that this content has a toggle action associated with it. To indicate
+     * that the toggle is on, use {@link Slice#HINT_SELECTED}. When the toggle state changes, the
+     * intent associated with it will be sent along with an extra {@link #EXTRA_TOGGLE_STATE}
+     * which can be retrieved to see the new state of the toggle.
+     */
+    public static final String SUBTYPE_TOGGLE = "toggle";
+
+    /**
+     * Key to retrieve an extra added to an intent when a control is changed.
+     */
+    public static final String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE";
+    /**
+     * Hint to indicate that this content should not be shown in the
+     * {@link androidx.app.slice.widget.SliceView#MODE_SMALL}
+     * and {@link androidx.app.slice.widget.SliceView#MODE_LARGE} modes of SliceView.
+     * This content may be used to populate
+     * the {@link androidx.app.slice.widget.SliceView#MODE_SHORTCUT} format of the slice.
+     */
+    public static final String HINT_HIDDEN = "hidden";
+}
diff --git a/slices/core/src/main/java/androidx/app/slice/core/SliceQuery.java b/slices/core/src/main/java/androidx/app/slice/core/SliceQuery.java
new file mode 100644
index 0000000..d799352
--- /dev/null
+++ b/slices/core/src/main/java/androidx/app/slice/core/SliceQuery.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright 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 androidx.app.slice.core;
+
+import static android.app.slice.SliceItem.FORMAT_ACTION;
+import static android.app.slice.SliceItem.FORMAT_COLOR;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
+
+import android.annotation.TargetApi;
+import android.support.annotation.RestrictTo;
+import android.text.TextUtils;
+
+import java.util.ArrayDeque;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Queue;
+import java.util.Spliterators;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceItem;
+
+/**
+ * Utilities for finding content within a Slice.
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+// TODO: Not expect 24.
+@TargetApi(24)
+public class SliceQuery {
+
+    /**
+     * @return Whether this item is appropriate to be considered a "start" item, i.e. go in the
+     *         front slot of a row.
+     */
+    public static boolean isStartType(SliceItem item) {
+        final String type = item.getFormat();
+        return (!item.hasHint(SliceHints.SUBTYPE_TOGGLE)
+                && (FORMAT_ACTION.equals(type) && (find(item, FORMAT_IMAGE) != null)))
+                || FORMAT_IMAGE.equals(type)
+                || FORMAT_TIMESTAMP.equals(type);
+    }
+
+    /**
+     * @return Finds the first slice that has non-slice children.
+     */
+    public static SliceItem findFirstSlice(SliceItem slice) {
+        if (!FORMAT_SLICE.equals(slice.getFormat())) {
+            return slice;
+        }
+        List<SliceItem> items = slice.getSlice().getItems();
+        for (int i = 0; i < items.size(); i++) {
+            if (FORMAT_SLICE.equals(items.get(i).getFormat())) {
+                SliceItem childSlice = items.get(i);
+                return findFirstSlice(childSlice);
+            } else {
+                // Doesn't have slice children so return it
+                return slice;
+            }
+        }
+        // Slices all the way down, just return it
+        return slice;
+    }
+
+    /**
+     * @return Whether this item is a simple action, i.e. an action that only has an icon.
+     */
+    public static boolean isSimpleAction(SliceItem item) {
+        if (FORMAT_ACTION.equals(item.getFormat())) {
+            List<SliceItem> items = item.getSlice().getItems();
+            boolean hasImage = false;
+            for (int i = 0; i < items.size(); i++) {
+                SliceItem child = items.get(i);
+                if (FORMAT_IMAGE.equals(child.getFormat()) && !hasImage) {
+                    hasImage = true;
+                } else if (FORMAT_COLOR.equals(child.getFormat())) {
+                    continue;
+                } else {
+                    return false;
+                }
+            }
+            return hasImage;
+        }
+        return false;
+    }
+
+    /**
+     */
+    public static boolean hasAnyHints(SliceItem item, String... hints) {
+        if (hints == null) return false;
+        List<String> itemHints = item.getHints();
+        for (String hint : hints) {
+            if (itemHints.contains(hint)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     */
+    public static boolean hasHints(SliceItem item, String... hints) {
+        if (hints == null) return true;
+        List<String> itemHints = item.getHints();
+        for (String hint : hints) {
+            if (!TextUtils.isEmpty(hint) && !itemHints.contains(hint)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     */
+    public static boolean hasHints(Slice item, String... hints) {
+        if (hints == null) return true;
+        List<String> itemHints = item.getHints();
+        for (String hint : hints) {
+            if (!TextUtils.isEmpty(hint) && !itemHints.contains(hint)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+
+    /**
+     */
+    public static SliceItem findNotContaining(SliceItem container, List<SliceItem> list) {
+        SliceItem ret = null;
+        while (ret == null && list.size() != 0) {
+            SliceItem remove = list.remove(0);
+            if (!contains(container, remove)) {
+                ret = remove;
+            }
+        }
+        return ret;
+    }
+
+    /**
+     */
+    private static boolean contains(SliceItem container, final SliceItem item) {
+        if (container == null || item == null) return false;
+        return stream(container).filter(new Predicate<SliceItem>() {
+            @Override
+            public boolean test(SliceItem s) {
+                return s == item;
+            }
+        }).findAny().isPresent();
+    }
+
+    /**
+     */
+    public static List<SliceItem> findAll(SliceItem s, String format) {
+        return findAll(s, format, (String[]) null, null);
+    }
+
+    /**
+     */
+    public static List<SliceItem> findAll(Slice s, String format, String hints, String nonHints) {
+        return findAll(s, format, new String[]{ hints }, new String[]{ nonHints });
+    }
+
+    /**
+     */
+    public static List<SliceItem> findAll(SliceItem s, String format, String hints,
+            String nonHints) {
+        return findAll(s, format, new String[]{ hints }, new String[]{ nonHints });
+    }
+
+    /**
+     */
+    public static List<SliceItem> findAll(Slice s, final String format, final String[] hints,
+            final String[] nonHints) {
+        return stream(s).filter(new Predicate<SliceItem>() {
+            @Override
+            public boolean test(SliceItem item) {
+                return checkFormat(item, format)
+                        && (hasHints(item, hints) && !hasAnyHints(item, nonHints));
+            }
+        }).collect(Collectors.<SliceItem>toList());
+    }
+
+    /**
+     */
+    public static List<SliceItem> findAll(SliceItem s, final String format, final String[] hints,
+            final String[] nonHints) {
+        return stream(s).filter(new Predicate<SliceItem>() {
+            @Override
+            public boolean test(SliceItem item) {
+                return checkFormat(item, format)
+                        && (hasHints(item, hints) && !hasAnyHints(item, nonHints));
+            }
+        }).collect(Collectors.<SliceItem>toList());
+    }
+
+    /**
+     */
+    public static SliceItem find(Slice s, String format, String hints, String nonHints) {
+        return find(s, format, new String[]{ hints }, new String[]{ nonHints });
+    }
+
+    /**
+     */
+    public static SliceItem find(Slice s, String format) {
+        return find(s, format, (String[]) null, null);
+    }
+
+    /**
+     */
+    public static SliceItem find(SliceItem s, String format) {
+        return find(s, format, (String[]) null, null);
+    }
+
+    /**
+     */
+    public static SliceItem find(SliceItem s, String format, String hints, String nonHints) {
+        return find(s, format, new String[]{ hints }, new String[]{ nonHints });
+    }
+
+    /**
+     */
+    public static SliceItem find(Slice s, final String format, final String[] hints,
+            final String[] nonHints) {
+        return stream(s).filter(new Predicate<SliceItem>() {
+            @Override
+            public boolean test(SliceItem item) {
+                return checkFormat(item, format)
+                        && (hasHints(item, hints) && !hasAnyHints(item, nonHints));
+            }
+        }).findFirst().orElse(null);
+    }
+
+    /**
+     */
+    public static SliceItem findSubtype(SliceItem s, final String format, final String subtype) {
+        return stream(s).filter(new Predicate<SliceItem>() {
+            @Override
+            public boolean test(SliceItem item) {
+                return checkFormat(item, format) && checkSubtype(item, subtype);
+            }
+        }).findFirst().orElse(null);
+    }
+
+    /**
+     */
+    public static SliceItem find(SliceItem s, final String format, final String[] hints,
+            final String[] nonHints) {
+        return stream(s).filter(new Predicate<SliceItem>() {
+            @Override
+            public boolean test(SliceItem item) {
+                return checkFormat(item, format)
+                        && (hasHints(item, hints) && !hasAnyHints(item, nonHints));
+            }
+        }).findFirst().orElse(null);
+    }
+
+    private static boolean checkFormat(SliceItem item, String format) {
+        return format == null || format.equals(item.getFormat());
+    }
+
+    private static boolean checkSubtype(SliceItem item, String subtype) {
+        return subtype == null || subtype.equals(item.getSubType());
+    }
+
+    /**
+     */
+    public static Stream<SliceItem> stream(SliceItem slice) {
+        Queue<SliceItem> items = new ArrayDeque<>();
+        items.add(slice);
+        return getSliceItemStream(items);
+    }
+
+    /**
+     */
+    public static Stream<SliceItem> stream(Slice slice) {
+        Queue<SliceItem> items = new ArrayDeque<>();
+        items.addAll(slice.getItems());
+        return getSliceItemStream(items);
+    }
+
+    /**
+     */
+    private static Stream<SliceItem> getSliceItemStream(final Queue<SliceItem> items) {
+        Iterator<SliceItem> iterator = new Iterator<SliceItem>() {
+            @Override
+            public boolean hasNext() {
+                return items.size() != 0;
+            }
+
+            @Override
+            public SliceItem next() {
+                SliceItem item = items.poll();
+                if (FORMAT_SLICE.equals(item.getFormat())
+                        || FORMAT_ACTION.equals(item.getFormat())) {
+                    items.addAll(item.getSlice().getItems());
+                }
+                return item;
+            }
+        };
+        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
+    }
+}
diff --git a/buildSrc/src/main/kotlin/android/support/KotlinNoOp.kt b/slices/core/src/main/java/androidx/app/slice/core/SliceSpecs.java
similarity index 62%
rename from buildSrc/src/main/kotlin/android/support/KotlinNoOp.kt
rename to slices/core/src/main/java/androidx/app/slice/core/SliceSpecs.java
index 968f6ca..a21633b 100644
--- a/buildSrc/src/main/kotlin/android/support/KotlinNoOp.kt
+++ b/slices/core/src/main/java/androidx/app/slice/core/SliceSpecs.java
@@ -14,11 +14,20 @@
  * limitations under the License.
  */
 
-package android.support
+package androidx.app.slice.core;
 
-class KotlinNoOp {
+import android.app.slice.SliceSpec;
+import android.support.annotation.RestrictTo;
 
-    fun noOp() {
-    }
+import java.util.Collections;
+import java.util.List;
 
-}
\ No newline at end of file
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public class SliceSpecs {
+
+    // TODO: Fill these in.
+    public static List<SliceSpec> SUPPORTED_SPECS = Collections.emptyList();
+}
diff --git a/slices/core/src/main/res-public/values-v28/strings.xml b/slices/core/src/main/res-public/values-v28/strings.xml
new file mode 100644
index 0000000..12dabc6
--- /dev/null
+++ b/slices/core/src/main/res-public/values-v28/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="slice_provider">androidx.app.slice.compat.SliceProviderWrapper</string>
+</resources>
\ No newline at end of file
diff --git a/slices/core/src/main/res-public/values/strings.xml b/slices/core/src/main/res-public/values/strings.xml
new file mode 100644
index 0000000..d492a38
--- /dev/null
+++ b/slices/core/src/main/res-public/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="slice_provider">androidx.app.slice.compat.SliceProviderCompat</string>
+</resources>
diff --git a/slices/view/Android.mk b/slices/view/Android.mk
new file mode 100644
index 0000000..6c487d0
--- /dev/null
+++ b/slices/view/Android.mk
@@ -0,0 +1,48 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# Here is the final static library that apps can link against.
+# Applications that use this library must specify
+#
+#   LOCAL_STATIC_ANDROID_LIBRARIES := \
+#       android-slices-core \
+#       android-slices-view
+#
+# in their makefiles to include the resources and their dependencies in their package.
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_MODULE := android-slices-view
+LOCAL_MANIFEST_FILE := src/main/AndroidManifest.xml
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under,src/main/java) \
+    $(call all-Iaidl-files-under,src/main/java)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/src/main/res
+
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations \
+    android-support-v7-recyclerview \
+    android-support-v4 \
+    android-support-compat \
+    android-slices-core \
+    apptoolkit-lifecycle-extensions \
+    apptoolkit-arch-core-runtime
+
+LOCAL_SHARED_ANDROID_LIBRARIES := \
+    android-support-v7-appcompat \
+
+LOCAL_JAR_EXCLUDE_FILES := none
+LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/slices/view/api/current.txt b/slices/view/api/current.txt
new file mode 100644
index 0000000..d7ac0c5
--- /dev/null
+++ b/slices/view/api/current.txt
@@ -0,0 +1,25 @@
+package androidx.app.slice.widget {
+
+  public final class SliceLiveData {
+    ctor public SliceLiveData();
+    method public static android.arch.lifecycle.LiveData<androidx.app.slice.Slice> fromIntent(android.content.Context, android.content.Intent);
+    method public static android.arch.lifecycle.LiveData<androidx.app.slice.Slice> fromUri(android.content.Context, android.net.Uri);
+  }
+
+  public class SliceView extends android.view.ViewGroup implements android.arch.lifecycle.Observer {
+    ctor public SliceView(android.content.Context);
+    ctor public SliceView(android.content.Context, android.util.AttributeSet);
+    ctor public SliceView(android.content.Context, android.util.AttributeSet, int);
+    ctor public SliceView(android.content.Context, android.util.AttributeSet, int, int);
+    method public int getMode();
+    method public void onChanged(androidx.app.slice.Slice);
+    method public void setMode(int);
+    method public void setScrollable(boolean);
+    method public void setSlice(androidx.app.slice.Slice);
+    field public static final int MODE_LARGE = 2; // 0x2
+    field public static final int MODE_SHORTCUT = 3; // 0x3
+    field public static final int MODE_SMALL = 1; // 0x1
+  }
+
+}
+
diff --git a/slices/view/build.gradle b/slices/view/build.gradle
new file mode 100644
index 0000000..35d5e93
--- /dev/null
+++ b/slices/view/build.gradle
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+import static android.support.dependencies.DependenciesKt.*
+import android.support.LibraryVersions
+import android.support.LibraryGroups
+
+plugins {
+    id("SupportAndroidLibraryPlugin")
+}
+
+dependencies {
+    implementation(project(":slices-core"))
+    implementation(project(":slices-builders"))
+    implementation(project(":recyclerview-v7"))
+    api(ARCH_LIFECYCLE_EXTENSIONS, libs.exclude_annotations_transitive)
+}
+
+supportLibrary {
+    name = "Slice views"
+    publish = true
+    mavenVersion = LibraryVersions.SUPPORT_LIBRARY
+    mavenGroup = LibraryGroups.SLICES
+    inceptionYear = "2017"
+    description = "A library that handles rendering of slice content into supported templates"
+    minSdkVersion = 19
+}
diff --git a/slices/view/lint-baseline.xml b/slices/view/lint-baseline.xml
new file mode 100644
index 0000000..49d372e
--- /dev/null
+++ b/slices/view/lint-baseline.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="4" by="lint 3.0.0">
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: SliceView.MODE_SMALL, SliceView.MODE_LARGE, SliceView.MODE_SHORTCUT"
+        errorLine1="        return mMode;"
+        errorLine2="               ~~~~~">
+        <location
+            file="src/main/java/androidx/app/slice/widget/SliceView.java"
+            line="290"
+            column="16"/>
+    </issue>
+
+</issues>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml b/slices/view/src/main/AndroidManifest.xml
similarity index 72%
copy from samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml
copy to slices/view/src/main/AndroidManifest.xml
index d6a1023..5e9dd17 100644
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml
+++ b/slices/view/src/main/AndroidManifest.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,8 +13,7 @@
      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">
-    <solid android:color="#FFFFFF"></solid>
-</shape>
\ No newline at end of file
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="androidx.app.slice.view">
+    <uses-sdk android:minSdkVersion="28"/>
+</manifest>
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/ActionRow.java b/slices/view/src/main/java/androidx/app/slice/widget/ActionRow.java
new file mode 100644
index 0000000..70cec4f
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/ActionRow.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import static android.app.slice.Slice.HINT_NO_TINT;
+import static android.app.slice.SliceItem.FORMAT_ACTION;
+import static android.app.slice.SliceItem.FORMAT_COLOR;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_REMOTE_INPUT;
+
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.app.RemoteInput;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.drawable.Icon;
+import android.os.AsyncTask;
+import android.support.annotation.RestrictTo;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewParent;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.function.Consumer;
+
+import androidx.app.slice.SliceItem;
+import androidx.app.slice.core.SliceQuery;
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@TargetApi(24)
+public class ActionRow extends FrameLayout {
+
+    private static final int MAX_ACTIONS = 5;
+    private final int mSize;
+    private final int mIconPadding;
+    private final LinearLayout mActionsGroup;
+    private final boolean mFullActions;
+    private int mColor = Color.BLACK;
+
+    public ActionRow(Context context, boolean fullActions) {
+        super(context);
+        mFullActions = fullActions;
+        mSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
+                context.getResources().getDisplayMetrics());
+        mIconPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12,
+                context.getResources().getDisplayMetrics());
+        mActionsGroup = new LinearLayout(context);
+        mActionsGroup.setOrientation(LinearLayout.HORIZONTAL);
+        mActionsGroup.setLayoutParams(
+                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+        addView(mActionsGroup);
+    }
+
+    private void setColor(int color) {
+        mColor = color;
+        for (int i = 0; i < mActionsGroup.getChildCount(); i++) {
+            View view = mActionsGroup.getChildAt(i);
+            SliceItem item = (SliceItem) view.getTag();
+            boolean tint = !item.hasHint(HINT_NO_TINT);
+            if (tint) {
+                ((ImageView) view).setImageTintList(ColorStateList.valueOf(mColor));
+            }
+        }
+    }
+
+    private ImageView addAction(Icon icon, boolean allowTint, SliceItem image) {
+        ImageView imageView = new ImageView(getContext());
+        imageView.setPadding(mIconPadding, mIconPadding, mIconPadding, mIconPadding);
+        imageView.setScaleType(ScaleType.FIT_CENTER);
+        imageView.setImageIcon(icon);
+        if (allowTint) {
+            imageView.setImageTintList(ColorStateList.valueOf(mColor));
+        }
+        imageView.setBackground(SliceViewUtil.getDrawable(getContext(),
+                android.R.attr.selectableItemBackground));
+        imageView.setTag(image);
+        addAction(imageView);
+        return imageView;
+    }
+
+    /**
+     * Set the actions and color for this action row.
+     */
+    public void setActions(SliceItem actionRow, SliceItem defColor) {
+        removeAllViews();
+        mActionsGroup.removeAllViews();
+        addView(mActionsGroup);
+
+        SliceItem color = SliceQuery.find(actionRow, FORMAT_COLOR);
+        if (color == null) {
+            color = defColor;
+        }
+        if (color != null) {
+            setColor(color.getColor());
+        }
+        SliceQuery.findAll(actionRow, FORMAT_ACTION).forEach(new Consumer<SliceItem>() {
+            @Override
+            public void accept(final SliceItem action) {
+                if (mActionsGroup.getChildCount() >= MAX_ACTIONS) {
+                    return;
+                }
+                SliceItem image = SliceQuery.find(action, FORMAT_IMAGE);
+                if (image == null) {
+                    return;
+                }
+                boolean tint = !image.hasHint(HINT_NO_TINT);
+                final SliceItem input = SliceQuery.find(action, FORMAT_REMOTE_INPUT);
+                if (input != null && input.getRemoteInput().getAllowFreeFormInput()) {
+                    addAction(image.getIcon(), tint, image).setOnClickListener(
+                            new OnClickListener() {
+                                @Override
+                                public void onClick(View v) {
+                                    handleRemoteInputClick(v, action.getAction(),
+                                            input.getRemoteInput());
+                                }
+                            });
+                    createRemoteInputView(mColor, getContext());
+                } else {
+                    addAction(image.getIcon(), tint, image).setOnClickListener(
+                            new OnClickListener() {
+                                @Override
+                                public void onClick(View v) {
+                                    AsyncTask.execute(new Runnable() {
+                                        @Override
+                                        public void run() {
+
+                                            try {
+                                                action.getAction().send();
+                                            } catch (CanceledException e) {
+                                                e.printStackTrace();
+                                            }
+                                        }
+                                    });
+                                }
+                            });
+                }
+            }
+        });
+        setVisibility(getChildCount() != 0 ? View.VISIBLE : View.GONE);
+    }
+
+    private void addAction(View child) {
+        mActionsGroup.addView(child, new LinearLayout.LayoutParams(mSize, mSize, 1));
+    }
+
+    private void createRemoteInputView(int color, Context context) {
+        View riv = RemoteInputView.inflate(context, this);
+        riv.setVisibility(View.INVISIBLE);
+        addView(riv, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+        riv.setBackgroundColor(color);
+    }
+
+    private boolean handleRemoteInputClick(View view, PendingIntent pendingIntent,
+            RemoteInput input) {
+        if (input == null) {
+            return false;
+        }
+
+        ViewParent p = view.getParent().getParent();
+        RemoteInputView riv = null;
+        while (p != null) {
+            if (p instanceof View) {
+                View pv = (View) p;
+                riv = findRemoteInputView(pv);
+                if (riv != null) {
+                    break;
+                }
+            }
+            p = p.getParent();
+        }
+        if (riv == null) {
+            return false;
+        }
+
+        int width = view.getWidth();
+        if (view instanceof TextView) {
+            // Center the reveal on the text which might be off-center from the TextView
+            TextView tv = (TextView) view;
+            if (tv.getLayout() != null) {
+                int innerWidth = (int) tv.getLayout().getLineWidth(0);
+                innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight();
+                width = Math.min(width, innerWidth);
+            }
+        }
+        int cx = view.getLeft() + width / 2;
+        int cy = view.getTop() + view.getHeight() / 2;
+        int w = riv.getWidth();
+        int h = riv.getHeight();
+        int r = Math.max(
+                Math.max(cx + cy, cx + (h - cy)),
+                Math.max((w - cx) + cy, (w - cx) + (h - cy)));
+
+        riv.setRevealParameters(cx, cy, r);
+        riv.setPendingIntent(pendingIntent);
+        riv.setRemoteInput(new RemoteInput[] {
+                input
+        }, input);
+        riv.focusAnimated();
+        return true;
+    }
+
+    private RemoteInputView findRemoteInputView(View v) {
+        if (v == null) {
+            return null;
+        }
+        return (RemoteInputView) v.findViewWithTag(RemoteInputView.VIEW_TAG);
+    }
+}
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/GridView.java b/slices/view/src/main/java/androidx/app/slice/widget/GridView.java
new file mode 100644
index 0000000..edccc2c
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/GridView.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import static android.app.slice.Slice.HINT_LARGE;
+import static android.app.slice.Slice.HINT_NO_TINT;
+import static android.app.slice.Slice.HINT_TITLE;
+import static android.app.slice.SliceItem.FORMAT_ACTION;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.os.AsyncTask;
+import android.support.annotation.RestrictTo;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceItem;
+import androidx.app.slice.core.SliceQuery;
+import androidx.app.slice.view.R;
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@TargetApi(24)
+public class GridView extends LinearLayout implements LargeSliceAdapter.SliceListView,
+        View.OnClickListener, SliceView.SliceModeView {
+
+    private static final String TAG = "GridView";
+
+    // TODO -- Should addRow notion to the builder so that apps could define the "see more" intent
+    private static final boolean ALLOW_SEE_MORE = false;
+
+    private static final int TITLE_TEXT_LAYOUT = R.layout.abc_slice_title;
+    private static final int TEXT_LAYOUT = R.layout.abc_slice_secondary_text;
+
+    // Max number of *just* images that can be shown in a row
+    private static final int MAX_IMAGES = 3;
+    // Max number of normal cell items that can be shown in a row
+    private static final int MAX_ALL = 5;
+
+    // Max number of text items that can show in a cell
+    private static final int MAX_CELL_TEXT = 2;
+    // Max number of text items that can show in a cell if the mode is small
+    private static final int MAX_CELL_TEXT_SMALL = 1;
+    // Max number of images that can show in a cell
+    private static final int MAX_CELL_IMAGES = 1;
+
+    private SliceItem mColorItem;
+    private boolean mIsAllImages;
+    private @SliceView.SliceMode int mSliceMode = 0;
+
+    private int mIconSize;
+    private int mLargeIconSize;
+    private int mBigPictureHeight;
+    private int mAllImagesHeight;
+
+    public GridView(Context context) {
+        this(context, null);
+    }
+
+    public GridView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        final Resources res = getContext().getResources();
+        mIconSize = res.getDimensionPixelSize(R.dimen.abc_slice_icon_size);
+        mLargeIconSize = res.getDimensionPixelSize(R.dimen.abc_slice_large_icon_size);
+        mBigPictureHeight = res.getDimensionPixelSize(R.dimen.abc_slice_grid_big_picture_height);
+        mAllImagesHeight = res.getDimensionPixelSize(R.dimen.abc_slice_grid_image_only_height);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (mIsAllImages) {
+            int count = getChildCount();
+            int height = (count == 1) ? mBigPictureHeight : mAllImagesHeight;
+            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
+            getLayoutParams().height = height;
+            for (int i = 0; i < count; i++) {
+                getChildAt(i).getLayoutParams().height = height;
+            }
+        }
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    /**
+     * Set the color for the items in this view.
+     */
+    @Override
+    public void setColor(SliceItem colorItem) {
+        mColorItem = colorItem;
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    @Override
+    public int getMode() {
+        return mSliceMode;
+    }
+
+    /**
+     * This is called when GridView is being used as a small template.
+     */
+    @Override
+    public void setSlice(Slice slice) {
+        mSliceMode = SliceView.MODE_SMALL;
+        Slice.Builder sb = new Slice.Builder(slice.getUri());
+        sb.addSubSlice(slice);
+        Slice parentSlice = sb.build();
+        populateViews(parentSlice.getItems().get(0));
+    }
+
+    /**
+     * This is called when GridView is being used as a component in a large template.
+     */
+    @Override
+    public void setSliceItem(SliceItem slice, boolean isHeader) {
+        mSliceMode = SliceView.MODE_LARGE;
+        populateViews(slice);
+    }
+
+    private void populateViews(SliceItem slice) {
+        mIsAllImages = true;
+        removeAllViews();
+        int total = 1;
+        if (FORMAT_SLICE.equals(slice.getFormat())) {
+            List<SliceItem> items = slice.getSlice().getItems();
+            // Check if it it's only one item that is a slice
+            if (items.size() == 1 && items.get(0).getFormat().equals(FORMAT_SLICE)) {
+                items = items.get(0).getSlice().getItems();
+            }
+            total = items.size();
+            for (int i = 0; i < total; i++) {
+                SliceItem item = items.get(i);
+                if (isFull()) {
+                    continue;
+                }
+                if (!addCell(item)) {
+                    mIsAllImages = false;
+                }
+            }
+        } else if (!isFull()) {
+            if (!addCell(slice)) {
+                mIsAllImages = false;
+            }
+        }
+        if (ALLOW_SEE_MORE && mIsAllImages && total > getChildCount()) {
+            addSeeMoreCount(total - getChildCount());
+        }
+    }
+
+    private void addSeeMoreCount(int numExtra) {
+        View last = getChildAt(getChildCount() - 1);
+        FrameLayout frame = new FrameLayout(getContext());
+        frame.setLayoutParams(last.getLayoutParams());
+
+        removeView(last);
+        frame.addView(last, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
+
+        TextView v = new TextView(getContext());
+        v.setTextColor(Color.WHITE);
+        v.setBackgroundColor(0x4d000000);
+        v.setText(getResources().getString(R.string.abc_slice_more_content, numExtra));
+        v.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
+        v.setGravity(Gravity.CENTER);
+        frame.addView(v, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
+
+        addView(frame);
+    }
+
+    private boolean isFull() {
+        return getChildCount() >= (mIsAllImages ? MAX_IMAGES : MAX_ALL);
+    }
+
+    /**
+     * Adds a cell to the grid view based on the provided {@link SliceItem}.
+     * @return true if this item is just an image.
+     */
+    private boolean addCell(SliceItem sliceItem) {
+        final int maxCellText = mSliceMode == SliceView.MODE_SMALL
+                ? MAX_CELL_TEXT_SMALL
+                : MAX_CELL_TEXT;
+        LinearLayout cellContainer = new LinearLayout(getContext());
+        cellContainer.setOrientation(LinearLayout.VERTICAL);
+        cellContainer.setGravity(Gravity.CENTER_HORIZONTAL);
+        final int color = mColorItem != null ? mColorItem.getColor() : -1;
+        final String format = sliceItem.getFormat();
+        if (FORMAT_SLICE.equals(format) || FORMAT_ACTION.equals(format)) {
+            // It's a slice -- try to add all the items we can to a cell.
+            List<SliceItem> items = sliceItem.getSlice().getItems();
+            SliceItem actionItem = null;
+            if (FORMAT_ACTION.equals(format)) {
+                actionItem = sliceItem;
+            }
+            if (items.size() == 1 && FORMAT_ACTION.equals(items.get(0).getFormat())) {
+                actionItem = items.get(0);
+                items = items.get(0).getSlice().getItems();
+            }
+            boolean imagesOnly = true;
+            int textCount = 0;
+            int imageCount = 0;
+            boolean added = false;
+            boolean singleItem = items.size() == 1;
+            List<SliceItem> textItems = null;
+            // In small format we display one text item and prefer titles
+            if (!singleItem && mSliceMode == SliceView.MODE_SMALL) {
+                // Get all our text items
+                textItems = items.stream().filter(new Predicate<SliceItem>() {
+                    @Override
+                    public boolean test(SliceItem s) {
+                        return FORMAT_TEXT.equals(s.getFormat());
+                    }
+                }).collect(Collectors.<SliceItem>toList());
+                // If we have more than 1 remove non-titles
+                Iterator<SliceItem> iterator = textItems.iterator();
+                while (textItems.size() > 1) {
+                    SliceItem item = iterator.next();
+                    if (!item.hasHint(HINT_TITLE)) {
+                        iterator.remove();
+                    }
+                }
+            }
+            for (int i = 0; i < items.size(); i++) {
+                SliceItem item = items.get(i);
+                final String itemFormat = item.getFormat();
+                if (textCount < maxCellText && (FORMAT_TEXT.equals(itemFormat)
+                        || FORMAT_TIMESTAMP.equals(itemFormat))) {
+                    if (textItems != null && !textItems.contains(item)) {
+                        continue;
+                    }
+                    if (addItem(item, color, cellContainer, singleItem)) {
+                        textCount++;
+                        imagesOnly = false;
+                        added = true;
+                    }
+                } else if (imageCount < MAX_CELL_IMAGES && FORMAT_IMAGE.equals(item.getFormat())) {
+                    if (addItem(item, color, cellContainer, singleItem)) {
+                        imageCount++;
+                        added = true;
+                    }
+                }
+            }
+            if (added) {
+                addView(cellContainer, new LayoutParams(0, WRAP_CONTENT, 1));
+                if (actionItem != null) {
+                    cellContainer.setTag(actionItem);
+                    makeClickable(cellContainer);
+                }
+            }
+            return imagesOnly;
+        } else if (addItem(sliceItem, color, this, true)) {
+            return FORMAT_IMAGE.equals(sliceItem.getFormat());
+        }
+        return false;
+    }
+
+    /**
+     * Adds simple items to a container. Simple items include icons, text, and timestamps.
+     * @return Whether an item was added.
+     */
+    private boolean addItem(SliceItem item, int color, ViewGroup container, boolean singleItem) {
+        final String format = item.getFormat();
+        View addedView = null;
+        if (FORMAT_TEXT.equals(format) || FORMAT_TIMESTAMP.equals(format)) {
+            boolean title = SliceQuery.hasAnyHints(item, HINT_LARGE, HINT_TITLE);
+            TextView tv = (TextView) LayoutInflater.from(getContext()).inflate(title
+                            ? TITLE_TEXT_LAYOUT : TEXT_LAYOUT, null);
+            CharSequence text = FORMAT_TIMESTAMP.equals(format)
+                    ? SliceViewUtil.getRelativeTimeString(item.getTimestamp())
+                    : item.getText();
+            tv.setText(text);
+            container.addView(tv);
+            addedView = tv;
+        } else if (FORMAT_IMAGE.equals(format)) {
+            ImageView iv = new ImageView(getContext());
+            iv.setImageIcon(item.getIcon());
+            if (color != -1 && !item.hasHint(HINT_NO_TINT)) {
+                iv.setColorFilter(color);
+            }
+            int size = mIconSize;
+            if (item.hasHint(HINT_LARGE)) {
+                iv.setScaleType(ScaleType.CENTER_CROP);
+                size = singleItem ? MATCH_PARENT : mLargeIconSize;
+            }
+            container.addView(iv, new LayoutParams(size, size));
+            addedView = iv;
+        }
+        return addedView != null;
+    }
+
+    private void makeClickable(View layout) {
+        layout.setOnClickListener(this);
+        layout.setBackground(SliceViewUtil.getDrawable(getContext(),
+                android.R.attr.selectableItemBackground));
+    }
+
+    @Override
+    public void onClick(View view) {
+        final SliceItem actionTag = (SliceItem) view.getTag();
+        if (actionTag != null && FORMAT_ACTION.equals(actionTag.getFormat())) {
+            AsyncTask.execute(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        actionTag.getAction().send();
+                    } catch (PendingIntent.CanceledException e) {
+                        Log.w(TAG, "PendingIntent for slice cannot be sent", e);
+                    }
+                }
+            });
+        }
+    }
+}
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/LargeSliceAdapter.java b/slices/view/src/main/java/androidx/app/slice/widget/LargeSliceAdapter.java
new file mode 100644
index 0000000..459723f
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/LargeSliceAdapter.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import static android.app.slice.Slice.HINT_HORIZONTAL;
+import static android.app.slice.Slice.SUBTYPE_MESSAGE;
+import static android.app.slice.Slice.SUBTYPE_SOURCE;
+import static android.app.slice.SliceItem.FORMAT_COLOR;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+
+import android.annotation.TargetApi;
+import android.app.slice.Slice;
+import android.content.Context;
+import android.support.annotation.RestrictTo;
+import android.support.v7.widget.RecyclerView;
+import android.util.ArrayMap;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import androidx.app.slice.SliceItem;
+import androidx.app.slice.core.SliceQuery;
+import androidx.app.slice.view.R;
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@TargetApi(24)
+public class LargeSliceAdapter extends RecyclerView.Adapter<LargeSliceAdapter.SliceViewHolder> {
+
+    public static final int TYPE_DEFAULT       = 1;
+    public static final int TYPE_HEADER        = 2; // TODO headers shouldn't scroll off
+    public static final int TYPE_GRID          = 3;
+    public static final int TYPE_MESSAGE       = 4;
+    public static final int TYPE_MESSAGE_LOCAL = 5;
+
+    private final IdGenerator mIdGen = new IdGenerator();
+    private final Context mContext;
+    private List<SliceWrapper> mSlices = new ArrayList<>();
+    private SliceItem mColor;
+
+    public LargeSliceAdapter(Context context) {
+        mContext = context;
+        setHasStableIds(true);
+    }
+
+    /**
+     * Set the {@link SliceItem}'s to be displayed in the adapter and the accent color.
+     */
+    public void setSliceItems(List<SliceItem> slices, SliceItem color) {
+        mColor = color;
+        mIdGen.resetUsage();
+        mSlices = slices.stream().map(new Function<SliceItem, SliceWrapper>() {
+            @Override
+            public SliceWrapper apply(SliceItem s) {
+                return new SliceWrapper(s, mIdGen);
+            }
+        }).collect(Collectors.<SliceWrapper>toList());
+        notifyDataSetChanged();
+    }
+
+    @Override
+    public SliceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        View v = inflateForType(viewType);
+        v.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+        return new SliceViewHolder(v);
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return mSlices.get(position).mType;
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return mSlices.get(position).mId;
+    }
+
+    @Override
+    public int getItemCount() {
+        return mSlices.size();
+    }
+
+    @Override
+    public void onBindViewHolder(SliceViewHolder holder, int position) {
+        SliceWrapper slice = mSlices.get(position);
+        if (holder.mSliceView != null) {
+            holder.mSliceView.setColor(mColor);
+            holder.mSliceView.setSliceItem(slice.mItem, position == 0 /* isHeader */);
+        }
+    }
+
+    private View inflateForType(int viewType) {
+        switch (viewType) {
+            case TYPE_GRID:
+                return LayoutInflater.from(mContext).inflate(R.layout.abc_slice_grid, null);
+            case TYPE_MESSAGE:
+                return LayoutInflater.from(mContext).inflate(R.layout.abc_slice_message, null);
+            case TYPE_MESSAGE_LOCAL:
+                return LayoutInflater.from(mContext).inflate(R.layout.abc_slice_message_local,
+                        null);
+        }
+        return new RowView(mContext);
+    }
+
+    protected static class SliceWrapper {
+        private final SliceItem mItem;
+        private final int mType;
+        private final long mId;
+
+        public SliceWrapper(SliceItem item, IdGenerator idGen) {
+            mItem = item;
+            mType = getFormat(item);
+            mId = idGen.getId(item);
+        }
+
+        public static int getFormat(SliceItem item) {
+            if (SUBTYPE_MESSAGE.equals(item.getSubType())) {
+                // TODO: Better way to determine me or not? Something more like Messaging style.
+                if (SliceQuery.findSubtype(item, null, SUBTYPE_SOURCE) != null) {
+                    return TYPE_MESSAGE;
+                } else {
+                    return TYPE_MESSAGE_LOCAL;
+                }
+            }
+            if (item.hasHint(HINT_HORIZONTAL)) {
+                return TYPE_GRID;
+            }
+            if (!item.hasHint(Slice.HINT_LIST_ITEM)) {
+                return TYPE_HEADER;
+            }
+            return TYPE_DEFAULT;
+        }
+    }
+
+    /**
+     * A {@link RecyclerView.ViewHolder} for presenting slices in {@link LargeSliceAdapter}.
+     */
+    public static class SliceViewHolder extends RecyclerView.ViewHolder {
+        public final SliceListView mSliceView;
+
+        public SliceViewHolder(View itemView) {
+            super(itemView);
+            mSliceView = itemView instanceof SliceListView ? (SliceListView) itemView : null;
+        }
+    }
+
+    /**
+     * View slices being displayed in {@link LargeSliceAdapter}.
+     */
+    public interface SliceListView {
+        /**
+         * Set the slice item for this view.
+         */
+        void setSliceItem(SliceItem slice, boolean isHeader);
+
+        /**
+         * Set the color for the items in this view.
+         */
+        void setColor(SliceItem color);
+    }
+
+    private static class IdGenerator {
+        private long mNextLong = 0;
+        private final ArrayMap<String, Long> mCurrentIds = new ArrayMap<>();
+        private final ArrayMap<String, Integer> mUsedIds = new ArrayMap<>();
+
+        public long getId(SliceItem item) {
+            String str = genString(item);
+            if (!mCurrentIds.containsKey(str)) {
+                mCurrentIds.put(str, mNextLong++);
+            }
+            long id = mCurrentIds.get(str);
+            int index = mUsedIds.getOrDefault(str, 0);
+            mUsedIds.put(str, index + 1);
+            return id + index * 10000;
+        }
+
+        private String genString(SliceItem item) {
+            final StringBuilder builder = new StringBuilder();
+            SliceQuery.stream(item).forEach(new Consumer<SliceItem>() {
+                @Override
+                public void accept(SliceItem i) {
+                    builder.append(i.getFormat());
+                    //i.removeHint(Slice.HINT_SELECTED);
+                    builder.append(i.getHints());
+                    switch (i.getFormat()) {
+                        case FORMAT_IMAGE:
+                            builder.append(i.getIcon());
+                            break;
+                        case FORMAT_TEXT:
+                            builder.append(i.getText());
+                            break;
+                        case FORMAT_COLOR:
+                            builder.append(i.getColor());
+                            break;
+                    }
+                }
+            });
+            return builder.toString();
+        }
+
+        public void resetUsage() {
+            mUsedIds.clear();
+        }
+    }
+}
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/LargeTemplateView.java b/slices/view/src/main/java/androidx/app/slice/widget/LargeTemplateView.java
new file mode 100644
index 0000000..eb03d91
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/LargeTemplateView.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import static android.app.slice.Slice.HINT_ACTIONS;
+import static android.app.slice.Slice.HINT_LIST;
+import static android.app.slice.Slice.HINT_LIST_ITEM;
+import static android.app.slice.Slice.HINT_PARTIAL;
+import static android.app.slice.SliceItem.FORMAT_COLOR;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.support.annotation.RestrictTo;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceItem;
+import androidx.app.slice.core.SliceQuery;
+import androidx.app.slice.view.R;
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@TargetApi(24)
+public class LargeTemplateView extends FrameLayout implements SliceView.SliceModeView {
+
+    private final LargeSliceAdapter mAdapter;
+    private final RecyclerView mRecyclerView;
+    private final int mDefaultHeight;
+    private Slice mSlice;
+    private boolean mIsScrollable;
+
+    public LargeTemplateView(Context context) {
+        super(context);
+
+        mRecyclerView = new RecyclerView(getContext());
+        mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+        mAdapter = new LargeSliceAdapter(context);
+        mRecyclerView.setAdapter(mAdapter);
+        addView(mRecyclerView);
+        mDefaultHeight = getResources().getDimensionPixelSize(R.dimen.abc_slice_large_height);
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    @Override
+    public @SliceView.SliceMode int getMode() {
+        return SliceView.MODE_LARGE;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        mRecyclerView.getLayoutParams().height = WRAP_CONTENT;
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        if (mRecyclerView.getMeasuredHeight() > width
+                || (mSlice != null && SliceQuery.hasHints(mSlice, HINT_PARTIAL))) {
+            mRecyclerView.getLayoutParams().height = width;
+        } else {
+            mRecyclerView.getLayoutParams().height = mRecyclerView.getMeasuredHeight();
+        }
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    @Override
+    public void setSlice(Slice slice) {
+        SliceItem color = SliceQuery.find(slice, FORMAT_COLOR);
+        mSlice = slice;
+        final List<SliceItem> items = new ArrayList<>();
+        final boolean[] hasHeader = new boolean[1];
+        if (SliceQuery.hasHints(slice, HINT_LIST)) {
+            addList(slice, items);
+        } else {
+            slice.getItems().forEach(new Consumer<SliceItem>() {
+                @Override
+                public void accept(SliceItem item) {
+                    if (item.hasHint(HINT_ACTIONS)) {
+                        return;
+                    } else if (FORMAT_COLOR.equals(item.getFormat())) {
+                        return;
+                    } else if (FORMAT_SLICE.equals(item.getFormat())
+                            && item.hasHint(HINT_LIST)) {
+                        addList(item.getSlice(), items);
+                    } else if (item.hasHint(HINT_LIST_ITEM)) {
+                        items.add(item);
+                    } else if (!hasHeader[0]) {
+                        hasHeader[0] = true;
+                        items.add(0, item);
+                    } else {
+                        items.add(item);
+                    }
+                }
+            });
+        }
+        mAdapter.setSliceItems(items, color);
+    }
+
+    private void addList(Slice slice, List<SliceItem> items) {
+        List<SliceItem> sliceItems = slice.getItems();
+        items.addAll(sliceItems);
+    }
+
+    /**
+     * Whether or not the content in this template should be scrollable.
+     */
+    public void setScrollable(boolean isScrollable) {
+        // TODO -- restrict / enable how much this view can show
+        mIsScrollable = isScrollable;
+    }
+}
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/MessageView.java b/slices/view/src/main/java/androidx/app/slice/widget/MessageView.java
new file mode 100644
index 0000000..e2678e1
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/MessageView.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import static android.app.slice.Slice.SUBTYPE_SOURCE;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.RestrictTo;
+import android.text.SpannableStringBuilder;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.function.Consumer;
+
+import androidx.app.slice.SliceItem;
+import androidx.app.slice.core.SliceQuery;
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@TargetApi(24)
+public class MessageView extends LinearLayout implements LargeSliceAdapter.SliceListView {
+
+    private TextView mDetails;
+    private ImageView mIcon;
+
+    public MessageView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mDetails = findViewById(android.R.id.summary);
+        mIcon = findViewById(android.R.id.icon);
+    }
+
+    @Override
+    public void setSliceItem(SliceItem slice, boolean isHeader) {
+        SliceItem source = SliceQuery.findSubtype(slice, FORMAT_IMAGE, SUBTYPE_SOURCE);
+        if (source != null) {
+            final int iconSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                    24, getContext().getResources().getDisplayMetrics());
+            // TODO try and turn this into a drawable
+            Bitmap iconBm = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
+            Canvas iconCanvas = new Canvas(iconBm);
+            Drawable d = source.getIcon().loadDrawable(getContext());
+            d.setBounds(0, 0, iconSize, iconSize);
+            d.draw(iconCanvas);
+            mIcon.setImageBitmap(SliceViewUtil.getCircularBitmap(iconBm));
+        }
+        final SpannableStringBuilder builder = new SpannableStringBuilder();
+        SliceQuery.findAll(slice, FORMAT_TEXT).forEach(new Consumer<SliceItem>() {
+            @Override
+            public void accept(SliceItem text) {
+                if (builder.length() != 0) {
+                    builder.append('\n');
+                }
+                builder.append(text.getText());
+            }
+        });
+        mDetails.setText(builder.toString());
+    }
+
+    @Override
+    public void setColor(SliceItem color) {
+
+    }
+
+}
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/RemoteInputView.java b/slices/view/src/main/java/androidx/app/slice/widget/RemoteInputView.java
new file mode 100644
index 0000000..da35018
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/RemoteInputView.java
@@ -0,0 +1,425 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import android.animation.Animator;
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.annotation.RestrictTo;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.app.slice.view.R;
+
+/**
+ * Host for the remote input.
+ *
+ * @hide
+ */
+// TODO this should be unified with SystemUI RemoteInputView (b/67527720)
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@TargetApi(23)
+public class RemoteInputView extends LinearLayout implements View.OnClickListener, TextWatcher {
+
+    private static final String TAG = "RemoteInput";
+
+    /**
+     * A marker object that let's us easily find views of this class.
+     */
+    public static final Object VIEW_TAG = new Object();
+
+    private RemoteEditText mEditText;
+    private ImageButton mSendButton;
+    private ProgressBar mProgressBar;
+    private PendingIntent mPendingIntent;
+    private RemoteInput[] mRemoteInputs;
+    private RemoteInput mRemoteInput;
+
+    private int mRevealCx;
+    private int mRevealCy;
+    private int mRevealR;
+    private boolean mResetting;
+
+    public RemoteInputView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mProgressBar = findViewById(R.id.remote_input_progress);
+        mSendButton = findViewById(R.id.remote_input_send);
+        mSendButton.setOnClickListener(this);
+
+        mEditText = (RemoteEditText) getChildAt(0);
+        mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
+            @Override
+            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+                final boolean isSoftImeEvent = event == null
+                        && (actionId == EditorInfo.IME_ACTION_DONE
+                                || actionId == EditorInfo.IME_ACTION_NEXT
+                                || actionId == EditorInfo.IME_ACTION_SEND);
+                final boolean isKeyboardEnterKey = event != null
+                        && isConfirmKey(event.getKeyCode())
+                        && event.getAction() == KeyEvent.ACTION_DOWN;
+
+                if (isSoftImeEvent || isKeyboardEnterKey) {
+                    if (mEditText.length() > 0) {
+                        sendRemoteInput();
+                    }
+                    // Consume action to prevent IME from closing.
+                    return true;
+                }
+                return false;
+            }
+        });
+        mEditText.addTextChangedListener(this);
+        mEditText.setInnerFocusable(false);
+        mEditText.mRemoteInputView = this;
+    }
+
+    private void sendRemoteInput() {
+        Bundle results = new Bundle();
+        results.putString(mRemoteInput.getResultKey(), mEditText.getText().toString());
+        Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        RemoteInput.addResultsToIntent(mRemoteInputs, fillInIntent,
+                results);
+
+        mEditText.setEnabled(false);
+        mSendButton.setVisibility(INVISIBLE);
+        mProgressBar.setVisibility(VISIBLE);
+        mEditText.mShowImeOnInputConnection = false;
+
+        // TODO: Figure out API for telling the system about slice interaction.
+        // Tell ShortcutManager that this package has been "activated".  ShortcutManager
+        // will reset the throttling for this package.
+        // Strictly speaking, the intent receiver may be different from the intent creator,
+        // but that's an edge case, and also because we can't always know which package will receive
+        // an intent, so we just reset for the creator.
+        //getContext().getSystemService(ShortcutManager.class).onApplicationActive(
+        //        mPendingIntent.getCreatorPackage(),
+        //        getContext().getUserId());
+
+        try {
+            mPendingIntent.send(getContext(), 0, fillInIntent);
+            reset();
+        } catch (PendingIntent.CanceledException e) {
+            Log.i(TAG, "Unable to send remote input result", e);
+            Toast.makeText(getContext(), "Failure sending pending intent for inline reply :(",
+                    Toast.LENGTH_SHORT).show();
+            reset();
+        }
+    }
+
+    /**
+     * Creates a remote input view.
+     */
+    public static RemoteInputView inflate(Context context, ViewGroup root) {
+        RemoteInputView v = (RemoteInputView) LayoutInflater.from(context).inflate(
+                R.layout.abc_slice_remote_input, root, false);
+        v.setTag(VIEW_TAG);
+        return v;
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v == mSendButton) {
+            sendRemoteInput();
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        super.onTouchEvent(event);
+
+        // We never want for a touch to escape to an outer view or one we covered.
+        return true;
+    }
+
+    private void onDefocus() {
+        setVisibility(INVISIBLE);
+    }
+
+    /**
+     * Set the pending intent for remote input.
+     */
+    public void setPendingIntent(PendingIntent pendingIntent) {
+        mPendingIntent = pendingIntent;
+    }
+
+    /**
+     * Set the remote inputs for this view.
+     */
+    public void setRemoteInput(RemoteInput[] remoteInputs, RemoteInput remoteInput) {
+        mRemoteInputs = remoteInputs;
+        mRemoteInput = remoteInput;
+        mEditText.setHint(mRemoteInput.getLabel());
+    }
+
+    /**
+     * Focuses the remote input view.
+     */
+    public void focusAnimated() {
+        if (getVisibility() != VISIBLE) {
+            Animator animator = ViewAnimationUtils.createCircularReveal(
+                    this, mRevealCx, mRevealCy, 0, mRevealR);
+            animator.setDuration(200);
+            animator.start();
+        }
+        focus();
+    }
+
+    private void focus() {
+        setVisibility(VISIBLE);
+        mEditText.setInnerFocusable(true);
+        mEditText.mShowImeOnInputConnection = true;
+        mEditText.setSelection(mEditText.getText().length());
+        mEditText.requestFocus();
+        updateSendButton();
+    }
+
+    private void reset() {
+        mResetting = true;
+
+        mEditText.getText().clear();
+        mEditText.setEnabled(true);
+        mSendButton.setVisibility(VISIBLE);
+        mProgressBar.setVisibility(INVISIBLE);
+        updateSendButton();
+        onDefocus();
+
+        mResetting = false;
+    }
+
+    @Override
+    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+        if (mResetting && child == mEditText) {
+            // Suppress text events if it happens during resetting. Ideally this would be
+            // suppressed by the text view not being shown, but that doesn't work here because it
+            // needs to stay visible for the animation.
+            return false;
+        }
+        return super.onRequestSendAccessibilityEvent(child, event);
+    }
+
+    private void updateSendButton() {
+        mSendButton.setEnabled(mEditText.getText().length() != 0);
+    }
+
+    @Override
+    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+    }
+
+    @Override
+    public void onTextChanged(CharSequence s, int start, int before, int count) {
+    }
+
+    @Override
+    public void afterTextChanged(Editable s) {
+        updateSendButton();
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    public void setRevealParameters(int cx, int cy, int r) {
+        mRevealCx = cx;
+        mRevealCy = cy;
+        mRevealR = r;
+    }
+
+    @Override
+    public void dispatchStartTemporaryDetach() {
+        super.dispatchStartTemporaryDetach();
+        // Detach the EditText temporarily such that it doesn't get onDetachedFromWindow and
+        // won't lose IME focus.
+        detachViewFromParent(mEditText);
+    }
+
+    @Override
+    public void dispatchFinishTemporaryDetach() {
+        if (isAttachedToWindow()) {
+            attachViewToParent(mEditText, 0, mEditText.getLayoutParams());
+        } else {
+            removeDetachedView(mEditText, false /* animate */);
+        }
+        super.dispatchFinishTemporaryDetach();
+    }
+
+    /**
+     * An EditText that changes appearance based on whether it's focusable and becomes un-focusable
+     * whenever the user navigates away from it or it becomes invisible.
+     */
+    public static class RemoteEditText extends EditText {
+
+        private final Drawable mBackground;
+        private RemoteInputView mRemoteInputView;
+        boolean mShowImeOnInputConnection;
+
+        public RemoteEditText(Context context, AttributeSet attrs) {
+            super(context, attrs);
+            mBackground = getBackground();
+        }
+
+        private void defocusIfNeeded(boolean animate) {
+            if (mRemoteInputView != null || isTemporarilyDetached()) {
+                if (isTemporarilyDetached()) {
+                    // We might get reattached but then the other one of HUN / expanded might steal
+                    // our focus, so we'll need to save our text here.
+                }
+                return;
+            }
+            if (isFocusable() && isEnabled()) {
+                setInnerFocusable(false);
+                if (mRemoteInputView != null) {
+                    mRemoteInputView.onDefocus();
+                }
+                mShowImeOnInputConnection = false;
+            }
+        }
+
+        @Override
+        protected void onVisibilityChanged(View changedView, int visibility) {
+            super.onVisibilityChanged(changedView, visibility);
+
+            if (!isShown()) {
+                defocusIfNeeded(false /* animate */);
+            }
+        }
+
+        @Override
+        protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+            super.onFocusChanged(focused, direction, previouslyFocusedRect);
+            if (!focused) {
+                defocusIfNeeded(true /* animate */);
+            }
+        }
+
+        @Override
+        public void getFocusedRect(Rect r) {
+            super.getFocusedRect(r);
+            r.top = getScrollY();
+            r.bottom = getScrollY() + (getBottom() - getTop());
+        }
+
+        @Override
+        public boolean onKeyDown(int keyCode, KeyEvent event) {
+            if (keyCode == KeyEvent.KEYCODE_BACK) {
+                // Eat the DOWN event here to prevent any default behavior.
+                return true;
+            }
+            return super.onKeyDown(keyCode, event);
+        }
+
+        @Override
+        public boolean onKeyUp(int keyCode, KeyEvent event) {
+            if (keyCode == KeyEvent.KEYCODE_BACK) {
+                defocusIfNeeded(true /* animate */);
+                return true;
+            }
+            return super.onKeyUp(keyCode, event);
+        }
+
+        @Override
+        public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+            final InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
+
+            if (mShowImeOnInputConnection && inputConnection != null) {
+                final InputMethodManager imm = getContext().getSystemService(
+                        InputMethodManager.class);
+                if (imm != null) {
+                    // onCreateInputConnection is called by InputMethodManager in the middle of
+                    // setting up the connection to the IME; wait with requesting the IME until that
+                    // work has completed.
+                    post(new Runnable() {
+                        @Override
+                        public void run() {
+                            imm.viewClicked(RemoteEditText.this);
+                            imm.showSoftInput(RemoteEditText.this, 0);
+                        }
+                    });
+                }
+            }
+
+            return inputConnection;
+        }
+
+        @Override
+        public void onCommitCompletion(CompletionInfo text) {
+            clearComposingText();
+            setText(text.getText());
+            setSelection(getText().length());
+        }
+
+        void setInnerFocusable(boolean focusable) {
+            setFocusableInTouchMode(focusable);
+            setFocusable(focusable);
+            setCursorVisible(focusable);
+
+            if (focusable) {
+                requestFocus();
+                setBackground(mBackground);
+            } else {
+                setBackground(null);
+            }
+
+        }
+    }
+
+    /** Whether key will, by default, trigger a click on the focused view.
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    public static final boolean isConfirmKey(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+            case KeyEvent.KEYCODE_ENTER:
+            case KeyEvent.KEYCODE_SPACE:
+            case KeyEvent.KEYCODE_NUMPAD_ENTER:
+                return true;
+            default:
+                return false;
+        }
+    }
+}
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/RowView.java b/slices/view/src/main/java/androidx/app/slice/widget/RowView.java
new file mode 100644
index 0000000..b903e3b
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/RowView.java
@@ -0,0 +1,477 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import static android.app.slice.Slice.HINT_LIST;
+import static android.app.slice.Slice.HINT_LIST_ITEM;
+import static android.app.slice.Slice.HINT_NO_TINT;
+import static android.app.slice.Slice.HINT_SELECTED;
+import static android.app.slice.Slice.HINT_TITLE;
+import static android.app.slice.SliceItem.FORMAT_ACTION;
+import static android.app.slice.SliceItem.FORMAT_COLOR;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
+
+import static androidx.app.slice.core.SliceHints.EXTRA_TOGGLE_STATE;
+
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.os.AsyncTask;
+import android.support.annotation.RestrictTo;
+import android.util.Log;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.Switch;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceItem;
+import androidx.app.slice.core.SliceHints;
+import androidx.app.slice.core.SliceQuery;
+import androidx.app.slice.view.R;
+
+/**
+ * Row item is in small template format and can be used to construct list items for use
+ * with {@link LargeTemplateView}.
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@TargetApi(23)
+public class RowView extends FrameLayout implements SliceView.SliceModeView,
+        LargeSliceAdapter.SliceListView, View.OnClickListener {
+
+    private static final String TAG = "RowView";
+
+    // The number of items that fit on the right hand side of a small slice
+    private static final int MAX_END_ITEMS = 3;
+
+    private int mIconSize;
+    private int mPadding;
+
+    // If this is being used as a small template we don't allow a start item, for list items we do.
+    private boolean mAllowStartItem;
+
+    private LinearLayout mStartContainer;
+    private LinearLayout mContent;
+    private TextView mPrimaryText;
+    private TextView mSecondaryText;
+    private View mDivider;
+    private CompoundButton mToggle;
+    private LinearLayout mEndContainer;
+
+    private SliceItem mColorItem;
+    private SliceItem mRowAction;
+
+    public RowView(Context context) {
+        super(context);
+        mIconSize = getContext().getResources().getDimensionPixelSize(R.dimen.abc_slice_icon_size);
+        mPadding = getContext().getResources().getDimensionPixelSize(R.dimen.abc_slice_padding);
+        inflate(context, R.layout.abc_slice_small_template, this);
+
+        mStartContainer = (LinearLayout) findViewById(R.id.icon_frame);
+        mContent = (LinearLayout) findViewById(android.R.id.content);
+        mPrimaryText = (TextView) findViewById(android.R.id.title);
+        mSecondaryText = (TextView) findViewById(android.R.id.summary);
+        mDivider = findViewById(R.id.divider);
+        mEndContainer = (LinearLayout) findViewById(android.R.id.widget_frame);
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    @Override
+    public @SliceView.SliceMode int getMode() {
+        return SliceView.MODE_SMALL;
+    }
+
+    @Override
+    public void setColor(SliceItem color) {
+        mColorItem = color;
+    }
+
+    /**
+     * This is called when RowView is being used as a component in a large template.
+     */
+    @Override
+    public void setSliceItem(SliceItem slice, boolean isHeader) {
+        mAllowStartItem = !isHeader; // Headers don't show start items
+        populateViews(slice, slice);
+    }
+
+    /**
+     * This is called when RowView is being used as a small template.
+     */
+    @Override
+    public void setSlice(Slice slice) {
+        mAllowStartItem = false;
+        Slice.Builder sb = new Slice.Builder(slice.getUri());
+        sb.addSubSlice(slice);
+        Slice parentSlice = sb.build();
+        populateViews(parentSlice.getItems().get(0), getHeaderItem(slice));
+    }
+
+    private SliceItem getHeaderItem(Slice slice) {
+        List<SliceItem> items = slice.getItems();
+        // See if a header is specified
+        SliceItem header = SliceQuery.find(slice, FORMAT_SLICE, null, HINT_LIST_ITEM);
+        if (header != null) {
+            return header;
+        }
+        // Otherwise use the first non-color item and use it if it's a slice
+        SliceItem firstSlice = null;
+        for (int i = 0; i < items.size(); i++) {
+            if (!FORMAT_COLOR.equals(items.get(i).getFormat())) {
+                firstSlice = items.get(i);
+                break;
+            }
+        }
+        if (firstSlice != null && FORMAT_SLICE.equals(firstSlice.getFormat())) {
+            // Check if this slice is appropriate to use to populate small template
+            if (firstSlice.hasHint(HINT_LIST)) {
+                // Check for header, use that if it exists
+                SliceItem listHeader = SliceQuery.find(firstSlice, FORMAT_SLICE,
+                        null,
+                        new String[] {
+                                HINT_LIST_ITEM, HINT_LIST
+                        });
+                if (listHeader != null) {
+                    return SliceQuery.findFirstSlice(listHeader);
+                } else {
+                    // Otherwise use the first list item
+                    SliceItem newFirst = firstSlice.getSlice().getItems().get(0);
+                    return SliceQuery.findFirstSlice(newFirst);
+                }
+            } else {
+                // Not a list, find first slice with non-slice children
+                return SliceQuery.findFirstSlice(firstSlice);
+            }
+        }
+        // Fallback, just use this and convert to SliceItem type slice
+        Slice.Builder sb = new Slice.Builder(slice.getUri());
+        Slice s = sb.addSubSlice(slice).build();
+        return s.getItems().get(0);
+    }
+
+    @TargetApi(24)
+    private void populateViews(SliceItem fullSlice, SliceItem sliceItem) {
+        resetViews();
+        ArrayList<SliceItem> items = new ArrayList<>();
+        if (FORMAT_SLICE.equals(sliceItem.getFormat())) {
+            items = new ArrayList<>(sliceItem.getSlice().getItems());
+        } else {
+            items.add(sliceItem);
+        }
+
+        // These are the things that can go in our small template
+        SliceItem startItem = null;
+        SliceItem titleItem = null;
+        SliceItem subTitle = null;
+        ArrayList<SliceItem> endItems = new ArrayList<>();
+
+        // If the first item is an action let's check if it should be used to populate the content
+        // or if it should be in the start position.
+        SliceItem firstSlice = items.size() > 0 ? items.get(0) : null;
+        if (firstSlice != null && FORMAT_ACTION.equals(firstSlice.getFormat())) {
+            if (!SliceQuery.isSimpleAction(firstSlice)) {
+                mRowAction = firstSlice;
+                items.remove(0);
+                // Populating with first action, bias to use slice associated with this action
+                items.addAll(0, mRowAction.getSlice().getItems());
+            }
+        }
+
+        // Look through our items and try to figure out main content
+        for (int i = 0; i < items.size(); i++) {
+            SliceItem item = items.get(i);
+            List<String> hints = item.getHints();
+            String itemType = item.getFormat();
+            if (i == 0 && SliceQuery.isStartType((item))) {
+                startItem = item;
+            } else if (hints.contains(HINT_TITLE)) {
+                // Things with these hints could go in the title / start position
+                if ((startItem == null || !startItem.hasHint(HINT_TITLE))
+                        && SliceQuery.isStartType(item)) {
+                    startItem = item;
+                } else if ((titleItem == null || !titleItem.hasHint(HINT_TITLE))
+                        && FORMAT_TEXT.equals(itemType)) {
+                    titleItem = item;
+                } else {
+                    endItems.add(item);
+                }
+            } else if (FORMAT_TEXT.equals(item.getFormat())) {
+                if (titleItem == null) {
+                    titleItem = item;
+                } else if (subTitle == null) {
+                    subTitle = item;
+                } else {
+                    endItems.add(item);
+                }
+            } else if (FORMAT_SLICE.equals(item.getFormat())) {
+                List<SliceItem> subItems = item.getSlice().getItems();
+                for (int j = 0; j < subItems.size(); j++) {
+                    endItems.add(subItems.get(j));
+                }
+            } else {
+                endItems.add(item);
+            }
+        }
+
+        SliceItem colorItem = SliceQuery.find(fullSlice, FORMAT_COLOR);
+        int color = colorItem != null
+                ? colorItem.getColor()
+                : (mColorItem != null)
+                        ? mColorItem.getColor()
+                        : -1;
+        // Populate main part of the template
+        if (startItem != null) {
+            if (mAllowStartItem) {
+                startItem = addItem(startItem, color, mStartContainer, 0 /* padding */)
+                        ? startItem
+                        : null;
+                if (startItem != null) {
+                    endItems.remove(startItem);
+                }
+            } else {
+                startItem = null;
+                endItems.add(0, startItem);
+            }
+        }
+        mStartContainer.setVisibility(startItem != null ? View.VISIBLE : View.GONE);
+        if (titleItem != null) {
+            mPrimaryText.setText(titleItem.getText());
+        }
+        mPrimaryText.setVisibility(titleItem != null ? View.VISIBLE : View.GONE);
+        if (subTitle != null) {
+            mSecondaryText.setText(subTitle.getText());
+        }
+        mSecondaryText.setVisibility(subTitle != null ? View.VISIBLE : View.GONE);
+
+        // Figure out what end items we're showing
+        // If we're showing an action in this row check if it's a toggle
+        if (mRowAction != null && SliceQuery.hasHints(mRowAction.getSlice(),
+                SliceHints.SUBTYPE_TOGGLE) && addToggle(mRowAction, color)) {
+            // Can't show more end actions if we have a toggle so we're done
+            makeClickable(this);
+            return;
+        }
+        // Check if we have a toggle somewhere in our end items
+        SliceItem toggleItem = endItems.stream()
+                .filter(new Predicate<SliceItem>() {
+                    @Override
+                    public boolean test(SliceItem item) {
+                        if (item == null) {
+                            return false;
+                        }
+                        return FORMAT_ACTION.equals(item.getFormat())
+                                && SliceQuery.hasHints(item.getSlice(), SliceHints.SUBTYPE_TOGGLE);
+                    }
+                })
+                .findFirst().orElse(null);
+        if (toggleItem != null) {
+            if (addToggle(toggleItem, color)) {
+                mDivider.setVisibility(mRowAction != null ? View.VISIBLE : View.GONE);
+                makeClickable(mRowAction != null ? mContent : this);
+                // Can't show more end actions if we have a toggle so we're done
+                return;
+            }
+        }
+        boolean clickableEndItem = false;
+        int itemCount = 0;
+        for (int i = 0; i < endItems.size(); i++) {
+            SliceItem item = endItems.get(i);
+            if (item == null) {
+                // do nothing
+            } else if (itemCount <= MAX_END_ITEMS) {
+                if (FORMAT_ACTION.equals(item.getFormat())
+                        && itemCount == 0
+                        && SliceQuery.hasHints(item.getSlice(), SliceHints.SUBTYPE_TOGGLE)
+                        && addToggle(item, color)) {
+                    // If a toggle is added we're done
+                    break;
+                } else if (addItem(item, color, mEndContainer, mPadding)) {
+                    itemCount++;
+                }
+            }
+        }
+        if (mRowAction != null) {
+            makeClickable(clickableEndItem ? mContent : this);
+        }
+    }
+
+    /**
+     * @return Whether a toggle was added.
+     */
+    private boolean addToggle(final SliceItem toggleItem, int color) {
+        if (!FORMAT_ACTION.equals(toggleItem.getFormat())
+                || !SliceQuery.hasHints(toggleItem.getSlice(), SliceHints.SUBTYPE_TOGGLE)) {
+            return false;
+        }
+
+        // Check if this is a custom toggle
+        Icon checkedIcon = null;
+        List<SliceItem> sliceItems = toggleItem.getSlice().getItems();
+        if (sliceItems.size() > 0) {
+            checkedIcon = FORMAT_IMAGE.equals(sliceItems.get(0).getFormat())
+                    ? sliceItems.get(0).getIcon()
+                    : null;
+        }
+        if (checkedIcon != null) {
+            if (color != -1) {
+                // TODO - Should these be tinted? What if the app wants diff colors per state?
+                checkedIcon.setTint(color);
+            }
+            mToggle = new ToggleButton(getContext());
+            ((ToggleButton) mToggle).setTextOff("");
+            ((ToggleButton) mToggle).setTextOn("");
+            mToggle.setBackground(checkedIcon.loadDrawable(getContext()));
+            mEndContainer.addView(mToggle);
+            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mToggle.getLayoutParams();
+            lp.width = mIconSize;
+            lp.height = mIconSize;
+        } else {
+            mToggle = new Switch(getContext());
+            mEndContainer.addView(mToggle);
+        }
+        mToggle.setChecked(SliceQuery.hasHints(toggleItem.getSlice(), HINT_SELECTED));
+        mToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                try {
+                    PendingIntent pi = toggleItem.getAction();
+                    Intent i = new Intent().putExtra(EXTRA_TOGGLE_STATE, isChecked);
+                    pi.send(getContext(), 0, i, null, null);
+                } catch (CanceledException e) {
+                    mToggle.setSelected(!isChecked);
+                }
+            }
+        });
+        return true;
+    }
+
+    /**
+     * Adds simple items to a container. Simple items include actions with icons, images, or
+     * timestamps.
+     *
+     * @return Whether an item was added to the view.
+     */
+    private boolean addItem(SliceItem sliceItem, int color, LinearLayout container, int padding) {
+        SliceItem image = null;
+        SliceItem action = null;
+        SliceItem timeStamp = null;
+        if (FORMAT_ACTION.equals(sliceItem.getFormat())
+                && !sliceItem.hasHint(SliceHints.SUBTYPE_TOGGLE)) {
+            image = SliceQuery.find(sliceItem.getSlice(), FORMAT_IMAGE);
+            timeStamp = SliceQuery.find(sliceItem.getSlice(), FORMAT_TIMESTAMP);
+            action = sliceItem;
+        } else if (FORMAT_IMAGE.equals(sliceItem.getFormat())) {
+            image = sliceItem;
+        } else if (FORMAT_TIMESTAMP.equals(sliceItem.getFormat())) {
+            timeStamp = sliceItem;
+        }
+        View addedView = null;
+        if (image != null) {
+            ImageView iv = new ImageView(getContext());
+            iv.setImageIcon(image.getIcon());
+            if (color != -1 && !sliceItem.hasHint(HINT_NO_TINT)) {
+                iv.setColorFilter(color);
+            }
+            container.addView(iv);
+            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) iv.getLayoutParams();
+            lp.width = mIconSize;
+            lp.height = mIconSize;
+            lp.setMarginStart(padding);
+            addedView = iv;
+        } else if (timeStamp != null) {
+            TextView tv = new TextView(getContext());
+            tv.setText(SliceViewUtil.getRelativeTimeString(sliceItem.getTimestamp()));
+            container.addView(tv);
+            addedView = tv;
+        }
+        if (action != null && addedView != null) {
+            final SliceItem sliceAction = action;
+            addedView.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    AsyncTask.execute(new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                sliceAction.getAction().send();
+                            } catch (CanceledException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    });
+                }
+            });
+            addedView.setBackground(SliceViewUtil.getDrawable(getContext(),
+                    android.R.attr.selectableItemBackground));
+        }
+        return addedView != null;
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (mRowAction != null && FORMAT_ACTION.equals(mRowAction.getFormat())) {
+            // Check for a row action
+            AsyncTask.execute(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        mRowAction.getAction().send();
+                    } catch (CanceledException e) {
+                        Log.w(TAG, "PendingIntent for slice cannot be sent", e);
+                    }
+                }
+            });
+        } else if (mToggle != null) {
+            // Or no row action so let's just toggle if we've got one
+            mToggle.toggle();
+        }
+    }
+
+    private void makeClickable(View layout) {
+        layout.setOnClickListener(this);
+        layout.setBackground(SliceViewUtil.getDrawable(getContext(),
+                android.R.attr.selectableItemBackground));
+    }
+
+    private void resetViews() {
+        mStartContainer.removeAllViews();
+        mEndContainer.removeAllViews();
+        mPrimaryText.setText(null);
+        mSecondaryText.setText(null);
+        mDivider.setVisibility(View.GONE);
+    }
+}
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/ShortcutView.java b/slices/view/src/main/java/androidx/app/slice/widget/ShortcutView.java
new file mode 100644
index 0000000..5a9890b
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/ShortcutView.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import static android.app.slice.Slice.HINT_LARGE;
+import static android.app.slice.Slice.HINT_TITLE;
+import static android.app.slice.Slice.SUBTYPE_SOURCE;
+import static android.app.slice.SliceItem.FORMAT_ACTION;
+import static android.app.slice.SliceItem.FORMAT_COLOR;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.OvalShape;
+import android.net.Uri;
+import android.support.annotation.RestrictTo;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceItem;
+import androidx.app.slice.core.SliceQuery;
+import androidx.app.slice.view.R;
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@TargetApi(23)
+public class ShortcutView extends FrameLayout implements SliceView.SliceModeView {
+
+    private static final String TAG = "ShortcutView";
+
+    private Uri mUri;
+    private PendingIntent mAction;
+    private SliceItem mLabel;
+    private SliceItem mIcon;
+
+    private int mLargeIconSize;
+    private int mSmallIconSize;
+
+    public ShortcutView(Context context) {
+        super(context);
+        final Resources res = getResources();
+        mSmallIconSize = res.getDimensionPixelSize(R.dimen.abc_slice_icon_size);
+        mLargeIconSize = res.getDimensionPixelSize(R.dimen.abc_slice_shortcut_size);
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    @Override
+    public void setSlice(Slice slice) {
+        mLabel = null;
+        mIcon = null;
+        mAction = null;
+        removeAllViews();
+        determineShortcutItems(getContext(), slice);
+        SliceItem colorItem = SliceQuery.find(slice, FORMAT_COLOR);
+        if (colorItem == null) {
+            colorItem = SliceQuery.find(slice, FORMAT_COLOR);
+        }
+        // TODO: pick better default colour
+        final int color = colorItem != null ? colorItem.getColor() : Color.GRAY;
+        ShapeDrawable circle = new ShapeDrawable(new OvalShape());
+        circle.setTint(color);
+        setBackground(circle);
+        if (mIcon != null) {
+            final boolean isLarge = mIcon.hasHint(HINT_LARGE)
+                    || SUBTYPE_SOURCE.equals(mIcon.getSubType());
+            final int iconSize = isLarge ? mLargeIconSize : mSmallIconSize;
+            SliceViewUtil.createCircledIcon(getContext(), color, iconSize, mIcon.getIcon(),
+                    isLarge, this /* parent */);
+            mUri = slice.getUri();
+            setClickable(true);
+        } else {
+            setClickable(false);
+        }
+    }
+
+    @Override
+    public @SliceView.SliceMode int getMode() {
+        return SliceView.MODE_SHORTCUT;
+    }
+
+    @Override
+    public boolean performClick() {
+        if (!callOnClick()) {
+            try {
+                if (mAction != null) {
+                    mAction.send();
+                } else {
+                    Intent intent = new Intent(Intent.ACTION_VIEW).setData(mUri);
+                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    getContext().startActivity(intent);
+                }
+            } catch (CanceledException e) {
+                e.printStackTrace();
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Looks at the slice and determines which items are best to use to compose the shortcut.
+     */
+    private void determineShortcutItems(Context context, Slice slice) {
+        SliceItem titleItem = SliceQuery.find(slice, FORMAT_ACTION,
+                HINT_TITLE, null);
+
+        if (titleItem != null) {
+            // Preferred case: hinted action containing hinted image and text
+            mAction = titleItem.getAction();
+            mIcon = SliceQuery.find(titleItem.getSlice(), FORMAT_IMAGE, HINT_TITLE,
+                    null);
+            mLabel = SliceQuery.find(titleItem.getSlice(), FORMAT_TEXT, HINT_TITLE,
+                    null);
+        } else {
+            // No hinted action; just use the first one
+            SliceItem actionItem = SliceQuery.find(slice, FORMAT_ACTION, (String) null,
+                    null);
+            mAction = (actionItem != null) ? actionItem.getAction() : null;
+        }
+        // First fallback: any hinted image and text
+        if (mIcon == null) {
+            mIcon = SliceQuery.find(slice, FORMAT_IMAGE, HINT_TITLE,
+                    null);
+        }
+        if (mLabel == null) {
+            mLabel = SliceQuery.find(slice, FORMAT_TEXT, HINT_TITLE,
+                    null);
+        }
+        // Second fallback: first image and text
+        if (mIcon == null) {
+            mIcon = SliceQuery.find(slice, FORMAT_IMAGE, (String) null,
+                    null);
+        }
+        if (mLabel == null) {
+            mLabel = SliceQuery.find(slice, FORMAT_TEXT, (String) null,
+                    null);
+        }
+        // Final fallback: use app info
+        if (mIcon == null || mLabel == null || mAction == null) {
+            PackageManager pm = context.getPackageManager();
+            ProviderInfo providerInfo = pm.resolveContentProvider(
+                    slice.getUri().getAuthority(), 0);
+            ApplicationInfo appInfo = providerInfo.applicationInfo;
+            if (appInfo != null) {
+                if (mIcon == null) {
+                    Slice.Builder sb = new Slice.Builder(slice.getUri());
+                    Drawable icon = pm.getApplicationIcon(appInfo);
+                    sb.addIcon(SliceViewUtil.createIconFromDrawable(icon), HINT_LARGE);
+                    mIcon = sb.build().getItems().get(0);
+                }
+                if (mLabel == null) {
+                    Slice.Builder sb = new Slice.Builder(slice.getUri());
+                    sb.addText(pm.getApplicationLabel(appInfo), null);
+                    mLabel = sb.build().getItems().get(0);
+                }
+                if (mAction == null) {
+                    mAction = PendingIntent.getActivity(context, 0,
+                            pm.getLaunchIntentForPackage(appInfo.packageName), 0);
+                }
+            }
+        }
+    }
+}
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/SliceLiveData.java b/slices/view/src/main/java/androidx/app/slice/widget/SliceLiveData.java
new file mode 100644
index 0000000..9b36ee1
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/SliceLiveData.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import android.arch.lifecycle.LiveData;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.support.annotation.NonNull;
+
+import androidx.app.slice.Slice;
+
+/**
+ * Class with factory methods for creating LiveData that observes slices.
+ *
+ * @see #fromUri(Context, Uri)
+ * @see LiveData
+ */
+public final class SliceLiveData {
+
+    /**
+     * Produces an {@link LiveData} that tracks a Slice for a given Uri. To use
+     * this method your app must have the permission to the slice Uri or hold
+     * {@link android.Manifest.permission#BIND_SLICE}).
+     */
+    public static LiveData<Slice> fromUri(Context context, Uri uri) {
+        return new SliceLiveDataImpl(context.getApplicationContext(), uri);
+    }
+
+    /**
+     * Produces an {@link LiveData} that tracks a Slice for a given Intent. To use
+     * this method your app must have the permission to the slice Uri or hold
+     * {@link android.Manifest.permission#BIND_SLICE}).
+     */
+    public static LiveData<Slice> fromIntent(@NonNull Context context, @NonNull Intent intent) {
+        return new SliceLiveDataImpl(context.getApplicationContext(), intent);
+    }
+
+    private static class SliceLiveDataImpl extends LiveData<Slice> {
+        private final Context mContext;
+        private final Intent mIntent;
+        private Uri mUri;
+
+        private SliceLiveDataImpl(Context context, Uri uri) {
+            super();
+            mContext = context;
+            mUri = uri;
+            mIntent = null;
+            // TODO: Check if uri points at a Slice?
+        }
+
+        private SliceLiveDataImpl(Context context, Intent intent) {
+            super();
+            mContext = context;
+            mUri = null;
+            mIntent = intent;
+        }
+
+        @Override
+        protected void onActive() {
+            AsyncTask.execute(mUpdateSlice);
+            if (mUri != null) {
+                mContext.getContentResolver().registerContentObserver(mUri, false, mObserver);
+            }
+        }
+
+        @Override
+        protected void onInactive() {
+            if (mUri != null) {
+                mContext.getContentResolver().unregisterContentObserver(mObserver);
+            }
+        }
+
+        private final Runnable mUpdateSlice = new Runnable() {
+            @Override
+            public void run() {
+                Slice s = mUri != null ? Slice.bindSlice(mContext, mUri)
+                        : Slice.bindSlice(mContext, mIntent);
+                if (mUri == null && s != null) {
+                    mContext.getContentResolver().registerContentObserver(s.getUri(),
+                            false, mObserver);
+                    mUri = s.getUri();
+                }
+                postValue(s);
+            }
+        };
+
+        private final ContentObserver mObserver = new ContentObserver(new Handler()) {
+            @Override
+            public void onChange(boolean selfChange) {
+                AsyncTask.execute(mUpdateSlice);
+            }
+        };
+    }
+}
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/SliceView.java b/slices/view/src/main/java/androidx/app/slice/widget/SliceView.java
new file mode 100644
index 0000000..6a40898
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/SliceView.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import static android.app.slice.Slice.HINT_ACTIONS;
+import static android.app.slice.Slice.HINT_HORIZONTAL;
+import static android.app.slice.SliceItem.FORMAT_COLOR;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+
+import android.arch.lifecycle.Observer;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.graphics.drawable.ColorDrawable;
+import android.net.Uri;
+import android.support.annotation.IntDef;
+import android.support.annotation.Nullable;
+import android.support.annotation.RestrictTo;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.List;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceItem;
+import androidx.app.slice.core.SliceQuery;
+import androidx.app.slice.view.R;
+
+/**
+ * A view for displaying a {@link Slice} which is a piece of app content and actions. SliceView is
+ * able to present slice content in a templated format outside of the associated app. The way this
+ * content is displayed depends on the structure of the slice, the hints associated with the
+ * content, and the mode that SliceView is configured for. The modes that SliceView supports are:
+ * <ul>
+ * <li><b>Shortcut</b>: A shortcut is presented as an icon and a text label representing the main
+ * content or action associated with the slice.</li>
+ * <li><b>Small</b>: The small format has a restricted height and can present a single
+ * {@link SliceItem} or a limited collection of items.</li>
+ * <li><b>Large</b>: The large format displays multiple small templates in a list, if scrolling is
+ * not enabled (see {@link #setScrollable(boolean)}) the view will show as many items as it can
+ * comfortably fit.</li>
+ * </ul>
+ * <p>
+ * When constructing a slice, the contents of it can be annotated with hints, these provide the OS
+ * with some information on how the content should be displayed. For example, text annotated with
+ * {@link android.app.slice.Slice#HINT_TITLE} would be placed in the title position of a template.
+ * A slice annotated with {@link android.app.slice.Slice#HINT_LIST} would present the child items
+ * of that slice in a list.
+ * <p>
+ * Example usage:
+ *
+ * <pre class="prettyprint">
+ * SliceView v = new SliceView(getContext());
+ * v.setMode(desiredMode);
+ * LiveData<Slice> liveData = SliceLiveData.fromUri(sliceUri);
+ * liveData.observe(lifecycleOwner, v);
+ * </pre>
+ * @see SliceLiveData
+ */
+public class SliceView extends ViewGroup implements Observer<Slice> {
+
+    private static final String TAG = "SliceView";
+
+    /**
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    public interface SliceModeView {
+
+        /**
+         * @return the mode of the slice being presented.
+         */
+        int getMode();
+
+        /**
+         * @param slice the slice to show in this view.
+         */
+        void setSlice(Slice slice);
+
+        /**
+         * @return the view.
+         */
+        View getView();
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({
+            MODE_SMALL, MODE_LARGE, MODE_SHORTCUT
+    })
+    public @interface SliceMode {}
+
+    /**
+     * Mode indicating this slice should be presented in small template format.
+     */
+    public static final int MODE_SMALL       = 1;
+    /**
+     * Mode indicating this slice should be presented in large template format.
+     */
+    public static final int MODE_LARGE       = 2;
+    /**
+     * Mode indicating this slice should be presented as an icon. A shortcut requires an intent,
+     * icon, and label. This can be indicated by using {@link android.app.slice.Slice#HINT_TITLE}
+     * on an action in a slice.
+     */
+    public static final int MODE_SHORTCUT    = 3;
+
+    /**
+     * Will select the type of slice binding based on size of the View. TODO: Put in some info about
+     * that selection.
+     */
+    private static final int MODE_AUTO = 0;
+
+    private int mMode = MODE_AUTO;
+    private SliceModeView mCurrentView;
+    private final ActionRow mActions;
+    private Slice mCurrentSlice;
+    private boolean mShowActions = true;
+    private boolean mIsScrollable;
+    private final int mShortcutSize;
+
+    public SliceView(Context context) {
+        this(context, null);
+    }
+
+    public SliceView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SliceView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public SliceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mActions = new ActionRow(getContext(), true);
+        mActions.setBackground(new ColorDrawable(0xffeeeeee));
+        mCurrentView = new LargeTemplateView(getContext());
+        addView(mCurrentView.getView(), getChildLp(mCurrentView.getView()));
+        addView(mActions, getChildLp(mActions));
+        mShortcutSize = getContext().getResources()
+                .getDimensionPixelSize(R.dimen.abc_slice_shortcut_size);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int mode = MeasureSpec.getMode(widthMeasureSpec);
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        if (MODE_SHORTCUT == mMode) {
+            width = mShortcutSize;
+        }
+        if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.UNSPECIFIED) {
+            widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
+        }
+        measureChildren(widthMeasureSpec, heightMeasureSpec);
+        int actionHeight = mActions.getVisibility() != View.GONE
+                ? mActions.getMeasuredHeight()
+                : 0;
+        int newHeightSpec = MeasureSpec.makeMeasureSpec(
+                mCurrentView.getView().getMeasuredHeight() + actionHeight, MeasureSpec.EXACTLY);
+        setMeasuredDimension(width, newHeightSpec);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        View v = mCurrentView.getView();
+        v.layout(0, 0, v.getMeasuredWidth(),
+                v.getMeasuredHeight());
+        if (mActions.getVisibility() != View.GONE) {
+            mActions.layout(0, v.getMeasuredHeight(), mActions.getMeasuredWidth(),
+                    v.getMeasuredHeight() + mActions.getMeasuredHeight());
+        }
+    }
+
+    @Override
+    public void onChanged(@Nullable Slice slice) {
+        setSlice(slice);
+    }
+
+    /**
+     * Populates this view to the provided {@link Slice}.
+     *
+     * This will not update automatically if the slice content changes, for live
+     * content see {@link SliceLiveData}.
+     */
+    public void setSlice(@Nullable Slice slice) {
+        mCurrentSlice = slice;
+        reinflate();
+    }
+
+    /**
+     * Set the mode this view should present in.
+     */
+    public void setMode(@SliceMode int mode) {
+        setMode(mode, false /* animate */);
+    }
+
+    /**
+     * Set whether this view should allow scrollable content when presenting in {@link #MODE_LARGE}.
+     */
+    public void setScrollable(boolean isScrollable) {
+        mIsScrollable = isScrollable;
+        reinflate();
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    public void setMode(@SliceMode int mode, boolean animate) {
+        if (animate) {
+            Log.e(TAG, "Animation not supported yet");
+        }
+        mMode = mode;
+        reinflate();
+    }
+
+    /**
+     * @return the mode this view is presenting in.
+     */
+    public @SliceMode int getMode() {
+        if (mMode == MODE_AUTO) {
+            return MODE_LARGE;
+        }
+        return mMode;
+    }
+
+    /**
+     * @hide
+     *
+     * Whether this view should show a row of actions with it.
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    public void setShowActionRow(boolean show) {
+        mShowActions = show;
+        reinflate();
+    }
+
+    private SliceModeView createView(int mode) {
+        switch (mode) {
+            case MODE_SHORTCUT:
+                return new ShortcutView(getContext());
+            case MODE_SMALL:
+                // Check if it's horizontal
+                if (SliceQuery.hasHints(mCurrentSlice, HINT_HORIZONTAL)) {
+                    return new GridView(getContext());
+                } else {
+                    return new RowView(getContext());
+                }
+        }
+        return new LargeTemplateView(getContext());
+    }
+
+    private void reinflate() {
+        if (mCurrentSlice == null) {
+            return;
+        }
+        // TODO: Smarter mapping here from one state to the next.
+        SliceItem color = SliceQuery.find(mCurrentSlice, FORMAT_COLOR);
+        List<SliceItem> items = mCurrentSlice.getItems();
+        SliceItem actionRow = SliceQuery.find(mCurrentSlice, FORMAT_SLICE,
+                HINT_ACTIONS,
+                null);
+        int mode = getMode();
+        if (mMode == mCurrentView.getMode()) {
+            mCurrentView.setSlice(mCurrentSlice);
+        } else {
+            removeAllViews();
+            mCurrentView = createView(mode);
+            addView(mCurrentView.getView(), getChildLp(mCurrentView.getView()));
+            addView(mActions, getChildLp(mActions));
+        }
+        if (mode == MODE_LARGE) {
+            ((LargeTemplateView) mCurrentView).setScrollable(mIsScrollable);
+        }
+        if (items.size() > 1 || (items.size() != 0 && items.get(0) != actionRow)) {
+            mCurrentView.getView().setVisibility(View.VISIBLE);
+            mCurrentView.setSlice(mCurrentSlice);
+        } else {
+            mCurrentView.getView().setVisibility(View.GONE);
+        }
+
+        boolean showActions = mShowActions && actionRow != null
+                && mode != MODE_SHORTCUT;
+        if (showActions) {
+            mActions.setActions(actionRow, color);
+            mActions.setVisibility(View.VISIBLE);
+        } else {
+            mActions.setVisibility(View.GONE);
+        }
+    }
+
+    private LayoutParams getChildLp(View child) {
+        if (child instanceof ShortcutView) {
+            return new LayoutParams(mShortcutSize, mShortcutSize);
+        } else {
+            return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+        }
+    }
+
+    private static void validate(Uri sliceUri) {
+        if (!ContentResolver.SCHEME_CONTENT.equals(sliceUri.getScheme())) {
+            throw new RuntimeException("Invalid uri " + sliceUri);
+        }
+        if (sliceUri.getPathSegments().size() == 0) {
+            throw new RuntimeException("Invalid uri " + sliceUri);
+        }
+    }
+}
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/SliceViewUtil.java b/slices/view/src/main/java/androidx/app/slice/widget/SliceViewUtil.java
new file mode 100644
index 0000000..c98215f
--- /dev/null
+++ b/slices/view/src/main/java/androidx/app/slice/widget/SliceViewUtil.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 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 androidx.app.slice.widget;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.support.annotation.AttrRes;
+import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
+import android.support.annotation.RestrictTo;
+import android.text.format.DateUtils;
+import android.view.Gravity;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import java.util.Calendar;
+
+/**
+ * A bunch of utilities for slice UI.
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@TargetApi(23)
+public class SliceViewUtil {
+
+    /**
+     */
+    @ColorInt
+    public static int getColorAccent(@NonNull Context context) {
+        return getColorAttr(context, android.R.attr.colorAccent);
+    }
+
+    /**
+     */
+    @ColorInt
+    public static int getColorError(@NonNull Context context) {
+        return getColorAttr(context, android.R.attr.colorError);
+    }
+
+    /**
+     */
+    @ColorInt
+    public static int getDefaultColor(@NonNull Context context, int resId) {
+        final ColorStateList list = context.getResources().getColorStateList(resId,
+                context.getTheme());
+
+        return list.getDefaultColor();
+    }
+
+    /**
+     */
+    @ColorInt
+    public static int getDisabled(@NonNull Context context, int inputColor) {
+        return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor);
+    }
+
+    /**
+     */
+    @ColorInt
+    public static int applyAlphaAttr(@NonNull Context context, @AttrRes int attr, int inputColor) {
+        TypedArray ta = context.obtainStyledAttributes(new int[] {
+                attr
+        });
+        float alpha = ta.getFloat(0, 0);
+        ta.recycle();
+        return applyAlpha(alpha, inputColor);
+    }
+
+    /**
+     */
+    @ColorInt
+    public static int applyAlpha(float alpha, int inputColor) {
+        alpha *= Color.alpha(inputColor);
+        return Color.argb((int) (alpha), Color.red(inputColor), Color.green(inputColor),
+                Color.blue(inputColor));
+    }
+
+    /**
+     */
+    @ColorInt
+    public static int getColorAttr(@NonNull Context context, @AttrRes int attr) {
+        TypedArray ta = context.obtainStyledAttributes(new int[] {
+                attr
+        });
+        @ColorInt int colorAccent = ta.getColor(0, 0);
+        ta.recycle();
+        return colorAccent;
+    }
+
+    /**
+     */
+    public static int getThemeAttr(@NonNull Context context, @AttrRes int attr) {
+        TypedArray ta = context.obtainStyledAttributes(new int[] {
+                attr
+        });
+        int theme = ta.getResourceId(0, 0);
+        ta.recycle();
+        return theme;
+    }
+
+    /**
+     */
+    public static Drawable getDrawable(@NonNull Context context, @AttrRes int attr) {
+        TypedArray ta = context.obtainStyledAttributes(new int[] {
+                attr
+        });
+        Drawable drawable = ta.getDrawable(0);
+        ta.recycle();
+        return drawable;
+    }
+
+    /**
+     */
+    public static Icon createIconFromDrawable(Drawable d) {
+        if (d instanceof BitmapDrawable) {
+            return Icon.createWithBitmap(((BitmapDrawable) d).getBitmap());
+        }
+        Bitmap b = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(),
+                Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(b);
+        d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+        d.draw(canvas);
+        return Icon.createWithBitmap(b);
+    }
+
+    /**
+     */
+    @TargetApi(28)
+    public static void createCircledIcon(@NonNull Context context, int color, int iconSizePx,
+            Icon icon, boolean isLarge, ViewGroup parent) {
+        ImageView v = new ImageView(context);
+        v.setImageIcon(icon);
+        parent.addView(v);
+        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
+        if (isLarge) {
+            // XXX better way to convert from icon -> bitmap or crop an icon (?)
+            Bitmap iconBm = Bitmap.createBitmap(iconSizePx, iconSizePx, Config.ARGB_8888);
+            Canvas iconCanvas = new Canvas(iconBm);
+            v.layout(0, 0, iconSizePx, iconSizePx);
+            v.draw(iconCanvas);
+            v.setImageBitmap(getCircularBitmap(iconBm));
+        } else {
+            v.setColorFilter(Color.WHITE);
+        }
+        lp.width = iconSizePx;
+        lp.height = iconSizePx;
+        lp.gravity = Gravity.CENTER;
+    }
+
+    /**
+     */
+    public static @NonNull Bitmap getCircularBitmap(Bitmap bitmap) {
+        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
+                bitmap.getHeight(), Config.ARGB_8888);
+        Canvas canvas = new Canvas(output);
+        final Paint paint = new Paint();
+        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+        paint.setAntiAlias(true);
+        canvas.drawARGB(0, 0, 0, 0);
+        canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
+                bitmap.getWidth() / 2, paint);
+        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
+        canvas.drawBitmap(bitmap, rect, rect, paint);
+        return output;
+    }
+
+    /**
+     */
+    public static CharSequence getRelativeTimeString(long time) {
+        return DateUtils.getRelativeTimeSpanString(time, Calendar.getInstance().getTimeInMillis(),
+                DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE);
+    }
+}
diff --git a/slices/view/src/main/res/drawable/abc_ic_slice_send.xml b/slices/view/src/main/res/drawable/abc_ic_slice_send.xml
new file mode 100644
index 0000000..9c18ac8
--- /dev/null
+++ b/slices/view/src/main/res/drawable/abc_ic_slice_send.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ Copyright 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:autoMirrored="true"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M4.02,42.0L46.0,24.0 4.02,6.0 4.0,20.0l30.0,4.0 -30.0,4.0z"/>
+</vector>
\ No newline at end of file
diff --git a/slices/view/src/main/res/drawable/abc_slice_remote_input_bg.xml b/slices/view/src/main/res/drawable/abc_slice_remote_input_bg.xml
new file mode 100644
index 0000000..64ac7bf
--- /dev/null
+++ b/slices/view/src/main/res/drawable/abc_slice_remote_input_bg.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#ff6c6c6c" />
+    <corners
+        android:bottomRightRadius="16dp"
+        android:bottomLeftRadius="16dp"/>
+</shape>
diff --git a/slices/view/src/main/res/drawable/abc_slice_ripple_drawable.xml b/slices/view/src/main/res/drawable/abc_slice_ripple_drawable.xml
new file mode 100644
index 0000000..22239f3
--- /dev/null
+++ b/slices/view/src/main/res/drawable/abc_slice_ripple_drawable.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 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.
+  -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:targetApi="24"
+    android:color="?android:attr/colorControlHighlight" />
diff --git a/slices/view/src/main/res/layout-v21/abc_slice_small_template.xml b/slices/view/src/main/res/layout-v21/abc_slice_small_template.xml
new file mode 100644
index 0000000..649e39f
--- /dev/null
+++ b/slices/view/src/main/res/layout-v21/abc_slice_small_template.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="@dimen/abc_slice_row_min_height"
+    android:maxHeight="@dimen/abc_slice_row_max_height"
+    android:gravity="center_vertical"
+    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:gravity="start|center_vertical"
+        android:orientation="horizontal"
+        android:paddingEnd="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp"/>
+
+    <LinearLayout
+        android:id="@android:id/content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:gravity="center_vertical"
+        android:orientation="vertical">
+
+        <TextView android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:maxLines="2"
+            android:textAppearance="?android:attr/textAppearanceListItem" />
+
+        <TextView android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="10" />
+
+    </LinearLayout>
+
+    <View
+        android:id="@+id/divider"
+        android:layout_width="1dp"
+        android:layout_height="match_parent"
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="8dp"
+        android:background="?android:attr/listDivider"
+        android:visibility="gone"/>
+
+    <LinearLayout android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="end|center_vertical"
+        android:orientation="horizontal" />
+
+</LinearLayout>
diff --git a/slices/view/src/main/res/layout/abc_slice_grid.xml b/slices/view/src/main/res/layout/abc_slice_grid.xml
new file mode 100644
index 0000000..7e264d0
--- /dev/null
+++ b/slices/view/src/main/res/layout/abc_slice_grid.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 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.
+  -->
+<androidx.app.slice.widget.GridView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="@dimen/abc_slice_grid_image_only_height"
+    android:gravity="center_vertical"
+    android:background="?android:attr/activatedBackgroundIndicator"
+    android:clipToPadding="false">
+</androidx.app.slice.widget.GridView>
diff --git a/slices/view/src/main/res/layout/abc_slice_message.xml b/slices/view/src/main/res/layout/abc_slice_message.xml
new file mode 100644
index 0000000..29368fb
--- /dev/null
+++ b/slices/view/src/main/res/layout/abc_slice_message.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 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.
+  -->
+<androidx.app.slice.widget.MessageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingTop="12dp"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:background="?android:attr/activatedBackgroundIndicator"
+    android:clipToPadding="false">
+
+    <LinearLayout
+        android:id="@+id/abc_icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="-4dp"
+        android:gravity="start|center_vertical"
+        android:orientation="horizontal"
+        android:paddingEnd="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp">
+        <!-- TODO: Support text source -->
+        <ImageView
+            android:id="@android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:maxWidth="48dp"
+            android:maxHeight="48dp" />
+    </LinearLayout>
+
+    <TextView android:id="@android:id/summary"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignStart="@android:id/title"
+        android:textAppearance="?android:attr/textAppearanceListItem"
+        android:maxLines="10" />
+</androidx.app.slice.widget.MessageView>
diff --git a/slices/view/src/main/res/layout/abc_slice_message_local.xml b/slices/view/src/main/res/layout/abc_slice_message_local.xml
new file mode 100644
index 0000000..d35bd60
--- /dev/null
+++ b/slices/view/src/main/res/layout/abc_slice_message_local.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 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.
+  -->
+<androidx.app.slice.widget.MessageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_vertical|end"
+    android:paddingTop="12dp"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:background="?android:attr/activatedBackgroundIndicator"
+    android:clipToPadding="false">
+
+    <TextView android:id="@android:id/summary"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignStart="@android:id/title"
+        android:layout_gravity="end"
+        android:gravity="end"
+        android:padding="8dp"
+        android:textAppearance="?android:attr/textAppearanceListItem"
+        android:background="#ffeeeeee"
+        android:maxLines="10" />
+
+</androidx.app.slice.widget.MessageView>
diff --git a/slices/view/src/main/res/layout/abc_slice_remote_input.xml b/slices/view/src/main/res/layout/abc_slice_remote_input.xml
new file mode 100644
index 0000000..293c95a
--- /dev/null
+++ b/slices/view/src/main/res/layout/abc_slice_remote_input.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright 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.
+  -->
+<!-- LinearLayout -->
+<androidx.app.slice.widget.RemoteInputView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/remote_input"
+        android:background="@drawable/abc_slice_remote_input_bg"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent">
+
+    <view class="androidx.app.slice.widget.RemoteInputView$RemoteEditText"
+            android:id="@+id/remote_input_text"
+            android:layout_height="match_parent"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            android:paddingTop="2dp"
+            android:paddingBottom="4dp"
+            android:paddingStart="16dp"
+            android:paddingEnd="12dp"
+            android:gravity="start|center_vertical"
+            android:textAppearance="?android:attr/textAppearance"
+            android:textColor="#FFFFFFFF"
+            android:textColorHint="#99ffffff"
+            android:textSize="16sp"
+            android:background="@null"
+            android:singleLine="true"
+            android:ellipsize="start"
+            android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
+            android:imeOptions="actionSend|flagNoExtractUi|flagNoFullscreen" />
+
+    <FrameLayout
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_vertical">
+
+        <ImageButton
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:paddingStart="12dp"
+                android:paddingEnd="24dp"
+                android:paddingTop="16dp"
+                android:paddingBottom="16dp"
+                android:id="@+id/remote_input_send"
+                android:src="@drawable/abc_ic_slice_send"
+                android:tint="#FFFFFF"
+                android:tintMode="src_in"
+                android:background="@drawable/abc_slice_ripple_drawable" />
+
+        <ProgressBar
+                android:id="@+id/remote_input_progress"
+                android:layout_width="24dp"
+                android:layout_height="24dp"
+                android:layout_marginEnd="6dp"
+                android:layout_gravity="center"
+                android:visibility="invisible"
+                android:indeterminate="true"
+                style="?android:attr/progressBarStyleSmall" />
+
+    </FrameLayout>
+
+</androidx.app.slice.widget.RemoteInputView>
\ No newline at end of file
diff --git a/slices/view/src/main/res/layout/abc_slice_secondary_text.xml b/slices/view/src/main/res/layout/abc_slice_secondary_text.xml
new file mode 100644
index 0000000..b446ddd
--- /dev/null
+++ b/slices/view/src/main/res/layout/abc_slice_secondary_text.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright 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.
+  -->
+<!-- LinearLayout -->
+<TextView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:textColor="?android:attr/textColorSecondary"
+        android:gravity="center"
+        android:layout_height="wrap_content"
+        android:padding="4dp"
+        android:layout_width="match_parent" />
diff --git a/slices/view/src/main/res/layout/abc_slice_small_template.xml b/slices/view/src/main/res/layout/abc_slice_small_template.xml
new file mode 100644
index 0000000..e673362
--- /dev/null
+++ b/slices/view/src/main/res/layout/abc_slice_small_template.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="@dimen/abc_slice_row_min_height"
+    android:maxHeight="@dimen/abc_slice_row_max_height"
+    android:gravity="center_vertical"
+    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:gravity="start|center_vertical"
+        android:orientation="horizontal"
+        android:paddingEnd="8dp"/>
+
+    <LinearLayout
+        android:id="@android:id/content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:gravity="center_vertical"
+        android:orientation="vertical">
+
+        <TextView android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceListItem"
+            android:textColor="?android:attr/textColorPrimary"
+            android:maxLines="2"/>
+
+        <TextView android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?attr/textAppearanceListItemSecondary"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="10" />
+
+    </LinearLayout>
+
+    <View
+        android:id="@+id/divider"
+        android:layout_width="1dp"
+        android:layout_height="match_parent"
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="8dp"
+        android:background="?android:attr/listDivider"
+        android:visibility="gone"/>
+
+    <LinearLayout android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingStart="8dp"
+        android:gravity="end|center_vertical"
+        android:orientation="horizontal" />
+
+</LinearLayout>
diff --git a/slices/view/src/main/res/layout/abc_slice_title.xml b/slices/view/src/main/res/layout/abc_slice_title.xml
new file mode 100644
index 0000000..e1bdf03
--- /dev/null
+++ b/slices/view/src/main/res/layout/abc_slice_title.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright 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.
+  -->
+
+<TextView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textColor="?android:attr/textColorPrimary"
+        android:gravity="center"
+        android:layout_height="wrap_content"
+        android:padding="4dp"
+        android:layout_width="match_parent" />
diff --git a/slices/view/src/main/res/values/dimens.xml b/slices/view/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..ff2fb97
--- /dev/null
+++ b/slices/view/src/main/res/values/dimens.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 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.
+  -->
+
+<resources>
+    <!-- General -->
+    <!-- Size of normal icons / images in a slice -->
+    <dimen name="abc_slice_icon_size">24dp</dimen>
+    <!-- Size of large icons / images in a slice -->
+    <dimen name="abc_slice_large_icon_size">48dp</dimen>
+    <!-- Standard padding used in a slice -->
+    <dimen name="abc_slice_padding">16dp</dimen>
+
+    <!-- Size of a slice shortcut view -->
+    <dimen name="abc_slice_shortcut_size">56dp</dimen>
+
+    <!-- Height of a large template -->
+    <dimen name="abc_slice_large_height">240dp</dimen>
+
+    <!-- Row view sizes-->
+    <!-- Min height of row view; default size if one line of text -->
+    <dimen name="abc_slice_row_min_height">48dp</dimen>
+    <!-- Max height of row view; default size if two lines of text -->
+    <dimen name="abc_slice_row_max_height">60dp</dimen>
+    <!-- Min height of a row showing an input field that is active -->
+    <dimen name="abc_slice_row_active_input_height">120dp</dimen>
+
+    <!-- Grid view sizes-->
+    <!-- Height of a grid row displaying only images -->
+    <dimen name="abc_slice_grid_image_only_height">86dp</dimen>
+    <!-- Height of a grid row showing text and images -->
+    <dimen name="abc_slice_grid_height">120dp</dimen>
+    <!-- Height of expanded grid row if showing a single large image -->
+    <dimen name="abc_slice_grid_big_picture_height">180dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/slices/view/src/main/res/values/strings.xml b/slices/view/src/main/res/values/strings.xml
new file mode 100644
index 0000000..b72c986
--- /dev/null
+++ b/slices/view/src/main/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 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.
+  -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Format string for indicating there is more content in a slice view -->
+    <string name="abc_slice_more_content">+ <xliff:g id="number" example="5">%1$d</xliff:g></string>
+</resources>
\ No newline at end of file
diff --git a/testutils/build.gradle b/testutils/build.gradle
index 074ab34..6a340b0 100644
--- a/testutils/build.gradle
+++ b/testutils/build.gradle
@@ -32,9 +32,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
     lintOptions {
         disable 'InvalidPackage' // Lint is unhappy about junit package
     }
diff --git a/transition/Android.mk b/transition/Android.mk
index 8c76d6b..f57ca0b 100644
--- a/transition/Android.mk
+++ b/transition/Android.mk
@@ -29,8 +29,9 @@
 LOCAL_SRC_FILES := \
     $(call all-java-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-annotations \
     android-support-v4
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
diff --git a/transition/build.gradle b/transition/build.gradle
index dcf3a76..7aef8b5 100644
--- a/transition/build.gradle
+++ b/transition/build.gradle
@@ -20,10 +20,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.res.srcDirs = [
                 'res',
diff --git a/tv-provider/Android.mk b/tv-provider/Android.mk
index 9427d0d..673a350 100644
--- a/tv-provider/Android.mk
+++ b/tv-provider/Android.mk
@@ -25,9 +25,10 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := \
-    android-support-compat \
+LOCAL_JAVA_LIBRARIES := \
     android-support-annotations
+LOCAL_SHARED_ANDROID_LIBRARIES := \
+    android-support-compat
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/tv-provider/build.gradle b/tv-provider/build.gradle
index 7090108..8cb0c9e 100644
--- a/tv-provider/build.gradle
+++ b/tv-provider/build.gradle
@@ -13,12 +13,6 @@
     androidTestImplementation(TEST_RUNNER)
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 21
-    }
-}
-
 supportLibrary {
     name = "Android Support TV Provider"
     publish = true
@@ -27,4 +21,5 @@
     inceptionYear = "2017"
     description = "Android Support Library for TV Provider"
     legacySourceLocation = true
+    minSdkVersion = 21
 }
\ No newline at end of file
diff --git a/tv-provider/lint-baseline.xml b/tv-provider/lint-baseline.xml
deleted file mode 100644
index 4387a5a..0000000
--- a/tv-provider/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-beta7">
-
-</issues>
diff --git a/v13/Android.mk b/v13/Android.mk
index 1a95b75..d316032 100644
--- a/v13/Android.mk
+++ b/v13/Android.mk
@@ -33,9 +33,10 @@
 # android-support-v13, so we need to keep it static until they can be fixed.
 LOCAL_STATIC_ANDROID_LIBRARIES := \
         android-support-v4
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
-        android-support-v4 \
-        android-support-annotations
+        android-support-v4
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
 LOCAL_JAR_EXCLUDE_FILES := none
diff --git a/v13/build.gradle b/v13/build.gradle
index 425a31f..88e0bc0 100644
--- a/v13/build.gradle
+++ b/v13/build.gradle
@@ -17,10 +17,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.java.srcDirs = [
                 'java'
diff --git a/v14/preference/Android.mk b/v14/preference/Android.mk
index 4885c3e..5228624 100644
--- a/v14/preference/Android.mk
+++ b/v14/preference/Android.mk
@@ -31,12 +31,13 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-v7-preference \
     android-support-v7-appcompat \
     android-support-v7-recyclerview \
-    android-support-v4 \
-    android-support-annotations
+    android-support-v4
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/v14/preference/build.gradle b/v14/preference/build.gradle
index c129cba..5c657b1 100644
--- a/v14/preference/build.gradle
+++ b/v14/preference/build.gradle
@@ -29,10 +29,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.res.srcDir 'res'
     }
diff --git a/v4/Android.mk b/v4/Android.mk
index 84fd5c3..03ae26a 100644
--- a/v4/Android.mk
+++ b/v4/Android.mk
@@ -27,13 +27,14 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 # Some projects expect to inherit android-support-annotations from
 # android-support-v4, so we need to keep it static until they can be fixed.
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_STATIC_ANDROID_LIBRARIES := \
     android-support-compat \
     android-support-media-compat \
     android-support-core-utils \
     android-support-core-ui \
-    android-support-fragment \
-    android-support-annotations
+    android-support-fragment
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
diff --git a/v4/build.gradle b/v4/build.gradle
index ac5a9f5..0558659 100644
--- a/v4/build.gradle
+++ b/v4/build.gradle
@@ -15,7 +15,6 @@
 
 android {
     defaultConfig {
-        minSdkVersion 14
         // This disables the builds tools automatic vector -> PNG generation
         generatedDensities = []
     }
diff --git a/v7/appcompat/build.gradle b/v7/appcompat/build.gradle
index a3b80a8..106d0aa 100644
--- a/v7/appcompat/build.gradle
+++ b/v7/appcompat/build.gradle
@@ -24,7 +24,6 @@
 
 android {
     defaultConfig {
-        minSdkVersion(14)
         // This disables the builds tools automatic vector -> PNG generation
         generatedDensities = []
     }
diff --git a/v7/appcompat/res-public/values/public_attrs.xml b/v7/appcompat/res-public/values/public_attrs.xml
index 8c9f9e9..3b811ec 100644
--- a/v7/appcompat/res-public/values/public_attrs.xml
+++ b/v7/appcompat/res-public/values/public_attrs.xml
@@ -102,6 +102,7 @@
      <public type="attr" name="customNavigationLayout"/>
      <public type="attr" name="dialogPreferredPadding"/>
      <public type="attr" name="dialogTheme"/>
+     <public type="attr" name="dialogCornerRadius"/>
      <public type="attr" name="displayOptions"/>
      <public type="attr" name="divider"/>
      <public type="attr" name="dividerHorizontal"/>
diff --git a/v7/appcompat/res/drawable-v21/abc_dialog_material_background.xml b/v7/appcompat/res/drawable-v21/abc_dialog_material_background.xml
new file mode 100644
index 0000000..7ef438b
--- /dev/null
+++ b/v7/appcompat/res/drawable-v21/abc_dialog_material_background.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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="16dp"
+       android:insetTop="16dp"
+       android:insetRight="16dp"
+       android:insetBottom="16dp">
+    <shape android:shape="rectangle">
+        <corners android:radius="?attr/dialogCornerRadius" />
+        <solid android:color="@android:color/white" />
+    </shape>
+</inset>
\ No newline at end of file
diff --git a/v7/appcompat/res/drawable/abc_dialog_material_background.xml b/v7/appcompat/res/drawable/abc_dialog_material_background.xml
index 18560fc..978565b 100644
--- a/v7/appcompat/res/drawable/abc_dialog_material_background.xml
+++ b/v7/appcompat/res/drawable/abc_dialog_material_background.xml
@@ -20,7 +20,7 @@
        android:insetRight="16dp"
        android:insetBottom="16dp">
     <shape android:shape="rectangle">
-        <corners android:radius="2dp" />
+        <corners android:radius="@dimen/abc_dialog_corner_radius_material" />
         <solid android:color="@android:color/white" />
     </shape>
 </inset>
\ No newline at end of file
diff --git a/v7/appcompat/res/values-bs/strings.xml b/v7/appcompat/res/values-bs/strings.xml
index 3687875..07d1411 100644
--- a/v7/appcompat/res/values-bs/strings.xml
+++ b/v7/appcompat/res/values-bs/strings.xml
@@ -29,8 +29,8 @@
     <string name="abc_searchview_description_voice" msgid="893419373245838918">"Glasovno pretraživanje"</string>
     <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"Odaberite aplikaciju"</string>
     <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"Prikaži sve"</string>
-    <string name="abc_shareactionprovider_share_with_application" msgid="3300176832234831527">"Podijeli koristeći aplikaciju <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"Podijeli sa"</string>
+    <string name="abc_shareactionprovider_share_with_application" msgid="3300176832234831527">"Dijeli koristeći aplikaciju <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"Dijeli sa"</string>
     <string name="abc_capital_on" msgid="3405795526292276155">"UKLJUČI"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ISKLJUČI"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Pretraži"</string>
diff --git a/v7/appcompat/res/values-hi/strings.xml b/v7/appcompat/res/values-hi/strings.xml
index 3a393c7..a31ab90 100644
--- a/v7/appcompat/res/values-hi/strings.xml
+++ b/v7/appcompat/res/values-hi/strings.xml
@@ -29,8 +29,8 @@
     <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="3300176832234831527">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> के साथ साझा करें"</string>
-    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"इसके द्वारा साझा करें"</string>
+    <string name="abc_shareactionprovider_share_with_application" msgid="3300176832234831527">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> के साथ शेयर करें"</string>
+    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"इसके साथ शेयर करें"</string>
     <string name="abc_capital_on" msgid="3405795526292276155">"चालू"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"बंद"</string>
     <string name="search_menu_title" msgid="146198913615257606">"सर्च"</string>
diff --git a/v7/appcompat/res/values-ta/strings.xml b/v7/appcompat/res/values-ta/strings.xml
index 4a2ad2f..971a3db 100644
--- a/v7/appcompat/res/values-ta/strings.xml
+++ b/v7/appcompat/res/values-ta/strings.xml
@@ -18,7 +18,7 @@
     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_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_searchview_description_search" msgid="8264924765203268293">"தேடு"</string>
diff --git a/v7/appcompat/res/values-uz/strings.xml b/v7/appcompat/res/values-uz/strings.xml
index 632e0b9..0417cba 100644
--- a/v7/appcompat/res/values-uz/strings.xml
+++ b/v7/appcompat/res/values-uz/strings.xml
@@ -28,7 +28,7 @@
     <string name="abc_searchview_description_submit" msgid="8928215447528550784">"So‘rov yaratish"</string>
     <string name="abc_searchview_description_voice" msgid="893419373245838918">"Ovozli qidiruv"</string>
     <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"Dastur tanlang"</string>
-    <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"Barchasini ko‘rish"</string>
+    <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"Hammasi"</string>
     <string name="abc_shareactionprovider_share_with_application" msgid="3300176832234831527">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> orqali ulashish"</string>
     <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"Ruxsat berish"</string>
     <string name="abc_capital_on" msgid="3405795526292276155">"YONIQ"</string>
diff --git a/v7/appcompat/res/values-v28/themes_base.xml b/v7/appcompat/res/values-v28/themes_base.xml
new file mode 100644
index 0000000..7dea6d5
--- /dev/null
+++ b/v7/appcompat/res/values-v28/themes_base.xml
@@ -0,0 +1,33 @@
+<?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.
+  -->
+
+<resources>
+
+    <style name="Base.Theme.AppCompat" parent="Base.V28.Theme.AppCompat" />
+    <style name="Base.Theme.AppCompat.Light" parent="Base.V28.Theme.AppCompat.Light" />
+
+    <style name="Base.V28.Theme.AppCompat" parent="Base.V26.Theme.AppCompat">
+        <!-- We can use the platform styles on API 28+ -->
+        <item name="dialogCornerRadius">?android:attr/dialogCornerRadius</item>
+    </style>
+
+    <style name="Base.V28.Theme.AppCompat.Light" parent="Base.V26.Theme.AppCompat.Light">
+        <!-- We can use the platform styles on API 28+ -->
+        <item name="dialogCornerRadius">?android:attr/dialogCornerRadius</item>
+    </style>
+
+</resources>
diff --git a/v7/appcompat/res/values-vi/strings.xml b/v7/appcompat/res/values-vi/strings.xml
index 9587bed..4560b4b 100644
--- a/v7/appcompat/res/values-vi/strings.xml
+++ b/v7/appcompat/res/values-vi/strings.xml
@@ -19,7 +19,7 @@
     <string name="abc_action_mode_done" msgid="4076576682505996667">"Xong"</string>
     <string name="abc_action_bar_home_description" msgid="4600421777120114993">"Điều hướng về trang chủ"</string>
     <string name="abc_action_bar_up_description" msgid="1594238315039666878">"Điều hướng lên trên"</string>
-    <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"Thêm tùy chọn"</string>
+    <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"Tùy chọn khác"</string>
     <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"Thu gọn"</string>
     <string name="abc_searchview_description_search" msgid="8264924765203268293">"Tìm kiếm"</string>
     <string name="abc_search_hint" msgid="7723749260725869598">"Tìm kiếm…"</string>
diff --git a/v7/appcompat/res/values/attrs.xml b/v7/appcompat/res/values/attrs.xml
index c48b7ba..7d26a32 100644
--- a/v7/appcompat/res/values/attrs.xml
+++ b/v7/appcompat/res/values/attrs.xml
@@ -189,6 +189,8 @@
         <attr name="dialogPreferredPadding" format="dimension" />
         <!-- The list divider used in alert dialogs. -->
         <attr name="listDividerAlertDialog" format="reference" />
+        <!-- Preferred corner radius of dialogs. -->
+        <attr name="dialogCornerRadius" format="dimension" />
 
         <!-- =================== -->
         <!-- Other widget styles -->
diff --git a/v7/appcompat/res/values/dimens.xml b/v7/appcompat/res/values/dimens.xml
index 5bcd4b4..6357caa 100644
--- a/v7/appcompat/res/values/dimens.xml
+++ b/v7/appcompat/res/values/dimens.xml
@@ -75,6 +75,7 @@
     <dimen name="abc_dialog_title_divider_material">8dp</dimen>
     <dimen name="abc_dialog_list_padding_top_no_title">8dp</dimen>
     <dimen name="abc_dialog_list_padding_bottom_no_buttons">8dp</dimen>
+    <dimen name="abc_dialog_corner_radius_material">2dp</dimen>
 
     <!-- Dialog button bar height -->
     <dimen name="abc_alert_dialog_button_bar_height">48dp</dimen>
diff --git a/v7/appcompat/res/values/themes_base.xml b/v7/appcompat/res/values/themes_base.xml
index a9acfce..6b4461f 100644
--- a/v7/appcompat/res/values/themes_base.xml
+++ b/v7/appcompat/res/values/themes_base.xml
@@ -265,6 +265,7 @@
         <!-- Dialog attributes -->
         <item name="dialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>
         <item name="dialogPreferredPadding">@dimen/abc_dialog_padding_material</item>
+        <item name="dialogCornerRadius">@dimen/abc_dialog_corner_radius_material</item>
 
         <item name="alertDialogTheme">@style/ThemeOverlay.AppCompat.Dialog.Alert</item>
         <item name="alertDialogStyle">@style/AlertDialog.AppCompat</item>
@@ -435,6 +436,7 @@
         <!-- Dialog attributes -->
         <item name="dialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>
         <item name="dialogPreferredPadding">@dimen/abc_dialog_padding_material</item>
+        <item name="dialogCornerRadius">@dimen/abc_dialog_corner_radius_material</item>
 
         <item name="alertDialogTheme">@style/ThemeOverlay.AppCompat.Dialog.Alert</item>
         <item name="alertDialogStyle">@style/AlertDialog.AppCompat.Light</item>
diff --git a/v7/appcompat/src/main/java/android/support/v7/widget/TooltipCompatHandler.java b/v7/appcompat/src/main/java/android/support/v7/widget/TooltipCompatHandler.java
index 3d3c300..63a6198 100644
--- a/v7/appcompat/src/main/java/android/support/v7/widget/TooltipCompatHandler.java
+++ b/v7/appcompat/src/main/java/android/support/v7/widget/TooltipCompatHandler.java
@@ -82,10 +82,10 @@
     public static void setTooltipText(View view, CharSequence tooltipText) {
         // The code below is not attempting to update the tooltip text
         // for a pending or currently active tooltip, because it may lead
-        // to updating the wrong tooltipin in some rare cases (e.g. when
+        // to updating the wrong tooltip in in some rare cases (e.g. when
         // action menu item views are recycled). Instead, the tooltip is
         // canceled/hidden. This might still be the wrong tooltip,
-        // but hiding wrong tooltip is less disruptive UX.
+        // but hiding a wrong tooltip is less disruptive UX.
         if (sPendingHandler != null && sPendingHandler.mAnchor == view) {
             setPendingHandler(null);
         }
diff --git a/v7/cardview/Android.mk b/v7/cardview/Android.mk
index 19d377c..2d9492d 100644
--- a/v7/cardview/Android.mk
+++ b/v7/cardview/Android.mk
@@ -27,7 +27,7 @@
 LOCAL_SRC_FILES := \
     $(call all-java-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := \
+LOCAL_JAVA_LIBRARIES := \
     android-support-annotations
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
diff --git a/v7/cardview/build.gradle b/v7/cardview/build.gradle
index a6f98e1..742376d 100644
--- a/v7/cardview/build.gradle
+++ b/v7/cardview/build.gradle
@@ -10,10 +10,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion(14)
-    }
-
     sourceSets {
         main.res.srcDir("res")
     }
diff --git a/v7/gridlayout/Android.mk b/v7/gridlayout/Android.mk
index 5091081..81791da 100644
--- a/v7/gridlayout/Android.mk
+++ b/v7/gridlayout/Android.mk
@@ -29,10 +29,11 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-compat \
-    android-support-core-ui \
-    android-support-annotations
+    android-support-core-ui
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/v7/gridlayout/build.gradle b/v7/gridlayout/build.gradle
index 7df5397..ae8bac0 100644
--- a/v7/gridlayout/build.gradle
+++ b/v7/gridlayout/build.gradle
@@ -15,10 +15,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.res.srcDir 'res'
     }
diff --git a/v7/mediarouter/build.gradle b/v7/mediarouter/build.gradle
index dbf3da5..a3fd18e 100644
--- a/v7/mediarouter/build.gradle
+++ b/v7/mediarouter/build.gradle
@@ -17,10 +17,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.java.srcDirs = [
                 'jellybean',
diff --git a/v7/mediarouter/res/values-da/strings.xml b/v7/mediarouter/res/values-da/strings.xml
index 44da892..d280d2c 100644
--- a/v7/mediarouter/res/values-da/strings.xml
+++ b/v7/mediarouter/res/values-da/strings.xml
@@ -34,7 +34,7 @@
     <string name="mr_controller_collapse_group" msgid="7924809056904240926">"Skjul"</string>
     <string name="mr_controller_album_art" msgid="6422801843540543585">"Albumgrafik"</string>
     <string name="mr_controller_volume_slider" msgid="2361785992211841709">"Lydstyrkeskyder"</string>
-    <string name="mr_controller_no_media_selected" msgid="6547130360349182381">"Der er ikke valgt nogen medier"</string>
+    <string name="mr_controller_no_media_selected" msgid="6547130360349182381">"Ingen medier er markeret"</string>
     <string name="mr_controller_no_info_available" msgid="5585418471741142924">"Der er ingen tilgængelige oplysninger"</string>
     <string name="mr_controller_casting_screen" msgid="4868457957151124867">"Skærmen castes"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-eu/strings.xml b/v7/mediarouter/res/values-eu/strings.xml
index f9b9f8d..11b1d00 100644
--- a/v7/mediarouter/res/values-eu/strings.xml
+++ b/v7/mediarouter/res/values-eu/strings.xml
@@ -22,7 +22,7 @@
     <string name="mr_cast_button_disconnected" msgid="816305490427819240">"Igortzeko botoia. Deskonektatuta"</string>
     <string name="mr_cast_button_connecting" msgid="2187642765091873834">"Igortzeko botoia. Konektatzen"</string>
     <string name="mr_cast_button_connected" msgid="5088427771788648085">"Igortzeko botoia. Konektatuta"</string>
-    <string name="mr_chooser_title" msgid="414301941546135990">"Igorri hona"</string>
+    <string name="mr_chooser_title" msgid="414301941546135990">"Igorri hona:"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Gailuak bilatzen"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Deskonektatu"</string>
     <string name="mr_controller_stop_casting" msgid="8857886794086583226">"Utzi igortzeari"</string>
diff --git a/v7/mediarouter/res/values-in/strings.xml b/v7/mediarouter/res/values-in/strings.xml
index 5e537af..e76b3e8 100644
--- a/v7/mediarouter/res/values-in/strings.xml
+++ b/v7/mediarouter/res/values-in/strings.xml
@@ -18,10 +18,10 @@
     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_button_content_description" msgid="3698378085901466129">"Tombol transmisi"</string>
-    <string name="mr_cast_button_disconnected" msgid="816305490427819240">"Tombol transmisi. Terputus"</string>
-    <string name="mr_cast_button_connecting" msgid="2187642765091873834">"Tombol transmisi. Menghubungkan"</string>
-    <string name="mr_cast_button_connected" msgid="5088427771788648085">"Tombol transmisi. Terhubung"</string>
+    <string name="mr_button_content_description" msgid="3698378085901466129">"Tombol Cast"</string>
+    <string name="mr_cast_button_disconnected" msgid="816305490427819240">"Tombol Cast. Terputus"</string>
+    <string name="mr_cast_button_connecting" msgid="2187642765091873834">"Tombol Cast. Menghubungkan"</string>
+    <string name="mr_cast_button_connected" msgid="5088427771788648085">"Tombol Cast. Terhubung"</string>
     <string name="mr_chooser_title" msgid="414301941546135990">"Transmisikan ke"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"Mencari perangkat"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"Putuskan sambungan"</string>
diff --git a/v7/mediarouter/res/values-ml/strings.xml b/v7/mediarouter/res/values-ml/strings.xml
index c7b50be..62258fb 100644
--- a/v7/mediarouter/res/values-ml/strings.xml
+++ b/v7/mediarouter/res/values-ml/strings.xml
@@ -26,7 +26,7 @@
     <string name="mr_chooser_searching" msgid="6349900579507521956">"ഉപകരണങ്ങൾ കണ്ടെത്തുന്നു"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"വിച്ഛേദിക്കുക"</string>
     <string name="mr_controller_stop_casting" msgid="8857886794086583226">"കാസ്റ്റുചെയ്യൽ നിർത്തുക"</string>
-    <string name="mr_controller_close_description" msgid="7333862312480583260">"അടയ്‌ക്കുക"</string>
+    <string name="mr_controller_close_description" msgid="7333862312480583260">"അവസാനിപ്പിക്കുക"</string>
     <string name="mr_controller_play" msgid="683634565969987458">"പ്ലേ ചെയ്യുക"</string>
     <string name="mr_controller_pause" msgid="5451884435510905406">"തൽക്കാലം നിർത്തൂ"</string>
     <string name="mr_controller_stop" msgid="735874641921425123">"നിര്‍ത്തുക"</string>
diff --git a/v7/mediarouter/res/values-mr/strings.xml b/v7/mediarouter/res/values-mr/strings.xml
index 27923d1..596b56a 100644
--- a/v7/mediarouter/res/values-mr/strings.xml
+++ b/v7/mediarouter/res/values-mr/strings.xml
@@ -20,7 +20,7 @@
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"डिव्हाइसेस"</string>
     <string name="mr_button_content_description" msgid="3698378085901466129">"कास्ट बटण"</string>
     <string name="mr_cast_button_disconnected" msgid="816305490427819240">"कास्ट बटण. डिस्कनेक्ट केले"</string>
-    <string name="mr_cast_button_connecting" msgid="2187642765091873834">"कास्ट बटण. कनेक्ट करीत आहे"</string>
+    <string name="mr_cast_button_connecting" msgid="2187642765091873834">"कास्ट बटण. कनेक्ट करत आहे"</string>
     <string name="mr_cast_button_connected" msgid="5088427771788648085">"कास्ट बटण. कनेक्ट केले"</string>
     <string name="mr_chooser_title" msgid="414301941546135990">"यावर कास्ट करा"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"डिव्हाइसेस शोधत आहे"</string>
@@ -36,5 +36,5 @@
     <string name="mr_controller_volume_slider" msgid="2361785992211841709">"व्हॉल्यूम स्लायडर"</string>
     <string name="mr_controller_no_media_selected" msgid="6547130360349182381">"मीडिया निवडला नाही"</string>
     <string name="mr_controller_no_info_available" msgid="5585418471741142924">"कोणतीही माहिती उपलब्ध नाही"</string>
-    <string name="mr_controller_casting_screen" msgid="4868457957151124867">"स्क्रीन कास्‍ट करीत आहे"</string>
+    <string name="mr_controller_casting_screen" msgid="4868457957151124867">"स्क्रीन कास्‍ट करत आहे"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ta/strings.xml b/v7/mediarouter/res/values-ta/strings.xml
index 99c6172..9888472 100644
--- a/v7/mediarouter/res/values-ta/strings.xml
+++ b/v7/mediarouter/res/values-ta/strings.xml
@@ -22,7 +22,7 @@
     <string name="mr_cast_button_disconnected" msgid="816305490427819240">"அனுப்புதல் பொத்தான். துண்டிக்கப்பட்டது"</string>
     <string name="mr_cast_button_connecting" msgid="2187642765091873834">"அனுப்புதல் பொத்தான். இணைக்கிறது"</string>
     <string name="mr_cast_button_connected" msgid="5088427771788648085">"அனுப்புதல் பொத்தான். இணைக்கப்பட்டது"</string>
-    <string name="mr_chooser_title" msgid="414301941546135990">"இதில் திரையிடு"</string>
+    <string name="mr_chooser_title" msgid="414301941546135990">"இதற்கு அனுப்பு"</string>
     <string name="mr_chooser_searching" msgid="6349900579507521956">"சாதனங்களைத் தேடுகிறது"</string>
     <string name="mr_controller_disconnect" msgid="1227264889412989580">"தொடர்பைத் துண்டி"</string>
     <string name="mr_controller_stop_casting" msgid="8857886794086583226">"அனுப்புவதை நிறுத்து"</string>
diff --git a/v7/mediarouter/res/values-tr/strings.xml b/v7/mediarouter/res/values-tr/strings.xml
index a0eb2e4..8189092 100644
--- a/v7/mediarouter/res/values-tr/strings.xml
+++ b/v7/mediarouter/res/values-tr/strings.xml
@@ -18,7 +18,7 @@
     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_button_content_description" msgid="3698378085901466129">"Yayın düğmesi"</string>
+    <string name="mr_button_content_description" msgid="3698378085901466129">"Yayınla düğmesi"</string>
     <string name="mr_cast_button_disconnected" msgid="816305490427819240">"Yayınla düğmesi. Bağlantı kesildi"</string>
     <string name="mr_cast_button_connecting" msgid="2187642765091873834">"Yayınla düğmesi. Bağlanıyor"</string>
     <string name="mr_cast_button_connected" msgid="5088427771788648085">"Yayınla düğmesi. Bağlandı"</string>
diff --git a/v7/palette/Android.mk b/v7/palette/Android.mk
index f823d30..4d680cf 100644
--- a/v7/palette/Android.mk
+++ b/v7/palette/Android.mk
@@ -30,10 +30,11 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src/main)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/src/main/res
 LOCAL_MANIFEST_FILE := AndroidManifest.xml
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-compat \
-    android-support-core-utils \
-    android-support-annotations
+    android-support-core-utils
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/v7/palette/build.gradle b/v7/palette/build.gradle
index a1b1fc9..b1b12c7 100644
--- a/v7/palette/build.gradle
+++ b/v7/palette/build.gradle
@@ -13,12 +13,6 @@
     androidTestImplementation(TEST_RUNNER)
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-}
-
 supportLibrary {
     name = "Android Support Palette v7"
     publish = true
diff --git a/v7/preference/Android.mk b/v7/preference/Android.mk
index 1e3e0b6..5a3f57a 100644
--- a/v7/preference/Android.mk
+++ b/v7/preference/Android.mk
@@ -31,12 +31,14 @@
 LOCAL_SRC_FILES := \
     $(call all-java-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-v7-appcompat \
     android-support-v7-recyclerview \
-    android-support-v4 \
-    android-support-annotations
+    android-support-v4
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
+LOCAL_EXPORT_PROGUARD_FLAG_FILES := proguard-rules.pro
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/v7/preference/build.gradle b/v7/preference/build.gradle
index 698afb6..2000ddd 100644
--- a/v7/preference/build.gradle
+++ b/v7/preference/build.gradle
@@ -34,10 +34,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 14
-    }
-
     sourceSets {
         main.res.srcDirs = [
                 'res',
diff --git a/v7/recyclerview/Android.mk b/v7/recyclerview/Android.mk
index dcebe88..a62c3cd 100644
--- a/v7/recyclerview/Android.mk
+++ b/v7/recyclerview/Android.mk
@@ -29,11 +29,13 @@
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-compat \
-    android-support-core-ui \
-    android-support-annotations
+    android-support-core-ui
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
+LOCAL_EXPORT_PROGUARD_FLAG_FILES := proguard-rules.pro
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/v7/recyclerview/api/current.txt b/v7/recyclerview/api/current.txt
index 0909d7d..5064ace 100644
--- a/v7/recyclerview/api/current.txt
+++ b/v7/recyclerview/api/current.txt
@@ -258,6 +258,7 @@
     method public abstract int getEnd();
     method public abstract int getEndAfterPadding();
     method public abstract int getEndPadding();
+    method public android.support.v7.widget.RecyclerView.LayoutManager getLayoutManager();
     method public abstract int getMode();
     method public abstract int getModeInOther();
     method public abstract int getStartAfterPadding();
diff --git a/v7/recyclerview/build.gradle b/v7/recyclerview/build.gradle
index 0a83989..a14ea97 100644
--- a/v7/recyclerview/build.gradle
+++ b/v7/recyclerview/build.gradle
@@ -24,10 +24,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion(14)
-    }
-
     sourceSets {
         main.res.srcDirs "res", "res-public"
     }
diff --git a/v7/recyclerview/src/main/java/android/support/v7/widget/LinearLayoutManager.java b/v7/recyclerview/src/main/java/android/support/v7/widget/LinearLayoutManager.java
index 27df490..fe4a37a 100644
--- a/v7/recyclerview/src/main/java/android/support/v7/widget/LinearLayoutManager.java
+++ b/v7/recyclerview/src/main/java/android/support/v7/widget/LinearLayoutManager.java
@@ -48,9 +48,9 @@
 
     static final boolean DEBUG = false;
 
-    public static final int HORIZONTAL = OrientationHelper.HORIZONTAL;
+    public static final int HORIZONTAL = RecyclerView.HORIZONTAL;
 
-    public static final int VERTICAL = OrientationHelper.VERTICAL;
+    public static final int VERTICAL = RecyclerView.VERTICAL;
 
     public static final int INVALID_OFFSET = Integer.MIN_VALUE;
 
@@ -66,7 +66,7 @@
      * Current orientation. Either {@link #HORIZONTAL} or {@link #VERTICAL}
      */
     @RecyclerView.Orientation
-    int mOrientation;
+    int mOrientation = RecyclerView.DEFAULT_ORIENTATION;
 
     /**
      * Helper class that keeps temporary layout state.
@@ -78,8 +78,6 @@
     /**
      * Many calculations are made depending on orientation. To keep it clean, this interface
      * helps {@link LinearLayoutManager} make those decisions.
-     * Based on {@link #mOrientation}, an implementation is lazily created in
-     * {@link #ensureLayoutState} method.
      */
     OrientationHelper mOrientationHelper;
 
@@ -154,7 +152,7 @@
      * @param context Current context, will be used to access resources.
      */
     public LinearLayoutManager(Context context) {
-        this(context, VERTICAL, false);
+        this(context, RecyclerView.DEFAULT_ORIENTATION, false);
     }
 
     /**
@@ -335,13 +333,16 @@
         if (orientation != HORIZONTAL && orientation != VERTICAL) {
             throw new IllegalArgumentException("invalid orientation:" + orientation);
         }
+
         assertNotInLayoutOrScroll(null);
-        if (orientation == mOrientation) {
-            return;
+
+        if (orientation != mOrientation || mOrientationHelper == null) {
+            mOrientationHelper =
+                    OrientationHelper.createOrientationHelper(this, orientation);
+            mAnchorInfo.mOrientationHelper = mOrientationHelper;
+            mOrientation = orientation;
+            requestLayout();
         }
-        mOrientation = orientation;
-        mOrientationHelper = null;
-        requestLayout();
     }
 
     /**
@@ -516,7 +517,7 @@
             // TestResizingRelayoutWithAutoMeasure), which happens if we were to call
             // updateAnchorInfoForLayout for an anchor that's not the focused view (e.g. a reference
             // child which can change between layout passes).
-            mAnchorInfo.assignFromViewAndKeepVisibleRect(focused);
+            mAnchorInfo.assignFromViewAndKeepVisibleRect(focused, getPosition(focused));
         }
         if (DEBUG) {
             Log.d(TAG, "Anchor info:" + mAnchorInfo);
@@ -781,7 +782,7 @@
         }
         final View focused = getFocusedChild();
         if (focused != null && anchorInfo.isViewValidAsAnchor(focused, state)) {
-            anchorInfo.assignFromViewAndKeepVisibleRect(focused);
+            anchorInfo.assignFromViewAndKeepVisibleRect(focused, getPosition(focused));
             return true;
         }
         if (mLastStackFromEnd != mStackFromEnd) {
@@ -791,7 +792,7 @@
                 ? findReferenceChildClosestToEnd(recycler, state)
                 : findReferenceChildClosestToStart(recycler, state);
         if (referenceChild != null) {
-            anchorInfo.assignFromView(referenceChild);
+            anchorInfo.assignFromView(referenceChild, getPosition(referenceChild));
             // If all visible views are removed in 1 pass, reference child might be out of bounds.
             // If that is the case, offset it back to 0 so that we use these pre-layout children.
             if (!state.isPreLayout() && supportsPredictiveItemAnimations()) {
@@ -985,9 +986,6 @@
         if (mLayoutState == null) {
             mLayoutState = createLayoutState();
         }
-        if (mOrientationHelper == null) {
-            mOrientationHelper = OrientationHelper.createOrientationHelper(this, mOrientation);
-        }
     }
 
     /**
@@ -2370,7 +2368,8 @@
     /**
      * Simple data class to keep Anchor information
      */
-    class AnchorInfo {
+    static class AnchorInfo {
+        OrientationHelper mOrientationHelper;
         int mPosition;
         int mCoordinate;
         boolean mLayoutFromEnd;
@@ -2413,13 +2412,13 @@
                     && lp.getViewLayoutPosition() < state.getItemCount();
         }
 
-        public void assignFromViewAndKeepVisibleRect(View child) {
+        public void assignFromViewAndKeepVisibleRect(View child, int position) {
             final int spaceChange = mOrientationHelper.getTotalSpaceChange();
             if (spaceChange >= 0) {
-                assignFromView(child);
+                assignFromView(child, position);
                 return;
             }
-            mPosition = getPosition(child);
+            mPosition = position;
             if (mLayoutFromEnd) {
                 final int prevLayoutEnd = mOrientationHelper.getEndAfterPadding() - spaceChange;
                 final int childEnd = mOrientationHelper.getDecoratedEnd(child);
@@ -2460,7 +2459,7 @@
             }
         }
 
-        public void assignFromView(View child) {
+        public void assignFromView(View child, int position) {
             if (mLayoutFromEnd) {
                 mCoordinate = mOrientationHelper.getDecoratedEnd(child)
                         + mOrientationHelper.getTotalSpaceChange();
@@ -2468,7 +2467,7 @@
                 mCoordinate = mOrientationHelper.getDecoratedStart(child);
             }
 
-            mPosition = getPosition(child);
+            mPosition = position;
         }
     }
 
diff --git a/v7/recyclerview/src/main/java/android/support/v7/widget/OrientationHelper.java b/v7/recyclerview/src/main/java/android/support/v7/widget/OrientationHelper.java
index 5e90f2e..99bcbaa 100644
--- a/v7/recyclerview/src/main/java/android/support/v7/widget/OrientationHelper.java
+++ b/v7/recyclerview/src/main/java/android/support/v7/widget/OrientationHelper.java
@@ -48,6 +48,14 @@
     }
 
     /**
+     * Returns the {@link android.support.v7.widget.RecyclerView.LayoutManager LayoutManager} that
+     * is associated with this OrientationHelper.
+     */
+    public RecyclerView.LayoutManager getLayoutManager() {
+        return mLayoutManager;
+    }
+
+    /**
      * Call this method after onLayout method is complete if state is NOT pre-layout.
      * This method records information like layout bounds that might be useful in the next layout
      * calculations.
@@ -435,4 +443,4 @@
             }
         };
     }
-}
\ No newline at end of file
+}
diff --git a/v7/recyclerview/src/main/java/android/support/v7/widget/RecyclerView.java b/v7/recyclerview/src/main/java/android/support/v7/widget/RecyclerView.java
index afadfc9..4a65553 100644
--- a/v7/recyclerview/src/main/java/android/support/v7/widget/RecyclerView.java
+++ b/v7/recyclerview/src/main/java/android/support/v7/widget/RecyclerView.java
@@ -217,6 +217,7 @@
     public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
     public static final int VERTICAL = LinearLayout.VERTICAL;
 
+    static final int DEFAULT_ORIENTATION = VERTICAL;
     public static final int NO_POSITION = -1;
     public static final long NO_ID = -1;
     public static final int INVALID_TYPE = -1;
@@ -2000,7 +2001,7 @@
             }
             mEatRequestLayout = 1;
         }
-        if (!performLayoutChildren) {
+        if (!performLayoutChildren && !mLayoutFrozen) {
             // Reset the layout request eaten counter.
             // This is necessary since eatRequest calls can be nested in which case the other
             // call will override the inner one.
@@ -10121,7 +10122,7 @@
             TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecyclerView,
                     defStyleAttr, defStyleRes);
             properties.orientation = a.getInt(R.styleable.RecyclerView_android_orientation,
-                    VERTICAL);
+                    DEFAULT_ORIENTATION);
             properties.spanCount = a.getInt(R.styleable.RecyclerView_spanCount, 1);
             properties.reverseLayout = a.getBoolean(R.styleable.RecyclerView_reverseLayout, false);
             properties.stackFromEnd = a.getBoolean(R.styleable.RecyclerView_stackFromEnd, false);
diff --git a/v7/recyclerview/src/main/java/android/support/v7/widget/StaggeredGridLayoutManager.java b/v7/recyclerview/src/main/java/android/support/v7/widget/StaggeredGridLayoutManager.java
index f3ea045..55fb14e 100644
--- a/v7/recyclerview/src/main/java/android/support/v7/widget/StaggeredGridLayoutManager.java
+++ b/v7/recyclerview/src/main/java/android/support/v7/widget/StaggeredGridLayoutManager.java
@@ -59,9 +59,9 @@
 
     static final boolean DEBUG = false;
 
-    public static final int HORIZONTAL = OrientationHelper.HORIZONTAL;
+    public static final int HORIZONTAL = RecyclerView.HORIZONTAL;
 
-    public static final int VERTICAL = OrientationHelper.VERTICAL;
+    public static final int VERTICAL = RecyclerView.VERTICAL;
 
     /**
      * Does not do anything to hide gaps.
diff --git a/v7/recyclerview/tests/Android.mk b/v7/recyclerview/tests/Android.mk
deleted file mode 100644
index c6299d7..0000000
--- a/v7/recyclerview/tests/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-# 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 := $(SUPPORT_CURRENT_SDK_VERSION)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := \
-    $(LOCAL_PATH)/res \
-    $(LOCAL_PATH)/../res
-
-LOCAL_STATIC_JAVA_LIBRARIES  := \
-        android-support-v7-recyclerview \
-        android-support-v4 \
-        android-support-annotations
-
-LOCAL_PACKAGE_NAME := RecyclerViewTests
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_AAPT_FLAGS := \
-        --auto-add-overlay \
-        --extra-packages android.support.v7.recyclerview
-
-include $(BUILD_PACKAGE)
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
index 77585b5..dd2c650 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
@@ -800,7 +800,7 @@
         });
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
     @Test
     public void hiddenNoneRemoveViewAccessibility() throws Throwable {
         final Config config = new Config();
@@ -905,6 +905,58 @@
     }
 
     @Test
+    public void layoutFrozenBug70402422() throws Throwable {
+        final Config config = new Config();
+        TestAdapter adapter = new TestAdapter(2);
+        adapter.setHasStableIds(false);
+        config.adapter(adapter);
+        setupByConfig(config, true);
+        final DummyItemAnimator itemAnimator = new DummyItemAnimator();
+        mRecyclerView.setItemAnimator(itemAnimator);
+
+        final View firstItemView = mRecyclerView
+                .findViewHolderForAdapterPosition(0).itemView;
+
+        itemAnimator.expect(DummyItemAnimator.REMOVE_START, 1);
+        mTestAdapter.deleteAndNotify(1, 1);
+        itemAnimator.waitFor(DummyItemAnimator.REMOVE_START);
+
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mRecyclerView.setLayoutFrozen(true);
+            }
+        });
+        // requestLayout during item animation, which should be eaten by setLayoutFrozen(true)
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                firstItemView.requestLayout();
+            }
+        });
+        assertTrue(firstItemView.isLayoutRequested());
+        assertFalse(mRecyclerView.isLayoutRequested());
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                itemAnimator.endAnimations();
+            }
+        });
+        // When setLayoutFrozen(false), the firstItemView should run a layout pass and clear
+        // isLayoutRequested() flag.
+        mLayoutManager.expectLayouts(1);
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mRecyclerView.setLayoutFrozen(false);
+            }
+        });
+        mLayoutManager.waitForLayout(1);
+        assertFalse(firstItemView.isLayoutRequested());
+        assertFalse(mRecyclerView.isLayoutRequested());
+    }
+
+    @Test
     public void keepFocusOnRelayout() throws Throwable {
         setupByConfig(new Config(VERTICAL, false, false).itemCount(500), true);
         int center = (mLayoutManager.findLastVisibleItemPosition()
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
index 1c03c0f..dbad400 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
@@ -46,6 +46,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -1532,7 +1533,33 @@
 
     @Test
     public void scrollToPositionCallback() throws Throwable {
-        RecyclerView recyclerView = new RecyclerView(getActivity());
+
+        class TestRecyclerView extends RecyclerView {
+
+            private CountDownLatch mDrawLatch;
+
+            TestRecyclerView(Context context) {
+                super(context);
+            }
+
+            public void expectDraws(int count) {
+                mDrawLatch = new CountDownLatch(count);
+            }
+
+            public void waitForDraw(int seconds) throws InterruptedException {
+                mDrawLatch.await(seconds, TimeUnit.SECONDS);
+            }
+
+            @Override
+            public void onDraw(Canvas c) {
+                super.onDraw(c);
+                if (mDrawLatch != null) {
+                    mDrawLatch.countDown();
+                }
+            }
+        }
+
+        TestRecyclerView recyclerView = new TestRecyclerView(getActivity());
         TestLayoutManager tlm = new TestLayoutManager() {
             int scrollPos = RecyclerView.NO_POSITION;
 
@@ -1562,7 +1589,6 @@
             @Override
             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                 rvCounter.incrementAndGet();
-                super.onScrolled(recyclerView, dx, dy);
             }
         });
 
@@ -1574,13 +1600,16 @@
                     }
                 });
 
+        recyclerView.expectDraws(1);
         tlm.expectLayouts(1);
         setRecyclerView(recyclerView);
         tlm.waitForLayout(2);
-
+        recyclerView.waitForDraw(2);
         assertEquals("RV on scroll should be called for initialization", 1, rvCounter.get());
         assertEquals("VTO on scroll should be called for initialization", 1,
                 viewGroupCounter.get());
+
+        recyclerView.expectDraws(1);
         tlm.expectLayouts(1);
         freezeLayout(true);
         scrollToPosition(3);
@@ -1588,13 +1617,15 @@
         freezeLayout(false);
         scrollToPosition(3);
         tlm.waitForLayout(2);
+        recyclerView.waitForDraw(2);
         assertEquals("RV on scroll should be called", 2, rvCounter.get());
         assertEquals("VTO on scroll should be called", 2, viewGroupCounter.get());
+
+        recyclerView.expectDraws(1);
         tlm.expectLayouts(1);
         requestLayoutOnUIThread(recyclerView);
         tlm.waitForLayout(2);
-        // wait for draw :/
-        Thread.sleep(1000);
+        recyclerView.waitForDraw(2);
         assertEquals("on scroll should NOT be called", 2, rvCounter.get());
         assertEquals("on scroll should NOT be called", 2, viewGroupCounter.get());
     }
diff --git a/viewpager2/OWNERS b/viewpager2/OWNERS
new file mode 100644
index 0000000..e24ee8b
--- /dev/null
+++ b/viewpager2/OWNERS
@@ -0,0 +1 @@
+jgielzak@google.com
\ No newline at end of file
diff --git a/viewpager2/build.gradle b/viewpager2/build.gradle
new file mode 100644
index 0000000..2fee643
--- /dev/null
+++ b/viewpager2/build.gradle
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+import static android.support.dependencies.DependenciesKt.*
+import android.support.LibraryGroups
+import android.support.LibraryVersions
+
+plugins {
+    id("SupportAndroidLibraryPlugin")
+}
+
+dependencies {
+    api(project(":support-core-utils"))
+    api(project(":recyclerview-v7"))
+
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+}
+
+android {
+    defaultConfig {
+        minSdkVersion 14
+    }
+}
+
+supportLibrary {
+    name = "AndroidX Widget ViewPager2"
+    mavenVersion = LibraryVersions.SUPPORT_LIBRARY
+    mavenGroup = LibraryGroups.SUPPORT
+    inceptionYear = "2017"
+    description = "AndroidX Widget ViewPager2"
+}
\ No newline at end of file
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_video_example.xml b/viewpager2/src/androidTest/AndroidManifest.xml
old mode 100644
new mode 100755
similarity index 60%
rename from samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_video_example.xml
rename to viewpager2/src/androidTest/AndroidManifest.xml
index 45b12b5..ac723e6
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_video_example.xml
+++ b/viewpager2/src/androidTest/AndroidManifest.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,9 +13,12 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:id="@+id/videoFragment">
 
-</RelativeLayout>
\ No newline at end of file
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="androidx.widget.viewpager2.test">
+    <uses-sdk android:targetSdkVersion="${target-sdk-version}"/>
+
+    <application android:supportsRtl="true">
+        <activity android:name="androidx.widget.viewpager2.tests.TestActivity"/>
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/viewpager2/src/androidTest/java/androidx/widget/viewpager2/tests/TestActivity.java b/viewpager2/src/androidTest/java/androidx/widget/viewpager2/tests/TestActivity.java
new file mode 100644
index 0000000..351ad9a
--- /dev/null
+++ b/viewpager2/src/androidTest/java/androidx/widget/viewpager2/tests/TestActivity.java
@@ -0,0 +1,30 @@
+/*
+ * 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 androidx.widget.viewpager2.tests;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import androidx.widget.viewpager2.test.R;
+
+public class TestActivity extends Activity {
+    @Override
+    public void onCreate(Bundle bundle) {
+        super.onCreate(bundle);
+        setContentView(R.layout.activity_test_layout);
+    }
+}
diff --git a/viewpager2/src/androidTest/java/androidx/widget/viewpager2/tests/ViewPager2Tests.java b/viewpager2/src/androidTest/java/androidx/widget/viewpager2/tests/ViewPager2Tests.java
new file mode 100644
index 0000000..7f5432b
--- /dev/null
+++ b/viewpager2/src/androidTest/java/androidx/widget/viewpager2/tests/ViewPager2Tests.java
@@ -0,0 +1,207 @@
+/*
+ * 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 androidx.widget.viewpager2.tests;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static android.support.v7.widget.RecyclerView.SCROLL_STATE_IDLE;
+import static android.support.v7.widget.RecyclerView.SCROLL_STATE_SETTLING;
+
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.support.annotation.NonNull;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.espresso.IdlingRegistry;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.action.ViewActions;
+import android.support.test.espresso.idling.CountingIdlingResource;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.Adapter;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+
+import androidx.widget.ViewPager2;
+import androidx.widget.viewpager2.test.R;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class ViewPager2Tests {
+    private static final int[] sColors = {
+            Color.parseColor("#BBA9FF00"),
+            Color.parseColor("#BB00E87E"),
+            Color.parseColor("#BB00C7FF"),
+            Color.parseColor("#BBB30CE8"),
+            Color.parseColor("#BBFF00D0")};
+
+    @Rule
+    public final ActivityTestRule<TestActivity> mActivityTestRule;
+    @Rule
+    public ExpectedException mExpectedException = ExpectedException.none();
+
+    private ViewPager2 mViewPager;
+    private CountingIdlingResource mIdlingResource;
+
+    public ViewPager2Tests() {
+        mActivityTestRule = new ActivityTestRule<>(TestActivity.class);
+    }
+
+    @Before
+    public void setUp() {
+        mViewPager = mActivityTestRule.getActivity().findViewById(R.id.view_pager);
+
+        mIdlingResource = new CountingIdlingResource(getClass().getSimpleName() + "IdlingResource");
+        mViewPager.addOnScrollListener(new RecyclerView.OnScrollListener() {
+            @Override
+            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+                if (newState == SCROLL_STATE_IDLE && !mIdlingResource.isIdleNow()) {
+                    mIdlingResource.decrement();
+                } else if (newState == SCROLL_STATE_SETTLING && mIdlingResource.isIdleNow()) {
+                    mIdlingResource.increment();
+                }
+            }
+        });
+        IdlingRegistry.getInstance().register(mIdlingResource);
+    }
+
+    @After
+    public void tearDown() {
+        IdlingRegistry.getInstance().unregister(mIdlingResource);
+    }
+
+    @Test
+    public void rendersAndHandlesSwiping() throws Throwable {
+        final int pageCount = sColors.length;
+
+        onView(withId(mViewPager.getId())).check(matches(isDisplayed()));
+        mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mViewPager.setAdapter(
+                        new Adapter<ViewHolder>() {
+                            @NonNull
+                            @Override
+                            public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,
+                                    int viewType) {
+                                return new ViewHolder(
+                                        mActivityTestRule.getActivity().getLayoutInflater().inflate(
+                                                R.layout.item_test_layout, parent, false)) {
+                                };
+                            }
+
+                            @Override
+                            public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+                                TextView view = (TextView) holder.itemView;
+                                view.setText(String.valueOf(position));
+                                view.setBackgroundColor(sColors[position]);
+                            }
+
+                            @Override
+                            public int getItemCount() {
+                                return pageCount;
+                            }
+                        });
+            }
+        });
+
+        final int pageIxFirst = 0;
+        final int pageIxLast = pageCount - 1;
+        final int swipeCount = pageCount + 1; // two swipes beyond edge to test 'edge behavior'
+        int pageNumber = pageIxFirst;
+        for (int i = 0; i < swipeCount; i++, pageNumber = Math.min(pageIxLast, ++pageNumber)) {
+            verifyView(pageNumber);
+            performSwipe(ViewActions.swipeLeft());
+        }
+        assertThat(pageNumber, equalTo(pageIxLast));
+        for (int i = 0; i < swipeCount; i++, pageNumber = Math.max(pageIxFirst, --pageNumber)) {
+            verifyView(pageNumber);
+            performSwipe(ViewActions.swipeRight());
+        }
+        assertThat(pageNumber, equalTo(pageIxFirst));
+    }
+
+    private void verifyView(int pageNumber) {
+        onView(allOf(withId(R.id.text_view), isDisplayed())).check(
+                matches(withText(String.valueOf(pageNumber))));
+    }
+
+    private void performSwipe(ViewAction swipeAction) throws InterruptedException {
+        onView(allOf(isDisplayed(), withId(R.id.text_view))).perform(swipeAction);
+    }
+
+    @Test
+    public void itemViewSizeMatchParentEnforced() {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage(
+                "Item's root view must fill the whole ViewPager2 (use match_parent)");
+
+        ViewPager2 viewPager = new ViewPager2(InstrumentationRegistry.getContext());
+        viewPager.setAdapter(new Adapter<ViewHolder>() {
+            @NonNull
+            @Override
+            public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+                View view = new View(parent.getContext());
+                view.setLayoutParams(new ViewGroup.LayoutParams(50, 50)); // arbitrary fixed size
+                return new ViewHolder(view) {
+                };
+            }
+
+            @Override
+            public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+                // do nothing
+            }
+
+            @Override
+            public int getItemCount() {
+                return 1;
+            }
+        });
+
+        viewPager.measure(0, 0); // equivalent of unspecified
+    }
+
+    @Test
+    public void childrenNotAllowed() throws Exception {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("ViewPager2 does not support direct child views");
+
+        Context context = InstrumentationRegistry.getContext();
+        ViewPager2 viewPager = new ViewPager2(context);
+        viewPager.addView(new View(context));
+    }
+
+    // TODO: verify correct padding behavior
+    // TODO: add test for screen orientation change
+}
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_main.xml b/viewpager2/src/androidTest/res/layout/activity_test_layout.xml
similarity index 74%
copy from samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_main.xml
copy to viewpager2/src/androidTest/res/layout/activity_test_layout.xml
index 9d2eda6..3037029 100644
--- a/samples/SupportLeanbackShowcase/app/src/main/res/layout/activity_main.xml
+++ b/viewpager2/src/androidTest/res/layout/activity_test_layout.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,12 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<RelativeLayout
-    android:id="@+id/fragmentContainer"
+
+<androidx.widget.ViewPager2
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/view_pager"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:deviceIds="tv"
-    tools:ignore="MergeRootFrame">
-</RelativeLayout>
+    android:background="#FFF"
+    android:padding="16dp"/>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml b/viewpager2/src/androidTest/res/layout/item_test_layout.xml
similarity index 75%
rename from samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml
rename to viewpager2/src/androidTest/res/layout/item_test_layout.xml
index d6a1023..dc6bdcf 100644
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml
+++ b/viewpager2/src/androidTest/res/layout/item_test_layout.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,8 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape
+
+<TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="#FFFFFF"></solid>
-</shape>
\ No newline at end of file
+    android:id="@+id/text_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center"/>
diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml b/viewpager2/src/main/AndroidManifest.xml
similarity index 72%
copy from samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml
copy to viewpager2/src/main/AndroidManifest.xml
index d6a1023..198a6f7 100644
--- a/samples/SupportLeanbackShowcase/app/src/main/res/drawable/wizard_important_action_item_background_focused.xml
+++ b/viewpager2/src/main/AndroidManifest.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,8 +13,8 @@
      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">
-    <solid android:color="#FFFFFF"></solid>
-</shape>
\ No newline at end of file
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="androidx.widget.viewpager2">
+    <uses-sdk android:minSdkVersion="14"/>
+</manifest>
\ No newline at end of file
diff --git a/viewpager2/src/main/java/androidx/widget/ViewPager2.java b/viewpager2/src/main/java/androidx/widget/ViewPager2.java
new file mode 100644
index 0000000..0e8e66c
--- /dev/null
+++ b/viewpager2/src/main/java/androidx/widget/ViewPager2.java
@@ -0,0 +1,176 @@
+/*
+ * 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 androidx.widget;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Rect;
+import android.support.annotation.NonNull;
+import android.support.annotation.RestrictTo;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.PagerSnapHelper;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.Adapter;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Work in progress: go/viewpager2
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+public class ViewPager2 extends ViewGroup {
+    // reused in layout(...)
+    private final Rect mTmpContainerRect = new Rect();
+    private final Rect mTmpChildRect = new Rect();
+
+    private RecyclerView mRecyclerView;
+
+    public ViewPager2(Context context) {
+        super(context);
+        initialize(context);
+    }
+
+    public ViewPager2(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public ViewPager2(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initialize(context);
+    }
+
+    @TargetApi(21)
+    public ViewPager2(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        // TODO(b/70663531): handle attrs, defStyleAttr, defStyleRes
+        super(context, attrs, defStyleAttr, defStyleRes);
+        initialize(context);
+    }
+
+    private void initialize(Context context) {
+        mRecyclerView = new RecyclerView(context);
+
+        LinearLayoutManager layoutManager = new LinearLayoutManager(context);
+        // TODO(b/69103581): add support for vertical layout
+        // TODO(b/69398856): add support for RTL
+        layoutManager.setOrientation(RecyclerView.HORIZONTAL);
+        mRecyclerView.setLayoutManager(layoutManager);
+
+        mRecyclerView.setLayoutParams(
+                new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+        // TODO(b/70666992): add automated test for orientation change
+        new PagerSnapHelper().attachToRecyclerView(mRecyclerView);
+
+        attachViewToParent(mRecyclerView, 0, mRecyclerView.getLayoutParams());
+    }
+
+    /**
+     * TODO(b/70663708): decide on an Adapter class (for now reusing RecyclerView.Adapter)
+     *
+     * @see RecyclerView#setAdapter(Adapter)
+     */
+    public <VH extends ViewHolder> void setAdapter(final Adapter<VH> adapter) {
+        mRecyclerView.setAdapter(new Adapter<VH>() {
+            private final Adapter<VH> mAdapter = adapter;
+
+            @NonNull
+            @Override
+            public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+                VH viewHolder = mAdapter.onCreateViewHolder(parent, viewType);
+
+                LayoutParams layoutParams = viewHolder.itemView.getLayoutParams();
+                if ((layoutParams.width | layoutParams.height) != LayoutParams.MATCH_PARENT) {
+                    // TODO(b/70666614): decide if throw an exception or wrap in FrameLayout
+                    // ourselves; consider accepting exact size equal to parent's exact size
+                    throw new IllegalStateException(String.format(
+                            "Item's root view must fill the whole %s (use match_parent)",
+                            ViewPager2.this.getClass().getSimpleName()));
+                }
+
+                return viewHolder;
+            }
+
+            @Override
+            public void onBindViewHolder(@NonNull VH holder, int position) {
+                mAdapter.onBindViewHolder(holder, position);
+            }
+
+            @Override
+            public int getItemCount() {
+                return mAdapter.getItemCount();
+            }
+        });
+    }
+
+    @Override
+    public void onViewAdded(View child) {
+        // TODO(b/70666620): consider adding a support for Decor views
+        throw new IllegalStateException(
+                getClass().getSimpleName() + " does not support direct child views");
+    }
+
+    /** @see RecyclerView#addOnScrollListener(RecyclerView.OnScrollListener) */
+    public void addOnScrollListener(RecyclerView.OnScrollListener listener) {
+        mRecyclerView.addOnScrollListener(listener);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // TODO(b/70666622): consider margin support
+        // TODO(b/70666626): consider delegating all this to RecyclerView
+        // TODO(b/70666625): write automated tests for this
+
+        measureChild(mRecyclerView, widthMeasureSpec, heightMeasureSpec);
+        int width = mRecyclerView.getMeasuredWidth();
+        int height = mRecyclerView.getMeasuredHeight();
+        int childState = mRecyclerView.getMeasuredState();
+
+        width += getPaddingLeft() + getPaddingRight();
+        height += getPaddingTop() + getPaddingBottom();
+
+        width = Math.max(width, getSuggestedMinimumWidth());
+        height = Math.max(height, getSuggestedMinimumHeight());
+
+        setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, childState),
+                resolveSizeAndState(height, heightMeasureSpec,
+                        childState << MEASURED_HEIGHT_STATE_SHIFT));
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int width = mRecyclerView.getMeasuredWidth();
+        int height = mRecyclerView.getMeasuredHeight();
+
+        // TODO(b/70666626): consider delegating padding handling to the RecyclerView to avoid
+        // an unnatural page transition effect: http://shortn/_Vnug3yZpQT
+        mTmpContainerRect.left = getPaddingLeft();
+        mTmpContainerRect.right = r - l - getPaddingRight();
+        mTmpContainerRect.top = getPaddingTop();
+        mTmpContainerRect.bottom = b - t - getPaddingBottom();
+
+        Gravity.apply(Gravity.TOP | Gravity.START, width, height, mTmpContainerRect, mTmpChildRect);
+        mRecyclerView.layout(mTmpChildRect.left, mTmpChildRect.top, mTmpChildRect.right,
+                mTmpChildRect.bottom);
+    }
+}
diff --git a/wear/Android.mk b/wear/Android.mk
index fe9b8d3..9e5bf5b 100644
--- a/wear/Android.mk
+++ b/wear/Android.mk
@@ -32,18 +32,22 @@
 
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
+LOCAL_AAPT2_ONLY := true
 LOCAL_MODULE := android-support-wear
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under,src/main/java)
+LOCAL_MANIFEST_FILE := src/main/AndroidManifest.xml
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_JAVA_LIBRARIES := \
+    android-support-annotations
 LOCAL_SHARED_ANDROID_LIBRARIES := \
-        android-support-core-ui \
-        android-support-annotations \
-        android-support-percent \
-        android-support-v7-recyclerview \
-        android-support-v4
+    android-support-core-ui \
+    android-support-percent \
+    android-support-v7-recyclerview \
+    android-support-v4 \
+    android-support-constraint-layout
 LOCAL_STATIC_JAVA_LIBRARIES := \
-        prebuilt-com.google.android.wearable-stubs
+    prebuilt-com.google.android.wearable-stubs
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
diff --git a/wear/api/current.txt b/wear/api/current.txt
index 3fd2465..9c5a543 100644
--- a/wear/api/current.txt
+++ b/wear/api/current.txt
@@ -1,6 +1,6 @@
 package android.support.wear.ambient {
 
-  public final class AmbientMode extends android.app.Fragment {
+  public final deprecated class AmbientMode extends android.app.Fragment {
     ctor public AmbientMode();
     method public static <T extends android.app.Activity> android.support.wear.ambient.AmbientMode.AmbientController attachAmbientSupport(T);
     field public static final java.lang.String EXTRA_BURN_IN_PROTECTION = "com.google.android.wearable.compat.extra.BURN_IN_PROTECTION";
@@ -23,6 +23,29 @@
     method public boolean isAmbient();
   }
 
+  public final class AmbientModeSupport extends android.support.v4.app.Fragment {
+    ctor public AmbientModeSupport();
+    method public static <T extends android.support.v4.app.FragmentActivity> android.support.wear.ambient.AmbientModeSupport.AmbientController attach(T);
+    field public static final java.lang.String EXTRA_BURN_IN_PROTECTION = "com.google.android.wearable.compat.extra.BURN_IN_PROTECTION";
+    field public static final java.lang.String EXTRA_LOWBIT_AMBIENT = "com.google.android.wearable.compat.extra.LOWBIT_AMBIENT";
+    field public static final java.lang.String FRAGMENT_TAG = "android.support.wearable.ambient.AmbientMode";
+  }
+
+  public static abstract class AmbientModeSupport.AmbientCallback {
+    ctor public AmbientModeSupport.AmbientCallback();
+    method public void onEnterAmbient(android.os.Bundle);
+    method public void onExitAmbient();
+    method public void onUpdateAmbient();
+  }
+
+  public static abstract interface AmbientModeSupport.AmbientCallbackProvider {
+    method public abstract android.support.wear.ambient.AmbientModeSupport.AmbientCallback getAmbientCallback();
+  }
+
+  public final class AmbientModeSupport.AmbientController {
+    method public boolean isAmbient();
+  }
+
 }
 
 package android.support.wear.utils {
diff --git a/wear/build.gradle b/wear/build.gradle
index 4937619..4878dab 100644
--- a/wear/build.gradle
+++ b/wear/build.gradle
@@ -22,10 +22,6 @@
 }
 
 android {
-    defaultConfig {
-        minSdkVersion 23
-    }
-
     sourceSets {
         main.res.srcDirs 'res', 'res-public'
         main.resources {
@@ -45,5 +41,5 @@
     mavenGroup = LibraryGroups.SUPPORT
     inceptionYear = "2016"
     description = "Android Wear Support UI"
-    legacySourceLocation = true
+    minSdkVersion = 23
 }
diff --git a/wear/tests/AndroidManifest.xml b/wear/src/androidTest/AndroidManifest.xml
similarity index 83%
rename from wear/tests/AndroidManifest.xml
rename to wear/src/androidTest/AndroidManifest.xml
index 67ccd91..f7da293 100644
--- a/wear/tests/AndroidManifest.xml
+++ b/wear/src/androidTest/AndroidManifest.xml
@@ -62,6 +62,20 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
+
+        <activity android:name="android.support.wear.ambient.AmbientModeSupportTestActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.support.wear.ambient.AmbientModeSupportResumeTestActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
         <!-- Test app is iOS compatible. -->
         <meta-data
             android:name="com.google.android.wearable.standalone"
diff --git a/wear/tests/NO_DOCS b/wear/src/androidTest/NO_DOCS
similarity index 100%
rename from wear/tests/NO_DOCS
rename to wear/src/androidTest/NO_DOCS
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientDelegateTest.java b/wear/src/androidTest/java/android/support/wear/ambient/AmbientDelegateTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/ambient/AmbientDelegateTest.java
rename to wear/src/androidTest/java/android/support/wear/ambient/AmbientDelegateTest.java
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientModeResumeTest.java b/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeResumeTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/ambient/AmbientModeResumeTest.java
rename to wear/src/androidTest/java/android/support/wear/ambient/AmbientModeResumeTest.java
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientModeResumeTestActivity.java b/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeResumeTestActivity.java
similarity index 100%
rename from wear/tests/src/android/support/wear/ambient/AmbientModeResumeTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/ambient/AmbientModeResumeTestActivity.java
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientModeTest.java b/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/ambient/AmbientModeTest.java
rename to wear/src/androidTest/java/android/support/wear/ambient/AmbientModeTest.java
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientModeTestActivity.java b/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeTestActivity.java
similarity index 100%
rename from wear/tests/src/android/support/wear/ambient/AmbientModeTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/ambient/AmbientModeTestActivity.java
diff --git a/wear/tests/src/android/support/wear/utils/MetadataTestActivity.java b/wear/src/androidTest/java/android/support/wear/utils/MetadataTestActivity.java
similarity index 99%
rename from wear/tests/src/android/support/wear/utils/MetadataTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/utils/MetadataTestActivity.java
index 86d92ab..b934b5b 100644
--- a/wear/tests/src/android/support/wear/utils/MetadataTestActivity.java
+++ b/wear/src/androidTest/java/android/support/wear/utils/MetadataTestActivity.java
@@ -34,4 +34,4 @@
         assertEquals(R.drawable.preview_face_circular,
                 MetadataConstants.getPreviewDrawableResourceId(this, true));
     }
-}
\ No newline at end of file
+}
diff --git a/wear/tests/src/android/support/wear/widget/BoxInsetLayoutTest.java b/wear/src/androidTest/java/android/support/wear/widget/BoxInsetLayoutTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/BoxInsetLayoutTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/BoxInsetLayoutTest.java
diff --git a/wear/tests/src/android/support/wear/widget/CircularProgressLayoutControllerTest.java b/wear/src/androidTest/java/android/support/wear/widget/CircularProgressLayoutControllerTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/CircularProgressLayoutControllerTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/CircularProgressLayoutControllerTest.java
diff --git a/wear/tests/src/android/support/wear/widget/CircularProgressLayoutTest.java b/wear/src/androidTest/java/android/support/wear/widget/CircularProgressLayoutTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/CircularProgressLayoutTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/CircularProgressLayoutTest.java
diff --git a/wear/tests/src/android/support/wear/widget/LayoutTestActivity.java b/wear/src/androidTest/java/android/support/wear/widget/LayoutTestActivity.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/LayoutTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/widget/LayoutTestActivity.java
diff --git a/wear/tests/src/android/support/wear/widget/RoundedDrawableTest.java b/wear/src/androidTest/java/android/support/wear/widget/RoundedDrawableTest.java
similarity index 99%
rename from wear/tests/src/android/support/wear/widget/RoundedDrawableTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/RoundedDrawableTest.java
index 21aee7b..b01b3fa 100644
--- a/wear/tests/src/android/support/wear/widget/RoundedDrawableTest.java
+++ b/wear/src/androidTest/java/android/support/wear/widget/RoundedDrawableTest.java
@@ -33,11 +33,11 @@
 import android.graphics.RectF;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.Build;
+import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.wear.test.R;
-import android.support.test.filters.SdkSuppress;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/wear/tests/src/android/support/wear/widget/ScrollManagerTest.java b/wear/src/androidTest/java/android/support/wear/widget/ScrollManagerTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/ScrollManagerTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/ScrollManagerTest.java
diff --git a/wear/tests/src/android/support/wear/widget/SwipeDismissFrameLayoutTest.java b/wear/src/androidTest/java/android/support/wear/widget/SwipeDismissFrameLayoutTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/SwipeDismissFrameLayoutTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/SwipeDismissFrameLayoutTest.java
diff --git a/wear/tests/src/android/support/wear/widget/SwipeDismissFrameLayoutTestActivity.java b/wear/src/androidTest/java/android/support/wear/widget/SwipeDismissFrameLayoutTestActivity.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/SwipeDismissFrameLayoutTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/widget/SwipeDismissFrameLayoutTestActivity.java
diff --git a/wear/tests/src/android/support/wear/widget/SwipeDismissPreferenceFragment.java b/wear/src/androidTest/java/android/support/wear/widget/SwipeDismissPreferenceFragment.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/SwipeDismissPreferenceFragment.java
rename to wear/src/androidTest/java/android/support/wear/widget/SwipeDismissPreferenceFragment.java
diff --git a/wear/tests/src/android/support/wear/widget/WearableLinearLayoutManagerTest.java b/wear/src/androidTest/java/android/support/wear/widget/WearableLinearLayoutManagerTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/WearableLinearLayoutManagerTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/WearableLinearLayoutManagerTest.java
diff --git a/wear/tests/src/android/support/wear/widget/WearableRecyclerViewTest.java b/wear/src/androidTest/java/android/support/wear/widget/WearableRecyclerViewTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/WearableRecyclerViewTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/WearableRecyclerViewTest.java
diff --git a/wear/tests/src/android/support/wear/widget/WearableRecyclerViewTestActivity.java b/wear/src/androidTest/java/android/support/wear/widget/WearableRecyclerViewTestActivity.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/WearableRecyclerViewTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/widget/WearableRecyclerViewTestActivity.java
diff --git a/wear/tests/src/android/support/wear/widget/drawer/DrawerTestActivity.java b/wear/src/androidTest/java/android/support/wear/widget/drawer/DrawerTestActivity.java
similarity index 97%
rename from wear/tests/src/android/support/wear/widget/drawer/DrawerTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/widget/drawer/DrawerTestActivity.java
index 14af0e1..414b97b 100644
--- a/wear/tests/src/android/support/wear/widget/drawer/DrawerTestActivity.java
+++ b/wear/src/androidTest/java/android/support/wear/widget/drawer/DrawerTestActivity.java
@@ -152,9 +152,9 @@
             DrawerStyle.ONLY_ACTION_DRAWER_WITH_TITLE
     })
     public @interface DrawerStyle {
-    int BOTH_DRAWER_NAV_SINGLE_PAGE = 0;
-    int BOTH_DRAWER_NAV_MULTI_PAGE = 1;
-    int ONLY_ACTION_DRAWER_WITH_TITLE = 2;
+        int BOTH_DRAWER_NAV_SINGLE_PAGE = 0;
+        int BOTH_DRAWER_NAV_MULTI_PAGE = 1;
+        int ONLY_ACTION_DRAWER_WITH_TITLE = 2;
     }
 
     /**
diff --git a/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java b/wear/src/androidTest/java/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
diff --git a/wear/tests/src/android/support/wear/widget/util/ArcSwipe.java b/wear/src/androidTest/java/android/support/wear/widget/util/ArcSwipe.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/util/ArcSwipe.java
rename to wear/src/androidTest/java/android/support/wear/widget/util/ArcSwipe.java
diff --git a/wear/tests/src/android/support/wear/widget/util/ArcSwipeTest.java b/wear/src/androidTest/java/android/support/wear/widget/util/ArcSwipeTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/util/ArcSwipeTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/util/ArcSwipeTest.java
diff --git a/wear/tests/src/android/support/wear/widget/util/AsyncViewActions.java b/wear/src/androidTest/java/android/support/wear/widget/util/AsyncViewActions.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/util/AsyncViewActions.java
rename to wear/src/androidTest/java/android/support/wear/widget/util/AsyncViewActions.java
diff --git a/wear/tests/src/android/support/wear/widget/util/MoreViewAssertions.java b/wear/src/androidTest/java/android/support/wear/widget/util/MoreViewAssertions.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/util/MoreViewAssertions.java
rename to wear/src/androidTest/java/android/support/wear/widget/util/MoreViewAssertions.java
diff --git a/wear/tests/src/android/support/wear/widget/util/WakeLockRule.java b/wear/src/androidTest/java/android/support/wear/widget/util/WakeLockRule.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/util/WakeLockRule.java
rename to wear/src/androidTest/java/android/support/wear/widget/util/WakeLockRule.java
diff --git a/wear/tests/src/com/google/android/wearable/compat/WearableActivityController.java b/wear/src/androidTest/java/com/google/android/wearable/compat/WearableActivityController.java
similarity index 100%
rename from wear/tests/src/com/google/android/wearable/compat/WearableActivityController.java
rename to wear/src/androidTest/java/com/google/android/wearable/compat/WearableActivityController.java
diff --git a/wear/tests/res/drawable/preview_face.png b/wear/src/androidTest/res/drawable/preview_face.png
similarity index 100%
rename from wear/tests/res/drawable/preview_face.png
rename to wear/src/androidTest/res/drawable/preview_face.png
Binary files differ
diff --git a/wear/tests/res/drawable/preview_face_circular.png b/wear/src/androidTest/res/drawable/preview_face_circular.png
similarity index 100%
rename from wear/tests/res/drawable/preview_face_circular.png
rename to wear/src/androidTest/res/drawable/preview_face_circular.png
Binary files differ
diff --git a/wear/tests/res/drawable/rounded_drawable.xml b/wear/src/androidTest/res/drawable/rounded_drawable.xml
similarity index 100%
rename from wear/tests/res/drawable/rounded_drawable.xml
rename to wear/src/androidTest/res/drawable/rounded_drawable.xml
diff --git a/wear/tests/res/drawable/test_drawable.xml b/wear/src/androidTest/res/drawable/test_drawable.xml
similarity index 100%
rename from wear/tests/res/drawable/test_drawable.xml
rename to wear/src/androidTest/res/drawable/test_drawable.xml
diff --git a/wear/tests/res/layout/box_inset_layout_testcase_1.xml b/wear/src/androidTest/res/layout/box_inset_layout_testcase_1.xml
similarity index 100%
rename from wear/tests/res/layout/box_inset_layout_testcase_1.xml
rename to wear/src/androidTest/res/layout/box_inset_layout_testcase_1.xml
diff --git a/wear/tests/res/layout/box_inset_layout_testcase_2.xml b/wear/src/androidTest/res/layout/box_inset_layout_testcase_2.xml
similarity index 100%
rename from wear/tests/res/layout/box_inset_layout_testcase_2.xml
rename to wear/src/androidTest/res/layout/box_inset_layout_testcase_2.xml
diff --git a/wear/tests/res/layout/box_inset_layout_testcase_3.xml b/wear/src/androidTest/res/layout/box_inset_layout_testcase_3.xml
similarity index 100%
rename from wear/tests/res/layout/box_inset_layout_testcase_3.xml
rename to wear/src/androidTest/res/layout/box_inset_layout_testcase_3.xml
diff --git a/wear/tests/res/layout/box_inset_layout_testcase_4.xml b/wear/src/androidTest/res/layout/box_inset_layout_testcase_4.xml
similarity index 100%
rename from wear/tests/res/layout/box_inset_layout_testcase_4.xml
rename to wear/src/androidTest/res/layout/box_inset_layout_testcase_4.xml
diff --git a/wear/tests/res/layout/circular_progress_layout.xml b/wear/src/androidTest/res/layout/circular_progress_layout.xml
similarity index 100%
rename from wear/tests/res/layout/circular_progress_layout.xml
rename to wear/src/androidTest/res/layout/circular_progress_layout.xml
diff --git a/wear/tests/res/layout/curved_offsetting_helper_child.xml b/wear/src/androidTest/res/layout/curved_offsetting_helper_child.xml
similarity index 100%
rename from wear/tests/res/layout/curved_offsetting_helper_child.xml
rename to wear/src/androidTest/res/layout/curved_offsetting_helper_child.xml
diff --git a/wear/tests/res/layout/rounded_drawable_layout.xml b/wear/src/androidTest/res/layout/rounded_drawable_layout.xml
similarity index 100%
rename from wear/tests/res/layout/rounded_drawable_layout.xml
rename to wear/src/androidTest/res/layout/rounded_drawable_layout.xml
diff --git a/wear/tests/res/layout/swipe_dismiss_layout_testcase_1.xml b/wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_1.xml
similarity index 100%
rename from wear/tests/res/layout/swipe_dismiss_layout_testcase_1.xml
rename to wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_1.xml
diff --git a/wear/tests/res/layout/swipe_dismiss_layout_testcase_2.xml b/wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_2.xml
similarity index 100%
rename from wear/tests/res/layout/swipe_dismiss_layout_testcase_2.xml
rename to wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_2.xml
diff --git a/wear/tests/res/layout/swipe_dismiss_layout_testcase_3.xml b/wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_3.xml
similarity index 100%
rename from wear/tests/res/layout/swipe_dismiss_layout_testcase_3.xml
rename to wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_3.xml
diff --git a/wear/tests/res/layout/test_multi_page_nav_drawer_layout.xml b/wear/src/androidTest/res/layout/test_multi_page_nav_drawer_layout.xml
similarity index 100%
rename from wear/tests/res/layout/test_multi_page_nav_drawer_layout.xml
rename to wear/src/androidTest/res/layout/test_multi_page_nav_drawer_layout.xml
diff --git a/wear/tests/res/layout/test_only_action_drawer_with_title_layout.xml b/wear/src/androidTest/res/layout/test_only_action_drawer_with_title_layout.xml
similarity index 100%
rename from wear/tests/res/layout/test_only_action_drawer_with_title_layout.xml
rename to wear/src/androidTest/res/layout/test_only_action_drawer_with_title_layout.xml
diff --git a/wear/tests/res/layout/test_single_page_nav_drawer_layout.xml b/wear/src/androidTest/res/layout/test_single_page_nav_drawer_layout.xml
similarity index 100%
rename from wear/tests/res/layout/test_single_page_nav_drawer_layout.xml
rename to wear/src/androidTest/res/layout/test_single_page_nav_drawer_layout.xml
diff --git a/wear/tests/res/layout/wearable_recycler_view_basic.xml b/wear/src/androidTest/res/layout/wearable_recycler_view_basic.xml
similarity index 100%
rename from wear/tests/res/layout/wearable_recycler_view_basic.xml
rename to wear/src/androidTest/res/layout/wearable_recycler_view_basic.xml
diff --git a/wear/tests/res/menu/action_drawer.xml b/wear/src/androidTest/res/menu/action_drawer.xml
similarity index 100%
rename from wear/tests/res/menu/action_drawer.xml
rename to wear/src/androidTest/res/menu/action_drawer.xml
diff --git a/wear/tests/res/values-sw213dp/styles.xml b/wear/src/androidTest/res/values-sw213dp/styles.xml
similarity index 100%
rename from wear/tests/res/values-sw213dp/styles.xml
rename to wear/src/androidTest/res/values-sw213dp/styles.xml
diff --git a/wear/tests/res/values/colors.xml b/wear/src/androidTest/res/values/colors.xml
similarity index 100%
rename from wear/tests/res/values/colors.xml
rename to wear/src/androidTest/res/values/colors.xml
diff --git a/wear/tests/res/values/dimens.xml b/wear/src/androidTest/res/values/dimens.xml
similarity index 100%
rename from wear/tests/res/values/dimens.xml
rename to wear/src/androidTest/res/values/dimens.xml
diff --git a/wear/tests/res/values/styles.xml b/wear/src/androidTest/res/values/styles.xml
similarity index 100%
rename from wear/tests/res/values/styles.xml
rename to wear/src/androidTest/res/values/styles.xml
diff --git a/wear/AndroidManifest.xml b/wear/src/main/AndroidManifest.xml
similarity index 100%
rename from wear/AndroidManifest.xml
rename to wear/src/main/AndroidManifest.xml
diff --git a/wear/src/main/java/android/support/wear/ambient/AmbientMode.java b/wear/src/main/java/android/support/wear/ambient/AmbientMode.java
index 0077a5b..d3a8a43 100644
--- a/wear/src/main/java/android/support/wear/ambient/AmbientMode.java
+++ b/wear/src/main/java/android/support/wear/ambient/AmbientMode.java
@@ -48,7 +48,9 @@
  *     AmbientMode.AmbientController controller = AmbientMode.attachAmbientSupport(this);
  *     boolean isAmbient =  controller.isAmbient();
  * }</pre>
+ * @deprecated please use {@link AmbientModeSupport} instead.
  */
+@Deprecated
 public final class AmbientMode extends Fragment {
     private static final String TAG = "AmbientMode";
 
diff --git a/wear/src/main/java/android/support/wear/ambient/AmbientModeSupport.java b/wear/src/main/java/android/support/wear/ambient/AmbientModeSupport.java
new file mode 100644
index 0000000..97e26d9
--- /dev/null
+++ b/wear/src/main/java/android/support/wear/ambient/AmbientModeSupport.java
@@ -0,0 +1,281 @@
+/*
+ * 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.wear.ambient;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.CallSuper;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.util.Log;
+
+import com.google.android.wearable.compat.WearableActivityController;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Use this as a headless Fragment to add ambient support to an Activity on Wearable devices.
+ * <p>
+ * The application that uses this should add the {@link android.Manifest.permission#WAKE_LOCK}
+ * permission to its manifest.
+ * <p>
+ * The primary entry  point for this code is the {@link #attach(FragmentActivity)} method.
+ * It should be called with an {@link FragmentActivity} as an argument and that
+ * {@link FragmentActivity} will then be able to receive ambient lifecycle events through
+ * an {@link AmbientCallback}. The {@link FragmentActivity} will also receive a
+ * {@link AmbientController} object from the attachment which can be used to query the current
+ * status of the ambient mode. An example of how to attach {@link AmbientModeSupport} to your
+ * {@link FragmentActivity} and use the {@link AmbientController} can be found below:
+ * <p>
+ * <pre class="prettyprint">{@code
+ *     AmbientMode.AmbientController controller = AmbientMode.attachAmbientSupport(this);
+ *     boolean isAmbient =  controller.isAmbient();
+ * }</pre>
+ */
+public final class AmbientModeSupport extends Fragment {
+    private static final String TAG = "AmbientMode";
+
+    /**
+     * Property in bundle passed to {@code AmbientCallback#onEnterAmbient(Bundle)} to indicate
+     * whether burn-in protection is required. When this property is set to true, views must be
+     * shifted around periodically in ambient mode. To ensure that content isn't shifted off
+     * the screen, avoid placing content within 10 pixels of the edge of the screen. Activities
+     * should also avoid solid white areas to prevent pixel burn-in. Both of these requirements
+     * only apply in ambient mode, and only when this property is set to true.
+     */
+    public static final String EXTRA_BURN_IN_PROTECTION =
+            WearableActivityController.EXTRA_BURN_IN_PROTECTION;
+
+    /**
+     * Property in bundle passed to {@code AmbientCallback#onEnterAmbient(Bundle)} to indicate
+     * whether the device has low-bit ambient mode. When this property is set to true, the screen
+     * supports fewer bits for each color in ambient mode. In this case, activities should disable
+     * anti-aliasing in ambient mode.
+     */
+    public static final String EXTRA_LOWBIT_AMBIENT =
+            WearableActivityController.EXTRA_LOWBIT_AMBIENT;
+
+    /**
+     * Fragment tag used by default when adding {@link AmbientModeSupport} to add ambient support to
+     * a {@link FragmentActivity}.
+     */
+    public static final String FRAGMENT_TAG = "android.support.wearable.ambient.AmbientMode";
+
+    /**
+     * Interface for any {@link Activity} that wishes to implement Ambient Mode. Use the
+     * {@link #getAmbientCallback()} method to return and {@link AmbientCallback} which can be used
+     * to bind the {@link AmbientModeSupport} to the instantiation of this interface.
+     * <p>
+     * <pre class="prettyprint">{@code
+     * return new AmbientMode.AmbientCallback() {
+     *     public void onEnterAmbient(Bundle ambientDetails) {...}
+     *     public void onExitAmbient(Bundle ambientDetails) {...}
+     *  }
+     * }</pre>
+     */
+    public interface AmbientCallbackProvider {
+        /**
+         * @return the {@link AmbientCallback} to be used by this class to communicate with the
+         * entity interested in ambient events.
+         */
+        AmbientCallback getAmbientCallback();
+    }
+
+    /**
+     * Callback to receive ambient mode state changes. It must be used by all users of AmbientMode.
+     */
+    public abstract static class AmbientCallback {
+        /**
+         * Called when an activity is entering ambient mode. This event is sent while an activity is
+         * running (after onResume, before onPause). All drawing should complete by the conclusion
+         * of this method. Note that {@code invalidate()} calls will be executed before resuming
+         * lower-power mode.
+         *
+         * @param ambientDetails bundle containing information about the display being used.
+         *                      It includes information about low-bit color and burn-in protection.
+         */
+        public void onEnterAmbient(Bundle ambientDetails) {}
+
+        /**
+         * Called when the system is updating the display for ambient mode. Activities may use this
+         * opportunity to update or invalidate views.
+         */
+        public void onUpdateAmbient() {}
+
+        /**
+         * Called when an activity should exit ambient mode. This event is sent while an activity is
+         * running (after onResume, before onPause).
+         */
+        public void onExitAmbient() {}
+    }
+
+    private final AmbientDelegate.AmbientCallback mCallback =
+            new AmbientDelegate.AmbientCallback() {
+                @Override
+                public void onEnterAmbient(Bundle ambientDetails) {
+                    if (mSuppliedCallback != null) {
+                        mSuppliedCallback.onEnterAmbient(ambientDetails);
+                    }
+                }
+
+                @Override
+                public void onExitAmbient() {
+                    if (mSuppliedCallback != null) {
+                        mSuppliedCallback.onExitAmbient();
+                    }
+                }
+
+                @Override
+                public void onUpdateAmbient() {
+                    if (mSuppliedCallback != null) {
+                        mSuppliedCallback.onUpdateAmbient();
+                    }
+                }
+            };
+    private AmbientDelegate mDelegate;
+    @Nullable
+    private AmbientCallback mSuppliedCallback;
+    private AmbientController mController;
+
+    /**
+     * Constructor
+     */
+    public AmbientModeSupport() {
+        mController = new AmbientController();
+    }
+
+    @Override
+    @CallSuper
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        mDelegate = new AmbientDelegate(getActivity(), new WearableControllerProvider(), mCallback);
+
+        if (context instanceof AmbientCallbackProvider) {
+            mSuppliedCallback = ((AmbientCallbackProvider) context).getAmbientCallback();
+        } else {
+            Log.w(TAG, "No callback provided - enabling only smart resume");
+        }
+    }
+
+    @Override
+    @CallSuper
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mDelegate.onCreate();
+        if (mSuppliedCallback != null) {
+            mDelegate.setAmbientEnabled();
+        }
+    }
+
+    @Override
+    @CallSuper
+    public void onResume() {
+        super.onResume();
+        mDelegate.onResume();
+    }
+
+    @Override
+    @CallSuper
+    public void onPause() {
+        mDelegate.onPause();
+        super.onPause();
+    }
+
+    @Override
+    @CallSuper
+    public void onStop() {
+        mDelegate.onStop();
+        super.onStop();
+    }
+
+    @Override
+    @CallSuper
+    public void onDestroy() {
+        mDelegate.onDestroy();
+        super.onDestroy();
+    }
+
+    @Override
+    @CallSuper
+    public void onDetach() {
+        mDelegate = null;
+        super.onDetach();
+    }
+
+    /**
+     * Attach ambient support to the given activity. Calling this method with an Activity
+     * implementing the {@link AmbientCallbackProvider} interface will provide you with an
+     * opportunity to react to ambient events such as {@code onEnterAmbient}. Alternatively,
+     * you can call this method with an Activity which does not implement
+     * the {@link AmbientCallbackProvider} interface and that will only enable the auto-resume
+     * functionality. This is equivalent to providing (@code null} from
+     * the {@link AmbientCallbackProvider}.
+     *
+     * @param activity the activity to attach ambient support to.
+     * @return the associated {@link AmbientController} which can be used to query the state of
+     * ambient mode.
+     */
+    public static <T extends FragmentActivity> AmbientController attach(T activity) {
+        FragmentManager fragmentManager = activity.getSupportFragmentManager();
+        AmbientModeSupport ambientFragment =
+                (AmbientModeSupport) fragmentManager.findFragmentByTag(FRAGMENT_TAG);
+        if (ambientFragment == null) {
+            AmbientModeSupport fragment = new AmbientModeSupport();
+            fragmentManager
+                    .beginTransaction()
+                    .add(fragment, FRAGMENT_TAG)
+                    .commit();
+            ambientFragment = fragment;
+        }
+        return ambientFragment.mController;
+    }
+
+    @Override
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        if (mDelegate != null) {
+            mDelegate.dump(prefix, fd, writer, args);
+        }
+    }
+
+    @VisibleForTesting
+    void setAmbientDelegate(AmbientDelegate delegate) {
+        mDelegate = delegate;
+    }
+
+    /**
+     * A class for interacting with the ambient mode on a wearable device. This class can be used to
+     * query the current state of ambient mode. An instance of this class is returned to the user
+     * when they attach their {@link Activity} to {@link AmbientModeSupport}.
+     */
+    public final class AmbientController {
+        private static final String TAG = "AmbientController";
+
+        // Do not initialize outside of this class.
+        AmbientController() {}
+
+        /**
+         * @return {@code true} if the activity is currently in ambient.
+         */
+        public boolean isAmbient() {
+            return mDelegate == null ? false : mDelegate.isAmbient();
+        }
+    }
+}
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientModeSupportResumeTest.java b/wear/tests/src/android/support/wear/ambient/AmbientModeSupportResumeTest.java
new file mode 100644
index 0000000..1f50105
--- /dev/null
+++ b/wear/tests/src/android/support/wear/ambient/AmbientModeSupportResumeTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 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.wear.ambient;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.wear.widget.util.WakeLockRule;
+
+import com.google.android.wearable.compat.WearableActivityController;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class AmbientModeSupportResumeTest {
+    @Rule
+    public final WakeLockRule mWakeLock = new WakeLockRule();
+
+    @Rule
+    public final ActivityTestRule<AmbientModeSupportResumeTestActivity> mActivityRule =
+            new ActivityTestRule<>(AmbientModeSupportResumeTestActivity.class);
+
+    @Test
+    public void testActivityDefaults() throws Throwable {
+        assertTrue(WearableActivityController.getLastInstance().isAutoResumeEnabled());
+        assertFalse(WearableActivityController.getLastInstance().isAmbientEnabled());
+    }
+}
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientModeSupportResumeTestActivity.java b/wear/tests/src/android/support/wear/ambient/AmbientModeSupportResumeTestActivity.java
new file mode 100644
index 0000000..8fb1fe5
--- /dev/null
+++ b/wear/tests/src/android/support/wear/ambient/AmbientModeSupportResumeTestActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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.wear.ambient;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+public class AmbientModeSupportResumeTestActivity extends FragmentActivity {
+    AmbientModeSupport.AmbientController mAmbientController;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAmbientController = AmbientModeSupport.attach(this);
+    }
+}
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientModeSupportTest.java b/wear/tests/src/android/support/wear/ambient/AmbientModeSupportTest.java
new file mode 100644
index 0000000..226d39b
--- /dev/null
+++ b/wear/tests/src/android/support/wear/ambient/AmbientModeSupportTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.wear.ambient;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.wear.widget.util.WakeLockRule;
+
+import com.google.android.wearable.compat.WearableActivityController;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class AmbientModeSupportTest {
+    @Rule
+    public final WakeLockRule mWakeLock = new WakeLockRule();
+
+    @Rule
+    public final ActivityTestRule<AmbientModeSupportTestActivity> mActivityRule =
+            new ActivityTestRule<>(AmbientModeSupportTestActivity.class);
+
+    @Test
+    public void testEnterAmbientCallback() throws Throwable {
+        AmbientModeSupportTestActivity activity = mActivityRule.getActivity();
+
+        WearableActivityController.getLastInstance().enterAmbient();
+        assertTrue(activity.mEnterAmbientCalled);
+        assertFalse(activity.mUpdateAmbientCalled);
+        assertFalse(activity.mExitAmbientCalled);
+    }
+
+    @Test
+    public void testUpdateAmbientCallback() throws Throwable {
+        AmbientModeSupportTestActivity activity = mActivityRule.getActivity();
+
+        WearableActivityController.getLastInstance().updateAmbient();
+        assertFalse(activity.mEnterAmbientCalled);
+        assertTrue(activity.mUpdateAmbientCalled);
+        assertFalse(activity.mExitAmbientCalled);
+    }
+
+    @Test
+    public void testExitAmbientCallback() throws Throwable {
+        AmbientModeSupportTestActivity activity = mActivityRule.getActivity();
+
+        WearableActivityController.getLastInstance().exitAmbient();
+        assertFalse(activity.mEnterAmbientCalled);
+        assertFalse(activity.mUpdateAmbientCalled);
+        assertTrue(activity.mExitAmbientCalled);
+    }
+
+    @Test
+    public void testIsAmbientEnabled() {
+        assertTrue(WearableActivityController.getLastInstance().isAmbientEnabled());
+    }
+
+    @Test
+    public void testCallsControllerIsAmbient() {
+        AmbientModeSupportTestActivity activity = mActivityRule.getActivity();
+
+        WearableActivityController.getLastInstance().setAmbient(true);
+        assertTrue(activity.getAmbientController().isAmbient());
+
+        WearableActivityController.getLastInstance().setAmbient(false);
+        assertFalse(activity.getAmbientController().isAmbient());
+    }
+}
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientModeSupportTestActivity.java b/wear/tests/src/android/support/wear/ambient/AmbientModeSupportTestActivity.java
new file mode 100644
index 0000000..fc33edf
--- /dev/null
+++ b/wear/tests/src/android/support/wear/ambient/AmbientModeSupportTestActivity.java
@@ -0,0 +1,62 @@
+/*
+ * 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.wear.ambient;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+public class AmbientModeSupportTestActivity extends FragmentActivity
+        implements AmbientModeSupport.AmbientCallbackProvider {
+    AmbientModeSupport.AmbientController mAmbientController;
+
+    boolean mEnterAmbientCalled;
+    boolean mUpdateAmbientCalled;
+    boolean mExitAmbientCalled;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAmbientController = AmbientModeSupport.attach(this);
+    }
+
+    @Override
+    public AmbientModeSupport.AmbientCallback getAmbientCallback() {
+        return new MyAmbientCallback();
+    }
+
+    private class MyAmbientCallback extends AmbientModeSupport.AmbientCallback {
+
+        @Override
+        public void onEnterAmbient(Bundle ambientDetails) {
+            mEnterAmbientCalled = true;
+        }
+
+        @Override
+        public void onUpdateAmbient() {
+            mUpdateAmbientCalled = true;
+        }
+
+        @Override
+        public void onExitAmbient() {
+            mExitAmbientCalled = true;
+        }
+    }
+
+    public AmbientModeSupport.AmbientController getAmbientController() {
+        return mAmbientController;
+    }
+
+}
diff --git a/webkit/lint-baseline.xml b/webkit/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/webkit/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>