Merge pie-platform-release to aosp-master - DO NOT MERGE

Change-Id: Icc267572262e5cfedfb69a1fb1698d6208a91de0
diff --git a/app-toolkit/common/src/main/java/androidx/arch/core/internal/SafeIterableMap.java b/app-toolkit/common/src/main/java/androidx/arch/core/internal/SafeIterableMap.java
index 8f3d7ce..bda1259 100644
--- a/app-toolkit/common/src/main/java/androidx/arch/core/internal/SafeIterableMap.java
+++ b/app-toolkit/common/src/main/java/androidx/arch/core/internal/SafeIterableMap.java
@@ -240,7 +240,6 @@
             return mNext != null;
         }
 
-        @SuppressWarnings("ReferenceEquality")
         @Override
         public void supportRemove(@NonNull Entry<K, V> entry) {
             if (mExpectedEnd == entry && entry == mNext) {
@@ -257,7 +256,6 @@
             }
         }
 
-        @SuppressWarnings("ReferenceEquality")
         private Entry<K, V> nextNode() {
             if (mNext == mExpectedEnd || mExpectedEnd == null) {
                 return null;
@@ -314,7 +312,6 @@
         private Entry<K, V> mCurrent;
         private boolean mBeforeStart = true;
 
-        @SuppressWarnings("ReferenceEquality")
         @Override
         public void supportRemove(@NonNull Entry<K, V> entry) {
             if (entry == mCurrent) {
@@ -382,7 +379,6 @@
             return mKey + "=" + mValue;
         }
 
-        @SuppressWarnings("ReferenceEquality")
         @Override
         public boolean equals(Object obj) {
             if (obj == this) {
diff --git a/app-toolkit/settings.gradle b/app-toolkit/settings.gradle
index a85d87c..817b552 100644
--- a/app-toolkit/settings.gradle
+++ b/app-toolkit/settings.gradle
@@ -64,7 +64,6 @@
 includeProject(":lifecycle:lifecycle-runtime", new File(supportRoot, "lifecycle/runtime"))
 includeProject(":lifecycle:lifecycle-service", new File(supportRoot, "lifecycle/service"))
 includeProject(":lifecycle:lifecycle-viewmodel", new File(supportRoot, "lifecycle/viewmodel"))
-includeProject(":lifecycle:lifecycle-viewmodel-ktx", new File(supportRoot, "lifecycle/viewmodel/ktx"))
 includeProject(":paging:integration-tests:testapp", new File(supportRoot, "paging/integration-tests/testapp"))
 includeProject(":paging:paging-common", new File(supportRoot, "paging/common"))
 includeProject(":paging:paging-runtime", new File(supportRoot, "paging/runtime"))
diff --git a/buildSrc/dependencies.gradle b/buildSrc/dependencies.gradle
index f7928eb..2608258 100644
--- a/buildSrc/dependencies.gradle
+++ b/buildSrc/dependencies.gradle
@@ -30,18 +30,6 @@
     exclude group: 'androidx.annotation'
 }
 
-libs.exclude_for_material = {
-    transitive = true
-    exclude group: 'androidx.annotation'
-    exclude group: 'androidx.core'
-    exclude group: 'androidx.legacy'
-    exclude group: 'androidx.fragment'
-    exclude group: 'androidx.transition'
-    exclude group: 'androidx.appcompat'
-    exclude group: 'androidx.recyclerview'
-    exclude group: 'androidx.cardview'
-}
-
 libs.exclude_for_espresso = {
     exclude group: 'androidx.annotation'
     exclude group: 'androidx.appcompat'
diff --git a/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt b/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
index 40ed9c4d..e74ee0c 100644
--- a/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
@@ -27,6 +27,7 @@
 import androidx.build.doclava.CHECK_API_CONFIG_RELEASE
 import androidx.build.doclava.CHECK_API_CONFIG_PATCH
 import androidx.build.doclava.ChecksConfig
+import androidx.build.docs.ConcatenateFilesTask
 import androidx.build.docs.GenerateDocsTask
 import androidx.build.jdiff.JDiffTask
 import com.android.build.gradle.AppExtension
@@ -46,6 +47,8 @@
 import org.gradle.api.tasks.compile.JavaCompile
 import org.gradle.api.tasks.javadoc.Javadoc
 import java.io.File
+import java.time.LocalDateTime
+import java.time.format.DateTimeFormatter
 import kotlin.collections.Collection
 import kotlin.collections.List
 import kotlin.collections.MutableMap
@@ -69,7 +72,13 @@
 
     private lateinit var rules: List<PublishDocsRules>
     private val docsTasks: MutableMap<String, GenerateDocsTask> = mutableMapOf()
+    private lateinit var aggregateOldApiTxtsTask: ConcatenateFilesTask
+    private lateinit var aggregateNewApiTxtsTask: ConcatenateFilesTask
+    private lateinit var generateDiffsTask: JDiffTask
 
+    /**
+     * Initialization that should happen only once (and on the root project)
+     */
     @JvmStatic
     fun configureDiffAndDocs(
         root: Project,
@@ -82,6 +91,10 @@
         anchorTask = root.tasks.create("anchorDocsTask")
         val doclavaConfiguration = root.configurations.getByName("doclava")
         val generateSdkApiTask = createGenerateSdkApiTask(root, doclavaConfiguration)
+        val now = LocalDateTime.now()
+        // The diff output assumes that each library is of the same version, but our libraries may each be of different versions
+        // So, we display the date as the new version
+        val newVersion = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
         rules.forEach {
             val task = createGenerateDocsTask(
                     project = root, generateSdkApiTask = generateSdkApiTask,
@@ -95,7 +108,41 @@
 
         root.tasks.create("generateDocs").dependsOn(docsTasks[TIP_OF_TREE.name])
 
+        val docletClasspath = doclavaConfiguration.resolve()
+
+        aggregateOldApiTxtsTask = root.tasks.create("aggregateOldApiTxts", ConcatenateFilesTask::class.java)
+        aggregateOldApiTxtsTask.Output = File(root.docsDir(), "previous.txt")
+
+        val oldApisTask = root.tasks.createWithConfig("oldApisXml", ApiXmlConversionTask::class.java) {
+            classpath = root.files(docletClasspath)
+            dependsOn(doclavaConfiguration)
+
+            inputApiFile = aggregateOldApiTxtsTask.Output
+            dependsOn(aggregateOldApiTxtsTask)
+
+            outputApiXmlFile = File(root.docsDir(), "previous.xml")
+        }
+
+        aggregateNewApiTxtsTask = root.tasks.create("aggregateNewApiTxts", ConcatenateFilesTask::class.java)
+        aggregateNewApiTxtsTask.Output = File(root.docsDir(), "$newVersion")
+
+        val newApisTask = root.tasks.createWithConfig("newApisXml", ApiXmlConversionTask::class.java) {
+            classpath = root.files(docletClasspath)
+
+            inputApiFile = aggregateNewApiTxtsTask.Output
+            dependsOn(aggregateNewApiTxtsTask)
+
+            outputApiXmlFile = File(root.docsDir(), "$newVersion.xml")
+        }
+
+        val jdiffConfiguration = root.configurations.getByName("jdiff")
+        generateDiffsTask = createGenerateDiffsTask(root,
+                oldApisTask,
+                newApisTask,
+                jdiffConfiguration)
+
         setupDocsProject()
+
         return anchorTask
     }
 
@@ -185,7 +232,7 @@
     }
 
     /**
-     * Registers a Java project for global docs generation, local API file generation, and
+     * Registers a Java project to be included in docs generation, local API file generation, and
      * local API diff generation tasks.
      */
     fun registerJavaProject(project: Project, extension: SupportLibraryExtension) {
@@ -205,16 +252,16 @@
                     "ignoring API tasks.")
             return
         }
-        val tasks = initializeApiChecksForProject(project)
+        val tasks = initializeApiChecksForProject(project, aggregateOldApiTxtsTask, aggregateNewApiTxtsTask)
         registerJavaProjectForDocsTask(tasks.generateApi, compileJava)
-        registerJavaProjectForDocsTask(tasks.generateDiffs, compileJava)
+        registerJavaProjectForDocsTask(generateDiffsTask, compileJava)
         setupDocsTasks(project, tasks)
         anchorTask.dependsOn(tasks.checkApiTask)
     }
 
     /**
-     * Registers an Android project for global docs generation, local API file generation, and
-     * local API diff generation tasks.
+     * Registers an Android project to be included in global docs generation, local API file
+     * generation, and local API diff generation tasks.
      */
     fun registerAndroidProject(
         project: Project,
@@ -248,9 +295,9 @@
                             "an api folder, ignoring API tasks.")
                     return@all
                 }
-                val tasks = initializeApiChecksForProject(project)
+                val tasks = initializeApiChecksForProject(project, aggregateOldApiTxtsTask, aggregateNewApiTxtsTask)
                 registerAndroidProjectForDocsTask(tasks.generateApi, variant)
-                registerAndroidProjectForDocsTask(tasks.generateDiffs, variant)
+                registerAndroidProjectForDocsTask(generateDiffsTask, variant)
                 setupDocsTasks(project, tasks)
                 anchorTask.dependsOn(tasks.checkApiTask)
             }
@@ -259,7 +306,7 @@
 
     private fun setupDocsTasks(project: Project, tasks: Tasks) {
         docsTasks.values.forEach { docs ->
-            tasks.generateDiffs.dependsOn(docs)
+            generateDiffsTask.dependsOn(docs)
             // Track API change history.
             docs.addSinceFilesFrom(project.projectDir)
             // Associate current API surface with the Maven artifact.
@@ -281,21 +328,20 @@
 
 private fun getLastReleasedApiFile(rootFolder: File, refVersion: Version?): File? {
     val apiDir = File(rootFolder, "api")
-    val lastFile = getLastReleasedApiFileFromDir(apiDir, refVersion)
-    if (lastFile != null) {
-        return lastFile
-    }
-
-    return null
+    return getLastReleasedApiFileFromDir(apiDir, refVersion)
 }
 
+/**
+ * Returns the api file with highest version among those having version less than refVersion
+ */
 private fun getLastReleasedApiFileFromDir(apiDir: File, refVersion: Version?): File? {
     var lastFile: File? = null
     var lastVersion: Version? = null
     apiDir.listFiles().forEach { file ->
-        Version.parseOrNull(file)?.let { version ->
-            if ((lastFile == null || lastVersion!! < version) &&
-                    (refVersion == null || version < refVersion)) {
+        val parsed = Version.parseOrNull(file)
+        parsed?.let { version ->
+            if ((lastFile == null || lastVersion!! < version)
+                    && (refVersion == null || version < refVersion)) {
                 lastFile = file
                 lastVersion = version
             }
@@ -327,7 +373,8 @@
     return File(apiDir, "current.txt")
 }
 
-// Generates API files
+
+// Creates a new task on the project for generating API files
 private fun createGenerateApiTask(project: Project, docletpathParam: Collection<File>) =
         project.tasks.createWithConfig("generateApi", DoclavaTask::class.java) {
             setDocletpath(docletpathParam)
@@ -345,6 +392,7 @@
             exclude("**/R.java")
         }
 
+// Creates a new task on the project for verifying the API
 private fun createCheckApiTask(
     project: Project,
     taskName: String,
@@ -437,57 +485,37 @@
         }
 
 /**
- * Converts the <code>fromApi</code>.txt file (or the most recently released
- * X.Y.Z.txt if not explicitly defined using -PfromAPi=<file>) to XML format
- * for use by JDiff.
+ * Returns the filepath of the previous API txt file (for computing diffs against)
  */
-private fun createOldApiXml(project: Project, doclavaConfig: Configuration) =
-        project.tasks.createWithConfig("oldApiXml", ApiXmlConversionTask::class.java) {
-            val toApi = project.processProperty("toApi")?.let {
-                Version.parseOrNull(it)
-            }
-            val fromApi = project.processProperty("fromApi")
-            classpath = project.files(doclavaConfig.resolve())
-            val rootFolder = project.projectDir
-            inputApiFile = if (fromApi != null) {
-                // Use an explicit API file.
-                File(rootFolder, "api/$fromApi.txt")
-            } else {
-                // Use the most recently released API file bounded by toApi.
-                getLastReleasedApiFile(rootFolder, toApi)
-            }
+private fun getOldApiTxt(project: Project): File? {
+    val toApi = project.processProperty("toApi")?.let {
+        Version.parseOrNull(it)
+    }
+    val fromApi = project.processProperty("fromApi")
+    val rootFolder = project.projectDir
+    if (fromApi != null) {
+        // Use an explicit API file.
+        return File(rootFolder, "api/$fromApi.txt")
+    } else {
+        // Use the most recently released API file bounded by toApi.
+        return getLastReleasedApiFile(rootFolder, toApi)
+    }
+}
 
-            outputApiXmlFile = File(project.docsDir(),
-                    "release/${stripExtension(inputApiFile?.name ?: "creation")}.xml")
 
-            dependsOn(doclavaConfig)
-        }
+data class FileProvider(val file: File, val task: Task?)
 
-/**
- * Converts the <code>toApi</code>.txt file (or current.txt if not explicitly
- * defined using -PtoApi=<file>) to XML format for use by JDiff.
- */
-private fun createNewApiXmlTask(
-    project: Project,
-    generateApi: DoclavaTask,
-    doclavaConfig: Configuration
-) =
-        project.tasks.createWithConfig("newApiXml", ApiXmlConversionTask::class.java) {
-            classpath = project.files(doclavaConfig.resolve())
-            val toApi = project.processProperty("toApi")
+private fun getNewApiTxt(project: Project, generateApi: DoclavaTask): FileProvider {
+    val toApi = project.processProperty("toApi")
+    if (toApi != null) {
+        // Use an explicit API file.
+        return FileProvider(File(project.projectDir, "api/$toApi.txt"), null)
+    } else {
+        // Use the current API file (e.g. current.txt).
+        return FileProvider(generateApi.apiFile!!, generateApi)
+    }
 
-            if (toApi != null) {
-                // Use an explicit API file.
-                inputApiFile = File(project.projectDir, "api/$toApi.txt")
-            } else {
-                // Use the current API file (e.g. current.txt).
-                inputApiFile = generateApi.apiFile!!
-                dependsOn(generateApi, doclavaConfig)
-            }
-
-            outputApiXmlFile = File(project.docsDir(),
-                    "release/${stripExtension(inputApiFile?.name ?: "creation")}.xml")
-        }
+}
 
 /**
  * Generates API diffs.
@@ -532,7 +560,7 @@
             newApiXmlFile = newApiTask.outputApiXmlFile
 
             val newApi = newApiXmlFile.name.substringBeforeLast('.')
-            val docsDir = project.rootProject.docsDir()
+            val docsDir = File(project.rootProject.docsDir(), "public")
 
             newJavadocPrefix = "../../../../../reference/"
             destinationDir = File(docsDir, "online/sdk/support_api_diff/${project.name}/$newApi")
@@ -543,6 +571,9 @@
 
             exclude("**/BuildConfig.java", "**/R.java")
             dependsOn(oldApiTask, newApiTask, jdiffConfig)
+            doLast {
+                project.logger.lifecycle("generated diffs into $destinationDir")
+            }
         }
 
 // Generates a distribution artifact for online docs.
@@ -642,11 +673,13 @@
 
 private data class Tasks(
     val generateApi: DoclavaTask,
-    val generateDiffs: JDiffTask,
     val checkApiTask: CheckApiTask
 )
 
-private fun initializeApiChecksForProject(project: Project): Tasks {
+/**
+ * Sets up api tasks for the given project
+ */
+private fun initializeApiChecksForProject(project: Project, aggregateOldApiTxtsTask: ConcatenateFilesTask, aggregateNewApiTxtsTask:ConcatenateFilesTask): Tasks {
     if (!project.hasProperty("docsDir")) {
         project.extensions.add("docsDir", File(project.rootProject.docsDir(), project.name))
     }
@@ -658,7 +691,7 @@
     val generateApi = createGenerateApiTask(project, docletClasspath)
     generateApi.dependsOn(doclavaConfiguration)
 
-    // Make sure the API surface has not broken since the last release.
+    // for verifying that the API surface has not broken since the last release
     val lastReleasedApiFile = getLastReleasedApiFile(workingDir, version)
 
     val whitelistFile = lastReleasedApiFile?.let { apiFile ->
@@ -696,15 +729,20 @@
 
     val updateApiTask = createUpdateApiTask(project, checkApiRelease)
     updateApiTask.dependsOn(checkApiRelease)
-    val newApiTask = createNewApiXmlTask(project, generateApi, doclavaConfiguration)
-    val oldApiTask = createOldApiXml(project, doclavaConfiguration)
 
-    val jdiffConfiguration = project.rootProject.configurations.getByName("jdiff")
-    val generateDiffTask = createGenerateDiffsTask(project,
-            oldApiTask,
-            newApiTask,
-            jdiffConfiguration)
-    return Tasks(generateApi, generateDiffTask, checkApi)
+
+    val oldApiTxt = getOldApiTxt(project)
+    if (oldApiTxt != null) {
+        aggregateOldApiTxtsTask.addInput(project.name, oldApiTxt)
+    }
+    val newApiTxtProvider = getNewApiTxt(project, generateApi)
+    aggregateNewApiTxtsTask.inputs.file(newApiTxtProvider.file)
+    aggregateNewApiTxtsTask.addInput(project.name, newApiTxtProvider.file)
+    if (newApiTxtProvider.task != null) {
+        aggregateNewApiTxtsTask.dependsOn(newApiTxtProvider.task)
+    }
+
+    return Tasks(generateApi, checkApi)
 }
 
 fun hasApiTasks(project: Project, extension: SupportLibraryExtension): Boolean {
diff --git a/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt b/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
index 7b0887d..be10aa6 100644
--- a/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
@@ -45,8 +45,6 @@
             "-Xep:JavaLangClash:ERROR",
             "-Xep:PrivateConstructorForUtilityClass:ERROR",
             "-Xep:TypeParameterUnusedInFormals:ERROR",
-            "-Xep:StringSplitter:ERROR",
-            "-Xep:ReferenceEquality:ERROR",
 
             // Nullaway
             "-XepIgnoreUnknownCheckNames", // https://github.com/uber/NullAway/issues/25
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt
index 66a302f..aad5982 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt
@@ -47,6 +47,7 @@
     const val LOCALBROADCASTMANAGER = "androidx.localbroadcastmanager"
     const val MEDIA = "androidx.media"
     const val MEDIAROUTER = "androidx.mediarouter"
+    const val MEDIAWIDGET = "androidx.mediawidget"
     const val PALETTE = "androidx.palette"
     const val PERCENTLAYOUT = "androidx.percentlayout"
     const val PREFERENCE = "androidx.preference"
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index 12160e1..7d81cd8 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -87,7 +87,7 @@
     /**
      * Version code for WorkManager
      */
-    val WORKMANAGER = Version("1.0.0-alpha02")
+    val WORKMANAGER = Version("1.0.0-alpha04")
 
     /**
      * Version code for Jetifier
diff --git a/buildSrc/src/main/kotlin/androidx/build/SupportJavaLibraryPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/SupportJavaLibraryPlugin.kt
index cee2955..e8bd816 100644
--- a/buildSrc/src/main/kotlin/androidx/build/SupportJavaLibraryPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/SupportJavaLibraryPlugin.kt
@@ -23,7 +23,6 @@
 import org.gradle.api.Plugin
 import org.gradle.api.Project
 import org.gradle.api.plugins.JavaPluginConvention
-import org.gradle.api.tasks.bundling.Jar
 import org.gradle.api.tasks.compile.JavaCompile
 
 /**
@@ -48,11 +47,6 @@
                 convention.targetCompatibility = JavaVersion.VERSION_1_7
             }
             DiffAndDocs.registerJavaProject(project, supportLibraryExtension)
-
-            project.tasks.withType(Jar::class.java) { jarTask ->
-                jarTask.setReproducibleFileOrder(true)
-                jarTask.setPreserveFileTimestamps(false)
-            }
         }
 
         project.apply(mapOf("plugin" to ErrorProneBasePlugin::class.java))
diff --git a/buildSrc/src/main/kotlin/androidx/build/SupportKotlinLibraryPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/SupportKotlinLibraryPlugin.kt
index 9558f76..d2a6ddba 100644
--- a/buildSrc/src/main/kotlin/androidx/build/SupportKotlinLibraryPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/SupportKotlinLibraryPlugin.kt
@@ -20,7 +20,6 @@
 import org.gradle.api.Plugin
 import org.gradle.api.Project
 import org.gradle.api.plugins.JavaPluginConvention
-import org.gradle.api.tasks.bundling.Jar
 
 class SupportKotlinLibraryPlugin : Plugin<Project> {
     override fun apply(project: Project) {
@@ -39,12 +38,6 @@
                 convention.sourceCompatibility = JavaVersion.VERSION_1_7
                 convention.targetCompatibility = JavaVersion.VERSION_1_7
             }
-
-            project.tasks.withType(Jar::class.java) { jarTask ->
-                jarTask.setReproducibleFileOrder(true)
-                jarTask.setPreserveFileTimestamps(false)
-            }
-
         }
 
         CheckExternalDependencyLicensesTask.configure(project)
diff --git a/buildSrc/src/main/kotlin/androidx/build/checkapi/ApiXmlConversionTask.kt b/buildSrc/src/main/kotlin/androidx/build/checkapi/ApiXmlConversionTask.kt
index f66706c..b191d56 100644
--- a/buildSrc/src/main/kotlin/androidx/build/checkapi/ApiXmlConversionTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/checkapi/ApiXmlConversionTask.kt
@@ -23,7 +23,7 @@
 import java.io.File
 
 /**
- * Task that converts the given API file to XML format.
+ * Task that converts the given API txt file to XML format.
  */
 open class ApiXmlConversionTask : JavaExec() {
     @Optional
diff --git a/buildSrc/src/main/kotlin/androidx/build/docs/ConcatenateFilesTask.kt b/buildSrc/src/main/kotlin/androidx/build/docs/ConcatenateFilesTask.kt
new file mode 100644
index 0000000..d97c701
--- /dev/null
+++ b/buildSrc/src/main/kotlin/androidx/build/docs/ConcatenateFilesTask.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.build.docs
+
+import org.gradle.api.Action
+import org.gradle.api.DefaultTask
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.OutputFile
+import java.io.File
+import java.util.SortedMap
+
+open class ConcatenateFilesTask : DefaultTask() {
+    private var keyedInputs: MutableMap<String, File> = mutableMapOf()
+
+    @get:OutputFile
+    lateinit var Output: File
+
+    // Adds the given input file
+    // The order that files are concatenated in is based on sorting the corresponding keys
+    fun addInput(key: String, inputFile: File) {
+        if (this.keyedInputs.containsKey(key)) {
+            throw IllegalArgumentException("Key $key already exists")
+        }
+        this.inputs.file(inputFile)
+        this.keyedInputs[key] = inputFile
+    }
+
+    @TaskAction
+    fun aggregate() {
+        val destFile = this.Output
+
+        // sort the input files to make sure this task always concatenates them in the same order
+        val sortedInputs = this.keyedInputs.toSortedMap()
+
+        val inputFiles = sortedInputs.values
+        if (inputFiles.contains(destFile)) {
+            throw IllegalArgumentException("Output file $destFile is also an input file")
+        }
+
+        val text = inputFiles.joinToString(separator = "") { file -> file.readText() }
+        this.project.logger.info("Joining ${inputFiles.count()} files, and storing the result in ${destFile.path}")
+        destFile.writeText(text)
+    }
+}
diff --git a/buildSrc/src/main/kotlin/androidx/build/jdiff/JDiffTask.kt b/buildSrc/src/main/kotlin/androidx/build/jdiff/JDiffTask.kt
index 10466ea..54e9ec6 100644
--- a/buildSrc/src/main/kotlin/androidx/build/jdiff/JDiffTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/jdiff/JDiffTask.kt
@@ -33,7 +33,7 @@
 open class JDiffTask : Javadoc() {
 
     /**
-     * Sets the doclet path which has the `com.google.doclava.Doclava` class.
+     * Sets the doclet path, which will be used to locate the `com.google.doclava.Doclava` class.
      *
      *
      * This option will override any doclet path set in this instance's
@@ -82,7 +82,7 @@
     }
 
     /**
-     * "Configures" this JDiffTask with parameters that might not be at their final values
+     * Configures this JDiffTask with parameters that might not be at their final values
      * until this task is run.
      */
     private fun configureJDiffTask() {
diff --git a/car/api/current.txt b/car/api/current.txt
index c9daf51..47ac4ca 100644
--- a/car/api/current.txt
+++ b/car/api/current.txt
@@ -397,8 +397,6 @@
     method public int getViewType();
     method protected void onBind(androidx.car.widget.SeekbarListItem.ViewHolder);
     method protected void resolveDirtyState();
-    method public void setMax(int);
-    method public void setOnSeekBarChangeListener(android.widget.SeekBar.OnSeekBarChangeListener);
     method public void setPrimaryActionEmptyIcon();
     method public void setPrimaryActionIcon(int);
     method public void setPrimaryActionIcon(android.graphics.drawable.Drawable);
diff --git a/car/build.gradle b/car/build.gradle
index 2c65ab4..1eacc0e 100644
--- a/car/build.gradle
+++ b/car/build.gradle
@@ -13,6 +13,7 @@
     api(project(":legacy-support-v4"))
     api(project(":recyclerview"))
     api(project(":gridlayout"))
+    api(project(":preference"))
     api(SUPPORT_DESIGN, libs.exclude_for_material)
 
     androidTestImplementation(TEST_RUNNER_TMP, libs.exclude_for_espresso)
diff --git a/car/res/drawable/ic_nav_arrow_back.xml b/car/res/drawable/ic_nav_arrow_back.xml
deleted file mode 100644
index 574e816..0000000
--- a/car/res/drawable/ic_nav_arrow_back.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT 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="48dp"
-    android:height="48dp"
-    android:viewportWidth="48"
-    android:viewportHeight="48">
-
-    <path
-        android:pathData="M0 0h48v48H0z" />
-    <path
-        android:fillColor="#000000"
-        android:pathData="M40 22H15.66l11.17-11.17L24 8 8 24l16 16 2.83-2.83L15.66 26H40v-4z" />
-</vector>
-
diff --git a/car/res/layout/car_alpha_jump_button.xml b/car/res/layout/car_alpha_jump_button.xml
index 443120c..c5e90fd 100644
--- a/car/res/layout/car_alpha_jump_button.xml
+++ b/car/res/layout/car_alpha_jump_button.xml
@@ -16,7 +16,7 @@
   -->
 
 <!-- This is sized in code, so we'll set it to 0dp for now. -->
-<androidx.cardview.widget.CardView
+<android.support.v7.widget.CardView
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:grid="http://schemas.android.com/apk/res-auto"
         android:layout_width="0dp"
@@ -32,4 +32,4 @@
         android:background="@drawable/car_card_ripple_background"
         android:id="@+id/button"
         android:gravity="center"/>
-</androidx.cardview.widget.CardView>
+</android.support.v7.widget.CardView>
diff --git a/car/res/layout/car_drawer_activity.xml b/car/res/layout/car_drawer_activity.xml
index 21a7cf2..e506d2a 100644
--- a/car/res/layout/car_drawer_activity.xml
+++ b/car/res/layout/car_drawer_activity.xml
@@ -24,7 +24,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-        <com.google.android.material.appbar.AppBarLayout
+        <android.support.design.widget.AppBarLayout
             android:id="@+id/appbar"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -38,7 +38,7 @@
                 android:layout_gravity="center_vertical"
                 android:minHeight="@dimen/car_app_bar_height"
                 style="?attr/toolbarStyle" />
-        </com.google.android.material.appbar.AppBarLayout>
+        </android.support.design.widget.AppBarLayout>
 
         <!-- The main content view. Fragments will be added here. -->
         <androidx.car.moderator.SpeedBumpView
diff --git a/car/res/layout/preference_category_material_car.xml b/car/res/layout/preference_category_material_car.xml
new file mode 100644
index 0000000..2012c69
--- /dev/null
+++ b/car/res/layout/preference_category_material_car.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingVertical="@dimen/car_preference_list_margin"
+    android:background="@drawable/car_card_ripple_background"
+    android:focusable="true"
+    android:orientation="horizontal">
+
+    <androidx.preference.internal.PreferenceImageView
+        android:id="@android:id/icon"
+        android:layout_width="@dimen/car_drawer_list_item_icon_size"
+        android:layout_height="@dimen/car_drawer_list_item_icon_size" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textAlignment="viewStart"
+            android:textAppearance="@style/TextAppearance.Car.Subheader"/>
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="?android:attr/textColorSecondary"/>
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/car/res/layout/preference_dropdown_material_car.xml b/car/res/layout/preference_dropdown_material_car.xml
new file mode 100644
index 0000000..932274a
--- /dev/null
+++ b/car/res/layout/preference_dropdown_material_car.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingVertical="@dimen/car_preference_list_margin"
+    android:background="@drawable/car_card_ripple_background"
+    android:focusable="true"
+    android:orientation="horizontal">
+
+    <Spinner
+        android:id="@+id/spinner"
+        android:layout_width="0dp"
+        android:layout_weight="0"
+        android:layout_height="wrap_content"
+        android:visibility="invisible" />
+
+    <androidx.preference.internal.PreferenceImageView
+        android:id="@android:id/icon"
+        android:layout_width="@dimen/car_drawer_list_item_icon_size"
+        android:layout_height="@dimen/car_drawer_list_item_icon_size" />
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:paddingTop="@dimen/car_preference_list_margin"
+        android:paddingBottom="@dimen/car_preference_list_margin">
+
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="@style/TextAppearance.Car.Body1" />
+
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="@style/TextAppearance.Car.Body2" />
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/car/res/layout/preference_material_car.xml b/car/res/layout/preference_material_car.xml
new file mode 100644
index 0000000..c3049a2
--- /dev/null
+++ b/car/res/layout/preference_material_car.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingVertical="@dimen/car_preference_list_margin"
+    android:background="@drawable/car_card_ripple_background"
+    android:focusable="true">
+
+    <androidx.preference.internal.PreferenceImageView
+        android:id="@android:id/icon"
+        android:layout_width="@dimen/car_drawer_list_item_icon_size"
+        android:layout_height="@dimen/car_drawer_list_item_icon_size"
+        android:layout_alignParentStart="true"
+        android:layout_centerVertical="true"/>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:layout_toEndOf="@android:id/icon"
+        android:layout_centerVertical="true">
+
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:textAppearance="@style/TextAppearance.Car.Body1" />
+
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="@style/TextAppearance.Car.Body2" />
+
+    </LinearLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <FrameLayout
+        android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignParentEnd="true" />
+
+</RelativeLayout>
diff --git a/car/res/layout/preference_material_car_child.xml b/car/res/layout/preference_material_car_child.xml
new file mode 100644
index 0000000..eec2d0b
--- /dev/null
+++ b/car/res/layout/preference_material_car_child.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingVertical="@dimen/car_preference_list_margin"
+    android:background="@drawable/car_card_ripple_background"
+    android:focusable="true">
+
+    <!-- Wrap in a FrameLayout so the full list item has a touch ripple -->
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="?android:attr/listPreferredItemPaddingStart">
+
+        <androidx.preference.internal.PreferenceImageView
+            android:id="@android:id/icon"
+            android:layout_width="@dimen/car_drawer_list_item_small_icon_size"
+            android:layout_height="@dimen/car_drawer_list_item_small_icon_size"
+            android:layout_centerVertical="true"
+            android:layout_alignParentStart="true"/>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:layout_toEndOf="@android:id/icon"
+            android:layout_centerVertical="true">
+
+            <TextView
+                android:id="@android:id/title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:textAppearance="@style/TextAppearance.Car.Label1" />
+
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.Car.Body3" />
+
+        </LinearLayout>
+
+        <!-- Preference should place its actual preference widget here. -->
+        <FrameLayout
+            android:id="@android:id/widget_frame"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_alignParentEnd="true" />
+
+    </RelativeLayout>
+
+</FrameLayout>
+
diff --git a/car/res/layout/preference_widget_seekbar_material_car.xml b/car/res/layout/preference_widget_seekbar_material_car.xml
new file mode 100644
index 0000000..0064045
--- /dev/null
+++ b/car/res/layout/preference_widget_seekbar_material_car.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<!-- Layout used by SeekBarPreference for the seekbar widget style. -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_vertical"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingVertical="@dimen/car_preference_list_margin"
+    android:orientation="horizontal">
+
+    <androidx.preference.internal.PreferenceImageView
+        android:id="@android:id/icon"
+        android:layout_width="@dimen/car_drawer_list_item_icon_size"
+        android:layout_height="@dimen/car_drawer_list_item_icon_size" />
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:textAppearance="@style/TextAppearance.Car.Body1"/>
+
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="@style/TextAppearance.Car.Body2"/>
+
+        <!-- Using UnPressableLinearLayout as a workaround to disable the pressed state propagation
+        to the children of this container layout. Otherwise, the animated pressed state will also
+        play for the thumb in the AbsSeekBar in addition to the preference's ripple background.
+        The background of the SeekBar is also set to null to disable the ripple background -->
+        <androidx.preference.UnPressableLinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@android:id/summary"
+                android:layout_alignStart="@android:id/title"
+                android:clipChildren="false"
+                android:clipToPadding="false">
+            <SeekBar
+                android:id="@+id/seekbar"
+                android:layout_width="0dp"
+                android:layout_weight="1"
+                android:layout_height="wrap_content"
+                android:paddingStart="@dimen/preference_seekbar_padding_start"
+                android:paddingEnd="@dimen/preference_seekbar_padding_end"
+                android:focusable="false"
+                android:clickable="false"
+                android:background="@null" />
+
+            <TextView
+                android:id="@+id/seekbar_value"
+                android:layout_width="@dimen/preference_seekbar_value_width"
+                android:layout_height="match_parent"
+                android:gravity="right|center_vertical"
+                android:textAppearance="@style/TextAppearance.Car.Body2"
+                android:fadingEdge="horizontal"
+                android:scrollbars="none"/>
+        </androidx.preference.UnPressableLinearLayout>
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/car/res/values-af/strings.xml b/car/res/values-af/strings.xml
index 1e90b40..f307fc7 100644
--- a/car/res/values-af/strings.xml
+++ b/car/res/values-af/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Konsentreer op die pad"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Vou knoppie in/uit"</string>
 </resources>
diff --git a/car/res/values-am/strings.xml b/car/res/values-am/strings.xml
index 6759ee3..30ae48e 100644
--- a/car/res/values-am/strings.xml
+++ b/car/res/values-am/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"መንገዱ ላይ ያተኩሩ"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"አዝራርን ዘርጋ/ሰብስብ"</string>
 </resources>
diff --git a/car/res/values-ar/strings.xml b/car/res/values-ar/strings.xml
index 845908b..e970ed9 100644
--- a/car/res/values-ar/strings.xml
+++ b/car/res/values-ar/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"ركِّز في الطريق"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"زر التوسيع/التصغير"</string>
 </resources>
diff --git a/car/res/values-as/strings.xml b/car/res/values-as/strings.xml
deleted file mode 100644
index e5a0015..0000000
--- a/car/res/values-as/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="speed_bump_lockout_message" msgid="5405697774899378511">"ৰাষ্টাত মনোযোগ দিয়ক"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"সম্প্ৰসাৰণ/সংকোচন বুটাম"</string>
-</resources>
diff --git a/car/res/values-az/strings.xml b/car/res/values-az/strings.xml
index b5e25dc..e813849 100644
--- a/car/res/values-az/strings.xml
+++ b/car/res/values-az/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Diqqətinizi yola yönəldin"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Düyməni genişləndirin/yığcamlaşdırın"</string>
 </resources>
diff --git a/car/res/values-b+sr+Latn/strings.xml b/car/res/values-b+sr+Latn/strings.xml
index 43dbac24..a83a82c 100644
--- a/car/res/values-b+sr+Latn/strings.xml
+++ b/car/res/values-b+sr+Latn/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Fokusirajte se na put"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Dugme Proširi/skupi"</string>
 </resources>
diff --git a/car/res/values-be/strings.xml b/car/res/values-be/strings.xml
index cfef873..80912e4 100644
--- a/car/res/values-be/strings.xml
+++ b/car/res/values-be/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Увага на дарогу"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Кнопка \"Разгарнуць/згарнуць\""</string>
 </resources>
diff --git a/car/res/values-bg/strings.xml b/car/res/values-bg/strings.xml
index 49e7a61..dd5811f 100644
--- a/car/res/values-bg/strings.xml
+++ b/car/res/values-bg/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Съсредоточете се върху пътя"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Бутон за разгъване/свиване"</string>
 </resources>
diff --git a/car/res/values-bn/strings.xml b/car/res/values-bn/strings.xml
index 4ab2ca4..fcf0165 100644
--- a/car/res/values-bn/strings.xml
+++ b/car/res/values-bn/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"মনোযোগ দিয়ে গাড়ি চালান"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"বোতাম বড় করুন/আড়াল করুন"</string>
 </resources>
diff --git a/car/res/values-bs/strings.xml b/car/res/values-bs/strings.xml
index 6ff5714..99e655e 100644
--- a/car/res/values-bs/strings.xml
+++ b/car/res/values-bs/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Fokusirajte se na cestu"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Dugme proširi/suzi"</string>
 </resources>
diff --git a/car/res/values-ca/strings.xml b/car/res/values-ca/strings.xml
index 8e20fd8..758f6e7 100644
--- a/car/res/values-ca/strings.xml
+++ b/car/res/values-ca/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Concentra\'t en la carretera"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Botó per desplegar o replegar"</string>
 </resources>
diff --git a/car/res/values-cs/strings.xml b/car/res/values-cs/strings.xml
index 1b4cad2..27090ef 100644
--- a/car/res/values-cs/strings.xml
+++ b/car/res/values-cs/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Soustřeďte se na silnici"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Tlačítko rozbalení/sbalení"</string>
 </resources>
diff --git a/car/res/values-da/strings.xml b/car/res/values-da/strings.xml
index 4a0e180..96cc062 100644
--- a/car/res/values-da/strings.xml
+++ b/car/res/values-da/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Hold øjnene på vejen"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Knappen Udvid/skjul"</string>
 </resources>
diff --git a/car/res/values-de/strings.xml b/car/res/values-de/strings.xml
index f670bd6..ee289ac 100644
--- a/car/res/values-de/strings.xml
+++ b/car/res/values-de/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Achte auf den Verkehr"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Schaltfläche zum Maximieren/Minimieren"</string>
 </resources>
diff --git a/car/res/values-el/strings.xml b/car/res/values-el/strings.xml
index 4010875..cf8ab8f 100644
--- a/car/res/values-el/strings.xml
+++ b/car/res/values-el/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Επικεντρωθείτε στον δρόμο"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Κουμπί ανάπτυξης/σύμπτυξης"</string>
 </resources>
diff --git a/car/res/values-en-rAU/strings.xml b/car/res/values-en-rAU/strings.xml
index a307f7e..8cc3360 100644
--- a/car/res/values-en-rAU/strings.xml
+++ b/car/res/values-en-rAU/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Focus on the road"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Expand/collapse button"</string>
 </resources>
diff --git a/car/res/values-en-rCA/strings.xml b/car/res/values-en-rCA/strings.xml
index a307f7e..8cc3360 100644
--- a/car/res/values-en-rCA/strings.xml
+++ b/car/res/values-en-rCA/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Focus on the road"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Expand/collapse button"</string>
 </resources>
diff --git a/car/res/values-en-rGB/strings.xml b/car/res/values-en-rGB/strings.xml
index a307f7e..8cc3360 100644
--- a/car/res/values-en-rGB/strings.xml
+++ b/car/res/values-en-rGB/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Focus on the road"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Expand/collapse button"</string>
 </resources>
diff --git a/car/res/values-en-rIN/strings.xml b/car/res/values-en-rIN/strings.xml
index a307f7e..8cc3360 100644
--- a/car/res/values-en-rIN/strings.xml
+++ b/car/res/values-en-rIN/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Focus on the road"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Expand/collapse button"</string>
 </resources>
diff --git a/car/res/values-en-rXC/strings.xml b/car/res/values-en-rXC/strings.xml
index 16d0daf..c11c1cb 100644
--- a/car/res/values-en-rXC/strings.xml
+++ b/car/res/values-en-rXC/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎Focus on the road‎‏‎‎‏‎"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎Expand/collapse button‎‏‎‎‏‎"</string>
 </resources>
diff --git a/car/res/values-es-rUS/strings.xml b/car/res/values-es-rUS/strings.xml
index 46a5e11..6ac20d7 100644
--- a/car/res/values-es-rUS/strings.xml
+++ b/car/res/values-es-rUS/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Concéntrate en el camino"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Botón Expandir/contraer"</string>
 </resources>
diff --git a/car/res/values-es/strings.xml b/car/res/values-es/strings.xml
index 33ed10b..09a493f 100644
--- a/car/res/values-es/strings.xml
+++ b/car/res/values-es/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Céntrate en la carretera"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Botón para mostrar u ocultar"</string>
 </resources>
diff --git a/car/res/values-et/strings.xml b/car/res/values-et/strings.xml
index 7561817..66f6e48 100644
--- a/car/res/values-et/strings.xml
+++ b/car/res/values-et/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Keskenduge teele"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Nupp Laienda/Ahenda"</string>
 </resources>
diff --git a/car/res/values-eu/strings.xml b/car/res/values-eu/strings.xml
index 0e92575..3773f71 100644
--- a/car/res/values-eu/strings.xml
+++ b/car/res/values-eu/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Jarri arreta errepidean"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Zabaltzeko/Tolesteko botoia"</string>
 </resources>
diff --git a/car/res/values-fa/strings.xml b/car/res/values-fa/strings.xml
index 59152f0..8668d6b 100644
--- a/car/res/values-fa/strings.xml
+++ b/car/res/values-fa/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"روی جاده تمرکز داشته باشید"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"دکمه بزرگ کردن/کوچک کردن"</string>
 </resources>
diff --git a/car/res/values-fi/strings.xml b/car/res/values-fi/strings.xml
index 5bbb440..e93cb9c 100644
--- a/car/res/values-fi/strings.xml
+++ b/car/res/values-fi/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Pidä katse tiessä"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Laajennus- ja tiivistyspainike"</string>
 </resources>
diff --git a/car/res/values-fr-rCA/strings.xml b/car/res/values-fr-rCA/strings.xml
index e90ddf2..f32315b 100644
--- a/car/res/values-fr-rCA/strings.xml
+++ b/car/res/values-fr-rCA/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Concentrez-vous sur la route"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Bouton Développer/Réduire"</string>
 </resources>
diff --git a/car/res/values-fr/strings.xml b/car/res/values-fr/strings.xml
index e90ddf2..f32315b 100644
--- a/car/res/values-fr/strings.xml
+++ b/car/res/values-fr/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Concentrez-vous sur la route"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Bouton Développer/Réduire"</string>
 </resources>
diff --git a/car/res/values-gl/strings.xml b/car/res/values-gl/strings.xml
index c89cc35..42bc515 100644
--- a/car/res/values-gl/strings.xml
+++ b/car/res/values-gl/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Céntrate na estrada"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Botón despregar/contraer"</string>
 </resources>
diff --git a/car/res/values-gu/strings.xml b/car/res/values-gu/strings.xml
index 4397f5d..f215ec2 100644
--- a/car/res/values-gu/strings.xml
+++ b/car/res/values-gu/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"રસ્તા પર ફોકસ કરો"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"વિસ્તાર કરો/સંકુચિત કરો બટન"</string>
 </resources>
diff --git a/car/res/values-hi/strings.xml b/car/res/values-hi/strings.xml
index 08d973b..53f8a8d 100644
--- a/car/res/values-hi/strings.xml
+++ b/car/res/values-hi/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"सड़क पर ध्यान दें"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"बड़ा/छोटा करने वाला बटन"</string>
 </resources>
diff --git a/car/res/values-hr/strings.xml b/car/res/values-hr/strings.xml
index 5714327c..0a08dcc 100644
--- a/car/res/values-hr/strings.xml
+++ b/car/res/values-hr/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Usredotočite se na cestu"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Gumb za proširivanje/sažimanje"</string>
 </resources>
diff --git a/car/res/values-hu/strings.xml b/car/res/values-hu/strings.xml
index 88c2577..3618719 100644
--- a/car/res/values-hu/strings.xml
+++ b/car/res/values-hu/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Figyeljen az útra"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Gomb kibontása/összecsukása"</string>
 </resources>
diff --git a/car/res/values-hy/strings.xml b/car/res/values-hy/strings.xml
index d97cd0a..3a85b41 100644
--- a/car/res/values-hy/strings.xml
+++ b/car/res/values-hy/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Հետևեք ճանապարհին"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"«Ծավալել/ծալել» կոճակ"</string>
 </resources>
diff --git a/car/res/values-in/strings.xml b/car/res/values-in/strings.xml
index faf2f43..81daf29 100644
--- a/car/res/values-in/strings.xml
+++ b/car/res/values-in/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Konsentrasi saat mengemudi"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Tombol luaskan/ciutkan"</string>
 </resources>
diff --git a/car/res/values-is/strings.xml b/car/res/values-is/strings.xml
index 7c2dd76..4b5d26d 100644
--- a/car/res/values-is/strings.xml
+++ b/car/res/values-is/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Einbeittu þér að akstrinum"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Hnappur til að stækka/minnka"</string>
 </resources>
diff --git a/car/res/values-it/strings.xml b/car/res/values-it/strings.xml
index d2b3f4f..b395409 100644
--- a/car/res/values-it/strings.xml
+++ b/car/res/values-it/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Concentrati sulla strada"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Pulsante Espandi/Comprimi"</string>
 </resources>
diff --git a/car/res/values-iw/strings.xml b/car/res/values-iw/strings.xml
index 79bad9c..ab92be5 100644
--- a/car/res/values-iw/strings.xml
+++ b/car/res/values-iw/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"עליך להתמקד בכביש"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"לחצן הרחבה וכיווץ"</string>
 </resources>
diff --git a/car/res/values-ja/strings.xml b/car/res/values-ja/strings.xml
index 87deba0..89fce3b 100644
--- a/car/res/values-ja/strings.xml
+++ b/car/res/values-ja/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"運転に集中してください"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"展開 / 折りたたみボタン"</string>
 </resources>
diff --git a/car/res/values-ka/strings.xml b/car/res/values-ka/strings.xml
index b525a9b..e3f2e07 100644
--- a/car/res/values-ka/strings.xml
+++ b/car/res/values-ka/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"კონცენტრირდით გზაზე"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"ღილაკის გაფართოება/ჩაკეცვა"</string>
 </resources>
diff --git a/car/res/values-kk/strings.xml b/car/res/values-kk/strings.xml
index ff327d3..bbccd56 100644
--- a/car/res/values-kk/strings.xml
+++ b/car/res/values-kk/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Жолға назар аударыңыз"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"\"Жаю/Жию\" түймесі"</string>
 </resources>
diff --git a/car/res/values-km/strings.xml b/car/res/values-km/strings.xml
index f9d9111..50fe2db 100644
--- a/car/res/values-km/strings.xml
+++ b/car/res/values-km/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"ផ្តោតលើ​ការបើកបរ"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"ប៊ូតុង​ពង្រីក/បង្រួម"</string>
 </resources>
diff --git a/car/res/values-kn/strings.xml b/car/res/values-kn/strings.xml
index 50ba985..6562ee2 100644
--- a/car/res/values-kn/strings.xml
+++ b/car/res/values-kn/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"ರಸ್ತೆಯ ಮೇಲೆ ಗಮನಹರಿಸಿ"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"ವಿಸ್ತರಿಸಿ/ಕುಗ್ಗಿಸಿ ಬಟನ್"</string>
 </resources>
diff --git a/car/res/values-ko/strings.xml b/car/res/values-ko/strings.xml
index 0081b5c..ac5865a 100644
--- a/car/res/values-ko/strings.xml
+++ b/car/res/values-ko/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"도로 상황에 집중하세요."</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"펼치기/접기 버튼"</string>
 </resources>
diff --git a/car/res/values-ky/strings.xml b/car/res/values-ky/strings.xml
index 8a752fa..3640239 100644
--- a/car/res/values-ky/strings.xml
+++ b/car/res/values-ky/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Жолго көңүл буруңуз"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Жайып көрсөтүү/жыйыштыруу баскычы"</string>
 </resources>
diff --git a/car/res/values-lo/strings.xml b/car/res/values-lo/strings.xml
index 02afe60..4af3152 100644
--- a/car/res/values-lo/strings.xml
+++ b/car/res/values-lo/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"ຕັ້ງໃຈຂັບລົດ"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"ປຸ່ມຫຍໍ້/ຂະຫຍາຍ"</string>
 </resources>
diff --git a/car/res/values-lt/strings.xml b/car/res/values-lt/strings.xml
index 5281e18..685bbe5 100644
--- a/car/res/values-lt/strings.xml
+++ b/car/res/values-lt/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Sutelkite dėmesį į kelią"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Mygtukas „Išskleisti / sutraukti“"</string>
 </resources>
diff --git a/car/res/values-lv/strings.xml b/car/res/values-lv/strings.xml
index 7b4372b..417d331 100644
--- a/car/res/values-lv/strings.xml
+++ b/car/res/values-lv/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Pievērsieties autovadīšanai"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Izvēršanas/sakļaušanas poga"</string>
 </resources>
diff --git a/car/res/values-mk/strings.xml b/car/res/values-mk/strings.xml
index 5184503..7377299 100644
--- a/car/res/values-mk/strings.xml
+++ b/car/res/values-mk/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Фокусирајте се на патот"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Копче за проширување/собирање"</string>
 </resources>
diff --git a/car/res/values-ml/strings.xml b/car/res/values-ml/strings.xml
index 8047b4c..d5ad91d 100644
--- a/car/res/values-ml/strings.xml
+++ b/car/res/values-ml/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"റോഡിൽ ശ്രദ്ധിക്കുക"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"വികസിപ്പിക്കുക/ചുരുക്കുക ബട്ടൺ"</string>
 </resources>
diff --git a/car/res/values-mn/strings.xml b/car/res/values-mn/strings.xml
index a8ef13c..4b249a4 100644
--- a/car/res/values-mn/strings.xml
+++ b/car/res/values-mn/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Зам дээр төвлөрөх"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Дэлгэх/буулгах товчлуур"</string>
 </resources>
diff --git a/car/res/values-mr/strings.xml b/car/res/values-mr/strings.xml
index 3032c97..c79f3f3 100644
--- a/car/res/values-mr/strings.xml
+++ b/car/res/values-mr/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"रस्त्यावर फोकस करा"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"बटण विस्‍तृत करा/कोलॅप्‍स करा"</string>
 </resources>
diff --git a/car/res/values-ms/strings.xml b/car/res/values-ms/strings.xml
index 301f7eb..d209113 100644
--- a/car/res/values-ms/strings.xml
+++ b/car/res/values-ms/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Beri tumpuan pada jalan raya"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Butang kembangkan/runtuhkan"</string>
 </resources>
diff --git a/car/res/values-my/strings.xml b/car/res/values-my/strings.xml
index f5317f7..438729a 100644
--- a/car/res/values-my/strings.xml
+++ b/car/res/values-my/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"လမ်းကို အာရုံစိုက်ရန်"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"ချဲ့ရန်/ခေါက်သိမ်းရန် ခလုတ်"</string>
 </resources>
diff --git a/car/res/values-nb/strings.xml b/car/res/values-nb/strings.xml
index e4c4810..eb3a144 100644
--- a/car/res/values-nb/strings.xml
+++ b/car/res/values-nb/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Fokuser på veien"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Vis/skjul-knapp"</string>
 </resources>
diff --git a/car/res/values-ne/strings.xml b/car/res/values-ne/strings.xml
index c4499b8..d066c0b 100644
--- a/car/res/values-ne/strings.xml
+++ b/car/res/values-ne/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"सडकमा ध्यान केन्द्रित गर्नु…"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"विस्तृत/संक्षिप्त गर्ने बटन"</string>
 </resources>
diff --git a/car/res/values-nl/strings.xml b/car/res/values-nl/strings.xml
index de08f63..7fcb11e 100644
--- a/car/res/values-nl/strings.xml
+++ b/car/res/values-nl/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Houd je aandacht op de weg"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Knop voor uitvouwen/samenvouwen"</string>
 </resources>
diff --git a/car/res/values-or/strings.xml b/car/res/values-or/strings.xml
deleted file mode 100644
index 3a003b8..0000000
--- a/car/res/values-or/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="speed_bump_lockout_message" msgid="5405697774899378511">"ରାସ୍ତା ଉପରେ ଧ୍ୟାନରଖନ୍ତୁ"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"ବିସ୍ତାର/ସଂକୋଚନ ବଟନ୍"</string>
-</resources>
diff --git a/car/res/values-pa/strings.xml b/car/res/values-pa/strings.xml
index 63a19f3..137bd2a 100644
--- a/car/res/values-pa/strings.xml
+++ b/car/res/values-pa/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"ਸੜਕ \'ਤੇ ਧਿਆਨ ਦਿਓ"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"ਵਿਸਤਾਰ ਕਰੋ/ਸਮੇਟੋ ਬਟਨ"</string>
 </resources>
diff --git a/car/res/values-pl/strings.xml b/car/res/values-pl/strings.xml
index 133d27e..c5aa323 100644
--- a/car/res/values-pl/strings.xml
+++ b/car/res/values-pl/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Skup się na drodze"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Przycisk zwijania/rozwijania"</string>
 </resources>
diff --git a/car/res/values-pt-rBR/strings.xml b/car/res/values-pt-rBR/strings.xml
index 6c6e459..a6c515a 100644
--- a/car/res/values-pt-rBR/strings.xml
+++ b/car/res/values-pt-rBR/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Foco na estrada"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Botão \"Expandir/Recolher\""</string>
 </resources>
diff --git a/car/res/values-pt-rPT/strings.xml b/car/res/values-pt-rPT/strings.xml
index 911b120..2338efe 100644
--- a/car/res/values-pt-rPT/strings.xml
+++ b/car/res/values-pt-rPT/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Concentre-se na estrada."</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Botão Expandir/reduzir"</string>
 </resources>
diff --git a/car/res/values-pt/strings.xml b/car/res/values-pt/strings.xml
index 6c6e459..a6c515a 100644
--- a/car/res/values-pt/strings.xml
+++ b/car/res/values-pt/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Foco na estrada"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Botão \"Expandir/Recolher\""</string>
 </resources>
diff --git a/car/res/values-ro/strings.xml b/car/res/values-ro/strings.xml
index 7fe204a..20cc3e7 100644
--- a/car/res/values-ro/strings.xml
+++ b/car/res/values-ro/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Concentrați-vă asupra drumului"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Butonul de extindere/restrângere"</string>
 </resources>
diff --git a/car/res/values-ru/strings.xml b/car/res/values-ru/strings.xml
index 6554dc3..198f7fa 100644
--- a/car/res/values-ru/strings.xml
+++ b/car/res/values-ru/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Следите за дорогой"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Кнопка \"Развернуть/свернуть\""</string>
 </resources>
diff --git a/car/res/values-si/strings.xml b/car/res/values-si/strings.xml
index 48977bd..530c12a 100644
--- a/car/res/values-si/strings.xml
+++ b/car/res/values-si/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"මාර්ගයට අවධානය යොමු කරන්න"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"දිග හැරීමේ/හැකිළීමේ බොත්තම"</string>
 </resources>
diff --git a/car/res/values-sk/strings.xml b/car/res/values-sk/strings.xml
index d8175c4..a959d09 100644
--- a/car/res/values-sk/strings.xml
+++ b/car/res/values-sk/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Sústreďte sa na cestu"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Tlačidlo rozbalenia/zbalenia"</string>
 </resources>
diff --git a/car/res/values-sl/strings.xml b/car/res/values-sl/strings.xml
index 85f2602..c0a8164 100644
--- a/car/res/values-sl/strings.xml
+++ b/car/res/values-sl/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Glejte na cesto"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Gumb za razširitev/strnitev"</string>
 </resources>
diff --git a/car/res/values-sq/strings.xml b/car/res/values-sq/strings.xml
index 87cb023..c8c91ef 100644
--- a/car/res/values-sq/strings.xml
+++ b/car/res/values-sq/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Përqendrohu te rruga"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Butoni i zgjerimit/palosjes"</string>
 </resources>
diff --git a/car/res/values-sr/strings.xml b/car/res/values-sr/strings.xml
index d3fe526..d7a6b85 100644
--- a/car/res/values-sr/strings.xml
+++ b/car/res/values-sr/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Фокусирајте се на пут"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Дугме Прошири/скупи"</string>
 </resources>
diff --git a/car/res/values-sv/strings.xml b/car/res/values-sv/strings.xml
index c4ae438..3798509 100644
--- a/car/res/values-sv/strings.xml
+++ b/car/res/values-sv/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Fokusera på körningen"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Knappen Utöka/komprimera"</string>
 </resources>
diff --git a/car/res/values-sw/strings.xml b/car/res/values-sw/strings.xml
index d3472f5..a5b76c7 100644
--- a/car/res/values-sw/strings.xml
+++ b/car/res/values-sw/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Tia makini barabarani"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Kitufe cha kupanua/kukunja"</string>
 </resources>
diff --git a/car/res/values-ta/strings.xml b/car/res/values-ta/strings.xml
index e13ede5..e97f385 100644
--- a/car/res/values-ta/strings.xml
+++ b/car/res/values-ta/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"வாகனம் ஓட்டும்போது கவனம் தேவை"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"விரிவாக்குவதற்கான/சுருக்குவதற்கான பட்டன்"</string>
 </resources>
diff --git a/car/res/values-te/strings.xml b/car/res/values-te/strings.xml
index b106363..9079a09 100644
--- a/car/res/values-te/strings.xml
+++ b/car/res/values-te/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"రహదారిపై దృష్టి ఉంచండి"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"విస్తరించు/కుదించు బటన్"</string>
 </resources>
diff --git a/car/res/values-th/strings.xml b/car/res/values-th/strings.xml
index 05be415..3ba0d6b 100644
--- a/car/res/values-th/strings.xml
+++ b/car/res/values-th/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"จดจ่อกับถนน"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"ปุ่มขยาย/ยุบ"</string>
 </resources>
diff --git a/car/res/values-tl/strings.xml b/car/res/values-tl/strings.xml
index a56c37c..395e555 100644
--- a/car/res/values-tl/strings.xml
+++ b/car/res/values-tl/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Tumuon sa kalsada"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Button na i-expand/i-collapse"</string>
 </resources>
diff --git a/car/res/values-tr/strings.xml b/car/res/values-tr/strings.xml
index b28b66e..a0f0b22 100644
--- a/car/res/values-tr/strings.xml
+++ b/car/res/values-tr/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Dikkatinizi yola verin"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Genişlet/daralt düğmesi"</string>
 </resources>
diff --git a/car/res/values-uk/strings.xml b/car/res/values-uk/strings.xml
index 1964936..2657348 100644
--- a/car/res/values-uk/strings.xml
+++ b/car/res/values-uk/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Зосередьтеся на дорозі"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Кнопка \"Розгорнути або згорнути\""</string>
 </resources>
diff --git a/car/res/values-ur/strings.xml b/car/res/values-ur/strings.xml
index c1d6b3e..60c578c 100644
--- a/car/res/values-ur/strings.xml
+++ b/car/res/values-ur/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"سڑک پر توجہ مرکوز کریں"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"پھیلائیں/سکیڑیں بٹن"</string>
 </resources>
diff --git a/car/res/values-uz/strings.xml b/car/res/values-uz/strings.xml
index a830b84..bdaba48 100644
--- a/car/res/values-uz/strings.xml
+++ b/car/res/values-uz/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Diqqatingizni yo‘lga qarating"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Yoyish/yig‘ish tugmasi"</string>
 </resources>
diff --git a/car/res/values-vi/strings.xml b/car/res/values-vi/strings.xml
index 144f41a..37457d4 100644
--- a/car/res/values-vi/strings.xml
+++ b/car/res/values-vi/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Tập trung vào đường đi"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Nút mở rộng/thu gọn"</string>
 </resources>
diff --git a/car/res/values-zh-rCN/strings.xml b/car/res/values-zh-rCN/strings.xml
index 0c2caeaa..ec0c3c4 100644
--- a/car/res/values-zh-rCN/strings.xml
+++ b/car/res/values-zh-rCN/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"请专心驾驶"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"“展开”/“收起”按钮"</string>
 </resources>
diff --git a/car/res/values-zh-rHK/strings.xml b/car/res/values-zh-rHK/strings.xml
index 09c1a9e..61102cc 100644
--- a/car/res/values-zh-rHK/strings.xml
+++ b/car/res/values-zh-rHK/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"請專心駕駛"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"展開/收合按鈕"</string>
 </resources>
diff --git a/car/res/values-zh-rTW/strings.xml b/car/res/values-zh-rTW/strings.xml
index 09c1a9e..61102cc 100644
--- a/car/res/values-zh-rTW/strings.xml
+++ b/car/res/values-zh-rTW/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"請專心駕駛"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"展開/收合按鈕"</string>
 </resources>
diff --git a/car/res/values-zu/strings.xml b/car/res/values-zu/strings.xml
index 9403834..bdf7337 100644
--- a/car/res/values-zu/strings.xml
+++ b/car/res/values-zu/strings.xml
@@ -17,5 +17,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="speed_bump_lockout_message" msgid="5405697774899378511">"Gxila emgwaqweni"</string>
-    <string name="action_bar_expand_collapse_button" msgid="196909968432559564">"Inkinobho yokunweba/ukugoqa"</string>
 </resources>
diff --git a/car/res/values/dimens.xml b/car/res/values/dimens.xml
index fd8d54d..94c8edc 100644
--- a/car/res/values/dimens.xml
+++ b/car/res/values/dimens.xml
@@ -215,4 +215,8 @@
     <dimen name="speed_bump_lock_out_message_height">96dp</dimen>
     <dimen name="speed_bump_lock_out_drawable_margin_bottom">8dp</dimen>
 
+    <!-- Preferences -->
+    <!-- list margin won't be necessary after PagedListView is brought in -->
+    <dimen name="car_preference_list_margin">8dp</dimen>
+
 </resources>
diff --git a/car/res/values/styles.xml b/car/res/values/styles.xml
index 67ad199..79978db 100644
--- a/car/res/values/styles.xml
+++ b/car/res/values/styles.xml
@@ -173,20 +173,6 @@
         <item name="android:textColor">@color/car_body4</item>
     </style>
 
-    <!-- The styling for action button text. -->
-    <style name="TextAppearance.Car.Action1">
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:textStyle">normal</item>
-        <item name="android:textAllCaps">true</item>
-        <item name="android:textSize">@dimen/car_action1_size</item>
-        <item name="android:textColor">@color/car_accent</item>
-    </style>
-
-    <!-- The styling for menu text in action bar. -->
-    <style name="TextAppearance.Car.ActionBar.Menu" parent="TextAppearance.Car.Action1">
-        <item name="android:textColor">?attr/actionMenuTextColor</item>
-    </style>
-
     <!-- Styles for TextInputLayout hints. -->
     <style name="TextAppearance.Car.Hint" parent="TextAppearance.Car.Body2" />
 
@@ -195,33 +181,11 @@
     <!-- ======= -->
     <eat-comment />
 
-    <!-- The styling for Toolbar used as action bar. -->
+    <!-- The styling for the action bar. -->
     <style name="Widget.Car.Toolbar" parent="Widget.AppCompat.Toolbar">
-        <item name="android:minHeight">?attr/actionBarSize</item>
-        <item name="background">@color/car_card</item>
-        <item name="contentInsetEnd">@dimen/car_keyline_1</item>
+        <item name="titleTextAppearance">@style/TextAppearance.Car.Title.Light</item>
         <item name="contentInsetStart">@dimen/car_keyline_1</item>
-        <item name="elevation">@dimen/car_action_bar_elevation</item>
-        <item name="subtitleTextAppearance">@style/TextAppearance.Car.Body2</item>
-        <item name="titleTextAppearance">@style/TextAppearance.Car.Title2</item>
-        <item name="navigationIcon">@drawable/ic_nav_arrow_back</item>
-    </style>
-
-    <!-- The styling for the navigation button in action bar. -->
-    <style name="Widget.Car.Toolbar.Button.Navigation"
-           parent="Widget.AppCompat.Toolbar.Button.Navigation">
-        <item name="android:background">@drawable/car_card_ripple_background</item>
-        <item name="android:scaleType">center</item>
-        <item name="android:tint">@color/car_tint</item>
-    </style>
-
-    <style name="Widget.Car.ActionButton" parent="Widget.AppCompat.ActionButton">
-        <item name="android:background">?attr/actionBarItemBackground</item>
-        <item name="android:minHeight">@dimen/car_action_bar_height</item>
-        <item name="android:paddingLeft">@dimen/car_padding_2</item>
-        <item name="android:paddingRight">@dimen/car_padding_2</item>
-        <item name="android:scaleType">fitCenter</item>
-        <item name="android:tint">@color/car_tint</item>
+        <item name="contentInsetEnd">@dimen/car_keyline_1</item>
     </style>
 
     <!-- The style for the menu bar (i.e. hamburger) and back arrow in the navigation drawer. -->
@@ -415,4 +379,107 @@
         <item name="android:background">@drawable/car_action_button_background</item>
         <item name="android:tint">@color/car_tint</item>
     </style>
+
+    <!-- ================= -->
+    <!-- Preference Themes -->
+    <!-- ================= -->
+    <eat-comment />
+
+    <style name="CarPreference">
+        <item name="android:layout">@layout/preference_material_car</item>
+        <item name="allowDividerAbove">true</item>
+        <item name="allowDividerBelow">true</item>
+        <item name="singleLineTitle">true</item>
+        <item name="iconSpaceReserved">false</item>
+    </style>
+
+    <style name="CarPreference.Information">
+        <item name="android:layout">@layout/preference_material_car</item>
+        <item name="android:enabled">false</item>
+        <item name="android:shouldDisableView">false</item>
+    </style>
+
+    <style name="CarPreference.Category">
+        <item name="android:layout">@layout/preference_category_material_car</item>
+        <item name="allowDividerAbove">true</item>
+        <item name="allowDividerBelow">true</item>
+        <item name="iconSpaceReserved">false</item>
+    </style>
+
+    <style name="CarPreference.CheckBoxPreference">
+        <item name="android:layout">@layout/preference_material_car</item>
+        <item name="allowDividerAbove">true</item>
+        <item name="allowDividerBelow">true</item>
+        <item name="iconSpaceReserved">false</item>
+        <item name="android:widgetLayout">@layout/preference_widget_checkbox</item>
+    </style>
+
+    <style name="CarPreference.SwitchPreferenceCompat">
+        <item name="android:layout">@layout/preference_material_car</item>
+        <item name="allowDividerAbove">true</item>
+        <item name="allowDividerBelow">true</item>
+        <item name="iconSpaceReserved">false</item>
+        <item name="android:widgetLayout">@layout/preference_widget_switch_compat</item>
+    </style>
+
+    <style name="CarPreference.SwitchPreference">
+        <item name="android:layout">@layout/preference_material_car</item>
+        <item name="allowDividerAbove">true</item>
+        <item name="allowDividerBelow">true</item>
+        <item name="singleLineTitle">true</item>
+        <item name="iconSpaceReserved">false</item>
+        <item name="android:widgetLayout">@layout/preference_widget_switch</item>
+    </style>
+
+    <style name="CarPreference.SeekBarPreference">
+        <item name="android:layout">@layout/preference_widget_seekbar_material_car</item>
+        <item name="adjustable">true</item>
+        <item name="showSeekBarValue">true</item>
+        <item name="allowDividerAbove">true</item>
+        <item name="allowDividerBelow">true</item>
+        <item name="iconSpaceReserved">false</item>
+        <item name="android:widgetLayout">@layout/preference_widget_seekbar</item>
+    </style>
+
+    <style name="CarPreference.PreferenceScreen">
+        <item name="android:layout">@layout/preference_material_car</item>
+        <item name="allowDividerAbove">true</item>
+        <item name="allowDividerBelow">true</item>
+        <item name="iconSpaceReserved">false</item>
+    </style>
+
+    <style name="CarPreference.DialogPreference">
+        <item name="android:layout">@layout/preference_material_car</item>
+        <item name="allowDividerAbove">true</item>
+        <item name="allowDividerBelow">true</item>
+        <item name="iconSpaceReserved">false</item>
+        <item name="android:positiveButtonText">@android:string/ok</item>
+        <item name="android:negativeButtonText">@android:string/cancel</item>
+    </style>
+
+    <style name="CarPreference.DialogPreference.EditTextPreference">
+        <item name="android:layout">@layout/preference_material_car</item>
+        <item name="allowDividerAbove">true</item>
+        <item name="allowDividerBelow">true</item>
+        <item name="singleLineTitle">true</item>
+        <item name="iconSpaceReserved">false</item>
+        <item name="android:dialogLayout">@layout/preference_dialog_edittext</item>
+    </style>
+
+    <style name="CarPreference.DropDown">
+        <item name="android:layout">@layout/preference_dropdown_material_car</item>
+        <item name="allowDividerAbove">true</item>
+        <item name="allowDividerBelow">true</item>
+        <item name="iconSpaceReserved">false</item>
+    </style>
+
+    <style name="CarPreferenceFragment">
+        <item name="android:divider">@drawable/car_list_divider</item>
+        <item name="allowDividerAfterLastItem">false</item>
+    </style>
+
+    <style name="CarPreferenceFragmentList">
+        <item name="android:paddingLeft">0dp</item>
+        <item name="android:paddingRight">0dp</item>
+    </style>
 </resources>
diff --git a/car/res/values/themes.xml b/car/res/values/themes.xml
index 7f862d7..35c0262 100644
--- a/car/res/values/themes.xml
+++ b/car/res/values/themes.xml
@@ -33,20 +33,13 @@
         <item name="android:editTextColor">@color/car_body1</item>
         <item name="android:colorControlNormal">@color/car_body2</item>
         <item name="android:seekBarStyle">@style/Widget.Car.SeekBar</item>
-        <item name="actionBarItemBackground">@drawable/car_card_ripple_background</item>
-        <item name="actionBarSize">@dimen/car_app_bar_height</item>
-        <item name="actionButtonStyle">@style/Widget.Car.ActionButton</item>
-        <item name="actionMenuTextAppearance">@style/TextAppearance.Car.ActionBar.Menu</item>
-        <item name="actionMenuTextColor">@color/car_accent</item>
         <item name="carDialogTheme">@style/Theme.Car.Dialog</item>
         <item name="colorControlHighlight">@color/car_card_ripple_background</item>
+        <item name="pagedListViewStyle">@style/Widget.Car.List</item>
         <item name="listItemBackgroundColor">@color/car_card</item>
         <item name="listItemTitleTextAppearance">@style/TextAppearance.Car.Body1</item>
         <item name="listItemBodyTextAppearance">@style/TextAppearance.Car.Body2</item>
         <item name="listItemSubheaderTextAppearance">@style/TextAppearance.Car.Subheader</item>
-        <item name="pagedListViewStyle">@style/Widget.Car.List</item>
-        <item name="toolbarNavigationButtonStyle">@style/Widget.Car.Toolbar.Button.Navigation</item>
-        <item name="toolbarStyle">@style/Widget.Car.Toolbar</item>
     </style>
 
     <!-- Theme for the Car that is a passthrough for the default theme. -->
@@ -187,4 +180,29 @@
         <item name="listItemTitleTextAppearance">@style/TextAppearance.Car.Body1.Light</item>
         <item name="listItemBodyTextAppearance">@style/TextAppearance.Car.Body2.Light</item>
     </style>
+
+
+    <!-- ================ -->
+    <!-- Preference Theme -->
+    <!-- ================ -->
+    <eat-comment />
+
+    <!-- Car theme for support library PreferenceFragments -->
+    <style name="PreferenceThemeOverlayCar">
+        <item name="preferenceScreenStyle">@style/CarPreference.PreferenceScreen</item>
+        <item name="preferenceFragmentCompatStyle">@style/CarPreferenceFragment</item>
+        <item name="preferenceFragmentStyle">@style/CarPreferenceFragment</item>
+        <item name="preferenceCategoryStyle">@style/CarPreference.Category</item>
+        <item name="preferenceStyle">@style/CarPreference</item>
+        <item name="preferenceInformationStyle">@style/CarPreference.Information</item>
+        <item name="checkBoxPreferenceStyle">@style/CarPreference.CheckBoxPreference</item>
+        <item name="switchPreferenceCompatStyle">@style/CarPreference.SwitchPreferenceCompat</item>
+        <item name="switchPreferenceStyle">@style/CarPreference.SwitchPreference</item>
+        <item name="seekBarPreferenceStyle">@style/CarPreference.SeekBarPreference</item>
+        <item name="dialogPreferenceStyle">@style/CarPreference.DialogPreference</item>
+        <item name="editTextPreferenceStyle">@style/CarPreference.DialogPreference.EditTextPreference</item>
+        <item name="dropdownPreferenceStyle">@style/CarPreference.DropDown</item>
+        <item name="preferenceFragmentListStyle">@style/CarPreferenceFragmentList</item>
+        <item name="android:preferenceLayoutChild">@layout/preference_material_car_child</item>
+    </style>
 </resources>
diff --git a/car/src/androidTest/java/androidx/car/navigation/utils/BundlableTest.java b/car/src/androidTest/java/androidx/car/navigation/utils/BundlableTest.java
new file mode 100644
index 0000000..7f149d0
--- /dev/null
+++ b/car/src/androidTest/java/androidx/car/navigation/utils/BundlableTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.navigation.utils;
+
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link Bundlable}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BundlableTest {
+    /**
+     * Serialization test value.
+     */
+    private static final TestBundlable TEST_VALUE = new TestBundlable()
+            .setInt(123)
+            .setString("TEST")
+            .setEnumValue(TestBundlable.TestEnum.VALUE1)
+            .setListValue(Arrays.asList(
+                    new TestBundlable()
+                            .setString("TEST2")
+                            .setEnumValue(TestBundlable.TestEnum.VALUE2),
+                    new TestBundlable()
+                            .setString("TEST3")
+            ))
+            .setBundlableValue(
+                    new TestBundlable()
+                            .setString("TEST4")
+            );
+
+    /**
+     * Equivalent to {@link #TEST_VALUE} after a schema change (see
+     * {@link TestBundlableNewVersion}). In this new schema, {@link TestBundlable} has its
+     * {@link TestBundlable#mStringValue} field deprecated, and a new
+     * {@link TestBundlableNewVersion#mNewValue} non-null field was added.
+     */
+    private static final TestBundlableNewVersion TEST_VALUE_NEW_VERSION =
+            new TestBundlableNewVersion()
+                    .setInt(123)
+                    .setEnumValue(TestBundlableNewVersion.TestEnum.VALUE1)
+                    .setListValue(Arrays.asList(
+                            new TestBundlableNewVersion()
+                                    .setEnumValue(TestBundlableNewVersion.TestEnum.VALUE2),
+                            new TestBundlableNewVersion()
+                    ))
+                    .setBundlableValue(
+                            new TestBundlableNewVersion()
+                    );
+
+    /**
+     * Expected value when interpreting {@link #TEST_VALUE_NEW_VERSION} using the same schema as
+     * {@link TestBundlable}. Given that {@link TestBundlableNewVersion#mNewValue} doesn't exist
+     * the old schema, and {@link TestBundlable#mStringValue} doesn't exist in the new schema,
+     * both values are dropped during serialization/deserialization.
+     */
+    private static final TestBundlable TEST_VALUE_NEW_VERSION_OLD_SCHEMA = new TestBundlable()
+            .setInt(123)
+            .setEnumValue(TestBundlable.TestEnum.VALUE1)
+            .setListValue(Arrays.asList(
+                    new TestBundlable()
+                            .setEnumValue(TestBundlable.TestEnum.VALUE2),
+                    new TestBundlable()
+            ))
+            .setBundlableValue(
+                    new TestBundlable()
+            );
+
+    private BundleMarshaller mBundleMarshaller = new BundleMarshaller();
+
+    /**
+     * Asserts that serializing and deserializing a {@link Bundlable} produces the same content.
+     * This includes testing instances with null values in them.
+     */
+    @Test
+    public void testSerializationDeserializationMaintainsContent() {
+        TestBundlable output = new TestBundlable();
+
+        TEST_VALUE.toBundle(mBundleMarshaller);
+        output.fromBundle(mBundleMarshaller);
+        assertEquals(TEST_VALUE, output);
+    }
+
+    /**
+     * Asserts that serialization and deserialization works in a forward compatible way, as long as
+     * they follow the versioning rules listed in {@link Bundlable}.
+     */
+    @Test
+    public void testForwardCompatibleChangesMaintainsCommonContent() {
+        TestBundlableNewVersion output = new TestBundlableNewVersion();
+
+        TEST_VALUE.toBundle(mBundleMarshaller);
+        output.fromBundle(mBundleMarshaller);
+        assertEquals(TEST_VALUE_NEW_VERSION, output);
+    }
+
+    /**
+     * Asserts that serialization and deserialization works in a backwards compatible way, as long
+     * as they follow the versioning rules listed in {@link Bundlable}.
+     */
+    @Test
+    public void testBackwardCompatibleChangesMaintainsCommonContent() {
+        TestBundlable output = new TestBundlable();
+
+        TEST_VALUE_NEW_VERSION.toBundle(mBundleMarshaller);
+        output.fromBundle(mBundleMarshaller);
+        assertEquals(TEST_VALUE_NEW_VERSION_OLD_SCHEMA, output);
+    }
+}
diff --git a/car/src/androidTest/java/androidx/car/navigation/utils/BundleMarshallerTest.java b/car/src/androidTest/java/androidx/car/navigation/utils/BundleMarshallerTest.java
new file mode 100644
index 0000000..cf5ac15
--- /dev/null
+++ b/car/src/androidTest/java/androidx/car/navigation/utils/BundleMarshallerTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.navigation.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.os.Bundle;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Unit tests for {@link BundleMarshaller}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BundleMarshallerTest {
+    private final BundleMarshaller mBundleMarshaller = new BundleMarshaller();
+
+    /**
+     * A random test value with a mix of primitives, null and non-null data.
+     */
+    private static final TestBundlable TEST_VALUE = new TestBundlable()
+            .setInt(1)
+            .setString("TEST")
+            .setBundlableValue(new TestBundlable()
+                    .setEnumValue(TestBundlable.TestEnum.VALUE1));
+
+    /**
+     * Tests that null values are serialized as expected.
+     */
+    @Test
+    public void serialization_nullCase() {
+        new TestBundlable().toBundle(mBundleMarshaller);
+
+        Bundle data = mBundleMarshaller.getBundle();
+        assertTrue(data.containsKey("intValue"));
+        assertEquals(0, data.getInt("intValue"));
+        assertNull(data.getString("stringValue"));
+        assertNull(data.getString("enumValue"));
+        assertTrue(data.getBoolean("bundlableValue._isNull"));
+        assertEquals(-1, data.getInt("bundlableListValue._size"));
+    }
+
+    /**
+     * Tests that nested {@link Bundlable}s are serialized as expected.
+     */
+    @Test
+    public void serialization_nestedBundlable() {
+        String stringValue = "TEST";
+        int intValue = 1;
+
+        new TestBundlable()
+                .setBundlableValue(new TestBundlable()
+                        .setInt(intValue)
+                        .setString(stringValue))
+                .toBundle(mBundleMarshaller);
+
+        Bundle data = mBundleMarshaller.getBundle();
+        assertTrue(data.containsKey("bundlableValue._isNull"));
+        assertFalse(data.getBoolean("bundlableValue._isNull"));
+        assertEquals(intValue, data.getInt("bundlableValue.intValue"));
+        assertEquals(stringValue, data.getString("bundlableValue.stringValue"));
+    }
+
+    /**
+     * Tests the correct serialization of a list of size 0.
+     */
+    @Test
+    public void listSerialization_listOfSize0() {
+        TestBundlable value = new TestBundlable().setListValue(new ArrayList<>());
+        value.toBundle(mBundleMarshaller);
+        Bundle data = mBundleMarshaller.getBundle();
+        assertEquals(0, data.getInt("bundlableListValue._size"));
+    }
+
+    /**
+     * Tests the correct serialization of a list of size n.
+     */
+    @Test
+    public void listSerialization_listOfSizeN() {
+        TestBundlable value = new TestBundlable().setListValue(Arrays.asList(
+                new TestBundlable().setInt(1),
+                new TestBundlable().setInt(2),
+                new TestBundlable().setInt(3)));
+        Bundle data = mBundleMarshaller.getBundle();
+        value.toBundle(mBundleMarshaller);
+        assertEquals(3, data.getInt("bundlableListValue._size"));
+        assertEquals(1, data.getInt("bundlableListValue.0.intValue"));
+        assertEquals(2, data.getInt("bundlableListValue.1.intValue"));
+        assertEquals(3, data.getInt("bundlableListValue.2.intValue"));
+    }
+
+    @Test
+    public void listSerialization_removingElementsInPlace() {
+        // Serialize and deserialize a list of a certain size
+        List<TestBundlable> mutableList = new ArrayList<>(Arrays.asList(
+                new TestBundlable().setInt(1),
+                new TestBundlable().setInt(2),
+                new TestBundlable().setInt(3)));
+        TestBundlable out = new TestBundlable().setListValue(mutableList);
+        TestBundlable in = new TestBundlable();
+        out.toBundle(mBundleMarshaller);
+        in.fromBundle(mBundleMarshaller);
+        assertEquals(out, in);
+
+        // Remove some elements and check that they are correctly removed during deserialization
+        mutableList.remove(0);
+        out.toBundle(mBundleMarshaller);
+        in.fromBundle(mBundleMarshaller);
+        assertEquals(out, in);
+    }
+
+    /**
+     * Tests that {@link BundleMarshaller#getDelta()} returns the same value as
+     * {@link BundleMarshaller#getBundle()} during the initial serialization.
+     */
+    @Test
+    public void deltaSerialization_equalsFullDataIfNotReset() {
+        TEST_VALUE.toBundle(mBundleMarshaller);
+        Bundle data = mBundleMarshaller.getBundle();
+        Bundle delta = mBundleMarshaller.getDelta();
+        assertBundlesEqual(data, delta);
+    }
+
+    /**
+     * Tests that {@link BundleMarshaller#getDelta()} is empty if no data is modified between
+     * serializations.
+     */
+    @Test
+    public void deltaSerialization_emptyIfNoDataIsModified() {
+        TEST_VALUE.toBundle(mBundleMarshaller);
+        mBundleMarshaller.resetDelta();
+        TEST_VALUE.toBundle(mBundleMarshaller);
+        Bundle delta = mBundleMarshaller.getDelta();
+        assertEquals(0, delta.size());
+    }
+
+    /**
+     * Tests that {@link BundleMarshaller#getDelta()} returns only the data that has been modified
+     * between two serializations.
+     */
+    @Test
+    public void deltaSerialization_onlyContainsModifiedData() {
+        // Serialize some base data
+        TestBundlable testValue = new TestBundlable()
+                .setInt(1)
+                .setString("TEST")
+                .setBundlableValue(new TestBundlable()
+                        .setEnumValue(TestBundlable.TestEnum.VALUE1));
+        testValue.toBundle(mBundleMarshaller);
+
+        // Reset change tracking and re-serialize after making some changes.
+        mBundleMarshaller.resetDelta();
+        testValue.setInt(2).setString(null);
+        testValue.mBundableValue.setEnumValue(TestBundlable.TestEnum.VALUE2);
+        testValue.toBundle(mBundleMarshaller);
+
+        Bundle expectedDelta = new Bundle();
+        expectedDelta.putInt("intValue", testValue.mIntValue);
+        expectedDelta.putString("stringValue", testValue.mStringValue);
+        expectedDelta.putString("bundlableValue.enumValue",
+                testValue.mBundableValue.mEnumValue.name());
+
+        Bundle delta = mBundleMarshaller.getDelta();
+        assertBundlesEqual(expectedDelta, delta);
+    }
+
+    /**
+     * Asserts that the provided {@link Bundle}s are equal. It throws {@link AssertionError}
+     * otherwise.
+     */
+    private void assertBundlesEqual(Bundle expected, Bundle actual) {
+        if (expected == null && actual == null) {
+            return;
+        }
+        if (expected == null || actual == null) {
+            fail(String.format("Expected %s value but found %s",
+                    expected != null ? "non-null" : "null",
+                    actual != null ? "non-null" : "null"));
+        }
+        if (!expected.keySet().equals(actual.keySet())) {
+            fail(String.format("Expected keys: %s, but found keys: %s",
+                    expected.keySet().stream().sorted().collect(Collectors.joining(",")),
+                    actual.keySet().stream().sorted().collect(Collectors.joining(","))));
+        }
+        for (String key : expected.keySet()) {
+            assertEquals(String.format("Expected '%s' at key '%s' but found '%s",
+                            expected.get(key), key, actual.get(key)),
+                    expected.get(key),
+                    actual.get(key));
+        }
+    }
+}
diff --git a/car/src/androidTest/java/androidx/car/navigation/utils/TestBundlable.java b/car/src/androidTest/java/androidx/car/navigation/utils/TestBundlable.java
new file mode 100644
index 0000000..1ca19d3
--- /dev/null
+++ b/car/src/androidTest/java/androidx/car/navigation/utils/TestBundlable.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.navigation.utils;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Reference implementation of a {@link Bundlable}
+ */
+class TestBundlable implements Bundlable {
+    private static final String INT_VALUE_KEY = "intValue";
+    private static final String STRING_VALUE_KEY = "stringValue";
+    private static final String ENUM_VALUE_KEY = "enumValue";
+    private static final String BUNDLABLE_VALUE_KEY = "bundlableValue";
+    private static final String BUNDLABLE_LIST_VALUE_KEY = "bundlableListValue";
+
+    enum TestEnum {
+        VALUE1,
+        VALUE2,
+        VALUE3,
+    }
+
+    int mIntValue;
+    String mStringValue;
+    TestEnum mEnumValue;
+    TestBundlable mBundableValue;
+    List<TestBundlable> mListValue;
+
+    @Override
+    public void toBundle(BundleMarshaller out) {
+        out.putInt(INT_VALUE_KEY, mIntValue);
+        out.putString(STRING_VALUE_KEY, mStringValue);
+        out.putEnum(ENUM_VALUE_KEY, mEnumValue);
+        out.putBundlable(BUNDLABLE_VALUE_KEY, mBundableValue);
+        out.putBundlableList(BUNDLABLE_LIST_VALUE_KEY, mListValue);
+    }
+
+    @Override
+    public void fromBundle(BundleMarshaller in) {
+        mIntValue = in.getInt(INT_VALUE_KEY);
+        mStringValue = in.getString(STRING_VALUE_KEY);
+        mEnumValue = in.getEnum(ENUM_VALUE_KEY, TestEnum.class);
+        mBundableValue = in.getBundlable(BUNDLABLE_VALUE_KEY, mBundableValue, TestBundlable::new);
+        mListValue = in.getBundlableList(BUNDLABLE_LIST_VALUE_KEY, mListValue, TestBundlable::new);
+    }
+
+    public TestBundlable setInt(int value) {
+        mIntValue = value;
+        return this;
+    }
+
+    public TestBundlable setString(String value) {
+        mStringValue = value;
+        return this;
+    }
+
+    public TestBundlable setEnumValue(TestEnum value) {
+        mEnumValue = value;
+        return this;
+    }
+
+    public TestBundlable setBundlableValue(TestBundlable value) {
+        mBundableValue = value;
+        return this;
+    }
+
+    public TestBundlable setListValue(List<TestBundlable> value) {
+        mListValue = value;
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        TestBundlable that = (TestBundlable) o;
+        return mIntValue == that.mIntValue
+                && Objects.equals(mStringValue, that.mStringValue)
+                && mEnumValue == that.mEnumValue
+                && Objects.equals(mBundableValue, that.mBundableValue)
+                && Objects.equals(mListValue, that.mListValue);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIntValue, mStringValue, mEnumValue, mBundableValue, mListValue);
+    }
+}
diff --git a/car/src/androidTest/java/androidx/car/navigation/utils/TestBundlableNewVersion.java b/car/src/androidTest/java/androidx/car/navigation/utils/TestBundlableNewVersion.java
new file mode 100644
index 0000000..58ee6f6
--- /dev/null
+++ b/car/src/androidTest/java/androidx/car/navigation/utils/TestBundlableNewVersion.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.navigation.utils;
+
+import androidx.annotation.NonNull;
+import androidx.core.util.Preconditions;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Example of a version change. This is a copy of {@link TestBundlable} but with one field
+ * deprecated ({@link TestBundlable#mStringValue}) and one field added
+ * ({@link TestBundlableNewVersion#mNewValue})
+ */
+class TestBundlableNewVersion implements Bundlable {
+    private static final String INT_VALUE_KEY = "intValue";
+    // In this version of TestBundlable, mStringValue field has been deprecated, and its key should
+    // not be re-used.
+    // private static final String STRING_VALUE_KEY = "stringValue";
+    private static final String ENUM_VALUE_KEY = "enumValue";
+    private static final String BUNDLABLE_VALUE_KEY = "bundlableValue";
+    private static final String BUNDLABLE_LIST_VALUE_KEY = "bundlableListValue";
+    private static final String NEW_VALUE_KEY = "newValue";
+
+    enum TestEnum {
+        VALUE1,
+        VALUE2,
+        VALUE3,
+    }
+
+    public static final String DEFAULT_NEW_VALUE = "TEST_V2";
+
+    int mIntValue;
+    TestEnum mEnumValue;
+    // In this version of TestBundlable, we simulate mStringValue being deprecated.
+    // String mStringValue;
+    TestBundlableNewVersion mBundableValue;
+    List<TestBundlableNewVersion> mListValue;
+    // In this version of TestBundlable, we simulate the creation of a new mandatory field.
+    @NonNull
+    String mNewValue;
+
+    TestBundlableNewVersion() {
+        mNewValue = DEFAULT_NEW_VALUE;
+    }
+
+    @Override
+    public void toBundle(@NonNull BundleMarshaller out) {
+        out.putInt(INT_VALUE_KEY, mIntValue);
+        // dest.putString(STRING_VALUE_KEY, mStringValue) is now deprecated.
+        out.putEnum(ENUM_VALUE_KEY, mEnumValue);
+        out.putBundlable(BUNDLABLE_VALUE_KEY, mBundableValue);
+        out.putBundlableList(BUNDLABLE_LIST_VALUE_KEY, mListValue);
+        // new required value
+        out.putString(NEW_VALUE_KEY, mNewValue);
+    }
+
+    @Override
+    public void fromBundle(@NonNull BundleMarshaller in) {
+        mIntValue = in.getInt(INT_VALUE_KEY);
+        // mStringValue = in.getString(STRING_VALUE_KEY) is now deprecated.
+        mEnumValue = in.getEnum(ENUM_VALUE_KEY, TestEnum.class);
+        mBundableValue = in.getBundlable(BUNDLABLE_VALUE_KEY, mBundableValue,
+                TestBundlableNewVersion::new);
+        mListValue = in.getBundlableList(BUNDLABLE_LIST_VALUE_KEY, mListValue,
+                TestBundlableNewVersion::new);
+        // new required value with a mandatory default
+        mNewValue = in.getStringNonNull(NEW_VALUE_KEY, DEFAULT_NEW_VALUE);
+    }
+
+    public TestBundlableNewVersion setInt(int value) {
+        mIntValue = value;
+        return this;
+    }
+
+    public TestBundlableNewVersion setEnumValue(TestEnum value) {
+        mEnumValue = value;
+        return this;
+    }
+
+    public TestBundlableNewVersion setBundlableValue(TestBundlableNewVersion value) {
+        mBundableValue = value;
+        return this;
+    }
+
+    public TestBundlableNewVersion setListValue(List<TestBundlableNewVersion> value) {
+        mListValue = value;
+        return this;
+    }
+
+    public TestBundlableNewVersion setNewValue(@NonNull String value) {
+        Preconditions.checkNotNull(value);
+        mNewValue = value;
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        TestBundlableNewVersion that = (TestBundlableNewVersion) o;
+        return mIntValue == that.mIntValue
+                && mEnumValue == that.mEnumValue
+                && Objects.equals(mBundableValue, that.mBundableValue)
+                && Objects.equals(mListValue, that.mListValue)
+                && Objects.equals(mNewValue, that.mNewValue);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIntValue, mEnumValue, mBundableValue, mListValue, mNewValue);
+    }
+}
diff --git a/car/src/androidTest/java/androidx/car/widget/SeekbarListItemTest.java b/car/src/androidTest/java/androidx/car/widget/SeekbarListItemTest.java
index 82f5268..13e10ff 100644
--- a/car/src/androidTest/java/androidx/car/widget/SeekbarListItemTest.java
+++ b/car/src/androidTest/java/androidx/car/widget/SeekbarListItemTest.java
@@ -419,3 +419,4 @@
         };
     }
 }
+
diff --git a/car/src/main/java/androidx/car/drawer/CarDrawerActivity.java b/car/src/main/java/androidx/car/drawer/CarDrawerActivity.java
index e43e002..ea944ff 100644
--- a/car/src/main/java/androidx/car/drawer/CarDrawerActivity.java
+++ b/car/src/main/java/androidx/car/drawer/CarDrawerActivity.java
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package androidx.car.drawer;
 
 import android.animation.ValueAnimator;
 import android.content.res.Configuration;
 import android.os.Bundle;
+import android.support.design.widget.AppBarLayout;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
@@ -33,8 +33,6 @@
 import androidx.car.R;
 import androidx.drawerlayout.widget.DrawerLayout;
 
-import com.google.android.material.appbar.AppBarLayout;
-
 /**
  * Common base Activity for car apps that need to present a Drawer.
  *
diff --git a/car/src/main/java/androidx/car/navigation/utils/Bundlable.java b/car/src/main/java/androidx/car/navigation/utils/Bundlable.java
new file mode 100644
index 0000000..65e8bf2
--- /dev/null
+++ b/car/src/main/java/androidx/car/navigation/utils/Bundlable.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.navigation.utils;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+
+/**
+ * Interface for classes whose instances can be written to and restored from a {@link Bundle}.
+ * Classes implementing the {@link Bundlable} interface must also provide a public default
+ * constructor, or a constructor that accepts {@link BundleMarshaller} as its only parameter.
+ * <p>
+ * This serialization protocol is designed to:
+ * <ul>
+ * <li>provide backward/forward compatibility between producers and consumers (following the
+ * Protocol Buffers pattern).
+ * <li>minimize the number of objects being allocated during both serialization and deserialization.
+ * </ul>
+ * <p>
+ * Implementations of this interface should comply to the following rules:
+ * <ul>
+ * <li>Fields should be serialized and deserialized using {@link BundleMarshaller} "put" and
+ * "get" methods.
+ * <li>Marshalling keys must be lower camel case alphanumerical identifiers (i.e.: "distanceUnit").
+ * (symbols such as "." and "_" are reserved by the system).
+ * <li>Field types should not be modified between versions of {@link Bundlable} objects to provide
+ * backward and forward compatibility. Only deprecations and additions are allowed.
+ * <li>When a field is deprecated, its marshalling key shouldn't be reused by any new field.
+ * <li>Enums are marshalled using {@link Enum#name()}. Because of this, enum values should not be
+ * renamed. Because enum values could be added or deprecated, clients must be prepared to accept
+ * null or a default value in case the server sends a value it doesn't know.
+ * <li>Fields annotated with {@link androidx.annotation.NonNull} should not be deprecated
+ * (as clients might not be prepared for their absence). Implementations of this interface should
+ * enforce this constraint, i.e. by initializing these fields at class instantiation, and using
+ * {@link androidx.core.util.Preconditions#checkNotNull(Object)} to prevent null values. If a new
+ * {@link androidx.annotation.NonNull} field is added on an existing {@link Bundlable}, the
+ * deserialization must provide a default value for it (as existing services won't provide values
+ * for it until they are updated).
+ * </ul>
+ * The following is an example of the suggested implementation:
+ * <pre>
+ * public class MyClass implements Bundlable {
+ *     private static final String FOO_VALUE_KEY = "fooValue";
+ *     private static final String BAR_VALUE_KEY = "barValue";
+ *
+ *     public enum MyEnum {
+ *         VALUE_1,
+ *         VALUE_2
+ *     }
+ *
+ *     public String mFooValue;
+ *     public MyEnum mBarValue;
+ *
+ *     &#064;Override
+ *     public void toBundle(@NonNull BundleMarshaller out) {
+ *         out.putString(FOO_VALUE_KEY, mFooValue);
+ *         out.putEnum(BAR_VALUE_KEY, mBarValue);
+ *     }
+ *
+ *     &#064;Override
+ *     public void fromBundle(@NonNull BundleMarshaller in) {
+ *         mFooValue = in.getString(FOO_VALUE_KEY);
+ *         mBarValue = in.getEnum(BAR_VALUE_KEY, MyEnum.class);
+ *     }
+ * }
+ * </pre>
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+public interface Bundlable {
+    /**
+     * Serializes this object into a {@link BundleMarshaller} by writing all its fields to it.
+     */
+    void toBundle(@NonNull BundleMarshaller out);
+
+    /**
+     * Deserializes this object from a {@link BundleMarshaller} by reading all its fields from it.
+     */
+    void fromBundle(@NonNull BundleMarshaller in);
+}
diff --git a/car/src/main/java/androidx/car/navigation/utils/BundleMarshaller.java b/car/src/main/java/androidx/car/navigation/utils/BundleMarshaller.java
new file mode 100644
index 0000000..1e6178a
--- /dev/null
+++ b/car/src/main/java/androidx/car/navigation/utils/BundleMarshaller.java
@@ -0,0 +1,514 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.navigation.utils;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+/**
+ * Class responsible for serializing and deserializing data into a {@link Bundle}. It also
+ * provides a way to detect what items in the {@link Bundle} have been modified during
+ * marshalling.
+ * <p>
+ * A single {@link BundleMarshaller} can be re-used to serialize or deserialize data multiple times.
+ * Similarity, deserialization can be done in-place, updating existing {@link Bundlable}s. This
+ * reduces the number of instances being allocated.
+ * <p>
+ * When serializing, use {@link #resetBundle()} before marshalling and {@link #getBundle()} to
+ * obtain an snap-shot of the serialized content. Or use {@link #resetDelta()} and
+ * {@link #getDelta()} to obtain a {@link Bundle} representing the patch between the last and
+ * the new serialized data.
+ * <p>
+ * When deserializing, use {@link #setBundle(Bundle)} to deserialize a {@link Bundle} containing an
+ * snap-shot, or {@link #applyDelta(Bundle)} to process a patch from the last deserialized data.
+ * <p>
+ * Keys used in the "get" and "put" methods must be lower camel case alphanumerical identifiers
+ * (e.g.: "distanceUnit"). Symbols like "." and "_" are reserved by the system.
+ * <p>
+ * When deserializing {@link List} objects, this class assumes that they implement random access
+ * (e.g. {@link ArrayList}), or they are relatively small (see more details at
+ * {@link #trimList(List, int)})
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+public class BundleMarshaller {
+    /**
+     * Separator used to concatenate identifiers when marshalling non-primitive types (e.g. lists
+     * or {@link Bundlable}s).
+     */
+    private static final String KEY_SEPARATOR = ".";
+    /**
+     * Identifier used to record if a given non-primitive field is null or not. This allows
+     * serializing null objects without the need of using reflection or static methods.
+     */
+    private static final String IS_NULL_KEY = "_isNull";
+    /**
+     * Identifier used to record the length of a collection. This allows serializing changes to the
+     * length of a collection without having to remove elements or having to iterate over every
+     * possible collection key.
+     */
+    private static final String SIZE_KEY = "_size";
+    /**
+     * Special value for {@link #SIZE_KEY} to serialize a null collection.
+     */
+    private static final int NULL_SIZE = -1;
+
+    private Bundle mBundle = new Bundle();
+    private String mKeyPrefix = "";
+    private final Bundle mBundleDelta = new Bundle();
+
+    /**
+     * Returns data serialized since the last time this instance was constructed, or
+     * {@link #resetBundle()} was called.
+     */
+    public Bundle getBundle() {
+        return mBundle;
+    }
+
+    /**
+     * Resets this {@link BundleMarshaller} causing {@link #getBundle()} to return an empty
+     * {@link Bundle} until the next marshalling is executed. This can be used occasionally to
+     * remove unused keys in the {@link Bundle}.
+     */
+    public void resetBundle() {
+        mBundle.clear();
+    }
+
+    /**
+     * Replaces the {@link Bundle} to serialize into or deserialize from.
+     */
+    public void setBundle(Bundle bundle) {
+        mBundle = bundle;
+    }
+
+    /**
+     * Gets a {@link Bundle} containing only the entries of {@link #getBundle()} that were modified
+     * since this instance was constructed, or {@link #resetDelta()} was called.
+     */
+    public Bundle getDelta() {
+        return mBundleDelta;
+    }
+
+    /**
+     * Merges the provided {@link Bundle} on top of the one stored in this {@link BundleMarshaller}.
+     *
+     * @param delta a {@link Bundle} containing entries to be updated on one stored in this
+     *              {@link BundleMarshaller} instance. Such {@link Bundle} can be produced by
+     *              using the {@link #resetDelta()} and {@link #getDelta()} methods during data
+     *              serialization.
+     */
+    public void applyDelta(Bundle delta) {
+        mBundle.putAll(delta);
+    }
+
+    /**
+     * Resets tracking of modified entries, causing {@link #getDelta()} to return an empty
+     * {@link Bundle} until the next marshalling is executed. This can be used between
+     * serializations make {@link #getDelta()} return only the differences.
+     */
+    public void resetDelta() {
+        mBundleDelta.clear();
+    }
+
+    /**
+     * Inserts an int value, replacing any existing value for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param value an int
+     */
+    public void putInt(@NonNull String key, int value) {
+        String mangledKey = getMangledKey(key);
+        if (!mBundle.containsKey(mangledKey) || mBundle.getInt(mangledKey) != value) {
+            mBundleDelta.putInt(mangledKey, value);
+            mBundle.putInt(mangledKey, value);
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or 0 if no mapping of the desired type
+     * exists for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @return an int
+     */
+    public int getInt(@NonNull String key) {
+        return mBundle.getInt(getMangledKey(key));
+    }
+
+    /**
+     * Inserts a float value, replacing any existing value for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param value a float
+     */
+    public void putFloat(@NonNull String key, float value) {
+        String mangledKey = getMangledKey(key);
+        if (!mBundle.containsKey(mangledKey)
+                || Float.compare(mBundle.getFloat(mangledKey), value) != 0) {
+            mBundleDelta.putFloat(mangledKey, value);
+            mBundle.putFloat(mangledKey, value);
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or 0.0f if no mapping of the desired type
+     * exists for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @return a float
+     */
+    public float getFloat(@NonNull String key) {
+        return mBundle.getFloat(getMangledKey(key));
+    }
+
+    /**
+     * Inserts a double value, replacing any existing value for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param value a double
+     */
+    public void putDouble(@NonNull String key, double value) {
+        String mangledKey = getMangledKey(key);
+        if (!mBundle.containsKey(mangledKey)
+                || Double.compare(mBundle.getDouble(mangledKey), value) != 0) {
+            mBundleDelta.putDouble(mangledKey, value);
+            mBundle.putDouble(mangledKey, value);
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or 0.0 if no mapping of the desired type
+     * exists for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @return a double
+     */
+    public double getDouble(@NonNull String key) {
+        return mBundle.getDouble(getMangledKey(key));
+    }
+
+    /**
+     * Inserts a boolean value, replacing any existing value for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param value a boolean
+     */
+    public void putBoolean(@NonNull String key, boolean value) {
+        String mangledKey = getMangledKey(key);
+        if (!mBundle.containsKey(mangledKey) || mBundle.getBoolean(mangledKey) != value) {
+            mBundleDelta.putBoolean(mangledKey, value);
+            mBundle.putBoolean(mangledKey, value);
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or false if no mapping of the desired type
+     * exists for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @return a boolean
+     */
+    public boolean getBoolean(@NonNull String key) {
+        return mBundle.getBoolean(getMangledKey(key));
+    }
+
+    /**
+     * Inserts a string value, replacing any existing value for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param value a string, or null
+     */
+    public void putString(@NonNull String key, @Nullable String value) {
+        String mangledKey = getMangledKey(key);
+        if (!mBundle.containsKey(mangledKey)
+                || !Objects.equals(mBundle.getString(mangledKey), value)) {
+            mBundleDelta.putString(mangledKey, value);
+            mBundle.putString(mangledKey, value);
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if no mapping of the desired type
+     * exists for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @return a string, or null
+     */
+    @Nullable
+    public String getString(@NonNull String key) {
+        return mBundle.getString(getMangledKey(key));
+    }
+
+    /**
+     * Returns the value associated with the given key, or the provided default value if no mapping
+     * of the desired type exists for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param defaultValue value to return if key does not exist or if a null value is associated
+     *                     with the given key.
+     * @return a string
+     */
+    @NonNull
+    public String getStringNonNull(@NonNull String key, @NonNull String defaultValue) {
+        return mBundle.getString(getMangledKey(key), defaultValue);
+    }
+
+    /**
+     * Inserts an enum value, replacing any existing value for the given key. The provided enum
+     * will be serialized as a string using {@link Enum#name()}.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param value an enum, or null
+     */
+    public <T extends Enum<T>> void putEnum(@NonNull String key, @Nullable T value) {
+        putString(key, value != null ? value.name() : null);
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if no mapping of the desired type
+     * exists for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param clazz {@link Enum} class to be used to deserialize the value.
+     * @param <T> {@link Enum} type to be returned.
+     * @return an enum, or null
+     */
+    @Nullable
+    public <T extends Enum<T>> T getEnum(@NonNull String key, @NonNull Class<T> clazz) {
+        String name = getString(key);
+        try {
+            return name != null ? Enum.valueOf(clazz, name) : null;
+        } catch (IllegalArgumentException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or the provided default value if no mapping
+     * of the desired type exists for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param clazz {@link Enum} class to be used to deserialize the value.
+     * @param defaultValue value to return if key does not exist or if a null value is associated
+     *                     with the given key.
+     * @param <T> {@link Enum} type to be returned.
+     * @return an enum
+     */
+    @NonNull
+    public <T extends Enum<T>> T getEnumNonNull(@NonNull String key, @NonNull Class<T> clazz,
+            @NonNull T defaultValue) {
+        T result = getEnum(key, clazz);
+        return result != null ? result : defaultValue;
+    }
+
+    /**
+     * Inserts a {@link Bundlable} value, replacing any existing value for the given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param value a {@link Bundlable}, or null
+     */
+    public <T extends Bundlable> void putBundlable(@NonNull String key, @Nullable T value) {
+        withKeyPrefix(key, () -> {
+            putBoolean(IS_NULL_KEY, value == null);
+            if (value != null) {
+                value.toBundle(this);
+            }
+        });
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if no mapping of the desired type
+     * exists for the given key. If a non-null "current" instance is provided, then the
+     * deserialization would be done in place. Otherwise, a new instance will be created using the
+     * provided factory.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param current current value (if available) to perform in-place deserialization, or null
+     * @param factory a {@link Supplier} capable of providing an instance of a {@link Bundlable} of
+     *                type T. The suggested implementation is to pass a reference to the default
+     *                constructor of that class.
+     * @param <T> {@link Bundlable} type to be returned.
+     * @return an instance of type T, or null
+     */
+    @Nullable
+    public <T extends Bundlable> T getBundlable(@NonNull String key, @Nullable T current,
+            @NonNull Supplier<T> factory) {
+        return withKeyPrefix(key, () -> {
+            if (getBoolean(IS_NULL_KEY)) {
+                return null;
+            }
+            T result = current != null ? current : factory.get();
+            result.fromBundle(this);
+            return result;
+        });
+    }
+
+    /**
+     * Returns the value associated with the given key, or a default value if no mapping of the
+     * desired type exists for the given key. If a non-null value is available, then such value
+     * will be deserialized in-place on the given "current" instance. Otherwise, a default value
+     * will be generated using the provided factory.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param current current value to perform in-place deserialization
+     * @param factory a {@link Supplier} capable of providing an instance of a {@link Bundlable} of
+     *                type T. The suggested implementation is to pass a reference to the default
+     *                constructor of that class.
+     * @param <T> {@link Bundlable} type to be returned.
+     * @return an instance of type T
+     */
+    @NonNull
+    public <T extends Bundlable> T getBundlableNonNull(@NonNull String key, @NonNull T current,
+            @NonNull Supplier<T> factory) {
+        T result = getBundlable(key, current, factory);
+        return result != null ? result : factory.get();
+    }
+
+    /**
+     * Inserts a {@link List} of {@link Bundlable} values, replacing any existing value for the
+     * given key.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param values a {@link List} of {@link Bundlable} values, or null
+     */
+    public <T extends Bundlable> void putBundlableList(@NonNull String key,
+            @Nullable List<T> values) {
+        withKeyPrefix(key, () -> {
+            putInt(SIZE_KEY, values != null ? values.size() : NULL_SIZE);
+            if (values != null) {
+                int pos = 0;
+                // Using for-each as the provided list might not implement random access (e.g. it
+                // might be a linked list).
+                for (T value : values) {
+                    putBundlable(String.valueOf(pos), value);
+                    pos++;
+                }
+            }
+        });
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if no mapping of the desired type
+     * exists for the given key. If a non-null "current" list is provided, then the deserialization
+     * would be done in place. Otherwise, a new list will be created and items will be instantiated
+     * using the provided factory.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param current current value (if available) to perform in-place deserialization, or null
+     * @param factory a {@link Supplier} capable of providing an instance of a {@link Bundlable} of
+     *                type T. The suggested implementation is to pass a reference to the default
+     *                constructor of that class.
+     * @param <T> {@link Bundlable} type to be returned.
+     * @return a list of instances of type T, or null. The resulting list might contain null
+     *         elements.
+     */
+    @Nullable
+    public <T extends Bundlable> List<T> getBundlableList(@NonNull String key,
+            @Nullable List<T> current, @NonNull Supplier<T> factory) {
+        return withKeyPrefix(key, () -> {
+            int listSize = getInt(SIZE_KEY);
+            if (listSize == NULL_SIZE) {
+                return null;
+            }
+            List<T> result = current != null ? current : new ArrayList<>(listSize);
+            if (result.size() > listSize) {
+                result.subList(listSize, result.size()).clear();
+            }
+            for (int pos = 0; pos < listSize; pos++) {
+                String subKey = String.valueOf(pos);
+                if (pos < result.size()) {
+                    result.set(pos, getBundlable(subKey, result.get(pos), factory));
+                } else {
+                    result.add(getBundlable(String.valueOf(pos),
+                            null /* force the creation of a new instance */,
+                            factory));
+                }
+            }
+            return result;
+        });
+    }
+
+    /**
+     * Returns the value associated with the given key, or an empty list if no mapping of the
+     * desired type exists for the given key. If a non-null "current" list is provided, then the
+     * deserialization would be done in place. Otherwise, a new list will be created and items will
+     * be instantiated using the provided factory.
+     *
+     * @param key lower camel case alphanumerical identifier
+     * @param current current value (if available) to perform in-place deserialization, or null
+     * @param factory a {@link Supplier} capable of providing an instance of a {@link Bundlable} of
+     *                type T. The suggested implementation is to pass a reference to the default
+     *                constructor of that class.
+     * @param <T> {@link Bundlable} type to be returned.
+     * @return a list of instances of type T, or an empty list. The resulting list might contain
+     *         null elements.
+     */
+    @NonNull
+    public <T extends Bundlable> List<T> getBundlableListNonNull(@NonNull String key,
+            @NonNull List<T> current, @NonNull Supplier<T> factory) {
+        List<T> result = getBundlableList(key, current, factory);
+        return result != null ? result : new ArrayList<>();
+    }
+
+    /**
+     * Executes the given {@link Runnable} in a context where {@link #getMangledKey(String)}
+     * includes the given key as part of the prefix. Calls to this method can be nested (the
+     * provided {@link Runnable} can call to this method if needed). This method should be used when
+     * serializing or deserializing nested objects.
+     * <p>
+     * For example: calling to {@link #withKeyPrefix(String, Runnable)} with "foo" as key and
+     * a {@link Runnable} that calls {@link #getMangledKey(String)} with "bar" as key, will
+     * cause such {@link #getMangledKey(String)} call to return "foo.bar".
+     */
+    private void withKeyPrefix(@NonNull String key, @NonNull Runnable runnable) {
+        String originalKeyPrefix = mKeyPrefix;
+        mKeyPrefix = mKeyPrefix + key + KEY_SEPARATOR;
+        runnable.run();
+        mKeyPrefix = originalKeyPrefix;
+    }
+
+    /**
+     * Similar to {@link #withKeyPrefix(String, Runnable)} but allows returning a value.
+     */
+    private <X> X withKeyPrefix(@NonNull String key, @NonNull Supplier<X> supplier) {
+        String originalKeyPrefix = mKeyPrefix;
+        mKeyPrefix = mKeyPrefix + key + KEY_SEPARATOR;
+        X res = supplier.get();
+        mKeyPrefix = originalKeyPrefix;
+        return res;
+    }
+
+    /**
+     * Returns a composed key based on the given one and the current serialization/deserialization
+     * key prefix (initially empty). This prefix can be temporarily changed with
+     * {@link #withKeyPrefix(String, Runnable)} or {@link #withKeyPrefix(String, Supplier)}.
+     */
+    private String getMangledKey(@NonNull String key) {
+        return mKeyPrefix + key;
+    }
+}
diff --git a/car/src/main/java/androidx/car/widget/SeekbarListItem.java b/car/src/main/java/androidx/car/widget/SeekbarListItem.java
index d859b63..0c64d12 100644
--- a/car/src/main/java/androidx/car/widget/SeekbarListItem.java
+++ b/car/src/main/java/androidx/car/widget/SeekbarListItem.java
@@ -66,8 +66,6 @@
  *
  * <p>When conflicting methods are called (e.g. setting primary action to both primary icon and
  * no icon), the last called method wins.
- *
- * {@code minimum value} is set to 0.
  */
 public class SeekbarListItem extends ListItem<SeekbarListItem.ViewHolder> {
 
@@ -102,9 +100,8 @@
 
     private String mText;
 
-    private int mMax;
     private int mProgress;
-    private int mSecondaryProgress;
+    private int mMax;
     private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener;
 
     @SupplementalActionType private int mSupplementalActionType = SUPPLEMENTAL_ACTION_NO_ACTION;
@@ -133,46 +130,6 @@
     }
 
     /**
-     * Sets max value of seekbar.
-     */
-    public void setMax(int max) {
-        mMax = max;
-        markDirty();
-    }
-
-    /**
-     * Sets progress of seekbar.
-     */
-    public void setProgress(int progress) {
-        mProgress = progress;
-        markDirty();
-    }
-
-    /**
-     * Sets secondary progress of seekbar.
-     */
-    public void setSecondaryProgress(int secondaryProgress) {
-        mSecondaryProgress = secondaryProgress;
-        markDirty();
-    }
-
-    /**
-     * Sets {@link SeekBar.OnSeekBarChangeListener}.
-     */
-    public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener listener) {
-        mOnSeekBarChangeListener = listener;
-        markDirty();
-    }
-
-    /**
-     * Sets text that sits on top of seekbar.
-     */
-    public void setText(String text) {
-        mText = text;
-        markDirty();
-    }
-
-    /**
      * Calculates the layout params for views in {@link ViewHolder}.
      */
     @Override
@@ -304,7 +261,6 @@
         mBinders.add(vh -> {
             vh.getSeekBar().setMax(mMax);
             vh.getSeekBar().setProgress(mProgress);
-            vh.getSeekBar().setSecondaryProgress(mSecondaryProgress);
             vh.getSeekBar().setOnSeekBarChangeListener(mOnSeekBarChangeListener);
 
             if (!TextUtils.isEmpty(mText)) {
diff --git a/compat/api/current.txt b/compat/api/current.txt
index 529cbba..0a19457 100644
--- a/compat/api/current.txt
+++ b/compat/api/current.txt
@@ -81,20 +81,6 @@
     method public static void setExactAndAllowWhileIdle(android.app.AlarmManager, int, long, android.app.PendingIntent);
   }
 
-  public class AppComponentFactory extends android.app.AppComponentFactory {
-    ctor public AppComponentFactory();
-    method public final android.app.Activity instantiateActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public android.app.Activity instantiateActivityCompat(java.lang.ClassLoader, java.lang.String, android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public final android.app.Application instantiateApplication(java.lang.ClassLoader, java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public android.app.Application instantiateApplicationCompat(java.lang.ClassLoader, java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public final android.content.ContentProvider instantiateProvider(java.lang.ClassLoader, java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public android.content.ContentProvider instantiateProviderCompat(java.lang.ClassLoader, java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public final android.content.BroadcastReceiver instantiateReceiver(java.lang.ClassLoader, java.lang.String, android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public android.content.BroadcastReceiver instantiateReceiverCompat(java.lang.ClassLoader, java.lang.String, android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public final android.app.Service instantiateService(java.lang.ClassLoader, java.lang.String, android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method public android.app.Service instantiateServiceCompat(java.lang.ClassLoader, java.lang.String, android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-  }
-
   public class AppLaunchChecker {
     ctor public deprecated AppLaunchChecker();
     method public static boolean hasStartedFromLauncher(android.content.Context);
@@ -177,7 +163,6 @@
     method public static int getBadgeIconType(android.app.Notification);
     method public static java.lang.String getCategory(android.app.Notification);
     method public static java.lang.String getChannelId(android.app.Notification);
-    method public static java.lang.CharSequence getContentTitle(android.app.Notification);
     method public static android.os.Bundle getExtras(android.app.Notification);
     method public static java.lang.String getGroup(android.app.Notification);
     method public static int getGroupAlertBehavior(android.app.Notification);
@@ -221,7 +206,6 @@
     field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
     field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession";
     field public static final java.lang.String EXTRA_MESSAGES = "android.messages";
-    field public static final java.lang.String EXTRA_MESSAGING_STYLE_USER = "android.messagingStyleUser";
     field public static final java.lang.String EXTRA_PEOPLE = "android.people";
     field public static final java.lang.String EXTRA_PICTURE = "android.picture";
     field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
@@ -458,8 +442,7 @@
   }
 
   public static class NotificationCompat.MessagingStyle extends androidx.core.app.NotificationCompat.Style {
-    ctor public deprecated NotificationCompat.MessagingStyle(java.lang.CharSequence);
-    ctor public NotificationCompat.MessagingStyle(androidx.core.app.Person);
+    ctor public NotificationCompat.MessagingStyle(java.lang.CharSequence);
     method public void addCompatExtras(android.os.Bundle);
     method public deprecated androidx.core.app.NotificationCompat.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
     method public androidx.core.app.NotificationCompat.MessagingStyle addMessage(java.lang.CharSequence, long, androidx.core.app.Person);
@@ -467,8 +450,7 @@
     method public static androidx.core.app.NotificationCompat.MessagingStyle extractMessagingStyleFromNotification(android.app.Notification);
     method public java.lang.CharSequence getConversationTitle();
     method public java.util.List<androidx.core.app.NotificationCompat.MessagingStyle.Message> getMessages();
-    method public androidx.core.app.Person getUser();
-    method public deprecated java.lang.CharSequence getUserDisplayName();
+    method public java.lang.CharSequence getUserDisplayName();
     method public boolean isGroupConversation();
     method public androidx.core.app.NotificationCompat.MessagingStyle setConversationTitle(java.lang.CharSequence);
     method public androidx.core.app.NotificationCompat.MessagingStyle setGroupConversation(boolean);
@@ -827,11 +809,6 @@
     method public static long getLongVersionCode(android.content.pm.PackageInfo);
   }
 
-  public final class PermissionInfoCompat {
-    method public static int getProtection(android.content.pm.PermissionInfo);
-    method public static int getProtectionFlags(android.content.pm.PermissionInfo);
-  }
-
   public class ShortcutInfoCompat {
     method public android.content.ComponentName getActivity();
     method public java.lang.CharSequence getDisabledMessage();
@@ -889,10 +866,6 @@
 
 package androidx.core.database {
 
-  public final class CursorWindowCompat {
-    method public android.database.CursorWindow create(java.lang.String, long);
-  }
-
   public final deprecated class DatabaseUtilsCompat {
     method public static deprecated java.lang.String[] appendSelectionArgs(java.lang.String[], java.lang.String[]);
     method public static deprecated java.lang.String concatenateWhere(java.lang.String, java.lang.String);
@@ -900,14 +873,6 @@
 
 }
 
-package androidx.core.database.sqlite {
-
-  public final class SQLiteCursorCompat {
-    method public void setFillWindowForwardOnly(android.database.sqlite.SQLiteCursor, boolean);
-  }
-
-}
-
 package androidx.core.graphics {
 
   public final class BitmapCompat {
@@ -1310,40 +1275,6 @@
     method public static java.lang.String maximizeAndGetScript(java.util.Locale);
   }
 
-  public class PrecomputedTextCompat implements android.text.Spannable {
-    method public char charAt(int);
-    method public static androidx.core.text.PrecomputedTextCompat create(java.lang.CharSequence, androidx.core.text.PrecomputedTextCompat.Params);
-    method public int getParagraphCount();
-    method public int getParagraphEnd(int);
-    method public int getParagraphStart(int);
-    method public androidx.core.text.PrecomputedTextCompat.Params getParams();
-    method public int getSpanEnd(java.lang.Object);
-    method public int getSpanFlags(java.lang.Object);
-    method public int getSpanStart(java.lang.Object);
-    method public <T> T[] getSpans(int, int, java.lang.Class<T>);
-    method public int length();
-    method public int nextSpanTransition(int, int, java.lang.Class);
-    method public void removeSpan(java.lang.Object);
-    method public void setSpan(java.lang.Object, int, int, int);
-    method public java.lang.CharSequence subSequence(int, int);
-  }
-
-  public static final class PrecomputedTextCompat.Params {
-    ctor public PrecomputedTextCompat.Params(android.text.PrecomputedText.Params);
-    method public int getBreakStrategy();
-    method public int getHyphenationFrequency();
-    method public android.text.TextDirectionHeuristic getTextDirection();
-    method public android.text.TextPaint getTextPaint();
-  }
-
-  public static class PrecomputedTextCompat.Params.Builder {
-    ctor public PrecomputedTextCompat.Params.Builder(android.text.TextPaint);
-    method public androidx.core.text.PrecomputedTextCompat.Params build();
-    method public androidx.core.text.PrecomputedTextCompat.Params.Builder setBreakStrategy(int);
-    method public androidx.core.text.PrecomputedTextCompat.Params.Builder setHyphenationFrequency(int);
-    method public androidx.core.text.PrecomputedTextCompat.Params.Builder setTextDirection(android.text.TextDirectionHeuristic);
-  }
-
   public abstract interface TextDirectionHeuristicCompat {
     method public abstract boolean isRtl(char[], int, int);
     method public abstract boolean isRtl(java.lang.CharSequence, int, int);
@@ -1470,15 +1401,6 @@
     method public abstract void onActionProviderVisibilityChanged(boolean);
   }
 
-  public final class DisplayCutoutCompat {
-    ctor public DisplayCutoutCompat(android.graphics.Rect, java.util.List<android.graphics.Rect>);
-    method public java.util.List<android.graphics.Rect> getBoundingRects();
-    method public int getSafeInsetBottom();
-    method public int getSafeInsetLeft();
-    method public int getSafeInsetRight();
-    method public int getSafeInsetTop();
-  }
-
   public final class DragAndDropPermissionsCompat {
     method public void release();
   }
@@ -2084,10 +2006,8 @@
 
   public class WindowInsetsCompat {
     ctor public WindowInsetsCompat(androidx.core.view.WindowInsetsCompat);
-    method public androidx.core.view.WindowInsetsCompat consumeDisplayCutout();
     method public androidx.core.view.WindowInsetsCompat consumeStableInsets();
     method public androidx.core.view.WindowInsetsCompat consumeSystemWindowInsets();
-    method public androidx.core.view.DisplayCutoutCompat getDisplayCutout();
     method public int getStableInsetBottom();
     method public int getStableInsetLeft();
     method public int getStableInsetRight();
@@ -2400,7 +2320,7 @@
     method public int getColumnSpan();
     method public int getRowIndex();
     method public int getRowSpan();
-    method public deprecated boolean isHeading();
+    method public boolean isHeading();
     method public boolean isSelected();
     method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat obtain(int, int, int, int, boolean, boolean);
     method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat obtain(int, int, int, int, boolean);
diff --git a/compat/res/values-as/strings.xml b/compat/res/values-as/strings.xml
deleted file mode 100644
index b9c349e..0000000
--- a/compat/res/values-as/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="status_bar_notification_info_overflow" msgid="7988687684186075107">"৯৯৯+"</string>
-</resources>
diff --git a/compat/res/values-or/strings.xml b/compat/res/values-or/strings.xml
deleted file mode 100644
index f544aef..0000000
--- a/compat/res/values-or/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="status_bar_notification_info_overflow" msgid="7988687684186075107">"999+"</string>
-</resources>
diff --git a/compat/src/androidTest/java/androidx/core/app/NotificationCompatTest.java b/compat/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
index 318a283e7..7cd90f8 100644
--- a/compat/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
+++ b/compat/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
@@ -30,7 +30,6 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import android.app.Notification;
 import android.content.Context;
@@ -529,29 +528,6 @@
     }
 
     @Test
-    public void testMessagingStyle_nullPerson() {
-        NotificationCompat.MessagingStyle messagingStyle =
-                new NotificationCompat.MessagingStyle("self name");
-        messagingStyle.addMessage("text", 200, (Person) null);
-
-        Notification notification = new NotificationCompat.Builder(mContext, "test id")
-                .setSmallIcon(1)
-                .setContentTitle("test title")
-                .setStyle(messagingStyle)
-                .build();
-
-        List<Message> result = NotificationCompat.MessagingStyle
-                .extractMessagingStyleFromNotification(notification)
-                .getMessages();
-
-        assertEquals(1, result.size());
-        assertEquals("text", result.get(0).getText());
-        assertEquals(200, result.get(0).getTimestamp());
-        assertNull(result.get(0).getPerson());
-        assertNull(result.get(0).getSender());
-    }
-
-    @Test
     public void testMessagingStyle_message() {
         NotificationCompat.MessagingStyle messagingStyle =
                 new NotificationCompat.MessagingStyle("self name");
@@ -584,16 +560,6 @@
     }
 
     @Test
-    public void testMessagingStyle_requiresNonEmptyUserName() {
-        try {
-            new NotificationCompat.MessagingStyle(new Person.Builder().build());
-            fail("Expected IllegalArgumentException about a non-empty user name.");
-        } catch (IllegalArgumentException e) {
-            // Expected
-        }
-    }
-
-    @Test
     public void testMessagingStyle_isGroupConversation() {
         mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
         NotificationCompat.MessagingStyle messagingStyle =
@@ -717,113 +683,19 @@
         assertTrue(result.isGroupConversation());
     }
 
-    @SdkSuppress(minSdkVersion = 28)
     @Test
-    public void testMessagingStyle_applyNoTitleAndNotGroup() {
+    public void testMessagingStyle_extras() {
         NotificationCompat.MessagingStyle messagingStyle =
-                new NotificationCompat.MessagingStyle("self name")
-                        .setGroupConversation(false)
-                        .addMessage(
-                                new Message(
-                                        "body",
-                                        1,
-                                        new Person.Builder().setName("example name").build()))
-                        .addMessage(new Message("body 2", 2, (Person) null));
-
-        Notification resultNotification = new NotificationCompat.Builder(mContext, "test id")
-                .setStyle(messagingStyle)
-                .build();
-        NotificationCompat.MessagingStyle resultCompatMessagingStyle =
-                NotificationCompat.MessagingStyle
-                        .extractMessagingStyleFromNotification(resultNotification);
-
-        // SDK >= 28 applies no title when none is provided to MessagingStyle.
-        assertNull(resultCompatMessagingStyle.getConversationTitle());
-        assertFalse(resultCompatMessagingStyle.isGroupConversation());
-    }
-
-    @SdkSuppress(minSdkVersion = 24, maxSdkVersion = 27)
-    @Test
-    public void testMessagingStyle_applyNoTitleAndNotGroup_legacy() {
-        NotificationCompat.MessagingStyle messagingStyle =
-                new NotificationCompat.MessagingStyle("self name")
-                        .setGroupConversation(false)
-                        .addMessage(
-                                new Message(
-                                        "body",
-                                        1,
-                                        new Person.Builder().setName("example name").build()))
-                        .addMessage(new Message("body 2", 2, (Person) null));
-
-        Notification resultNotification = new NotificationCompat.Builder(mContext, "test id")
-                .setStyle(messagingStyle)
-                .build();
-        NotificationCompat.MessagingStyle resultCompatMessagingStyle =
-                NotificationCompat.MessagingStyle
-                        .extractMessagingStyleFromNotification(resultNotification);
-
-        // SDK [24, 27] applies first incoming message sender name as Notification content title.
-        assertEquals("example name", NotificationCompat.getContentTitle(resultNotification));
-        assertNull(resultCompatMessagingStyle.getConversationTitle());
-        assertFalse(resultCompatMessagingStyle.isGroupConversation());
-    }
-
-    @SdkSuppress(minSdkVersion = 28)
-    @Test
-    public void testMessagingStyle_applyConversationTitleAndNotGroup() {
-        NotificationCompat.MessagingStyle messagingStyle =
-                new NotificationCompat.MessagingStyle("self name")
-                        .setGroupConversation(false)
-                        .setConversationTitle("test title");
-
-        Notification resultNotification = new NotificationCompat.Builder(mContext, "test id")
-                .setStyle(messagingStyle)
-                .build();
-        NotificationCompat.MessagingStyle resultMessagingStyle =
-                NotificationCompat.MessagingStyle
-                        .extractMessagingStyleFromNotification(resultNotification);
-
-        // SDK >= 28 applies provided title to MessagingStyle.
-        assertEquals("test title", resultMessagingStyle.getConversationTitle());
-        assertFalse(resultMessagingStyle.isGroupConversation());
-    }
-
-    @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 27)
-    @Test
-    public void testMessagingStyle_applyConversationTitleAndNotGroup_legacy() {
-        NotificationCompat.MessagingStyle messagingStyle =
-                new NotificationCompat.MessagingStyle("self name")
-                        .setGroupConversation(false)
-                        .setConversationTitle("test title");
-
-        Notification resultNotification = new NotificationCompat.Builder(mContext, "test id")
-                .setStyle(messagingStyle)
-                .build();
-        NotificationCompat.MessagingStyle resultMessagingStyle =
-                NotificationCompat.MessagingStyle
-                        .extractMessagingStyleFromNotification(resultNotification);
-
-        // SDK <= 27 applies MessagingStyle title as Notification content title.
-        assertEquals("test title", NotificationCompat.getContentTitle(resultNotification));
-        assertEquals("test title", resultMessagingStyle.getConversationTitle());
-        assertFalse(resultMessagingStyle.isGroupConversation());
-    }
-
-    @Test
-    public void testMessagingStyle_restoreFromCompatExtras() {
-        NotificationCompat.MessagingStyle messagingStyle =
-                new NotificationCompat.MessagingStyle(
-                        new Person.Builder().setName("test name").build())
+                new NotificationCompat.MessagingStyle("test name")
                         .setGroupConversation(true);
         Bundle bundle = new Bundle();
         messagingStyle.addCompatExtras(bundle);
 
         NotificationCompat.MessagingStyle resultMessagingStyle =
-                new NotificationCompat.MessagingStyle(new Person.Builder().setName("temp").build());
+                new NotificationCompat.MessagingStyle("test name");
         resultMessagingStyle.restoreFromCompatExtras(bundle);
 
         assertTrue(resultMessagingStyle.isGroupConversation());
-        assertEquals("test name", resultMessagingStyle.getUser().getName());
     }
 
     @Test
@@ -891,16 +763,6 @@
         verifyInvisibleActionExists(notification);
     }
 
-    @Test
-    @SdkSuppress(minSdkVersion = 19)
-    public void getContentTitle() {
-        Notification notification = new NotificationCompat.Builder(mContext, "test channel")
-                .setContentTitle("example title")
-                .build();
-
-        assertEquals("example title", NotificationCompat.getContentTitle(notification));
-    }
-
     private static void verifyInvisibleActionExists(Notification notification) {
         List<NotificationCompat.Action> result =
                 NotificationCompat.getInvisibleActions(notification);
diff --git a/compat/src/androidTest/java/androidx/core/content/pm/PermissionInfoCompatTest.java b/compat/src/androidTest/java/androidx/core/content/pm/PermissionInfoCompatTest.java
deleted file mode 100644
index 79613be..0000000
--- a/compat/src/androidTest/java/androidx/core/content/pm/PermissionInfoCompatTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.core.content.pm;
-
-import android.content.pm.PermissionInfo;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class PermissionInfoCompatTest {
-    @Test
-    public void testGetProtectionAndFlags() {
-        PermissionInfo pi = new PermissionInfo();
-
-        pi.protectionLevel = PermissionInfo.PROTECTION_DANGEROUS
-                | PermissionInfo.PROTECTION_FLAG_PRIVILEGED;
-
-        Assert.assertEquals(PermissionInfo.PROTECTION_DANGEROUS,
-                PermissionInfoCompat.getProtection(pi));
-
-        Assert.assertEquals(PermissionInfo.PROTECTION_FLAG_PRIVILEGED,
-                PermissionInfoCompat.getProtectionFlags(pi));
-
-        pi.protectionLevel = 0xf | 0xfff0;
-        Assert.assertEquals(0xf, PermissionInfoCompat.getProtection(pi));
-        Assert.assertEquals(0xfff0, PermissionInfoCompat.getProtectionFlags(pi));
-    }
-}
diff --git a/compat/src/androidTest/java/androidx/core/text/PrecomputedTextCompatTest.java b/compat/src/androidTest/java/androidx/core/text/PrecomputedTextCompatTest.java
deleted file mode 100644
index a822b7c..0000000
--- a/compat/src/androidTest/java/androidx/core/text/PrecomputedTextCompatTest.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.core.text;
-
-import static android.text.TextDirectionHeuristics.LTR;
-import static android.text.TextDirectionHeuristics.RTL;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.graphics.Color;
-import android.support.test.filters.SdkSuppress;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.text.Layout;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.TextDirectionHeuristics;
-import android.text.TextPaint;
-import android.text.style.BackgroundColorSpan;
-import android.text.style.TypefaceSpan;
-
-import androidx.core.text.PrecomputedTextCompat.Params;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class PrecomputedTextCompatTest {
-
-    private static final CharSequence NULL_CHAR_SEQUENCE = null;
-    private static final String STRING = "Hello, World!";
-    private static final String MULTIPARA_STRING = "Hello,\nWorld!";
-
-    private static final int SPAN_START = 3;
-    private static final int SPAN_END = 7;
-    private static final TypefaceSpan SPAN = new TypefaceSpan("serif");
-    private static final Spanned SPANNED;
-    static {
-        final SpannableStringBuilder ssb = new SpannableStringBuilder(STRING);
-        ssb.setSpan(SPAN, SPAN_START, SPAN_END, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
-        SPANNED = ssb;
-    }
-
-    private static final TextPaint PAINT = new TextPaint();
-
-    @Test
-    public void testParams_create() {
-        assertNotNull(new Params.Builder(PAINT).build());
-        assertNotNull(new Params.Builder(PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE).build());
-        assertNotNull(new Params.Builder(PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL).build());
-        assertNotNull(new Params.Builder(PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                .setTextDirection(LTR).build());
-    }
-
-    @Test
-    public void testParams_SetGet() {
-        assertEquals(Layout.BREAK_STRATEGY_SIMPLE, new Params.Builder(PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE).build().getBreakStrategy());
-        assertEquals(Layout.HYPHENATION_FREQUENCY_NONE, new Params.Builder(PAINT)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE).build()
-                .getHyphenationFrequency());
-        assertEquals(RTL, new Params.Builder(PAINT).setTextDirection(RTL).build()
-                .getTextDirection());
-    }
-
-    @Test
-    @SdkSuppress(minSdkVersion = 23)
-    public void testParams_GetDefaultValues() {
-        assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY,
-                new Params.Builder(PAINT).build().getBreakStrategy());
-        assertEquals(Layout.HYPHENATION_FREQUENCY_NORMAL,
-                new Params.Builder(PAINT).build().getHyphenationFrequency());
-    }
-
-    @Test
-    @SdkSuppress(minSdkVersion = 18)
-    public void testParams_GetDefaultValues2() {
-        assertEquals(TextDirectionHeuristics.FIRSTSTRONG_LTR,
-                new Params.Builder(PAINT).build().getTextDirection());
-    }
-
-    @Test
-    @SdkSuppress(minSdkVersion = 23)
-    public void testParams_equals() {
-        final Params base = new Params.Builder(PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                .setTextDirection(LTR).build();
-
-        assertFalse(base.equals(null));
-        assertTrue(base.equals(base));
-        assertFalse(base.equals(new Object()));
-
-        Params other = new Params.Builder(PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                .setTextDirection(LTR).build();
-        assertTrue(base.equals(other));
-        assertTrue(other.equals(base));
-        assertEquals(base.hashCode(), other.hashCode());
-
-        other = new Params.Builder(PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                .setTextDirection(LTR).build();
-        assertFalse(base.equals(other));
-        assertFalse(other.equals(base));
-
-        other = new Params.Builder(PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
-                .setTextDirection(LTR).build();
-        assertFalse(base.equals(other));
-        assertFalse(other.equals(base));
-
-
-        other = new Params.Builder(PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                .setTextDirection(RTL).build();
-        assertFalse(base.equals(other));
-        assertFalse(other.equals(base));
-
-
-        TextPaint anotherPaint = new TextPaint(PAINT);
-        anotherPaint.setTextSize(PAINT.getTextSize() * 2.0f);
-        other = new Params.Builder(anotherPaint)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                .setTextDirection(LTR).build();
-        assertFalse(base.equals(other));
-        assertFalse(other.equals(base));
-    }
-
-    @Test
-    public void testParams_equals2() {
-        final Params base = new Params.Builder(PAINT).build();
-
-        assertFalse(base.equals(null));
-        assertTrue(base.equals(base));
-        assertFalse(base.equals(new Object()));
-
-        Params other = new Params.Builder(PAINT).build();
-        assertTrue(base.equals(other));
-        assertTrue(other.equals(base));
-        assertEquals(base.hashCode(), other.hashCode());
-
-        TextPaint paint = new TextPaint(PAINT);
-        paint.setTextSize(paint.getTextSize() * 2.0f + 1.0f);
-        other = new Params.Builder(paint).build();
-        assertFalse(base.equals(other));
-        assertFalse(other.equals(base));
-    }
-
-    @Test
-    public void testCreate_withNull() {
-        final Params param = new Params.Builder(PAINT).build();
-        try {
-            PrecomputedTextCompat.create(NULL_CHAR_SEQUENCE, param);
-            fail();
-        } catch (NullPointerException e) {
-            // pass
-        }
-        try {
-            PrecomputedTextCompat.create(STRING, null);
-            fail();
-        } catch (NullPointerException e) {
-            // pass
-        }
-    }
-
-    @Test
-    public void testCharSequenceInteface() {
-        final Params param = new Params.Builder(PAINT).build();
-        final CharSequence s = PrecomputedTextCompat.create(STRING, param);
-        assertEquals(STRING.length(), s.length());
-        assertEquals('H', s.charAt(0));
-        assertEquals('e', s.charAt(1));
-        assertEquals('l', s.charAt(2));
-        assertEquals('l', s.charAt(3));
-        assertEquals('o', s.charAt(4));
-        assertEquals(',', s.charAt(5));
-        assertEquals("Hello, World!", s.toString());
-
-        final CharSequence s3 = s.subSequence(0, 3);
-        assertEquals(3, s3.length());
-        assertEquals('H', s3.charAt(0));
-        assertEquals('e', s3.charAt(1));
-        assertEquals('l', s3.charAt(2));
-
-    }
-
-    @Test
-    public void testSpannedInterface_Spanned() {
-        final Params param = new Params.Builder(PAINT).build();
-        final Spanned s = PrecomputedTextCompat.create(SPANNED, param);
-        final TypefaceSpan[] spans = s.getSpans(0, s.length(), TypefaceSpan.class);
-        assertNotNull(spans);
-        assertEquals(1, spans.length);
-        assertEquals(SPAN, spans[0]);
-
-        assertEquals(SPAN_START, s.getSpanStart(SPAN));
-        assertEquals(SPAN_END, s.getSpanEnd(SPAN));
-        assertTrue((s.getSpanFlags(SPAN) & Spanned.SPAN_INCLUSIVE_EXCLUSIVE) != 0);
-
-        assertEquals(SPAN_START, s.nextSpanTransition(0, s.length(), TypefaceSpan.class));
-        assertEquals(SPAN_END, s.nextSpanTransition(SPAN_START, s.length(), TypefaceSpan.class));
-    }
-
-    @Test
-    public void testSpannedInterface_Spannable() {
-        final BackgroundColorSpan span = new BackgroundColorSpan(Color.RED);
-        final Params param = new Params.Builder(PAINT).build();
-        final Spannable s = PrecomputedTextCompat.create(STRING, param);
-        assertEquals(0, s.getSpans(0, s.length(), BackgroundColorSpan.class).length);
-
-        s.setSpan(span, SPAN_START, SPAN_END, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
-
-        final BackgroundColorSpan[] spans = s.getSpans(0, s.length(), BackgroundColorSpan.class);
-        assertEquals(SPAN_START, s.getSpanStart(span));
-        assertEquals(SPAN_END, s.getSpanEnd(span));
-        assertTrue((s.getSpanFlags(span) & Spanned.SPAN_INCLUSIVE_EXCLUSIVE) != 0);
-
-        assertEquals(SPAN_START, s.nextSpanTransition(0, s.length(), BackgroundColorSpan.class));
-        assertEquals(SPAN_END,
-                s.nextSpanTransition(SPAN_START, s.length(), BackgroundColorSpan.class));
-
-        s.removeSpan(span);
-        assertEquals(0, s.getSpans(0, s.length(), BackgroundColorSpan.class).length);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testSpannedInterface_Spannable_setSpan_MetricsAffectingSpan() {
-        final Params param = new Params.Builder(PAINT).build();
-        final Spannable s = PrecomputedTextCompat.create(SPANNED, param);
-        s.setSpan(SPAN, SPAN_START, SPAN_END, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testSpannedInterface_Spannable_removeSpan_MetricsAffectingSpan() {
-        final Params param = new Params.Builder(PAINT).build();
-        final Spannable s = PrecomputedTextCompat.create(SPANNED, param);
-        s.removeSpan(SPAN);
-    }
-
-    @Test
-    public void testSpannedInterface_String() {
-        final Params param = new Params.Builder(PAINT).build();
-        final Spanned s = PrecomputedTextCompat.create(STRING, param);
-        TypefaceSpan[] spans = s.getSpans(0, s.length(), TypefaceSpan.class);
-        assertNotNull(spans);
-        assertEquals(0, spans.length);
-
-        assertEquals(-1, s.getSpanStart(SPAN));
-        assertEquals(-1, s.getSpanEnd(SPAN));
-        assertEquals(0, s.getSpanFlags(SPAN));
-
-        assertEquals(s.length(), s.nextSpanTransition(0, s.length(), TypefaceSpan.class));
-    }
-
-    @Test
-    public void testGetParagraphCount() {
-        final Params param = new Params.Builder(PAINT).build();
-        final PrecomputedTextCompat pm = PrecomputedTextCompat.create(STRING, param);
-        assertEquals(1, pm.getParagraphCount());
-        assertEquals(0, pm.getParagraphStart(0));
-        assertEquals(STRING.length(), pm.getParagraphEnd(0));
-
-        final PrecomputedTextCompat pm1 = PrecomputedTextCompat.create(MULTIPARA_STRING, param);
-        assertEquals(2, pm1.getParagraphCount());
-        assertEquals(0, pm1.getParagraphStart(0));
-        assertEquals(7, pm1.getParagraphEnd(0));
-        assertEquals(7, pm1.getParagraphStart(1));
-        assertEquals(pm1.length(), pm1.getParagraphEnd(1));
-    }
-
-}
diff --git a/compat/src/androidTest/java/androidx/core/view/DisplayCutoutCompatTest.java b/compat/src/androidTest/java/androidx/core/view/DisplayCutoutCompatTest.java
deleted file mode 100644
index 88a31f6..0000000
--- a/compat/src/androidTest/java/androidx/core/view/DisplayCutoutCompatTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.core.view;
-
-import static android.os.Build.VERSION.SDK_INT;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNull;
-
-import android.graphics.Rect;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Arrays;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class DisplayCutoutCompatTest {
-
-    DisplayCutoutCompat mCutoutTop;
-    DisplayCutoutCompat mCutoutTopBottom;
-    DisplayCutoutCompat mCutoutTopBottomClone;
-    DisplayCutoutCompat mCutoutLeftRight;
-
-    @Before
-    public void setUp() throws Exception {
-        mCutoutTop = new DisplayCutoutCompat(new Rect(0, 10, 0, 0), Arrays.asList(
-                new Rect(50, 0, 60, 10)));
-        mCutoutTopBottom = new DisplayCutoutCompat(new Rect(0, 10, 0, 20), Arrays.asList(
-                new Rect(50, 0, 60, 10),
-                new Rect(50, 100, 60, 120)));
-        mCutoutTopBottomClone = new DisplayCutoutCompat(new Rect(0, 10, 0, 20), Arrays.asList(
-                new Rect(50, 0, 60, 10),
-                new Rect(50, 100, 60, 120)));
-        mCutoutLeftRight = new DisplayCutoutCompat(new Rect(30, 0, 40, 0), Arrays.asList(
-                new Rect(0, 50, 30, 60),
-                new Rect(100, 60, 140, 50)));
-    }
-
-    @Test
-    public void testSafeInsets() {
-        if (SDK_INT >= 28) {
-            assertEquals("left", 30, mCutoutLeftRight.getSafeInsetLeft());
-            assertEquals("top", 10, mCutoutTopBottom.getSafeInsetTop());
-            assertEquals("right", 40, mCutoutLeftRight.getSafeInsetRight());
-            assertEquals("bottom", 20, mCutoutTopBottom.getSafeInsetBottom());
-        } else {
-            assertEquals("left", 0, mCutoutLeftRight.getSafeInsetLeft());
-            assertEquals("top", 0, mCutoutTopBottom.getSafeInsetTop());
-            assertEquals("right", 0, mCutoutLeftRight.getSafeInsetRight());
-            assertEquals("bottom", 0, mCutoutTopBottom.getSafeInsetBottom());
-        }
-    }
-
-    @Test
-    public void testBoundingRects() {
-        if (SDK_INT >= 28) {
-            assertEquals(Arrays.asList(new Rect(50, 0, 60, 10)), mCutoutTop.getBoundingRects());
-        } else {
-            assertNull(mCutoutTop.getBoundingRects());
-        }
-    }
-
-    @Test
-    public void testEquals() {
-        assertEquals(mCutoutTopBottomClone, mCutoutTopBottom);
-
-        if (SDK_INT >= 28) {
-            assertNotEquals(mCutoutTopBottom, mCutoutLeftRight);
-        }
-    }
-    @Test
-    public void testHashCode() {
-        assertEquals(mCutoutTopBottomClone.hashCode(), mCutoutTopBottom.hashCode());
-    }
-}
diff --git a/compat/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java b/compat/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java
index 3e668b4..7b862c2 100644
--- a/compat/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java
+++ b/compat/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java
@@ -19,9 +19,9 @@
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeTrue;
 
 import android.os.Build;
-import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -68,9 +68,9 @@
         assertThat(nodeCompat.getTooltipText(), equalTo(tooltipText));
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetSetShowingHintText() {
+        assumeTrue(Build.VERSION.SDK_INT >= 19);
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
         nodeCompat.setShowingHintText(true);
         assertThat(nodeCompat.isShowingHintText(), is(true));
@@ -78,9 +78,9 @@
         assertThat(nodeCompat.isShowingHintText(), is(false));
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetSetScreenReaderFocusable() {
+        assumeTrue(Build.VERSION.SDK_INT >= 19);
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
         nodeCompat.setScreenReaderFocusable(true);
         assertThat(nodeCompat.isScreenReaderFocusable(), is(true));
@@ -88,18 +88,14 @@
         assertThat(nodeCompat.isScreenReaderFocusable(), is(false));
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetSetHeading() {
+        assumeTrue(Build.VERSION.SDK_INT >= 19);
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
         nodeCompat.setHeading(true);
         assertThat(nodeCompat.isHeading(), is(true));
         nodeCompat.setHeading(false);
         assertThat(nodeCompat.isHeading(), is(false));
-        AccessibilityNodeInfoCompat.CollectionItemInfoCompat collectionItemInfo =
-                AccessibilityNodeInfoCompat.CollectionItemInfoCompat.obtain(0, 1, 0, 1, true);
-        nodeCompat.setCollectionItemInfo(collectionItemInfo);
-        assertThat(nodeCompat.isHeading(), is(true));
     }
 
     private AccessibilityNodeInfoCompat obtainedWrappedNodeCompat() {
diff --git a/compat/src/main/java/androidx/core/app/AppComponentFactory.java b/compat/src/main/java/androidx/core/app/AppComponentFactory.java
deleted file mode 100644
index b6383da..0000000
--- a/compat/src/main/java/androidx/core/app/AppComponentFactory.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.core.app;
-
-import static androidx.core.app.CoreComponentFactory.checkCompatWrapper;
-
-import android.app.Activity;
-import android.app.Application;
-import android.app.Service;
-import android.content.BroadcastReceiver;
-import android.content.ContentProvider;
-import android.content.Intent;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-
-import java.lang.reflect.InvocationTargetException;
-
-/**
- * Version of {@link android.app.AppComponentFactory} that works with androidx libraries.
- *
- * Note: This will only work on API 28+ and does not backport AppComponentFactory functionality.
- */
-@RequiresApi(28)
-public class AppComponentFactory extends android.app.AppComponentFactory {
-
-    /**
-     * @see #instantiateActivityCompat
-     */
-    @Override
-    public final Activity instantiateActivity(ClassLoader cl, String className, Intent intent)
-            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-        return checkCompatWrapper(instantiateActivityCompat(cl, className, intent));
-    }
-
-    /**
-     * @see #instantiateApplicationCompat
-     */
-    @Override
-    public final Application instantiateApplication(ClassLoader cl, String className)
-            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-        return checkCompatWrapper(instantiateApplicationCompat(cl, className));
-    }
-
-    /**
-     * @see #instantiateReceiverCompat
-     */
-    @Override
-    public final BroadcastReceiver instantiateReceiver(ClassLoader cl, String className,
-            Intent intent)
-            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-        return checkCompatWrapper(instantiateReceiverCompat(cl, className, intent));
-    }
-
-    /**
-     * @see #instantiateProviderCompat
-     */
-    @Override
-    public final ContentProvider instantiateProvider(ClassLoader cl, String className)
-            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-        return checkCompatWrapper(instantiateProviderCompat(cl, className));
-    }
-
-    /**
-     * @see #instantiateServiceCompat
-     */
-    @Override
-    public final Service instantiateService(ClassLoader cl, String className, Intent intent)
-            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-        return checkCompatWrapper(instantiateServiceCompat(cl, className, intent));
-    }
-
-    /**
-     * Allows application to override the creation of the application object. This can be used to
-     * perform things such as dependency injection or class loader changes to these
-     * classes.
-     * <p>
-     * This method is only intended to provide a hook for instantiation. It does not provide
-     * earlier access to the Application object. The returned object will not be initialized
-     * as a Context yet and should not be used to interact with other android APIs.
-     *
-     * @param cl        The default classloader to use for instantiation.
-     * @param className The class to be instantiated.
-     */
-    public @NonNull Application instantiateApplicationCompat(@NonNull ClassLoader cl,
-            @NonNull String className)
-            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-        try {
-            return (Application) cl.loadClass(className).getDeclaredConstructor().newInstance();
-        } catch (InvocationTargetException | NoSuchMethodException e) {
-            throw new RuntimeException("Couldn't call constructor", e);
-        }
-    }
-
-    /**
-     * Allows application to override the creation of activities. This can be used to
-     * perform things such as dependency injection or class loader changes to these
-     * classes.
-     * <p>
-     * This method is only intended to provide a hook for instantiation. It does not provide
-     * earlier access to the Activity object. The returned object will not be initialized
-     * as a Context yet and should not be used to interact with other android APIs.
-     *
-     * @param cl        The default classloader to use for instantiation.
-     * @param className The class to be instantiated.
-     * @param intent    Intent creating the class.
-     */
-    public @NonNull Activity instantiateActivityCompat(@NonNull ClassLoader cl,
-            @NonNull String className, @Nullable Intent intent)
-            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-        try {
-            return (Activity) cl.loadClass(className).getDeclaredConstructor().newInstance();
-        } catch (InvocationTargetException | NoSuchMethodException e) {
-            throw new RuntimeException("Couldn't call constructor", e);
-        }
-    }
-
-    /**
-     * Allows application to override the creation of receivers. This can be used to
-     * perform things such as dependency injection or class loader changes to these
-     * classes.
-     *
-     * @param cl        The default classloader to use for instantiation.
-     * @param className The class to be instantiated.
-     * @param intent    Intent creating the class.
-     */
-    public @NonNull BroadcastReceiver instantiateReceiverCompat(@NonNull ClassLoader cl,
-            @NonNull String className, @Nullable Intent intent)
-            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-        try {
-            return (BroadcastReceiver) cl.loadClass(className).getDeclaredConstructor()
-                    .newInstance();
-        } catch (InvocationTargetException | NoSuchMethodException e) {
-            throw new RuntimeException("Couldn't call constructor", e);
-        }
-    }
-
-    /**
-     * Allows application to override the creation of services. This can be used to
-     * perform things such as dependency injection or class loader changes to these
-     * classes.
-     * <p>
-     * This method is only intended to provide a hook for instantiation. It does not provide
-     * earlier access to the Service object. The returned object will not be initialized
-     * as a Context yet and should not be used to interact with other android APIs.
-     *
-     * @param cl        The default classloader to use for instantiation.
-     * @param className The class to be instantiated.
-     * @param intent    Intent creating the class.
-     */
-    public @NonNull Service instantiateServiceCompat(@NonNull ClassLoader cl,
-            @NonNull String className, @Nullable Intent intent)
-            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-        try {
-            return (Service) cl.loadClass(className).getDeclaredConstructor().newInstance();
-        } catch (InvocationTargetException | NoSuchMethodException e) {
-            throw new RuntimeException("Couldn't call constructor", e);
-        }
-    }
-
-    /**
-     * Allows application to override the creation of providers. This can be used to
-     * perform things such as dependency injection or class loader changes to these
-     * classes.
-     * <p>
-     * This method is only intended to provide a hook for instantiation. It does not provide
-     * earlier access to the ContentProvider object. The returned object will not be initialized
-     * with a Context yet and should not be used to interact with other android APIs.
-     *
-     * @param cl        The default classloader to use for instantiation.
-     * @param className The class to be instantiated.
-     */
-    public @NonNull ContentProvider instantiateProviderCompat(@NonNull ClassLoader cl,
-            @NonNull String className)
-            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-        try {
-            return (ContentProvider) cl.loadClass(className).getDeclaredConstructor().newInstance();
-        } catch (InvocationTargetException | NoSuchMethodException e) {
-            throw new RuntimeException("Couldn't call constructor", e);
-        }
-    }
-}
diff --git a/compat/src/main/java/androidx/core/app/CoreComponentFactory.java b/compat/src/main/java/androidx/core/app/CoreComponentFactory.java
index b55f03f..ef6acc1 100644
--- a/compat/src/main/java/androidx/core/app/CoreComponentFactory.java
+++ b/compat/src/main/java/androidx/core/app/CoreComponentFactory.java
@@ -50,8 +50,7 @@
     }
 
     @Override
-    public BroadcastReceiver instantiateReceiver(ClassLoader cl, String className,
-            Intent intent)
+    public BroadcastReceiver instantiateReceiver(ClassLoader cl, String className, Intent intent)
             throws InstantiationException, IllegalAccessException, ClassNotFoundException {
         return checkCompatWrapper(super.instantiateReceiver(cl, className, intent));
     }
@@ -68,7 +67,7 @@
         return checkCompatWrapper(super.instantiateService(cl, className, intent));
     }
 
-    static <T> T checkCompatWrapper(T obj) {
+    private <T> T checkCompatWrapper(T obj) {
         if (obj instanceof CompatWrapped) {
             T wrapper = (T) ((CompatWrapped) obj).getWrapper();
             if (wrapper != null) {
diff --git a/compat/src/main/java/androidx/core/app/NotificationCompat.java b/compat/src/main/java/androidx/core/app/NotificationCompat.java
index 4d7bf40..9e60574 100644
--- a/compat/src/main/java/androidx/core/app/NotificationCompat.java
+++ b/compat/src/main/java/androidx/core/app/NotificationCompat.java
@@ -386,17 +386,13 @@
 
     /**
      * Notification key: the username to be displayed for all messages sent by the user
-     * including direct replies {@link MessagingStyle} notification.
+     * including
+     * direct replies
+     * {@link MessagingStyle} notification.
      */
     public static final String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
 
     /**
-     * Notification key: the person to display for all messages sent by the user, including direct
-     * replies to {@link MessagingStyle} notifications.
-     */
-    public static final String EXTRA_MESSAGING_STYLE_USER = "android.messagingStyleUser";
-
-    /**
      * Notification key: a {@link String} to be displayed as the title to a conversation
      * represented by a {@link MessagingStyle}
      */
@@ -1676,9 +1672,6 @@
         }
 
         /**
-         * Applies the compat style data to the framework {@link Notification} in a backwards
-         * compatible way. All other data should be stored within the Notification's extras.
-         *
          * @hide
          */
         @RestrictTo(LIBRARY_GROUP)
@@ -2158,54 +2151,29 @@
          */
         public static final int MAXIMUM_RETAINED_MESSAGES = 25;
 
-        private final List<Message> mMessages = new ArrayList<>();
-        private Person mUser;
-        private @Nullable CharSequence mConversationTitle;
-        private @Nullable Boolean mIsGroupConversation;
+        CharSequence mUserDisplayName;
+        @Nullable CharSequence mConversationTitle;
+        List<Message> mMessages = new ArrayList<>();
+        @Nullable Boolean mIsGroupConversation;
 
-        /** Private empty constructor for {@link Style#restoreFromCompatExtras(Bundle)}. */
-        private MessagingStyle() {}
+        MessagingStyle() {
+        }
 
         /**
          * @param userDisplayName Required - the name to be displayed for any replies sent by the
          * user before the posting app reposts the notification with those messages after they've
          * been actually sent and in previous messages sent by the user added in
          * {@link #addMessage(Message)}
-         * @deprecated Use {@code #MessagingStyle(Person)} instead.
          */
-        @Deprecated
         public MessagingStyle(@NonNull CharSequence userDisplayName) {
-            mUser = new Person.Builder().setName(userDisplayName).build();
+            mUserDisplayName = userDisplayName;
         }
 
         /**
-         * Creates a new {@link MessagingStyle} object. Note that {@link Person} must have a
-         * non-empty name.
-         *
-         * @param user This {@link Person}'s name will be shown when this app's notification is
-         * being replied to. It's used temporarily so the app has time to process the send request
-         * and repost the notification with updates to the conversation.
+         * Returns the name to be displayed for any replies sent by the user
          */
-        public MessagingStyle(@NonNull Person user) {
-            if (TextUtils.isEmpty(user.getName())) {
-                throw new IllegalArgumentException("User's name must not be empty.");
-            }
-            mUser = user;
-        }
-
-        /**
-         * Returns the name to be displayed for any replies sent by the user.
-         *
-         * @deprecated Use {@link #getUser()} instead.
-         */
-        @Deprecated
         public CharSequence getUserDisplayName() {
-            return mUser.getName();
-        }
-
-        /** Returns the person to be used for any replies sent by the user. */
-        public Person getUser() {
-            return mUser;
+            return mUserDisplayName;
         }
 
         /**
@@ -2346,20 +2314,19 @@
          */
         public static MessagingStyle extractMessagingStyleFromNotification(
                 Notification notification) {
+            MessagingStyle style;
             Bundle extras = NotificationCompat.getExtras(notification);
-            if (extras != null
-                    && !extras.containsKey(EXTRA_SELF_DISPLAY_NAME)
-                    && !extras.containsKey(EXTRA_MESSAGING_STYLE_USER)) {
-                return null;
+            if (extras != null && !extras.containsKey(EXTRA_SELF_DISPLAY_NAME)) {
+                style = null;
+            } else {
+                try {
+                    style = new MessagingStyle();
+                    style.restoreFromCompatExtras(extras);
+                } catch (ClassCastException e) {
+                    style = null;
+                }
             }
-
-            try {
-                MessagingStyle style = new MessagingStyle();
-                style.restoreFromCompatExtras(extras);
-                return style;
-            } catch (ClassCastException e) {
-                return null;
-            }
+            return style;
         }
 
         /**
@@ -2376,36 +2343,14 @@
 
             if (Build.VERSION.SDK_INT >= 24) {
                 Notification.MessagingStyle style =
-                        new Notification.MessagingStyle(mUser.getName());
-
-                // In SDK < 28, base Android will assume a MessagingStyle notification is a group
-                // chat if the conversation title is set. In compat, this isn't the case as we've
-                // introduced #setGroupConversation. When we apply these settings to base Android
-                // notifications, we should only set base Android's MessagingStyle conversation
-                // title if it's a group conversation OR SDK >= 28. Otherwise we set the
-                // Notification content title so Android won't think it's a group conversation.
-                if (isGroupConversation() || Build.VERSION.SDK_INT >= 28) {
-                    // If group or non-legacy, set MessagingStyle#mConversationTitle.
-                    style.setConversationTitle(mConversationTitle);
-                } else {
-                    // Otherwise set Notification#mContentTitle.
-                    builder.getBuilder().setContentTitle(mConversationTitle);
-                }
-
-                // For SDK >= 28, we can simply denote the group conversation status regardless of
-                // if we set the conversation title or not.
-                if (Build.VERSION.SDK_INT >= 28) {
-                    style.setGroupConversation(mIsGroupConversation);
-                }
-
+                        new Notification.MessagingStyle(mUserDisplayName)
+                                .setConversationTitle(mConversationTitle);
                 for (MessagingStyle.Message message : mMessages) {
-                    CharSequence name = null;
-                    if (message.getPerson() != null) {
-                        name = message.getPerson().getName();
-                    }
                     Notification.MessagingStyle.Message frameworkMessage =
                             new Notification.MessagingStyle.Message(
-                                    message.getText(), message.getTimestamp(), name);
+                                    message.getText(),
+                                    message.getTimestamp(),
+                                    message.getSender());
                     if (message.getDataMimeType() != null) {
                         frameworkMessage.setData(message.getDataMimeType(), message.getDataUri());
                     }
@@ -2418,11 +2363,7 @@
                 if (mConversationTitle != null) {
                     builder.getBuilder().setContentTitle(mConversationTitle);
                 } else if (latestIncomingMessage != null) {
-                    builder.getBuilder().setContentTitle("");
-                    if (latestIncomingMessage.getPerson() != null) {
-                        builder.getBuilder().setContentTitle(
-                                latestIncomingMessage.getPerson().getName());
-                    }
+                    builder.getBuilder().setContentTitle(latestIncomingMessage.getSender());
                 }
                 // Set the text
                 if (latestIncomingMessage != null) {
@@ -2456,8 +2397,7 @@
             for (int i = mMessages.size() - 1; i >= 0; i--) {
                 MessagingStyle.Message message = mMessages.get(i);
                 // Incoming messages have a non-empty sender.
-                if (message.getPerson() != null
-                        && !TextUtils.isEmpty(message.getPerson().getName())) {
+                if (!TextUtils.isEmpty(message.getSender())) {
                     return message;
                 }
             }
@@ -2471,7 +2411,7 @@
         private boolean hasMessagesWithoutSender() {
             for (int i = mMessages.size() - 1; i >= 0; i--) {
                 MessagingStyle.Message message = mMessages.get(i);
-                if (message.getPerson() != null && message.getPerson().getName() == null) {
+                if (message.getSender() == null) {
                     return true;
                 }
             }
@@ -2483,10 +2423,10 @@
             SpannableStringBuilder sb = new SpannableStringBuilder();
             final boolean afterLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
             int color = afterLollipop ? Color.BLACK : Color.WHITE;
-            CharSequence replyName =
-                    message.getPerson() == null ? "" : message.getPerson().getName();
-            if (TextUtils.isEmpty(replyName)) {
-                replyName = mUser.getName();
+            CharSequence replyName = message.getSender();
+            if (TextUtils.isEmpty(message.getSender())) {
+                replyName = mUserDisplayName == null
+                        ? "" : mUserDisplayName;
                 color = afterLollipop && mBuilder.getColor() != NotificationCompat.COLOR_DEFAULT
                         ? mBuilder.getColor()
                         : color;
@@ -2510,9 +2450,9 @@
         @Override
         public void addCompatExtras(Bundle extras) {
             super.addCompatExtras(extras);
-            extras.putCharSequence(EXTRA_SELF_DISPLAY_NAME, mUser.getName());
-            extras.putBundle(EXTRA_MESSAGING_STYLE_USER, mUser.toBundle());
-
+            if (mUserDisplayName != null) {
+                extras.putCharSequence(EXTRA_SELF_DISPLAY_NAME, mUserDisplayName);
+            }
             if (mConversationTitle != null) {
                 extras.putCharSequence(EXTRA_CONVERSATION_TITLE, mConversationTitle);
             }
@@ -2532,21 +2472,11 @@
         @Override
         protected void restoreFromCompatExtras(Bundle extras) {
             mMessages.clear();
-            // Call to #restore requires that there either be a display name OR a user.
-            if (extras.containsKey(EXTRA_MESSAGING_STYLE_USER)) {
-                // New path simply unpacks Person, but checks if there's a valid name.
-                mUser = Person.fromBundle(extras.getBundle(EXTRA_MESSAGING_STYLE_USER));
-            } else {
-                // Legacy extra simply builds Person with a name.
-                mUser = new Person.Builder()
-                        .setName(extras.getString(EXTRA_SELF_DISPLAY_NAME))
-                        .build();
-            }
-
+            mUserDisplayName = extras.getString(EXTRA_SELF_DISPLAY_NAME);
             mConversationTitle = extras.getString(EXTRA_CONVERSATION_TITLE);
             Parcelable[] parcelables = extras.getParcelableArray(EXTRA_MESSAGES);
             if (parcelables != null) {
-                mMessages.addAll(Message.getMessagesFromBundleArray(parcelables));
+                mMessages = Message.getMessagesFromBundleArray(parcelables);
             }
             if (extras.containsKey(EXTRA_IS_GROUP_CONVERSATION)) {
                 mIsGroupConversation = extras.getBoolean(EXTRA_IS_GROUP_CONVERSATION);
@@ -2668,7 +2598,7 @@
             @Deprecated
             @Nullable
             public CharSequence getSender() {
-                return mPerson == null ? null : mPerson.getName();
+                return mPerson.getName();
             }
 
             /** Returns the {@link Person} sender of this message. */
@@ -2699,9 +2629,6 @@
                 }
                 bundle.putLong(KEY_TIMESTAMP, mTimestamp);
                 if (mPerson != null) {
-                    // We must add both as Frameworks depends on this extra directly in order to
-                    // render properly.
-                    bundle.putCharSequence(KEY_SENDER, mPerson.getName());
                     bundle.putBundle(KEY_PERSON, mPerson.toBundle());
                 }
                 if (mDataMimeType != null) {
@@ -2747,21 +2674,22 @@
                         return null;
                     }
 
-                    Person person = null;
-                    if (bundle.containsKey(KEY_PERSON)) {
-                        person = Person.fromBundle(bundle.getBundle(KEY_PERSON));
-                    } else if (bundle.containsKey(KEY_SENDER)) {
-                        // Legacy person
-                        person = new Person.Builder()
-                                .setName(bundle.getCharSequence(KEY_SENDER))
-                                .build();
+                    Message message;
+                    if (bundle.containsKey(KEY_SENDER)) {
+                        // Legacy sender
+                        message = new Message(
+                                bundle.getCharSequence(KEY_TEXT),
+                                bundle.getLong(KEY_TIMESTAMP),
+                                new Person.Builder()
+                                        .setName(bundle.getCharSequence(KEY_SENDER))
+                                        .build());
+                    } else {
+                        message = new Message(
+                                bundle.getCharSequence(KEY_TEXT),
+                                bundle.getLong(KEY_TIMESTAMP),
+                                Person.fromBundle(bundle.getBundle(KEY_PERSON)));
                     }
 
-                    Message message = new Message(
-                            bundle.getCharSequence(KEY_TEXT),
-                            bundle.getLong(KEY_TIMESTAMP),
-                            person);
-
                     if (bundle.containsKey(KEY_DATA_MIME_TYPE)
                             && bundle.containsKey(KEY_DATA_URI)) {
                         message.setData(bundle.getString(KEY_DATA_MIME_TYPE),
@@ -5105,12 +5033,6 @@
         return result;
     }
 
-    /** Returns the content title of a {@link Notification}. **/
-    @RequiresApi(19)
-    public static CharSequence getContentTitle(Notification notification) {
-        return notification.extras.getCharSequence(Notification.EXTRA_TITLE);
-    }
-
     /**
      * Get the category of this notification in a backwards compatible
      * manner.
diff --git a/compat/src/main/java/androidx/core/app/NotificationManagerCompat.java b/compat/src/main/java/androidx/core/app/NotificationManagerCompat.java
index e8b6188..3660de3 100644
--- a/compat/src/main/java/androidx/core/app/NotificationManagerCompat.java
+++ b/compat/src/main/java/androidx/core/app/NotificationManagerCompat.java
@@ -267,7 +267,7 @@
             // Parse the string again if it is different from the last time this method was called.
             if (enabledNotificationListeners != null
                     && !enabledNotificationListeners.equals(sEnabledNotificationListeners)) {
-                final String[] components = enabledNotificationListeners.split(":", -1);
+                final String[] components = enabledNotificationListeners.split(":");
                 Set<String> packageNames = new HashSet<String>(components.length);
                 for (String component : components) {
                     ComponentName componentName = ComponentName.unflattenFromString(component);
diff --git a/compat/src/main/java/androidx/core/content/pm/PermissionInfoCompat.java b/compat/src/main/java/androidx/core/content/pm/PermissionInfoCompat.java
deleted file mode 100644
index df095a6..0000000
--- a/compat/src/main/java/androidx/core/content/pm/PermissionInfoCompat.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.core.content.pm;
-
-import android.annotation.SuppressLint;
-import android.content.pm.PermissionInfo;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-import androidx.core.os.BuildCompat;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Helper for accessing features in {@link PermissionInfo}.
- */
-public final class PermissionInfoCompat {
-    private PermissionInfoCompat() {
-    }
-
-    /** @hide */
-    @IntDef(flag = false, value = {
-            PermissionInfo.PROTECTION_NORMAL,
-            PermissionInfo.PROTECTION_DANGEROUS,
-            PermissionInfo.PROTECTION_SIGNATURE,
-            PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM,
-    })
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Protection {}
-
-    /** @hide */
-    @SuppressLint("UniqueConstants") // because _SYSTEM and _PRIVILEGED are aliases.
-    @IntDef(flag = true, value = {
-            PermissionInfo.PROTECTION_FLAG_PRIVILEGED,
-            PermissionInfo.PROTECTION_FLAG_SYSTEM,
-            PermissionInfo.PROTECTION_FLAG_DEVELOPMENT,
-            PermissionInfo.PROTECTION_FLAG_APPOP,
-            PermissionInfo.PROTECTION_FLAG_PRE23,
-            PermissionInfo.PROTECTION_FLAG_INSTALLER,
-            PermissionInfo.PROTECTION_FLAG_VERIFIER,
-            PermissionInfo.PROTECTION_FLAG_PREINSTALLED,
-            PermissionInfo.PROTECTION_FLAG_SETUP,
-            PermissionInfo.PROTECTION_FLAG_INSTANT,
-            PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY,
-    })
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ProtectionFlags {}
-
-    /**
-     * Return the base permission type of a {@link PermissionInfo}.
-     */
-    @SuppressLint("WrongConstant") // for "PermissionInfo.PROTECTION_MASK_BASE"
-    @Protection
-    public static int getProtection(@NonNull PermissionInfo permissionInfo) {
-        if (BuildCompat.isAtLeastP()) {
-            return permissionInfo.getProtection();
-        } else {
-            return permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
-        }
-    }
-
-    /**
-     * Return the additional protection flags of a {@link PermissionInfo}.
-     */
-    @SuppressLint("WrongConstant") // for "~PermissionInfo.PROTECTION_MASK_BASE"
-    @ProtectionFlags
-    public static int getProtectionFlags(@NonNull PermissionInfo permissionInfo) {
-        if (BuildCompat.isAtLeastP()) {
-            return permissionInfo.getProtectionFlags();
-        } else {
-            return permissionInfo.protectionLevel & ~PermissionInfo.PROTECTION_MASK_BASE;
-        }
-    }
-}
diff --git a/compat/src/main/java/androidx/core/database/CursorWindowCompat.java b/compat/src/main/java/androidx/core/database/CursorWindowCompat.java
deleted file mode 100644
index c675977..0000000
--- a/compat/src/main/java/androidx/core/database/CursorWindowCompat.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.core.database;
-
-import android.database.CursorWindow;
-import android.os.Build;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.os.BuildCompat;
-
-/**
- * Helper for accessing features in {@link android.database.CursorWindow}
- */
-public final class CursorWindowCompat {
-
-    private CursorWindowCompat() {
-        /* Hide constructor */
-    }
-
-    /**
-     * Creates a CursorWindow of the specified size.
-     * <p>
-     * Prior to Android P, this method will return a CursorWindow of size defined by the platform.
-     */
-    @NonNull
-    public CursorWindow create(@Nullable String name, long windowSizeBytes) {
-        if (BuildCompat.isAtLeastP()) {
-            return new CursorWindow(name, windowSizeBytes);
-        } else if (Build.VERSION.SDK_INT >= 15) {
-            return new CursorWindow(name);
-        } else {
-            //noinspection deprecation
-            return new CursorWindow(false);
-        }
-    }
-}
diff --git a/compat/src/main/java/androidx/core/database/sqlite/SQLiteCursorCompat.java b/compat/src/main/java/androidx/core/database/sqlite/SQLiteCursorCompat.java
deleted file mode 100644
index ebbc037..0000000
--- a/compat/src/main/java/androidx/core/database/sqlite/SQLiteCursorCompat.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.core.database.sqlite;
-
-import android.database.sqlite.SQLiteCursor;
-
-import androidx.annotation.NonNull;
-import androidx.core.os.BuildCompat;
-
-/**
- * Helper for accessing features in {@link android.database.AbstractWindowedCursor}
- */
-public final class SQLiteCursorCompat {
-
-    private SQLiteCursorCompat() {
-        /* Hide constructor */
-    }
-
-    /**
-     * Controls whether the cursor is filled starting at the position passed to
-     * {@link SQLiteCursor#moveToPosition(int)}.
-     * <p>
-     * By default, SQLiteCursor will optimize for accesses around the requested row index by loading
-     * data on either side of it. Pass true to this method to disable that behavior, useful to
-     * optimize multi-window, continuous reads.
-     * <p>
-     * Prior to Android P, this method will do nothing.
-     */
-    public void setFillWindowForwardOnly(
-            @NonNull SQLiteCursor cursor, boolean fillWindowForwardOnly) {
-        if (BuildCompat.isAtLeastP()) {
-            cursor.setFillWindowForwardOnly(fillWindowForwardOnly);
-        }
-    }
-}
diff --git a/compat/src/main/java/androidx/core/graphics/drawable/IconCompat.java b/compat/src/main/java/androidx/core/graphics/drawable/IconCompat.java
index 4c296ea..366ddf3 100644
--- a/compat/src/main/java/androidx/core/graphics/drawable/IconCompat.java
+++ b/compat/src/main/java/androidx/core/graphics/drawable/IconCompat.java
@@ -569,58 +569,6 @@
         return bundle;
     }
 
-    @Override
-    public String toString() {
-        if (mType == TYPE_UNKOWN) {
-            return String.valueOf(mObj1);
-        }
-        final StringBuilder sb = new StringBuilder("Icon(typ=").append(typeToString(mType));
-        switch (mType) {
-            case TYPE_BITMAP:
-            case TYPE_ADAPTIVE_BITMAP:
-                sb.append(" size=")
-                        .append(((Bitmap) mObj1).getWidth())
-                        .append("x")
-                        .append(((Bitmap) mObj1).getHeight());
-                break;
-            case TYPE_RESOURCE:
-                sb.append(" pkg=")
-                        .append(getResPackage())
-                        .append(" id=")
-                        .append(String.format("0x%08x", getResId()));
-                break;
-            case TYPE_DATA:
-                sb.append(" len=").append(mInt1);
-                if (mInt2 != 0) {
-                    sb.append(" off=").append(mInt2);
-                }
-                break;
-            case TYPE_URI:
-                sb.append(" uri=").append(mObj1);
-                break;
-        }
-        if (mTintList != null) {
-            sb.append(" tint=");
-            sb.append(mTintList);
-        }
-        if (mTintMode != DEFAULT_TINT_MODE) {
-            sb.append(" mode=").append(mTintMode);
-        }
-        sb.append(")");
-        return sb.toString();
-    }
-
-    private static String typeToString(int x) {
-        switch (x) {
-            case TYPE_BITMAP: return "BITMAP";
-            case TYPE_ADAPTIVE_BITMAP: return "BITMAP_MASKABLE";
-            case TYPE_DATA: return "DATA";
-            case TYPE_RESOURCE: return "RESOURCE";
-            case TYPE_URI: return "URI";
-            default: return "UNKNOWN";
-        }
-    }
-
     /**
      * Extracts an icon from a bundle that was added using {@link #toBundle()}.
      */
diff --git a/compat/src/main/java/androidx/core/os/LocaleHelper.java b/compat/src/main/java/androidx/core/os/LocaleHelper.java
index 5ce4c82..001d657 100644
--- a/compat/src/main/java/androidx/core/os/LocaleHelper.java
+++ b/compat/src/main/java/androidx/core/os/LocaleHelper.java
@@ -33,7 +33,7 @@
     // Simpleton implementation for Locale.forLanguageTag(...)
     static Locale forLanguageTag(String str) {
         if (str.contains("-")) {
-            String[] args = str.split("-", -1);
+            String[] args = str.split("-");
             if (args.length > 2) {
                 return new Locale(args[0], args[1], args[2]);
             } else if (args.length > 1) {
@@ -42,7 +42,7 @@
                 return new Locale(args[0]);
             }
         } else if (str.contains("_")) {
-            String[] args = str.split("_", -1);
+            String[] args = str.split("_");
             if (args.length > 2) {
                 return new Locale(args[0], args[1], args[2]);
             } else if (args.length > 1) {
diff --git a/compat/src/main/java/androidx/core/os/LocaleListCompat.java b/compat/src/main/java/androidx/core/os/LocaleListCompat.java
index 0be1ff3..a933877 100644
--- a/compat/src/main/java/androidx/core/os/LocaleListCompat.java
+++ b/compat/src/main/java/androidx/core/os/LocaleListCompat.java
@@ -289,7 +289,7 @@
         if (list == null || list.isEmpty()) {
             return getEmptyLocaleList();
         } else {
-            final String[] tags = list.split(",", -1);
+            final String[] tags = list.split(",");
             final Locale[] localeArray = new Locale[tags.length];
             for (int i = 0; i < localeArray.length; i++) {
                 localeArray[i] = Build.VERSION.SDK_INT >= 21
diff --git a/compat/src/main/java/androidx/core/os/LocaleListHelper.java b/compat/src/main/java/androidx/core/os/LocaleListHelper.java
index 137d9cd..0a656bc 100644
--- a/compat/src/main/java/androidx/core/os/LocaleListHelper.java
+++ b/compat/src/main/java/androidx/core/os/LocaleListHelper.java
@@ -273,7 +273,7 @@
         if (list == null || list.isEmpty()) {
             return getEmptyLocaleList();
         } else {
-            final String[] tags = list.split(",", -1);
+            final String[] tags = list.split(",");
             final Locale[] localeArray = new Locale[tags.length];
             for (int i = 0; i < localeArray.length; i++) {
                 localeArray[i] = LocaleHelper.forLanguageTag(tags[i]);
diff --git a/compat/src/main/java/androidx/core/text/PrecomputedTextCompat.java b/compat/src/main/java/androidx/core/text/PrecomputedTextCompat.java
deleted file mode 100644
index 075ebb1..0000000
--- a/compat/src/main/java/androidx/core/text/PrecomputedTextCompat.java
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.core.text;
-
-import android.os.Build;
-import android.text.Layout;
-import android.text.PrecomputedText;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.StaticLayout;
-import android.text.TextDirectionHeuristic;
-import android.text.TextDirectionHeuristics;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.text.style.MetricAffectingSpan;
-
-import androidx.annotation.IntRange;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.core.os.BuildCompat;
-import androidx.core.util.ObjectsCompat;
-import androidx.core.util.Preconditions;
-
-import java.util.ArrayList;
-
-/**
- * A text which has the character metrics data.
- *
- * A text object that contains the character metrics data and can be used to improve the performance
- * of text layout operations. When a PrecomputedTextCompat is created with a given
- * {@link CharSequence}, it will measure the text metrics during the creation. This PrecomputedText
- * instance can be set on {@link android.widget.TextView} or {@link StaticLayout}. Since the text
- * layout information will be included in this instance, {@link android.widget.TextView} or
- * {@link StaticLayout} will not have to recalculate this information.
- *
- * On API 28 or later, there is full PrecomputedText support by framework. From API 21 to API 27,
- * PrecomputedTextCompat relies on internal text layout cache. PrecomputedTextCompat immediately
- * computes the text layout in the constuctor to warm up the internal text layout cache. On API 20
- * or before, PrecomputedTextCompat does nothing.
- *
- * Note that any {@link android.text.NoCopySpan} attached to the original text won't be passed to
- * PrecomputedText.
- */
-public class PrecomputedTextCompat implements Spannable {
-    private static final char LINE_FEED = '\n';
-
-    /**
-     * The information required for building {@link PrecomputedTextCompat}.
-     *
-     * Contains information required for precomputing text measurement metadata, so it can be done
-     * in isolation of a {@link android.widget.TextView} or {@link StaticLayout}, when final layout
-     * constraints are not known.
-     */
-    public static final class Params {
-        private final @NonNull TextPaint mPaint;
-
-        // null on API 17 or before, non null on API 18 or later.
-        private final @Nullable TextDirectionHeuristic mTextDir;
-
-        private final int mBreakStrategy;
-
-        private final int mHyphenationFrequency;
-
-        private final PrecomputedText.Params mWrapped;
-
-        /**
-         * A builder for creating {@link Params}.
-         */
-        public static class Builder {
-            // The TextPaint used for measurement.
-            private final @NonNull TextPaint mPaint;
-
-            // The requested text direction.
-            private TextDirectionHeuristic mTextDir;
-
-            // The break strategy for this measured text.
-            private int mBreakStrategy;
-
-            // The hyphenation frequency for this measured text.
-            private int mHyphenationFrequency;
-
-            /**
-             * Builder constructor.
-             *
-             * @param paint the paint to be used for drawing
-             */
-            public Builder(@NonNull TextPaint paint) {
-                mPaint = paint;
-                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                    mBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY;
-                    mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NORMAL;
-                } else {
-                    mBreakStrategy = mHyphenationFrequency = 0;
-                }
-                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
-                    mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR;
-                } else {
-                    mTextDir = null;
-                }
-            }
-
-            /**
-             * Set the line break strategy.
-             *
-             * The default value is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}.
-             *
-             * On API 22 and below, this has no effect as there is no line break strategy.
-             *
-             * @param strategy the break strategy
-             * @return PrecomputedTextCompat.Builder instance
-             * @see StaticLayout.Builder#setBreakStrategy
-             * @see android.widget.TextView#setBreakStrategy
-             */
-            @RequiresApi(23)
-            public Builder setBreakStrategy(int strategy) {
-                mBreakStrategy = strategy;
-                return this;
-            }
-
-            /**
-             * Set the hyphenation frequency.
-             *
-             * The default value is {@link Layout#HYPHENATION_FREQUENCY_NORMAL}.
-             *
-             * On API 22 and below, this has no effect as there is no hyphenation frequency.
-             *
-             * @param frequency the hyphenation frequency
-             * @return PrecomputedTextCompat.Builder instance
-             * @see StaticLayout.Builder#setHyphenationFrequency
-             * @see android.widget.TextView#setHyphenationFrequency
-             */
-            @RequiresApi(23)
-            public Builder setHyphenationFrequency(int frequency) {
-                mHyphenationFrequency = frequency;
-                return this;
-            }
-
-            /**
-             * Set the text direction heuristic.
-             *
-             * The default value is {@link TextDirectionHeuristics#FIRSTSTRONG_LTR}.
-             *
-             * On API 17 or before, text direction heuristics cannot be modified, so this method
-             * does nothing.
-             *
-             * @param textDir the text direction heuristic for resolving bidi behavior
-             * @return PrecomputedTextCompat.Builder instance
-             * @see StaticLayout.Builder#setTextDirection
-             */
-            @RequiresApi(18)
-            public Builder setTextDirection(@NonNull TextDirectionHeuristic textDir) {
-                mTextDir = textDir;
-                return this;
-            }
-
-            /**
-             * Build the {@link Params}.
-             *
-             * @return the layout parameter
-             */
-            public @NonNull Params build() {
-                return new Params(mPaint, mTextDir, mBreakStrategy, mHyphenationFrequency);
-            }
-        }
-
-        private Params(@NonNull TextPaint paint, @NonNull TextDirectionHeuristic textDir,
-                int strategy, int frequency) {
-            if (BuildCompat.isAtLeastP()) {
-                mWrapped = new PrecomputedText.Params.Builder(paint).setBreakStrategy(strategy)
-                        .setHyphenationFrequency(frequency).setTextDirection(textDir).build();
-            } else {
-                mWrapped = null;
-            }
-            mPaint = paint;
-            mTextDir = textDir;
-            mBreakStrategy = strategy;
-            mHyphenationFrequency = frequency;
-        }
-
-        @RequiresApi(28)
-        public Params(@NonNull PrecomputedText.Params wrapped) {
-            mPaint = wrapped.getTextPaint();
-            mTextDir = wrapped.getTextDirection();
-            mBreakStrategy = wrapped.getBreakStrategy();
-            mHyphenationFrequency = wrapped.getHyphenationFrequency();
-            mWrapped = wrapped;
-
-        }
-
-        /**
-         * Returns the {@link TextPaint} for this text.
-         *
-         * @return A {@link TextPaint}
-         */
-        public @NonNull TextPaint getTextPaint() {
-            return mPaint;
-        }
-
-        /**
-         * Returns the {@link TextDirectionHeuristic} for this text.
-         *
-         * On API 17 and below, this returns null, otherwise returns non-null
-         * TextDirectionHeuristic.
-         *
-         * @return the {@link TextDirectionHeuristic}
-         */
-        @RequiresApi(18)
-        public @Nullable TextDirectionHeuristic getTextDirection() {
-            return mTextDir;
-        }
-
-        /**
-         * Returns the break strategy for this text.
-         *
-         * On API 22 and below, this returns 0.
-         *
-         * @return the line break strategy
-         */
-        @RequiresApi(23)
-        public int getBreakStrategy() {
-            return mBreakStrategy;
-        }
-
-        /**
-         * Returns the hyphenation frequency for this text.
-         *
-         * On API 22 and below, this returns 0.
-         *
-         * @return the hyphenation frequency
-         */
-        @RequiresApi(23)
-        public int getHyphenationFrequency() {
-            return mHyphenationFrequency;
-        }
-
-        /**
-         * Check if the same text layout.
-         *
-         * @return true if this and the given param result in the same text layout
-         */
-        @Override
-        public boolean equals(@Nullable Object o) {
-            if (o == this) {
-                return true;
-            }
-            if (o == null || !(o instanceof Params)) {
-                return false;
-            }
-            Params other = (Params) o;
-            if (mWrapped != null) {
-                return mWrapped.equals(other.mWrapped);
-            }
-
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                if (mBreakStrategy != other.getBreakStrategy()) {
-                    return false;
-                }
-                if (mHyphenationFrequency != other.getHyphenationFrequency()) {
-                    return false;
-                }
-            }
-
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
-                if (mTextDir != other.getTextDirection()) {
-                    return false;
-                }
-            }
-
-            if (mPaint.getTextSize() != other.getTextPaint().getTextSize()) {
-                return false;
-            }
-            if (mPaint.getTextScaleX() != other.getTextPaint().getTextScaleX()) {
-                return false;
-            }
-            if (mPaint.getTextSkewX() != other.getTextPaint().getTextSkewX()) {
-                return false;
-            }
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-                if (mPaint.getLetterSpacing() != other.getTextPaint().getLetterSpacing()) {
-                    return false;
-                }
-                if (!TextUtils.equals(mPaint.getFontFeatureSettings(),
-                        other.getTextPaint().getFontFeatureSettings())) {
-                    return false;
-                }
-            }
-            if (mPaint.getFlags() != other.getTextPaint().getFlags()) {
-                return false;
-            }
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                if (!mPaint.getTextLocales().equals(other.getTextPaint().getTextLocales())) {
-                    return false;
-                }
-            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-                if (!mPaint.getTextLocale().equals(other.getTextPaint().getTextLocale())) {
-                    return false;
-                }
-            }
-            if (mPaint.getTypeface() == null) {
-                if (other.getTextPaint().getTypeface() != null) {
-                    return false;
-                }
-            } else if (!mPaint.getTypeface().equals(other.getTextPaint().getTypeface())) {
-                return false;
-            }
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                return ObjectsCompat.hash(mPaint.getTextSize(), mPaint.getTextScaleX(),
-                        mPaint.getTextSkewX(), mPaint.getLetterSpacing(), mPaint.getFlags(),
-                        mPaint.getTextLocales(), mPaint.getTypeface(), mPaint.isElegantTextHeight(),
-                        mTextDir, mBreakStrategy, mHyphenationFrequency);
-            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-                return ObjectsCompat.hash(mPaint.getTextSize(), mPaint.getTextScaleX(),
-                        mPaint.getTextSkewX(), mPaint.getLetterSpacing(), mPaint.getFlags(),
-                        mPaint.getTextLocale(), mPaint.getTypeface(), mPaint.isElegantTextHeight(),
-                        mTextDir, mBreakStrategy, mHyphenationFrequency);
-            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
-                return ObjectsCompat.hash(mPaint.getTextSize(), mPaint.getTextScaleX(),
-                        mPaint.getTextSkewX(), mPaint.getFlags(), mPaint.getTextLocale(),
-                        mPaint.getTypeface(), mTextDir, mBreakStrategy, mHyphenationFrequency);
-            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-                return ObjectsCompat.hash(mPaint.getTextSize(), mPaint.getTextScaleX(),
-                        mPaint.getTextSkewX(), mPaint.getFlags(), mPaint.getTextLocale(),
-                        mPaint.getTypeface(), mTextDir, mBreakStrategy, mHyphenationFrequency);
-            } else {
-                return ObjectsCompat.hash(mPaint.getTextSize(), mPaint.getTextScaleX(),
-                        mPaint.getTextSkewX(), mPaint.getFlags(), mPaint.getTypeface(), mTextDir,
-                        mBreakStrategy, mHyphenationFrequency);
-            }
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder("{");
-            sb.append("textSize=" + mPaint.getTextSize());
-            sb.append(", textScaleX=" + mPaint.getTextScaleX());
-            sb.append(", textSkewX=" + mPaint.getTextSkewX());
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-                sb.append(", letterSpacing=" + mPaint.getLetterSpacing());
-                sb.append(", elegantTextHeight=" + mPaint.isElegantTextHeight());
-            }
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                sb.append(", textLocale=" + mPaint.getTextLocales());
-            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-                sb.append(", textLocale=" + mPaint.getTextLocale());
-            }
-            sb.append(", typeface=" + mPaint.getTypeface());
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-                sb.append(", variationSettings=" + mPaint.getFontVariationSettings());
-            }
-            sb.append(", textDir=" + mTextDir);
-            sb.append(", breakStrategy=" + mBreakStrategy);
-            sb.append(", hyphenationFrequency=" + mHyphenationFrequency);
-            sb.append("}");
-            return sb.toString();
-        }
-    };
-
-    // The original text.
-    private final @NonNull Spannable mText;
-
-    private final @NonNull Params mParams;
-
-    // The list of measured paragraph info.
-    private final @NonNull int[] mParagraphEnds;
-
-    // null on API 27 or before. Non-null on API 28 or later
-    private final @Nullable PrecomputedText mWrapped;
-
-    /**
-     * Create a new {@link PrecomputedText} which will pre-compute text measurement and glyph
-     * positioning information.
-     * <p>
-     * This can be expensive, so computing this on a background thread before your text will be
-     * presented can save work on the UI thread.
-     * </p>
-     *
-     * Note that any {@link android.text.NoCopySpan} attached to the text won't be passed to the
-     * created PrecomputedText.
-     *
-     * @param text the text to be measured
-     * @param params parameters that define how text will be precomputed
-     * @return A {@link PrecomputedText}
-     */
-    public static PrecomputedTextCompat create(@NonNull CharSequence text, @NonNull Params params) {
-        Preconditions.checkNotNull(text);
-        Preconditions.checkNotNull(params);
-
-        if (BuildCompat.isAtLeastP() && params.mWrapped != null) {
-            return new PrecomputedTextCompat(PrecomputedText.create(text, params.mWrapped), params);
-        }
-
-        ArrayList<Integer> ends = new ArrayList<>();
-
-        int paraEnd = 0;
-        int end = text.length();
-        for (int paraStart = 0; paraStart < end; paraStart = paraEnd) {
-            paraEnd = TextUtils.indexOf(text, LINE_FEED, paraStart, end);
-            if (paraEnd < 0) {
-                // No LINE_FEED(U+000A) character found. Use end of the text as the paragraph
-                // end.
-                paraEnd = end;
-            } else {
-                paraEnd++;  // Includes LINE_FEED(U+000A) to the prev paragraph.
-            }
-
-            ends.add(paraEnd);
-        }
-        int[] result = new int[ends.size()];
-        for (int i = 0; i < ends.size(); ++i) {
-            result[i] = ends.get(i);
-        }
-
-        // No framework support for PrecomputedText
-        // Compute text layout and throw away StaticLayout for the purpose of warming up the
-        // internal text layout cache.
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            StaticLayout.Builder.obtain(text, 0, text.length(), params.getTextPaint(),
-                    Integer.MAX_VALUE)
-                    .setBreakStrategy(params.getBreakStrategy())
-                    .setHyphenationFrequency(params.getHyphenationFrequency())
-                    .setTextDirection(params.getTextDirection())
-                    .build();
-        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            new StaticLayout(text, params.getTextPaint(), Integer.MAX_VALUE,
-                    Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
-        } else {
-            // There is no way of precomputing text layout on API 20 or before
-            // Do nothing
-        }
-
-        return new PrecomputedTextCompat(text, params, result);
-    }
-
-    // Use PrecomputedText.create instead.
-    private PrecomputedTextCompat(@NonNull CharSequence text, @NonNull Params params,
-            @NonNull int[] paraEnds) {
-        mText = new SpannableString(text);
-        mParams = params;
-        mParagraphEnds = paraEnds;
-        mWrapped = null;
-    }
-
-    @RequiresApi(28)
-    private PrecomputedTextCompat(@NonNull PrecomputedText precomputed, @NonNull Params params) {
-        mText = precomputed;
-        mParams = params;
-        mParagraphEnds = null;
-        mWrapped = precomputed;
-    }
-
-    /**
-     * Returns the layout parameters used to measure this text.
-     */
-    public @NonNull Params getParams() {
-        return mParams;
-    }
-
-    /**
-     * Returns the count of paragraphs.
-     */
-    public @IntRange(from = 0) int getParagraphCount() {
-        if (BuildCompat.isAtLeastP()) {
-            return mWrapped.getParagraphCount();
-        } else {
-            return mParagraphEnds.length;
-        }
-    }
-
-    /**
-     * Returns the paragraph start offset of the text.
-     */
-    public @IntRange(from = 0) int getParagraphStart(@IntRange(from = 0) int paraIndex) {
-        Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex");
-        if (BuildCompat.isAtLeastP()) {
-            return mWrapped.getParagraphStart(paraIndex);
-        } else {
-            return paraIndex == 0 ? 0 : mParagraphEnds[paraIndex - 1];
-        }
-    }
-
-    /**
-     * Returns the paragraph end offset of the text.
-     */
-    public @IntRange(from = 0) int getParagraphEnd(@IntRange(from = 0) int paraIndex) {
-        Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex");
-        if (BuildCompat.isAtLeastP()) {
-            return mWrapped.getParagraphEnd(paraIndex);
-        } else {
-            return mParagraphEnds[paraIndex];
-        }
-    }
-
-
-    private int findParaIndex(@IntRange(from = 0) int pos) {
-        for (int i = 0; i < mParagraphEnds.length; ++i) {
-            if (pos < mParagraphEnds[i]) {
-                return i;
-            }
-        }
-        throw new IndexOutOfBoundsException(
-                "pos must be less than " + mParagraphEnds[mParagraphEnds.length - 1]
-                        + ", gave " + pos);
-    }
-
-    ///////////////////////////////////////////////////////////////////////////////////////////////
-    // Spannable overrides
-    //
-    // Do not allow to modify MetricAffectingSpan
-
-    /**
-     * @throws IllegalArgumentException if {@link MetricAffectingSpan} is specified.
-     */
-    @Override
-    public void setSpan(Object what, int start, int end, int flags) {
-        if (what instanceof MetricAffectingSpan) {
-            throw new IllegalArgumentException(
-                    "MetricAffectingSpan can not be set to PrecomputedText.");
-        }
-        if (BuildCompat.isAtLeastP()) {
-            mWrapped.setSpan(what, start, end, flags);
-        } else {
-            mText.setSpan(what, start, end, flags);
-        }
-    }
-
-    /**
-     * @throws IllegalArgumentException if {@link MetricAffectingSpan} is specified.
-     */
-    @Override
-    public void removeSpan(Object what) {
-        if (what instanceof MetricAffectingSpan) {
-            throw new IllegalArgumentException(
-                    "MetricAffectingSpan can not be removed from PrecomputedText.");
-        }
-        if (BuildCompat.isAtLeastP()) {
-            mWrapped.removeSpan(what);
-        } else {
-            mText.removeSpan(what);
-        }
-    }
-
-    ///////////////////////////////////////////////////////////////////////////////////////////////
-    // Spanned overrides
-    //
-    // Just proxy for underlying mText if appropriate.
-
-    @Override
-    public <T> T[] getSpans(int start, int end, Class<T> type) {
-        if (BuildCompat.isAtLeastP()) {
-            return mWrapped.getSpans(start, end, type);
-        } else {
-            return mText.getSpans(start, end, type);
-        }
-
-    }
-
-    @Override
-    public int getSpanStart(Object tag) {
-        return mText.getSpanStart(tag);
-    }
-
-    @Override
-    public int getSpanEnd(Object tag) {
-        return mText.getSpanEnd(tag);
-    }
-
-    @Override
-    public int getSpanFlags(Object tag) {
-        return mText.getSpanFlags(tag);
-    }
-
-    @Override
-    public int nextSpanTransition(int start, int limit, Class type) {
-        return mText.nextSpanTransition(start, limit, type);
-    }
-
-    ///////////////////////////////////////////////////////////////////////////////////////////////
-    // CharSequence overrides.
-    //
-    // Just proxy for underlying mText.
-
-    @Override
-    public int length() {
-        return mText.length();
-    }
-
-    @Override
-    public char charAt(int index) {
-        return mText.charAt(index);
-    }
-
-    @Override
-    public CharSequence subSequence(int start, int end) {
-        return mText.subSequence(start, end);
-    }
-
-    @Override
-    public String toString() {
-        return mText.toString();
-    }
-}
diff --git a/compat/src/main/java/androidx/core/view/DisplayCutoutCompat.java b/compat/src/main/java/androidx/core/view/DisplayCutoutCompat.java
deleted file mode 100644
index 0ce108c..0000000
--- a/compat/src/main/java/androidx/core/view/DisplayCutoutCompat.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.core.view;
-
-import static android.os.Build.VERSION.SDK_INT;
-
-import android.graphics.Rect;
-import android.view.DisplayCutout;
-
-import java.util.List;
-
-
-/**
- * Represents the area of the display that is not functional for displaying content.
- *
- * <p>{@code DisplayCutoutCompat} instances are immutable.
- */
-public final class DisplayCutoutCompat {
-
-    private final Object mDisplayCutout;
-
-    /**
-     * Creates a DisplayCutout instance.
-     *
-     * @param safeInsets the insets from each edge which avoid the display cutout as returned by
-     *                   {@link #getSafeInsetTop()} etc.
-     * @param boundingRects the bounding rects of the display cutouts as returned by
-     *               {@link #getBoundingRects()} ()}.
-     */
-    // TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE)
-    public DisplayCutoutCompat(Rect safeInsets, List<Rect> boundingRects) {
-        this(SDK_INT >= 28 ? new DisplayCutout(safeInsets, boundingRects) : null);
-    }
-
-    private DisplayCutoutCompat(Object displayCutout) {
-        mDisplayCutout = displayCutout;
-    }
-
-    /** Returns the inset from the top which avoids the display cutout in pixels. */
-    public int getSafeInsetTop() {
-        if (SDK_INT >= 28) {
-            return ((DisplayCutout) mDisplayCutout).getSafeInsetTop();
-        } else {
-            return 0;
-        }
-    }
-
-    /** Returns the inset from the bottom which avoids the display cutout in pixels. */
-    public int getSafeInsetBottom() {
-        if (SDK_INT >= 28) {
-            return ((DisplayCutout) mDisplayCutout).getSafeInsetBottom();
-        } else {
-            return 0;
-        }
-    }
-
-    /** Returns the inset from the left which avoids the display cutout in pixels. */
-    public int getSafeInsetLeft() {
-        if (SDK_INT >= 28) {
-            return ((DisplayCutout) mDisplayCutout).getSafeInsetLeft();
-        } else {
-            return 0;
-        }
-    }
-
-    /** Returns the inset from the right which avoids the display cutout in pixels. */
-    public int getSafeInsetRight() {
-        if (SDK_INT >= 28) {
-            return ((DisplayCutout) mDisplayCutout).getSafeInsetRight();
-        } else {
-            return 0;
-        }
-    }
-
-    /**
-     * Returns a list of {@code Rect}s, each of which is the bounding rectangle for a non-functional
-     * area on the display.
-     *
-     * There will be at most one non-functional area per short edge of the device, and none on
-     * the long edges.
-     *
-     * @return a list of bounding {@code Rect}s, one for each display cutout area.
-     */
-    public List<Rect> getBoundingRects() {
-        if (SDK_INT >= 28) {
-            return ((DisplayCutout) mDisplayCutout).getBoundingRects();
-        } else {
-            return null;
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        DisplayCutoutCompat other = (DisplayCutoutCompat) o;
-        return mDisplayCutout == null ? other.mDisplayCutout == null
-                : mDisplayCutout.equals(other.mDisplayCutout);
-    }
-
-    @Override
-    public int hashCode() {
-        return mDisplayCutout == null ? 0 : mDisplayCutout.hashCode();
-    }
-
-    @Override
-    public String toString() {
-        return "DisplayCutoutCompat{" + mDisplayCutout + "}";
-    }
-
-    static DisplayCutoutCompat wrap(Object displayCutout) {
-        return displayCutout == null ? null : new DisplayCutoutCompat(displayCutout);
-    }
-}
diff --git a/compat/src/main/java/androidx/core/view/WindowInsetsCompat.java b/compat/src/main/java/androidx/core/view/WindowInsetsCompat.java
index 003044a..eef9b12 100644
--- a/compat/src/main/java/androidx/core/view/WindowInsetsCompat.java
+++ b/compat/src/main/java/androidx/core/view/WindowInsetsCompat.java
@@ -20,7 +20,6 @@
 
 import android.graphics.Rect;
 import android.view.WindowInsets;
-import androidx.annotation.Nullable;
 
 /**
  * Describes a set of insets for window content.
@@ -344,34 +343,6 @@
         }
     }
 
-    /**
-     * Returns the display cutout if there is one.
-     *
-     * @return the display cutout or null if there is none
-     * @see DisplayCutoutCompat
-     */
-    @Nullable
-    public DisplayCutoutCompat getDisplayCutout() {
-        if (SDK_INT >= 28) {
-            return DisplayCutoutCompat.wrap(((WindowInsets) mInsets).getDisplayCutout());
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Returns a copy of this WindowInsets with the cutout fully consumed.
-     *
-     * @return A modified copy of this WindowInsets
-     */
-    public WindowInsetsCompat consumeDisplayCutout() {
-        if (SDK_INT >= 28) {
-            return new WindowInsetsCompat(((WindowInsets) mInsets).consumeDisplayCutout());
-        } else {
-            return null;
-        }
-    }
-
     @Override
     public boolean equals(Object o) {
         if (this == o) {
diff --git a/compat/src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java b/compat/src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java
index 015a77f2..16b570f 100644
--- a/compat/src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java
+++ b/compat/src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java
@@ -642,9 +642,7 @@
          * @param rowSpan The number of rows the item spans.
          * @param columnIndex The column index at which the item is located.
          * @param columnSpan The number of columns the item spans.
-         * @param heading Whether the item is a heading. This should be set to false and the newer
-         *                {@link AccessibilityNodeInfoCompat#setHeading(boolean)} used to identify
-         *                headings.
+         * @param heading Whether the item is a heading.
          * @param selected Whether the item is selected.
          * @return An instance.
          */
@@ -668,9 +666,7 @@
          * @param rowSpan The number of rows the item spans.
          * @param columnIndex The column index at which the item is located.
          * @param columnSpan The number of columns the item spans.
-         * @param heading Whether the item is a heading. This should be set to false and the newer
-         *                {@link AccessibilityNodeInfoCompat#setHeading(boolean)} used to identify
-         *                headings.
+         * @param heading Whether the item is a heading.
          * @return An instance.
          */
         public static CollectionItemInfoCompat obtain(int rowIndex, int rowSpan,
@@ -744,7 +740,6 @@
          * heading, table header, etc.
          *
          * @return If the item is a heading.
-         * @deprecated Use {@link AccessibilityNodeInfoCompat#isHeading()}
          */
         public boolean isHeading() {
             if (Build.VERSION.SDK_INT >= 19) {
@@ -3318,16 +3313,11 @@
 
     /**
      * Returns whether node represents a heading.
-     * <p><strong>Note:</strong> Returns {@code true} if either {@link #setHeading(boolean)}
-     * marks this node as a heading or if the node has a {@link CollectionItemInfoCompat} that marks
-     * it as such, to accomodate apps that use the now-deprecated API.</p>
      *
      * @return {@code true} if the node is a heading, {@code false} otherwise.
      */
     public boolean isHeading() {
-        if (getBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING)) return true;
-        CollectionItemInfoCompat collectionItemInfo = getCollectionItemInfo();
-        return (collectionItemInfo != null) && (collectionItemInfo.isHeading());
+        return getBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING);
     }
 
     /**
diff --git a/core/ktx/api/current.txt b/core/ktx/api/current.txt
index 883cbc9..61d7de8 100644
--- a/core/ktx/api/current.txt
+++ b/core/ktx/api/current.txt
@@ -308,16 +308,6 @@
 
 }
 
-package androidx.core.location {
-
-  public final class LocationKt {
-    ctor public LocationKt();
-    method public static operator double component1(android.location.Location);
-    method public static operator double component2(android.location.Location);
-  }
-
-}
-
 package androidx.core.net {
 
   public final class UriKt {
@@ -363,7 +353,6 @@
     method public static void forEachIndexed(android.preference.PreferenceGroup, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super android.preference.Preference,kotlin.Unit> action);
     method public static operator android.preference.Preference get(android.preference.PreferenceGroup, CharSequence key);
     method public static operator android.preference.Preference get(android.preference.PreferenceGroup, int index);
-    method public static kotlin.sequences.Sequence<android.preference.Preference> getChildren(android.preference.PreferenceGroup);
     method public static int getSize(android.preference.PreferenceGroup);
     method public static boolean isEmpty(android.preference.PreferenceGroup);
     method public static boolean isNotEmpty(android.preference.PreferenceGroup);
@@ -399,8 +388,6 @@
     method public static android.text.SpannableStringBuilder italic(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
     method public static android.text.SpannableStringBuilder scale(android.text.SpannableStringBuilder, float proportion, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
     method public static android.text.SpannableStringBuilder strikeThrough(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
-    method public static android.text.SpannableStringBuilder subscript(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
-    method public static android.text.SpannableStringBuilder superscript(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
     method public static android.text.SpannableStringBuilder underline(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
   }
 
@@ -618,12 +605,10 @@
     method public static void forEach(android.view.Menu, kotlin.jvm.functions.Function1<? super android.view.MenuItem,kotlin.Unit> action);
     method public static void forEachIndexed(android.view.Menu, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super android.view.MenuItem,kotlin.Unit> action);
     method public static operator android.view.MenuItem get(android.view.Menu, int index);
-    method public static kotlin.sequences.Sequence<android.view.MenuItem> getChildren(android.view.Menu);
     method public static int getSize(android.view.Menu);
     method public static boolean isEmpty(android.view.Menu);
     method public static boolean isNotEmpty(android.view.Menu);
     method public static operator java.util.Iterator<android.view.MenuItem> iterator(android.view.Menu);
-    method public static operator void minusAssign(android.view.Menu, android.view.MenuItem item);
   }
 
   public final class ViewGroupKt {
diff --git a/core/ktx/src/androidTest/java/androidx/core/location/LocationTest.kt b/core/ktx/src/androidTest/java/androidx/core/location/LocationTest.kt
deleted file mode 100644
index 0f289ef..0000000
--- a/core/ktx/src/androidTest/java/androidx/core/location/LocationTest.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.core.location
-
-import android.location.Location
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-class LocationTest {
-    @Test fun destructuring() {
-        val (lat, lon) = Location("").apply {
-            latitude = 1.0
-            longitude = 2.0
-        }
-        assertEquals(lat, 1.0, 0.0)
-        assertEquals(lon, 2.0, 0.0)
-    }
-}
diff --git a/core/ktx/src/androidTest/java/androidx/core/preference/PreferenceGroupTest.kt b/core/ktx/src/androidTest/java/androidx/core/preference/PreferenceGroupTest.kt
index 120718e..0653a28 100644
--- a/core/ktx/src/androidTest/java/androidx/core/preference/PreferenceGroupTest.kt
+++ b/core/ktx/src/androidTest/java/androidx/core/preference/PreferenceGroupTest.kt
@@ -173,13 +173,4 @@
             iterator.next()
         }
     }
-
-    @Test fun children() {
-        val preferences = listOf(Preference(context), Preference(context), Preference(context))
-        preferences.forEach { preferenceGroup.addPreference(it) }
-
-        preferenceGroup.children.forEachIndexed { index, child ->
-            assertSame(preferences[index], child)
-        }
-    }
 }
diff --git a/core/ktx/src/androidTest/java/androidx/core/text/SpannableStringBuilderTest.kt b/core/ktx/src/androidTest/java/androidx/core/text/SpannableStringBuilderTest.kt
index c66dd1f..5d67e83 100644
--- a/core/ktx/src/androidTest/java/androidx/core/text/SpannableStringBuilderTest.kt
+++ b/core/ktx/src/androidTest/java/androidx/core/text/SpannableStringBuilderTest.kt
@@ -186,49 +186,15 @@
         assertEquals(12, result.getSpanEnd(scale))
     }
 
-    @Test fun builderSuperscript() {
-        val result: SpannedString = buildSpannedString {
-            append("Hello, ")
-            superscript {
-                append("World")
-            }
-        }
-        assertEquals("Hello, World", result.toString())
-
-        val spans = result.getSpans<Any>()
-        assertEquals(1, spans.size)
-
-        val superscript = spans.filterIsInstance<SuperscriptSpan>().single()
-        assertEquals(7, result.getSpanStart(superscript))
-        assertEquals(12, result.getSpanEnd(superscript))
-    }
-
-    @Test fun builderSubscript() {
-        val result: SpannedString = buildSpannedString {
-            append("Hello, ")
-            subscript {
-                append("World")
-            }
-        }
-        assertEquals("Hello, World", result.toString())
-
-        val spans = result.getSpans<Any>()
-        assertEquals(1, spans.size)
-
-        val subscript = spans.filterIsInstance<SubscriptSpan>().single()
-        assertEquals(7, result.getSpanStart(subscript))
-        assertEquals(12, result.getSpanEnd(subscript))
-    }
-
     @Test fun nested() {
         val result: SpannedString = buildSpannedString {
             color(RED) {
                 append('H')
-                subscript {
+                inSpans(SubscriptSpan()) {
                     append('e')
                 }
                 append('l')
-                superscript {
+                inSpans(SuperscriptSpan()) {
                     append('l')
                 }
                 append('o')
diff --git a/core/ktx/src/androidTest/java/androidx/core/view/MenuTest.kt b/core/ktx/src/androidTest/java/androidx/core/view/MenuTest.kt
index 313ed1b..18e1b56 100644
--- a/core/ktx/src/androidTest/java/androidx/core/view/MenuTest.kt
+++ b/core/ktx/src/androidTest/java/androidx/core/view/MenuTest.kt
@@ -45,20 +45,6 @@
         assertTrue(item2 in menu)
     }
 
-    @Test fun minusAssign() {
-        val item1 = menu.add(NONE, 1, NONE, "")
-        val item2 = menu.add(NONE, 2, NONE, "")
-
-        assertEquals(2, menu.size)
-
-        menu -= item2
-        assertEquals(1, menu.size)
-        assertSame(item1, menu.getItem(0))
-
-        menu -= item1
-        assertEquals(0, menu.size)
-    }
-
     @Test fun size() {
         assertEquals(0, menu.size)
 
@@ -146,16 +132,4 @@
         assertFalse(item2 in menu)
         assertEquals(0, menu.size())
     }
-
-    @Test fun children() {
-        val items = listOf(
-            menu.add(NONE, 1, NONE, ""),
-            menu.add(NONE, 2, NONE, ""),
-            menu.add(NONE, 3, NONE, "")
-        )
-
-        menu.children.forEachIndexed { index, child ->
-            assertSame(items[index], child)
-        }
-    }
 }
diff --git a/core/ktx/src/androidTest/java/androidx/core/view/ViewTest.kt b/core/ktx/src/androidTest/java/androidx/core/view/ViewTest.kt
index 1ccd517..0b7cfa2 100644
--- a/core/ktx/src/androidTest/java/androidx/core/view/ViewTest.kt
+++ b/core/ktx/src/androidTest/java/androidx/core/view/ViewTest.kt
@@ -17,9 +17,7 @@
 package androidx.core.view
 
 import android.graphics.Bitmap
-import android.graphics.Color
 import android.support.test.InstrumentationRegistry
-import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.widget.LinearLayout
@@ -177,29 +175,6 @@
         assertSame(Bitmap.Config.RGB_565, bitmap.config)
     }
 
-    @Test
-    fun toBitmapScrolls() {
-        val scrollView = LayoutInflater.from(context)!!
-                .inflate(R.layout.test_bitmap_scrolls, null, false)
-
-        val size = 100
-
-        scrollView.measure(
-                View.MeasureSpec.makeMeasureSpec(size, View.MeasureSpec.EXACTLY),
-                View.MeasureSpec.makeMeasureSpec(size, View.MeasureSpec.EXACTLY))
-        scrollView.layout(0, 0, size, size)
-
-        val noScroll = scrollView.toBitmap()
-        assertEquals(Color.WHITE, noScroll.getPixel(0, 0))
-        assertEquals(Color.WHITE, noScroll.getPixel(size - 1, size - 1))
-
-        scrollView.scrollTo(0, size)
-        val scrolls = scrollView.toBitmap()
-
-        assertEquals(Color.BLACK, scrolls.getPixel(0, 0))
-        assertEquals(Color.BLACK, scrolls.getPixel(size - 1, size - 1))
-    }
-
     @Test fun isVisible() {
         view.isVisible = true
         assertTrue(view.isVisible)
diff --git a/core/ktx/src/androidTest/res/layout/test_bitmap_scrolls.xml b/core/ktx/src/androidTest/res/layout/test_bitmap_scrolls.xml
deleted file mode 100644
index c2cad5c..0000000
--- a/core/ktx/src/androidTest/res/layout/test_bitmap_scrolls.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~       http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="100px"
-    android:layout_height="100px"
-    android:scrollbars="none"
-    >
-
-    <LinearLayout
-        android:layout_width="100px"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
-
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="100px"
-            android:background="@android:color/white" />
-
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="100px"
-            android:background="@android:color/black" />
-
-    </LinearLayout>
-
-</ScrollView>
\ No newline at end of file
diff --git a/core/ktx/src/main/java/androidx/core/location/Location.kt b/core/ktx/src/main/java/androidx/core/location/Location.kt
deleted file mode 100644
index fe48322..0000000
--- a/core/ktx/src/main/java/androidx/core/location/Location.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:Suppress("NOTHING_TO_INLINE")
-
-package androidx.core.location
-
-import android.location.Location
-
-/**
- * Returns the latitude of this [Location].
- *
- * This method allows to use destructuring declarations when working with [Location],
- * for example:
- * ```
- * val (lat, lon) = myLocation
- * ```
- */
-inline operator fun Location.component1() = this.latitude
-
-/**
- * Returns the longitude of this [Location].
- *
- * This method allows to use destructuring declarations when working with [Location],
- * for example:
- * ```
- * val (lat, lon) = myLocation
- * ```
- */
-inline operator fun Location.component2() = this.longitude
diff --git a/core/ktx/src/main/java/androidx/core/preference/PreferenceGroup.kt b/core/ktx/src/main/java/androidx/core/preference/PreferenceGroup.kt
index 5df18a6..ab37dee 100644
--- a/core/ktx/src/main/java/androidx/core/preference/PreferenceGroup.kt
+++ b/core/ktx/src/main/java/androidx/core/preference/PreferenceGroup.kt
@@ -41,8 +41,8 @@
 /** Returns `true` if `preference` is found in this preference group. */
 @Deprecated("Use Jetpack preference library")
 operator fun PreferenceGroup.contains(preference: Preference): Boolean {
-    for (index in 0 until preferenceCount) {
-        if (getPreference(index) == preference) {
+    for (index in 0 until size) {
+        if (get(index) == preference) {
             return true
         }
     }
@@ -76,7 +76,7 @@
 /** Performs the given action on each preference in this preference group. */
 @Deprecated("Use Jetpack preference library")
 inline fun PreferenceGroup.forEach(action: (preference: Preference) -> Unit) {
-    for (index in 0 until preferenceCount) {
+    for (index in 0 until size) {
         action(get(index))
     }
 }
@@ -84,7 +84,7 @@
 /** Performs the given action on each preference in this preference group, providing its sequential index. */
 @Deprecated("Use Jetpack preference library")
 inline fun PreferenceGroup.forEachIndexed(action: (index: Int, preference: Preference) -> Unit) {
-    for (index in 0 until preferenceCount) {
+    for (index in 0 until size) {
         action(index, get(index))
     }
 }
diff --git a/core/ktx/src/main/java/androidx/core/text/SpannableStringBuilder.kt b/core/ktx/src/main/java/androidx/core/text/SpannableStringBuilder.kt
index e49ccd2..5834a34 100644
--- a/core/ktx/src/main/java/androidx/core/text/SpannableStringBuilder.kt
+++ b/core/ktx/src/main/java/androidx/core/text/SpannableStringBuilder.kt
@@ -26,8 +26,6 @@
 import android.text.style.RelativeSizeSpan
 import android.text.style.StrikethroughSpan
 import android.text.style.StyleSpan
-import android.text.style.SubscriptSpan
-import android.text.style.SuperscriptSpan
 import android.text.style.UnderlineSpan
 import androidx.annotation.ColorInt
 
@@ -136,19 +134,3 @@
     proportion: Float,
     builderAction: SpannableStringBuilder.() -> Unit
 ) = inSpans(RelativeSizeSpan(proportion), builderAction = builderAction)
-
-/**
- * Wrap appended text in [builderAction] in a [SuperscriptSpan].
- *
- * @see SpannableStringBuilder.inSpans
- */
-inline fun SpannableStringBuilder.superscript(builderAction: SpannableStringBuilder.() -> Unit) =
-    inSpans(SuperscriptSpan(), builderAction = builderAction)
-
-/**
- * Wrap appended text in [builderAction] in a [SubscriptSpan].
- *
- * @see SpannableStringBuilder.inSpans
- */
-inline fun SpannableStringBuilder.subscript(builderAction: SpannableStringBuilder.() -> Unit) =
-    inSpans(SubscriptSpan(), builderAction = builderAction)
diff --git a/core/ktx/src/main/java/androidx/core/view/Menu.kt b/core/ktx/src/main/java/androidx/core/view/Menu.kt
index 069e61d..7ab479f 100644
--- a/core/ktx/src/main/java/androidx/core/view/Menu.kt
+++ b/core/ktx/src/main/java/androidx/core/view/Menu.kt
@@ -31,7 +31,7 @@
 /** Returns `true` if [item] is found in this menu. */
 operator fun Menu.contains(item: MenuItem): Boolean {
     @Suppress("LoopToCallChain")
-    for (index in 0 until size()) {
+    for (index in 0 until size) {
         if (getItem(index) == item) {
             return true
         }
@@ -39,9 +39,6 @@
     return false
 }
 
-/** Removes [item] from this menu. */
-inline operator fun Menu.minusAssign(item: MenuItem) = removeItem(item.itemId)
-
 /** Returns the number of items in this menu. */
 inline val Menu.size get() = size()
 
@@ -72,9 +69,3 @@
     override fun next() = getItem(index++) ?: throw IndexOutOfBoundsException()
     override fun remove() = removeItem(--index)
 }
-
-/** Returns a [Sequence] over the items in this menu. */
-val Menu.children: Sequence<MenuItem>
-    get() = object : Sequence<MenuItem> {
-        override fun iterator() = this@children.iterator()
-    }
diff --git a/core/ktx/src/main/java/androidx/core/view/View.kt b/core/ktx/src/main/java/androidx/core/view/View.kt
index bc2e34d..fcb0256 100644
--- a/core/ktx/src/main/java/androidx/core/view/View.kt
+++ b/core/ktx/src/main/java/androidx/core/view/View.kt
@@ -195,10 +195,7 @@
     if (!ViewCompat.isLaidOut(this)) {
         throw IllegalStateException("View needs to be laid out before calling toBitmap()")
     }
-    return Bitmap.createBitmap(width, height, config).applyCanvas {
-        translate(-scrollX.toFloat(), -scrollY.toFloat())
-        draw(this)
-    }
+    return Bitmap.createBitmap(width, height, config).applyCanvas(::draw)
 }
 
 /**
diff --git a/customview/src/main/java/androidx/customview/widget/ExploreByTouchHelper.java b/customview/src/main/java/androidx/customview/widget/ExploreByTouchHelper.java
index dbe8455..b49afc8 100644
--- a/customview/src/main/java/androidx/customview/widget/ExploreByTouchHelper.java
+++ b/customview/src/main/java/androidx/customview/widget/ExploreByTouchHelper.java
@@ -188,7 +188,7 @@
                 updateHoveredVirtualView(virtualViewId);
                 return (virtualViewId != INVALID_ID);
             case MotionEvent.ACTION_HOVER_EXIT:
-                if (mHoveredVirtualViewId != INVALID_ID) {
+                if (mAccessibilityFocusedVirtualViewId != INVALID_ID) {
                     updateHoveredVirtualView(INVALID_ID);
                     return true;
                 }
diff --git a/exifinterface/src/main/java/androidx/exifinterface/media/ExifInterface.java b/exifinterface/src/main/java/androidx/exifinterface/media/ExifInterface.java
index d685bf1..f697f24 100644
--- a/exifinterface/src/main/java/androidx/exifinterface/media/ExifInterface.java
+++ b/exifinterface/src/main/java/androidx/exifinterface/media/ExifInterface.java
@@ -3920,7 +3920,7 @@
                         break;
                     }
                     case IFD_FORMAT_USHORT: {
-                        final String[] values = value.split(",", -1);
+                        final String[] values = value.split(",");
                         final int[] intArray = new int[values.length];
                         for (int j = 0; j < values.length; ++j) {
                             intArray[j] = Integer.parseInt(values[j]);
@@ -3930,7 +3930,7 @@
                         break;
                     }
                     case IFD_FORMAT_SLONG: {
-                        final String[] values = value.split(",", -1);
+                        final String[] values = value.split(",");
                         final int[] intArray = new int[values.length];
                         for (int j = 0; j < values.length; ++j) {
                             intArray[j] = Integer.parseInt(values[j]);
@@ -3940,7 +3940,7 @@
                         break;
                     }
                     case IFD_FORMAT_ULONG: {
-                        final String[] values = value.split(",", -1);
+                        final String[] values = value.split(",");
                         final long[] longArray = new long[values.length];
                         for (int j = 0; j < values.length; ++j) {
                             longArray[j] = Long.parseLong(values[j]);
@@ -3950,10 +3950,10 @@
                         break;
                     }
                     case IFD_FORMAT_URATIONAL: {
-                        final String[] values = value.split(",", -1);
+                        final String[] values = value.split(",");
                         final Rational[] rationalArray = new Rational[values.length];
                         for (int j = 0; j < values.length; ++j) {
-                            final String[] numbers = values[j].split("/", -1);
+                            final String[] numbers = values[j].split("/");
                             rationalArray[j] = new Rational((long) Double.parseDouble(numbers[0]),
                                     (long) Double.parseDouble(numbers[1]));
                         }
@@ -3962,10 +3962,10 @@
                         break;
                     }
                     case IFD_FORMAT_SRATIONAL: {
-                        final String[] values = value.split(",", -1);
+                        final String[] values = value.split(",");
                         final Rational[] rationalArray = new Rational[values.length];
                         for (int j = 0; j < values.length; ++j) {
-                            final String[] numbers = values[j].split("/", -1);
+                            final String[] numbers = values[j].split("/");
                             rationalArray[j] = new Rational((long) Double.parseDouble(numbers[0]),
                                     (long) Double.parseDouble(numbers[1]));
                         }
@@ -3974,7 +3974,7 @@
                         break;
                     }
                     case IFD_FORMAT_DOUBLE: {
-                        final String[] values = value.split(",", -1);
+                        final String[] values = value.split(",");
                         final double[] doubleArray = new double[values.length];
                         for (int j = 0; j < values.length; ++j) {
                             doubleArray[j] = Double.parseDouble(values[j]);
@@ -4510,7 +4510,7 @@
         setAttribute(TAG_GPS_SPEED_REF, "K");
         setAttribute(TAG_GPS_SPEED, new Rational(location.getSpeed()
                 * TimeUnit.HOURS.toSeconds(1) / 1000).toString());
-        String[] dateTime = sFormatter.format(new Date(location.getTime())).split("\\s+", -1);
+        String[] dateTime = sFormatter.format(new Date(location.getTime())).split("\\s+");
         setAttribute(ExifInterface.TAG_GPS_DATESTAMP, dateTime[0]);
         setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, dateTime[1]);
     }
@@ -4643,18 +4643,18 @@
 
     private static double convertRationalLatLonToDouble(String rationalString, String ref) {
         try {
-            String [] parts = rationalString.split(",", -1);
+            String [] parts = rationalString.split(",");
 
             String [] pair;
-            pair = parts[0].split("/", -1);
+            pair = parts[0].split("/");
             double degrees = Double.parseDouble(pair[0].trim())
                     / Double.parseDouble(pair[1].trim());
 
-            pair = parts[1].split("/", -1);
+            pair = parts[1].split("/");
             double minutes = Double.parseDouble(pair[0].trim())
                     / Double.parseDouble(pair[1].trim());
 
-            pair = parts[2].split("/", -1);
+            pair = parts[2].split("/");
             double seconds = Double.parseDouble(pair[0].trim())
                     / Double.parseDouble(pair[1].trim());
 
@@ -6017,7 +6017,7 @@
         // See TIFF 6.0 Section 2, "Image File Directory".
         // Take the first component if there are more than one component.
         if (entryValue.contains(",")) {
-            String[] entryValues = entryValue.split(",", -1);
+            String[] entryValues = entryValue.split(",");
             Pair<Integer, Integer> dataFormat = guessDataFormat(entryValues[0]);
             if (dataFormat.first == IFD_FORMAT_STRING) {
                 return dataFormat;
@@ -6049,7 +6049,7 @@
         }
 
         if (entryValue.contains("/")) {
-            String[] rationalNumber = entryValue.split("/", -1);
+            String[] rationalNumber = entryValue.split("/");
             if (rationalNumber.length == 2) {
                 try {
                     long numerator = (long) Double.parseDouble(rationalNumber[0]);
diff --git a/heifwriter/src/main/java/androidx/heifwriter/EglWindowSurface.java b/heifwriter/src/main/java/androidx/heifwriter/EglWindowSurface.java
index 35d34d4..9b5df45 100644
--- a/heifwriter/src/main/java/androidx/heifwriter/EglWindowSurface.java
+++ b/heifwriter/src/main/java/androidx/heifwriter/EglWindowSurface.java
@@ -25,8 +25,6 @@
 import android.util.Log;
 import android.view.Surface;
 
-import java.util.Objects;
-
 /**
  * Holds state associated with a Surface used for MediaCodec encoder input.
  * <p>
@@ -65,7 +63,7 @@
      */
     private void eglSetup() {
         mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
-        if (Objects.equals(mEGLDisplay, EGL14.EGL_NO_DISPLAY)) {
+        if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
             throw new RuntimeException("unable to get EGL14 display");
         }
         int[] version = new int[2];
@@ -132,7 +130,7 @@
     }
 
     private void releaseEGLSurface() {
-        if (!Objects.equals(mEGLDisplay, EGL14.EGL_NO_DISPLAY)) {
+        if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
             EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
             mEGLSurface = EGL14.EGL_NO_SURFACE;
         }
@@ -143,7 +141,7 @@
      * Surface that was passed to our constructor.
      */
     public void release() {
-        if (!Objects.equals(mEGLDisplay, EGL14.EGL_NO_DISPLAY)) {
+        if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
             EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
             EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
             EGL14.eglReleaseThread();
diff --git a/jetifier/jetifier/processor/src/main/kotlin/com/android/tools/build/jetifier/processor/transform/bytecode/CoreRemapperImpl.kt b/jetifier/jetifier/processor/src/main/kotlin/com/android/tools/build/jetifier/processor/transform/bytecode/CoreRemapperImpl.kt
index aa29bdc..b5ab7ea 100644
--- a/jetifier/jetifier/processor/src/main/kotlin/com/android/tools/build/jetifier/processor/transform/bytecode/CoreRemapperImpl.kt
+++ b/jetifier/jetifier/processor/src/main/kotlin/com/android/tools/build/jetifier/processor/transform/bytecode/CoreRemapperImpl.kt
@@ -61,11 +61,11 @@
             return value
         }
 
-        val mappedType = context.config.typesMap.mapType(type)
-        if (mappedType != null) {
-            changesDone = changesDone || mappedType != type
-            Log.i(TAG, "Map string: '%s' -> '%s'", type, mappedType)
-            return mappedType.toDotNotation()
+        val result = context.config.typesMap.mapType(type)
+        if (result != null) {
+            changesDone = changesDone || result != type
+            Log.i(TAG, "Map string: '%s' -> '%s'", type, result)
+            return result.toDotNotation()
         }
 
         // We might be working with an internal type or field reference, e.g.
@@ -81,10 +81,10 @@
 
         // Try rewrite rules
         if (context.useFallbackIfTypeIsMissing) {
-            val rewrittenType = context.config.rulesMap.rewriteType(type)
-            if (rewrittenType != null) {
-                Log.i(TAG, "Map string: '%s' -> '%s' via fallback", value, rewrittenType)
-                return rewrittenType.toDotNotation()
+            val result = context.config.rulesMap.rewriteType(type)
+            if (result != null) {
+                Log.i(TAG, "Map string: '%s' -> '%s' via fallback", value, result)
+                return result.toDotNotation()
             }
         }
 
diff --git a/jetifier/jetifier/source-transformer/rewriteMake.py b/jetifier/jetifier/source-transformer/rewriteMake.py
index b33d4c1..a8ee1d7 100755
--- a/jetifier/jetifier/source-transformer/rewriteMake.py
+++ b/jetifier/jetifier/source-transformer/rewriteMake.py
@@ -88,6 +88,7 @@
 android-arch-room-migration,androidx.room_room-migration
 android-arch-room-runtime,androidx.room_room-runtime
 android-arch-room-testing,androidx.room_room-testing
+android-support-design,com.google.android.material_material
 $(ANDROID_SUPPORT_DESIGN_TARGETS),com.google.android.material_material"""
 
 reader = csv.reader(target_map.split('\n'), delimiter=',')
diff --git a/jetifier/jetifier/source-transformer/rewritePackageNames.py b/jetifier/jetifier/source-transformer/rewritePackageNames.py
index 32d9a91..8e348a4 100755
--- a/jetifier/jetifier/source-transformer/rewritePackageNames.py
+++ b/jetifier/jetifier/source-transformer/rewritePackageNames.py
@@ -95,7 +95,7 @@
   rewriterTextBuilder = StringBuilder()
   rewriteRules = executionConfig.jetifierConfig.getTypesMap()
   for rule in rewriteRules:
-    rewriterTextBuilder.add("s|").add(rule.fromName.replace(".", "\.")).add("|").add(rule.toName).add("|g\n")
+    rewriterTextBuilder.add("s|").add(rule.fromName).add("|").add(rule.toName).add("|g\n")
   for rule in HARDCODED_RULES_REVERSE:
     rewriterTextBuilder.add(rule)
   scriptPath = "/tmp/jetifier-sed-script.txt"
diff --git a/leanback/src/main/res/values-as/strings.xml b/leanback/src/main/res/values-as/strings.xml
deleted file mode 100644
index eb3b2b0..0000000
--- a/leanback/src/main/res/values-as/strings.xml
+++ /dev/null
@@ -1,59 +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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="lb_navigation_menu_contentDescription" msgid="8126335323963415494">"নেভিগেশ্বন মেনু"</string>
-    <string name="orb_search_action" msgid="7534843523462177008">"সন্ধান সম্পৰ্কীয় কাৰ্য"</string>
-    <string name="lb_search_bar_hint" msgid="4819380969103509861">"সন্ধান"</string>
-    <string name="lb_search_bar_hint_speech" msgid="2795474673510974502">"সন্ধান কৰিবলৈ কথা কওক"</string>
-    <string name="lb_search_bar_hint_with_title" msgid="7453744869467668159">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> সন্ধান কৰক"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="5851694095153624617">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> সন্ধান কৰিবলৈ কথা কওক"</string>
-    <string name="lb_control_display_fast_forward_multiplier" msgid="2721825378927619928">"%1$dX"</string>
-    <string name="lb_control_display_rewind_multiplier" msgid="6173753802428649303">"%1$dX"</string>
-    <string name="lb_playback_controls_play" msgid="1590369760862605402">"প্লে কৰক"</string>
-    <string name="lb_playback_controls_pause" msgid="1769131316742618433">"পজ কৰক"</string>
-    <string name="lb_playback_controls_fast_forward" msgid="8966769845721269304">"ফাষ্ট ফৰৱাৰ্ড"</string>
-    <string name="lb_playback_controls_fast_forward_multiplier" msgid="801276177839339511">"ফাষ্ট ফৰৱার্ড কৰক %1$dX"</string>
-    <string name="lb_playback_controls_rewind" msgid="1412664391757869774">"ৰিৱাইণ্ড কৰক"</string>
-    <string name="lb_playback_controls_rewind_multiplier" msgid="8651612807713092781">"ৰিৱাইণ্ড কৰক %1$dX"</string>
-    <string name="lb_playback_controls_skip_next" msgid="4877009494447817003">"পৰৱৰ্তীটোলৈ এৰি যাওক"</string>
-    <string name="lb_playback_controls_skip_previous" msgid="3147124289285911980">"আগৰটোলৈ এৰি যাওক"</string>
-    <string name="lb_playback_controls_more_actions" msgid="2827883329510404797">"অধিক কাৰ্য"</string>
-    <string name="lb_playback_controls_thumb_up" msgid="8332816524260995892">"থাম্ব আপ বাছনি নাইকিয়া কৰক"</string>
-    <string name="lb_playback_controls_thumb_up_outline" msgid="1038344559734334272">"থাম্ব আপ বাছনি কৰক"</string>
-    <string name="lb_playback_controls_thumb_down" msgid="5075744418630733006">"থাম্ব ডাউন বাছনি নাইকিয়া কৰক"</string>
-    <string name="lb_playback_controls_thumb_down_outline" msgid="2847309435442474470">"থাম্ব ডাউন বাছনি কৰক"</string>
-    <string name="lb_playback_controls_repeat_none" msgid="5812341701962930499">"একো পুনৰাই প্লে নকৰিব"</string>
-    <string name="lb_playback_controls_repeat_all" msgid="5164826436271322261">"সকলো পুনৰাই প্লে কৰক"</string>
-    <string name="lb_playback_controls_repeat_one" msgid="7675097479246139440">"এটা পুনৰাই প্লে কৰক"</string>
-    <string name="lb_playback_controls_shuffle_enable" msgid="7809089255981448519">"সান-মিহলি সক্ষম কৰক"</string>
-    <string name="lb_playback_controls_shuffle_disable" msgid="8182435535948303910">"সান-মিহলি অক্ষম কৰক"</string>
-    <string name="lb_playback_controls_high_quality_enable" msgid="1862669142355962638">"উচ্চ মানৰ প্লেবেক সক্ষম কৰক"</string>
-    <string name="lb_playback_controls_high_quality_disable" msgid="3000046054608531995">"উচ্চ মান অক্ষম কৰক"</string>
-    <string name="lb_playback_controls_closed_captioning_enable" msgid="3934392140182327163">"ছাব-টাইটেল সক্ষম কৰক"</string>
-    <string name="lb_playback_controls_closed_captioning_disable" msgid="5508271941331836786">"ছাব-টাইটেল অক্ষম কৰক"</string>
-    <string name="lb_playback_controls_picture_in_picture" msgid="8800305194045609275">"চিত্ৰৰ ভিতৰত চিত্ৰ ম\'ড আৰম্ভ কৰক"</string>
-    <string name="lb_playback_time_separator" msgid="6549544638083578695">"/"</string>
-    <string name="lb_playback_controls_shown" msgid="7794717158616536936">"মিডিয়াৰ নিয়ন্ত্ৰণসমূহ দেখুওৱা হ\'ল"</string>
-    <string name="lb_playback_controls_hidden" msgid="619396299825306757">"মিডিয়াৰ নিয়ন্ত্ৰণসমূহ লুকুৱাই ৰখা হৈছে, দেখুওৱাবলৈ ডি-পেডত টিপক"</string>
-    <string name="lb_guidedaction_finish_title" msgid="7747913934287176843">"সমাপ্ত"</string>
-    <string name="lb_guidedaction_continue_title" msgid="1122271825827282965">"অব্যাহত ৰাখক"</string>
-    <string name="lb_media_player_error" msgid="8748646000835486516">"MediaPlayer ত্ৰুটি ক\'ড %1$d, অতিৰিক্ত %2$d"</string>
-    <string name="lb_onboarding_get_started" msgid="7674487829030291492">"আৰম্ভ কৰক"</string>
-    <string name="lb_onboarding_accessibility_next" msgid="4213611627196077555">"পৰৱৰ্তী"</string>
-</resources>
diff --git a/leanback/src/main/res/values-be/strings.xml b/leanback/src/main/res/values-be/strings.xml
index a4038d6..2828004 100644
--- a/leanback/src/main/res/values-be/strings.xml
+++ b/leanback/src/main/res/values-be/strings.xml
@@ -21,8 +21,8 @@
     <string name="orb_search_action" msgid="7534843523462177008">"Пошук"</string>
     <string name="lb_search_bar_hint" msgid="4819380969103509861">"Пошук"</string>
     <string name="lb_search_bar_hint_speech" msgid="2795474673510974502">"Прамоўце пошукавы запыт"</string>
-    <string name="lb_search_bar_hint_with_title" msgid="7453744869467668159">"Шукаць тут: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="5851694095153624617">"Прамоўце запыт для пошуку тут: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title" msgid="7453744869467668159">"Шукаць тут <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="5851694095153624617">"Прамоўце пошукавы запыт тут <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_control_display_fast_forward_multiplier" msgid="2721825378927619928">"%1$dX"</string>
     <string name="lb_control_display_rewind_multiplier" msgid="6173753802428649303">"%1$dX"</string>
     <string name="lb_playback_controls_play" msgid="1590369760862605402">"Прайграць"</string>
@@ -53,7 +53,7 @@
     <string name="lb_playback_controls_hidden" msgid="619396299825306757">"Элементы кіравання мультымедыя схаваны. Каб паказаць іх, націсніце d-pad"</string>
     <string name="lb_guidedaction_finish_title" msgid="7747913934287176843">"Завяршыць"</string>
     <string name="lb_guidedaction_continue_title" msgid="1122271825827282965">"Працягнуць"</string>
-    <string name="lb_media_player_error" msgid="8748646000835486516">"Код памылкі MediaPlayer: %1$d (дадатковы: %2$d)"</string>
+    <string name="lb_media_player_error" msgid="8748646000835486516">"Код памылкі MediaPlayer %1$d дадаткова %2$d"</string>
     <string name="lb_onboarding_get_started" msgid="7674487829030291492">"ПАЧАЦЬ"</string>
     <string name="lb_onboarding_accessibility_next" msgid="4213611627196077555">"Далей"</string>
 </resources>
diff --git a/leanback/src/main/res/values-bs/strings.xml b/leanback/src/main/res/values-bs/strings.xml
index d114d87..33111a1 100644
--- a/leanback/src/main/res/values-bs/strings.xml
+++ b/leanback/src/main/res/values-bs/strings.xml
@@ -19,7 +19,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="lb_navigation_menu_contentDescription" msgid="8126335323963415494">"Meni za navigaciju"</string>
     <string name="orb_search_action" msgid="7534843523462177008">"Pretraživanje"</string>
-    <string name="lb_search_bar_hint" msgid="4819380969103509861">"Pretražite"</string>
+    <string name="lb_search_bar_hint" msgid="4819380969103509861">"Traži"</string>
     <string name="lb_search_bar_hint_speech" msgid="2795474673510974502">"Kažite nešto da pokrenete pretragu"</string>
     <string name="lb_search_bar_hint_with_title" msgid="7453744869467668159">"Pretraži <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="5851694095153624617">"Kažite nešto da pokrenete pretragu <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
diff --git a/leanback/src/main/res/values-es/strings.xml b/leanback/src/main/res/values-es/strings.xml
index 53e6797..dc33a6b 100644
--- a/leanback/src/main/res/values-es/strings.xml
+++ b/leanback/src/main/res/values-es/strings.xml
@@ -22,7 +22,7 @@
     <string name="lb_search_bar_hint" msgid="4819380969103509861">"Haz una búsqueda"</string>
     <string name="lb_search_bar_hint_speech" msgid="2795474673510974502">"Habla para buscar"</string>
     <string name="lb_search_bar_hint_with_title" msgid="7453744869467668159">"Busca <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="5851694095153624617">"Habla para buscar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="5851694095153624617">"Busca <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> por voz"</string>
     <string name="lb_control_display_fast_forward_multiplier" msgid="2721825378927619928">"%1$dx"</string>
     <string name="lb_control_display_rewind_multiplier" msgid="6173753802428649303">"%1$dx"</string>
     <string name="lb_playback_controls_play" msgid="1590369760862605402">"Reproducir"</string>
@@ -47,7 +47,7 @@
     <string name="lb_playback_controls_high_quality_disable" msgid="3000046054608531995">"Inhabilitar alta calidad"</string>
     <string name="lb_playback_controls_closed_captioning_enable" msgid="3934392140182327163">"Habilitar subtítulos"</string>
     <string name="lb_playback_controls_closed_captioning_disable" msgid="5508271941331836786">"Inhabilitar subtítulos"</string>
-    <string name="lb_playback_controls_picture_in_picture" msgid="8800305194045609275">"Activar modo imagen en imagen"</string>
+    <string name="lb_playback_controls_picture_in_picture" msgid="8800305194045609275">"Activar modo pantalla en pantalla"</string>
     <string name="lb_playback_time_separator" msgid="6549544638083578695">"/"</string>
     <string name="lb_playback_controls_shown" msgid="7794717158616536936">"Controles multimedia mostrados"</string>
     <string name="lb_playback_controls_hidden" msgid="619396299825306757">"Controles multimedia ocultos (pulsa la cruceta para mostrarlos)"</string>
diff --git a/leanback/src/main/res/values-eu/strings.xml b/leanback/src/main/res/values-eu/strings.xml
index 72c433f..6b7226f 100644
--- a/leanback/src/main/res/values-eu/strings.xml
+++ b/leanback/src/main/res/values-eu/strings.xml
@@ -49,8 +49,8 @@
     <string name="lb_playback_controls_closed_captioning_disable" msgid="5508271941331836786">"Desgaitu azpitituluak"</string>
     <string name="lb_playback_controls_picture_in_picture" msgid="8800305194045609275">"Aktibatu \"Pantaila txiki gainjarri\" modua"</string>
     <string name="lb_playback_time_separator" msgid="6549544638083578695">"/"</string>
-    <string name="lb_playback_controls_shown" msgid="7794717158616536936">"Multimedia-edukia kontrolatzeko aukerak ikusgai"</string>
-    <string name="lb_playback_controls_hidden" msgid="619396299825306757">"Ezkutatuta daude multimedia-edukia kontrolatzeko aukerak. Haiek erakusteko, sakatu nabigazio-gurutzea."</string>
+    <string name="lb_playback_controls_shown" msgid="7794717158616536936">"Multimedia kontrolatzeko aukerak ikusgai"</string>
+    <string name="lb_playback_controls_hidden" msgid="619396299825306757">"Ezkutatuta daude multimedia-edukia kontrolatzeko aukerak. Erakusteko, sakatu nabigazio-gurutzea."</string>
     <string name="lb_guidedaction_finish_title" msgid="7747913934287176843">"Amaitu"</string>
     <string name="lb_guidedaction_continue_title" msgid="1122271825827282965">"Egin aurrera"</string>
     <string name="lb_media_player_error" msgid="8748646000835486516">"MediaPlayer errore-kodea: %1$d (%2$d gehigarria)"</string>
diff --git a/leanback/src/main/res/values-fr-rCA/strings.xml b/leanback/src/main/res/values-fr-rCA/strings.xml
index ad38e94..de3fde5 100644
--- a/leanback/src/main/res/values-fr-rCA/strings.xml
+++ b/leanback/src/main/res/values-fr-rCA/strings.xml
@@ -32,7 +32,7 @@
     <string name="lb_playback_controls_rewind" msgid="1412664391757869774">"Retour arrière"</string>
     <string name="lb_playback_controls_rewind_multiplier" msgid="8651612807713092781">"Retour rapide à %1$dX"</string>
     <string name="lb_playback_controls_skip_next" msgid="4877009494447817003">"Passer à l\'élément suivant"</string>
-    <string name="lb_playback_controls_skip_previous" msgid="3147124289285911980">"Retourner à l\'élément précédent"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="3147124289285911980">"Passer à l\'élément précédent"</string>
     <string name="lb_playback_controls_more_actions" msgid="2827883329510404797">"Autres actions"</string>
     <string name="lb_playback_controls_thumb_up" msgid="8332816524260995892">"Désélectionner la mention « J\'aime »"</string>
     <string name="lb_playback_controls_thumb_up_outline" msgid="1038344559734334272">"Sélectionner la mention « J\'aime »"</string>
diff --git a/leanback/src/main/res/values-ja/strings.xml b/leanback/src/main/res/values-ja/strings.xml
index 96f27e28..22980f1 100644
--- a/leanback/src/main/res/values-ja/strings.xml
+++ b/leanback/src/main/res/values-ja/strings.xml
@@ -43,8 +43,8 @@
     <string name="lb_playback_controls_repeat_one" msgid="7675097479246139440">"1 曲をリピート"</string>
     <string name="lb_playback_controls_shuffle_enable" msgid="7809089255981448519">"シャッフルを有効にする"</string>
     <string name="lb_playback_controls_shuffle_disable" msgid="8182435535948303910">"シャッフルを無効にする"</string>
-    <string name="lb_playback_controls_high_quality_enable" msgid="1862669142355962638">"高画質を有効にする"</string>
-    <string name="lb_playback_controls_high_quality_disable" msgid="3000046054608531995">"高画質を無効にする"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="1862669142355962638">"高品質を有効にする"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="3000046054608531995">"高品質を無効にする"</string>
     <string name="lb_playback_controls_closed_captioning_enable" msgid="3934392140182327163">"クローズド キャプションを有効にする"</string>
     <string name="lb_playback_controls_closed_captioning_disable" msgid="5508271941331836786">"クローズド キャプションを無効にする"</string>
     <string name="lb_playback_controls_picture_in_picture" msgid="8800305194045609275">"ピクチャー イン ピクチャー モードに移動"</string>
diff --git a/leanback/src/main/res/values-ko/strings.xml b/leanback/src/main/res/values-ko/strings.xml
index b1587b91..9eacb53 100644
--- a/leanback/src/main/res/values-ko/strings.xml
+++ b/leanback/src/main/res/values-ko/strings.xml
@@ -40,7 +40,7 @@
     <string name="lb_playback_controls_thumb_down_outline" msgid="2847309435442474470">"싫어요 선택"</string>
     <string name="lb_playback_controls_repeat_none" msgid="5812341701962930499">"반복 안함"</string>
     <string name="lb_playback_controls_repeat_all" msgid="5164826436271322261">"전체 반복"</string>
-    <string name="lb_playback_controls_repeat_one" msgid="7675097479246139440">"한 개 반복"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="7675097479246139440">"한 항목 반복"</string>
     <string name="lb_playback_controls_shuffle_enable" msgid="7809089255981448519">"셔플 사용 설정"</string>
     <string name="lb_playback_controls_shuffle_disable" msgid="8182435535948303910">"셔플 사용 중지"</string>
     <string name="lb_playback_controls_high_quality_enable" msgid="1862669142355962638">"고품질 사용 설정"</string>
diff --git a/leanback/src/main/res/values-mr/strings.xml b/leanback/src/main/res/values-mr/strings.xml
index 07b4e14..b01e273 100644
--- a/leanback/src/main/res/values-mr/strings.xml
+++ b/leanback/src/main/res/values-mr/strings.xml
@@ -29,7 +29,7 @@
     <!-- String.format failed for translation -->
     <!-- no translation found for lb_control_display_rewind_multiplier (6173753802428649303) -->
     <skip />
-    <string name="lb_playback_controls_play" msgid="1590369760862605402">"प्ले"</string>
+    <string name="lb_playback_controls_play" msgid="1590369760862605402">"खेळा"</string>
     <string name="lb_playback_controls_pause" msgid="1769131316742618433">"विराम द्या"</string>
     <string name="lb_playback_controls_fast_forward" msgid="8966769845721269304">"पुढे ढकला"</string>
     <string name="lb_playback_controls_fast_forward_multiplier" msgid="801276177839339511">"फास्ट फॉरवर्ड %1$d"</string>
@@ -38,10 +38,10 @@
     <string name="lb_playback_controls_skip_next" msgid="4877009494447817003">"पुढील वगळा"</string>
     <string name="lb_playback_controls_skip_previous" msgid="3147124289285911980">"मागील वगळा"</string>
     <string name="lb_playback_controls_more_actions" msgid="2827883329510404797">"आणखी क्रिया"</string>
-    <string name="lb_playback_controls_thumb_up" msgid="8332816524260995892">"थंब अप निवड रद्द करा"</string>
-    <string name="lb_playback_controls_thumb_up_outline" msgid="1038344559734334272">"थंब अप निवडा"</string>
-    <string name="lb_playback_controls_thumb_down" msgid="5075744418630733006">"थंब डाउन निवड रद्द करा"</string>
-    <string name="lb_playback_controls_thumb_down_outline" msgid="2847309435442474470">"थंब डाउन निवडा"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="8332816524260995892">"वर अंगठा निवड रद्द करा"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1038344559734334272">"वर अंगठा निवडा"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="5075744418630733006">"खाली अंगठा निवड रद्द करा"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2847309435442474470">"खाली अंगठा निवडा"</string>
     <string name="lb_playback_controls_repeat_none" msgid="5812341701962930499">"काहीही रिपीट करू नका"</string>
     <string name="lb_playback_controls_repeat_all" msgid="5164826436271322261">"सर्व रिपीट करा"</string>
     <string name="lb_playback_controls_repeat_one" msgid="7675097479246139440">"एक रिपीट करा"</string>
diff --git a/leanback/src/main/res/values-or/strings.xml b/leanback/src/main/res/values-or/strings.xml
deleted file mode 100644
index ce6d1ea..0000000
--- a/leanback/src/main/res/values-or/strings.xml
+++ /dev/null
@@ -1,59 +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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="lb_navigation_menu_contentDescription" msgid="8126335323963415494">"ନେଭିଗେଶନ୍ ମେନୁ"</string>
-    <string name="orb_search_action" msgid="7534843523462177008">"ଖୋଜିବା କାମ"</string>
-    <string name="lb_search_bar_hint" msgid="4819380969103509861">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
-    <string name="lb_search_bar_hint_speech" msgid="2795474673510974502">"ଖୋଜିବା ପାଇଁ କୁହନ୍ତୁ"</string>
-    <string name="lb_search_bar_hint_with_title" msgid="7453744869467668159">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ଖୋଜନ୍ତୁ"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="5851694095153624617">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ଖୋଜିବା ପାଇଁ କୁହନ୍ତୁ"</string>
-    <string name="lb_control_display_fast_forward_multiplier" msgid="2721825378927619928">"%1$dX"</string>
-    <string name="lb_control_display_rewind_multiplier" msgid="6173753802428649303">"%1$dX"</string>
-    <string name="lb_playback_controls_play" msgid="1590369760862605402">"ଚଲାନ୍ତୁ"</string>
-    <string name="lb_playback_controls_pause" msgid="1769131316742618433">"ପଜ୍‍ କରନ୍ତୁ"</string>
-    <string name="lb_playback_controls_fast_forward" msgid="8966769845721269304">"ଫାଷ୍ଟ ଫର୍‌ୱାର୍ଡ"</string>
-    <string name="lb_playback_controls_fast_forward_multiplier" msgid="801276177839339511">"%1$dX ବେଗରେ ଫାଷ୍ଟ ଫରୱାର୍ଡ"</string>
-    <string name="lb_playback_controls_rewind" msgid="1412664391757869774">"ରିୱାଇଣ୍ଡ"</string>
-    <string name="lb_playback_controls_rewind_multiplier" msgid="8651612807713092781">"%1$dX ବେଗରେ ରିୱାଇଣ୍ଡ କରନ୍ତୁ"</string>
-    <string name="lb_playback_controls_skip_next" msgid="4877009494447817003">"ପରବର୍ତ୍ତୀକୁ ଯାଆନ୍ତୁ"</string>
-    <string name="lb_playback_controls_skip_previous" msgid="3147124289285911980">"ପୂର୍ବଟିକୁ ଛାଡ଼ିଦିଅନ୍ତୁ"</string>
-    <string name="lb_playback_controls_more_actions" msgid="2827883329510404797">"ଅଧିକ ଗତିବିଧି"</string>
-    <string name="lb_playback_controls_thumb_up" msgid="8332816524260995892">"ପସନ୍ଦକୁ ଚୟନ କରନ୍ତୁ ନାହିଁ"</string>
-    <string name="lb_playback_controls_thumb_up_outline" msgid="1038344559734334272">"ପସନ୍ଦକୁ ଚୟନ କରନ୍ତୁ"</string>
-    <string name="lb_playback_controls_thumb_down" msgid="5075744418630733006">"ପସନ୍ଦହୀନକୁ ଚୟନ କରନ୍ତୁ ନାହିଁ"</string>
-    <string name="lb_playback_controls_thumb_down_outline" msgid="2847309435442474470">"ପସନ୍ଦହୀନକୁ ଚୟନ କରନ୍ତୁ"</string>
-    <string name="lb_playback_controls_repeat_none" msgid="5812341701962930499">"କୌଣସିଟି ଦୋହରାନ୍ତୁ ନାହିଁ"</string>
-    <string name="lb_playback_controls_repeat_all" msgid="5164826436271322261">"ସବୁଗୁଡ଼ିକୁ ଦୋହରାନ୍ତୁ"</string>
-    <string name="lb_playback_controls_repeat_one" msgid="7675097479246139440">"ଗୋଟିଏ ଦୋହରାନ୍ତୁ"</string>
-    <string name="lb_playback_controls_shuffle_enable" msgid="7809089255981448519">"ଅଦଳବଦଳକୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
-    <string name="lb_playback_controls_shuffle_disable" msgid="8182435535948303910">"ଅଦଳବଦଳକୁ ଅକ୍ଷମ କରନ୍ତୁ"</string>
-    <string name="lb_playback_controls_high_quality_enable" msgid="1862669142355962638">"ଉଚ୍ଚ କ୍ୱାଲିଟୀକୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
-    <string name="lb_playback_controls_high_quality_disable" msgid="3000046054608531995">"ଉଚ୍ଚ କ୍ୱାଲିଟୀକୁ ଅକ୍ଷମ କରନ୍ତୁ"</string>
-    <string name="lb_playback_controls_closed_captioning_enable" msgid="3934392140182327163">"କ୍ଲୋଜଡ୍‍ କ୍ୟାପ୍ସନିଙ୍ଗକୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
-    <string name="lb_playback_controls_closed_captioning_disable" msgid="5508271941331836786">"କ୍ଲୋଜଡ୍‍ କ୍ୟାପ୍ସନିଙ୍ଗକୁ ଅକ୍ଷମ କରନ୍ତୁ"</string>
-    <string name="lb_playback_controls_picture_in_picture" msgid="8800305194045609275">"ଛବି ଭିତରେ ଛବି ମୋଡ୍‌ରେ ପ୍ରବେଶ କରନ୍ତୁ"</string>
-    <string name="lb_playback_time_separator" msgid="6549544638083578695">"/"</string>
-    <string name="lb_playback_controls_shown" msgid="7794717158616536936">"ମିଡିଆ ନିୟନ୍ତ୍ରଣ ଦେଖାଯାଇଛି"</string>
-    <string name="lb_playback_controls_hidden" msgid="619396299825306757">"ମିଡିଆ ନିୟନ୍ତ୍ରଣ ଲୁଚିଯାଇଛି, ଦେଖାଇବାକୁ ଡି-ପ୍ୟାଡ୍‍ ଦବାନ୍ତୁ"</string>
-    <string name="lb_guidedaction_finish_title" msgid="7747913934287176843">"ସମାପ୍ତ କରନ୍ତୁ"</string>
-    <string name="lb_guidedaction_continue_title" msgid="1122271825827282965">"ଜାରି ରଖନ୍ତୁ"</string>
-    <string name="lb_media_player_error" msgid="8748646000835486516">"MediaPlayer ତ୍ରୁଟି କୋଡ୍‍ %1$d ଅତିରିକ୍ତ %2$d"</string>
-    <string name="lb_onboarding_get_started" msgid="7674487829030291492">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
-    <string name="lb_onboarding_accessibility_next" msgid="4213611627196077555">"ପରବର୍ତ୍ତୀ"</string>
-</resources>
diff --git a/leanback/src/main/res/values-pt-rBR/strings.xml b/leanback/src/main/res/values-pt-rBR/strings.xml
index 6acead9..01d56cb 100644
--- a/leanback/src/main/res/values-pt-rBR/strings.xml
+++ b/leanback/src/main/res/values-pt-rBR/strings.xml
@@ -41,8 +41,8 @@
     <string name="lb_playback_controls_repeat_none" msgid="5812341701962930499">"Não repetir"</string>
     <string name="lb_playback_controls_repeat_all" msgid="5164826436271322261">"Repetir tudo"</string>
     <string name="lb_playback_controls_repeat_one" msgid="7675097479246139440">"Repetir um item"</string>
-    <string name="lb_playback_controls_shuffle_enable" msgid="7809089255981448519">"Ativar ordem aleatória"</string>
-    <string name="lb_playback_controls_shuffle_disable" msgid="8182435535948303910">"Desativar ordem aleatória"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="7809089255981448519">"Ativar reprodução aleatória"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8182435535948303910">"Desativar reprodução aleatória"</string>
     <string name="lb_playback_controls_high_quality_enable" msgid="1862669142355962638">"Ativar alta qualidade"</string>
     <string name="lb_playback_controls_high_quality_disable" msgid="3000046054608531995">"Desativar alta qualidade"</string>
     <string name="lb_playback_controls_closed_captioning_enable" msgid="3934392140182327163">"Ativar closed captioning"</string>
diff --git a/leanback/src/main/res/values-pt/strings.xml b/leanback/src/main/res/values-pt/strings.xml
index 6acead9..01d56cb 100644
--- a/leanback/src/main/res/values-pt/strings.xml
+++ b/leanback/src/main/res/values-pt/strings.xml
@@ -41,8 +41,8 @@
     <string name="lb_playback_controls_repeat_none" msgid="5812341701962930499">"Não repetir"</string>
     <string name="lb_playback_controls_repeat_all" msgid="5164826436271322261">"Repetir tudo"</string>
     <string name="lb_playback_controls_repeat_one" msgid="7675097479246139440">"Repetir um item"</string>
-    <string name="lb_playback_controls_shuffle_enable" msgid="7809089255981448519">"Ativar ordem aleatória"</string>
-    <string name="lb_playback_controls_shuffle_disable" msgid="8182435535948303910">"Desativar ordem aleatória"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="7809089255981448519">"Ativar reprodução aleatória"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8182435535948303910">"Desativar reprodução aleatória"</string>
     <string name="lb_playback_controls_high_quality_enable" msgid="1862669142355962638">"Ativar alta qualidade"</string>
     <string name="lb_playback_controls_high_quality_disable" msgid="3000046054608531995">"Desativar alta qualidade"</string>
     <string name="lb_playback_controls_closed_captioning_enable" msgid="3934392140182327163">"Ativar closed captioning"</string>
diff --git a/leanback/src/main/res/values-te/strings.xml b/leanback/src/main/res/values-te/strings.xml
index e4ee49e6..312b570 100644
--- a/leanback/src/main/res/values-te/strings.xml
+++ b/leanback/src/main/res/values-te/strings.xml
@@ -55,5 +55,5 @@
     <string name="lb_guidedaction_continue_title" msgid="1122271825827282965">"కొనసాగించండి"</string>
     <string name="lb_media_player_error" msgid="8748646000835486516">"MediaPlayer ఎర్రర్ కోడ్ %1$d అదనంగా %2$d"</string>
     <string name="lb_onboarding_get_started" msgid="7674487829030291492">"ప్రారంభించు"</string>
-    <string name="lb_onboarding_accessibility_next" msgid="4213611627196077555">"తర్వాత"</string>
+    <string name="lb_onboarding_accessibility_next" msgid="4213611627196077555">"తదుపరి"</string>
 </resources>
diff --git a/leanback/src/main/res/values-uz/strings.xml b/leanback/src/main/res/values-uz/strings.xml
index 95e0b67..50a86af 100644
--- a/leanback/src/main/res/values-uz/strings.xml
+++ b/leanback/src/main/res/values-uz/strings.xml
@@ -21,8 +21,8 @@
     <string name="orb_search_action" msgid="7534843523462177008">"Qidiruv amali"</string>
     <string name="lb_search_bar_hint" msgid="4819380969103509861">"Qidiruv"</string>
     <string name="lb_search_bar_hint_speech" msgid="2795474673510974502">"Qidirish uchun gapiring"</string>
-    <string name="lb_search_bar_hint_with_title" msgid="7453744869467668159">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ichidan qidirish"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="5851694095153624617">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ichidan qidirish uchun gapiring"</string>
+    <string name="lb_search_bar_hint_with_title" msgid="7453744869467668159">"Qidirish: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="5851694095153624617">"Qidirish uchun ayting: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_control_display_fast_forward_multiplier" msgid="2721825378927619928">"%1$dX"</string>
     <string name="lb_control_display_rewind_multiplier" msgid="6173753802428649303">"%1$dX"</string>
     <string name="lb_playback_controls_play" msgid="1590369760862605402">"Ijro"</string>
@@ -39,14 +39,14 @@
     <string name="lb_playback_controls_thumb_down" msgid="5075744418630733006">"Salbiy baho tanlovini bekor qilish"</string>
     <string name="lb_playback_controls_thumb_down_outline" msgid="2847309435442474470">"Salbiy bahoni tanlash"</string>
     <string name="lb_playback_controls_repeat_none" msgid="5812341701962930499">"Takrorlamaslik"</string>
-    <string name="lb_playback_controls_repeat_all" msgid="5164826436271322261">"Hammasini takrorlash"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="5164826436271322261">"Barchasini takrorlash"</string>
     <string name="lb_playback_controls_repeat_one" msgid="7675097479246139440">"Bir marta takrorlash"</string>
     <string name="lb_playback_controls_shuffle_enable" msgid="7809089255981448519">"Aralashtirish funksiyasini yoqish"</string>
-    <string name="lb_playback_controls_shuffle_disable" msgid="8182435535948303910">"Aralashtirmaslik"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8182435535948303910">"Aralashtirish funksiyasini o‘chirish"</string>
     <string name="lb_playback_controls_high_quality_enable" msgid="1862669142355962638">"Yuqori sifatni yoqish"</string>
-    <string name="lb_playback_controls_high_quality_disable" msgid="3000046054608531995">"Yuqori sifatda ijro qilmaslik"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="3000046054608531995">"Yuqori sifatni o‘chirib qo‘yish"</string>
     <string name="lb_playback_controls_closed_captioning_enable" msgid="3934392140182327163">"Taglavhalarni yoqish"</string>
-    <string name="lb_playback_controls_closed_captioning_disable" msgid="5508271941331836786">"Taglavhalarni chiqarmaslik"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="5508271941331836786">"Taglavhalarni o‘chirib qo‘yish"</string>
     <string name="lb_playback_controls_picture_in_picture" msgid="8800305194045609275">"Tasvir ustida tasvir rejimiga kirish"</string>
     <string name="lb_playback_time_separator" msgid="6549544638083578695">"/"</string>
     <string name="lb_playback_controls_shown" msgid="7794717158616536936">"Boshqaruv elementlari ochiq"</string>
diff --git a/leanback/src/main/res/values-zh-rCN/strings.xml b/leanback/src/main/res/values-zh-rCN/strings.xml
index 4e6cbd4..9ba86b4 100644
--- a/leanback/src/main/res/values-zh-rCN/strings.xml
+++ b/leanback/src/main/res/values-zh-rCN/strings.xml
@@ -54,6 +54,6 @@
     <string name="lb_guidedaction_finish_title" msgid="7747913934287176843">"完成"</string>
     <string name="lb_guidedaction_continue_title" msgid="1122271825827282965">"继续"</string>
     <string name="lb_media_player_error" msgid="8748646000835486516">"MediaPlayer 错误代码:%1$d extra %2$d"</string>
-    <string name="lb_onboarding_get_started" msgid="7674487829030291492">"开始使用"</string>
+    <string name="lb_onboarding_get_started" msgid="7674487829030291492">"开始"</string>
     <string name="lb_onboarding_accessibility_next" msgid="4213611627196077555">"继续"</string>
 </resources>
diff --git a/leanback/src/main/res/values-zh-rTW/strings.xml b/leanback/src/main/res/values-zh-rTW/strings.xml
index 9aea4d2..bcaf11e 100644
--- a/leanback/src/main/res/values-zh-rTW/strings.xml
+++ b/leanback/src/main/res/values-zh-rTW/strings.xml
@@ -34,10 +34,10 @@
     <string name="lb_playback_controls_skip_next" msgid="4877009494447817003">"跳至下一個項目"</string>
     <string name="lb_playback_controls_skip_previous" msgid="3147124289285911980">"跳至上一個項目"</string>
     <string name="lb_playback_controls_more_actions" msgid="2827883329510404797">"更多動作"</string>
-    <string name="lb_playback_controls_thumb_up" msgid="8332816524260995892">"取消選取「喜歡」"</string>
-    <string name="lb_playback_controls_thumb_up_outline" msgid="1038344559734334272">"選取「喜歡」"</string>
-    <string name="lb_playback_controls_thumb_down" msgid="5075744418630733006">"取消選取「不喜歡」"</string>
-    <string name="lb_playback_controls_thumb_down_outline" msgid="2847309435442474470">"選取「不喜歡」"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="8332816524260995892">"取消選取喜歡"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1038344559734334272">"選取喜歡"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="5075744418630733006">"取消選取不喜歡"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2847309435442474470">"選取不喜歡"</string>
     <string name="lb_playback_controls_repeat_none" msgid="5812341701962930499">"不重複播放"</string>
     <string name="lb_playback_controls_repeat_all" msgid="5164826436271322261">"重複播放所有項目"</string>
     <string name="lb_playback_controls_repeat_one" msgid="7675097479246139440">"重複播放單一項目"</string>
diff --git a/lifecycle/viewmodel/ktx/build.gradle b/lifecycle/viewmodel/ktx/build.gradle
deleted file mode 100644
index a963911..0000000
--- a/lifecycle/viewmodel/ktx/build.gradle
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 androidx.build.dependencies.DependenciesKt.*
-import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
-
-plugins {
-    id("SupportAndroidLibraryPlugin")
-    id("org.jetbrains.kotlin.android")
-}
-
-android {
-    buildTypes {
-        debug {
-            testCoverageEnabled = false // Breaks Kotlin compiler.
-        }
-    }
-}
-
-dependencies {
-    api(project(":lifecycle:lifecycle-viewmodel"))
-    api(KOTLIN_STDLIB)
-
-    testImplementation(JUNIT)
-    testImplementation(TEST_RUNNER)
-}
-
-supportLibrary {
-    name = "Android Lifecycle ViewModel Kotlin Extensions"
-    publish = true
-    mavenVersion = LibraryVersions.LIFECYCLES_VIEWMODEL
-    mavenGroup = LibraryGroups.LIFECYCLE
-    inceptionYear = "2018"
-    description = "Kotlin extensions for 'viewmodel' artifact"
-}
diff --git a/lifecycle/viewmodel/ktx/src/main/AndroidManifest.xml b/lifecycle/viewmodel/ktx/src/main/AndroidManifest.xml
deleted file mode 100644
index 75b1d20..0000000
--- a/lifecycle/viewmodel/ktx/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT 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 package="androidx.lifecycle.viewmodel.ktx"/>
diff --git a/lifecycle/viewmodel/ktx/src/main/java/androidx/lifecycle/ViewModelProvider.kt b/lifecycle/viewmodel/ktx/src/main/java/androidx/lifecycle/ViewModelProvider.kt
deleted file mode 100644
index bc42e1b..0000000
--- a/lifecycle/viewmodel/ktx/src/main/java/androidx/lifecycle/ViewModelProvider.kt
+++ /dev/null
@@ -1,28 +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.lifecycle
-
-import androidx.annotation.MainThread
-
-/**
- * Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or
- * an activity), associated with this `ViewModelProvider`.
- *
- * @see ViewModelProvider.get(Class)
- */
-@MainThread
-inline fun <reified VM : ViewModel> ViewModelProvider.get() = get(VM::class.java)
diff --git a/lifecycle/viewmodel/ktx/src/test/java/androidx/lifecycle/ViewModelProviderTest.kt b/lifecycle/viewmodel/ktx/src/test/java/androidx/lifecycle/ViewModelProviderTest.kt
deleted file mode 100644
index e8e76ce..0000000
--- a/lifecycle/viewmodel/ktx/src/test/java/androidx/lifecycle/ViewModelProviderTest.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.lifecycle
-
-import android.support.test.filters.SmallTest
-import org.junit.Assert.assertNotNull
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-@SmallTest
-class ViewModelProviderTest {
-    class TestViewModel : ViewModel()
-
-    @Test
-    fun providerReifiedGet() {
-        val factory = object : ViewModelProvider.Factory {
-            override fun <T : ViewModel> create(modelClass: Class<T>) = modelClass.newInstance()
-        }
-        val provider = ViewModelProvider(ViewModelStore(), factory)
-
-        val viewModel = provider.get<TestViewModel>()
-        assertNotNull(viewModel)
-    }
-}
diff --git a/media-widget/api/current.txt b/media-widget/api/current.txt
deleted file mode 100644
index d81423b..0000000
--- a/media-widget/api/current.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-package androidx.media.widget {
-
-  public class MediaControlView2 extends android.view.ViewGroup {
-    ctor public MediaControlView2(android.content.Context);
-    ctor public MediaControlView2(android.content.Context, android.util.AttributeSet);
-    ctor public MediaControlView2(android.content.Context, android.util.AttributeSet, int);
-    method public void onMeasure(int, int);
-    method public void requestPlayButtonFocus();
-    method public void setOnFullScreenListener(androidx.media.widget.MediaControlView2.OnFullScreenListener);
-  }
-
-  public static abstract interface MediaControlView2.OnFullScreenListener {
-    method public abstract void onFullScreen(android.view.View, boolean);
-  }
-
-  public class VideoView2 extends android.view.ViewGroup {
-    ctor public VideoView2(android.content.Context);
-    ctor public VideoView2(android.content.Context, android.util.AttributeSet);
-    ctor public VideoView2(android.content.Context, android.util.AttributeSet, int);
-    method public androidx.media.widget.MediaControlView2 getMediaControlView2();
-    method public float getSpeed();
-    method public int getViewType();
-    method public boolean isSubtitleEnabled();
-    method public void onAttachedToWindow();
-    method public void onDetachedFromWindow();
-    method public void onMeasure(int, int);
-    method public void setAudioAttributes(android.media.AudioAttributes);
-    method public void setAudioFocusRequest(int);
-    method public void setMediaControlView2(androidx.media.widget.MediaControlView2, long);
-    method public void setSpeed(float);
-    method public void setSubtitleEnabled(boolean);
-    method public void setVideoUri(android.net.Uri, java.util.Map<java.lang.String, java.lang.String>);
-    method public void setViewType(int);
-    field public static final int VIEW_TYPE_SURFACEVIEW = 0; // 0x0
-    field public static final int VIEW_TYPE_TEXTUREVIEW = 1; // 0x1
-  }
-
-}
-
diff --git a/media-widget/build.gradle b/media-widget/build.gradle
index e6ff65d..de3f9d9 100644
--- a/media-widget/build.gradle
+++ b/media-widget/build.gradle
@@ -37,13 +37,10 @@
 }
 
 supportLibrary {
-    name = "Android Support Media Widget"
+    name = "Android Media Support Library"
     publish = true
     mavenVersion = LibraryVersions.SUPPORT_LIBRARY
     mavenGroup = LibraryGroups.MEDIA
     inceptionYear = "2011"
-    description = "Android Support Media Widget"
-    minSdkVersion = 19
-    failOnDeprecationWarnings = false
-    failOnDeprecationWarnings = false
+    description = "Android Media Support Library"
 }
diff --git a/media-widget/src/androidTest/AndroidManifest.xml b/media-widget/src/androidTest/AndroidManifest.xml
index 5304a48..dd6e9e0 100644
--- a/media-widget/src/androidTest/AndroidManifest.xml
+++ b/media-widget/src/androidTest/AndroidManifest.xml
@@ -1,26 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright 2018 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
+  ~ Copyright 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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="androidx.media.widget.test">
     <uses-sdk android:targetSdkVersion="${target-sdk-version}"/>
 
     <application>
         <activity android:name="androidx.media.widget.VideoView2TestActivity"
-            android:theme="@style/Theme.AppCompat"
             android:configChanges="keyboardHidden|orientation|screenSize"
             android:label="VideoView2TestActivity">
             <intent-filter>
diff --git a/media-widget/src/androidTest/java/androidx/media/widget/VideoView2Test.java b/media-widget/src/androidTest/java/androidx/media/widget/VideoView2Test.java
index da38bd2..2876e47 100644
--- a/media-widget/src/androidTest/java/androidx/media/widget/VideoView2Test.java
+++ b/media-widget/src/androidTest/java/androidx/media/widget/VideoView2Test.java
@@ -61,7 +61,7 @@
 /**
  * Test {@link VideoView2}.
  */
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.P) // TODO: KITKAT
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP) // TODO: KITKAT
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 public class VideoView2Test {
@@ -107,17 +107,10 @@
             @Override
             public void run() {
                 // Keep screen on while testing.
-                if (Build.VERSION.SDK_INT >= 27) {
-                    mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-                    mActivity.setTurnScreenOn(true);
-                    mActivity.setShowWhenLocked(true);
-                    mKeyguardManager.requestDismissKeyguard(mActivity, null);
-                } else {
-                    mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
-                            | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
-                            | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
-                            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
-                }
+                mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+                mActivity.setTurnScreenOn(true);
+                mActivity.setShowWhenLocked(true);
+                mKeyguardManager.requestDismissKeyguard(mActivity, null);
             }
         });
         mInstrumentation.waitForIdleSync();
diff --git a/media-widget/src/androidTest/java/androidx/media/widget/VideoView2TestActivity.java b/media-widget/src/androidTest/java/androidx/media/widget/VideoView2TestActivity.java
index 912d336..d6a3ebc 100644
--- a/media-widget/src/androidTest/java/androidx/media/widget/VideoView2TestActivity.java
+++ b/media-widget/src/androidTest/java/androidx/media/widget/VideoView2TestActivity.java
@@ -16,15 +16,15 @@
 
 package androidx.media.widget;
 
+import android.app.Activity;
 import android.os.Bundle;
 
-import androidx.fragment.app.FragmentActivity;
 import androidx.media.widget.test.R;
 
 /**
  * A minimal application for {@link VideoView2} test.
  */
-public class VideoView2TestActivity extends FragmentActivity {
+public class VideoView2TestActivity extends Activity {
     /**
      * Called with the activity is first created.
      */
diff --git a/media-widget/src/main/java/androidx/media/widget/BaseLayout.java b/media-widget/src/main/java/androidx/media/widget/BaseLayout.java
index 982513a..0b6988a 100644
--- a/media-widget/src/main/java/androidx/media/widget/BaseLayout.java
+++ b/media-widget/src/main/java/androidx/media/widget/BaseLayout.java
@@ -39,7 +39,7 @@
     }
 
     BaseLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, 0);
     }
 
     BaseLayout(@NonNull Context context, @Nullable AttributeSet attrs,
diff --git a/media-widget/src/main/java/androidx/media/widget/MediaControlView2.java b/media-widget/src/main/java/androidx/media/widget/MediaControlView2.java
index a8371f2..89fa946 100644
--- a/media-widget/src/main/java/androidx/media/widget/MediaControlView2.java
+++ b/media-widget/src/main/java/androidx/media/widget/MediaControlView2.java
@@ -27,7 +27,6 @@
 import android.support.v4.media.session.PlaybackStateCompat;
 import android.util.AttributeSet;
 import android.view.Gravity;
-import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -52,8 +51,6 @@
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.media.SessionToken2;
-import androidx.mediarouter.app.MediaRouteButton;
-import androidx.mediarouter.media.MediaRouteSelector;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -63,34 +60,41 @@
 import java.util.List;
 import java.util.Locale;
 
+// import androidx.mediarouter.app.MediaRouteButton;
+// import androidx.mediarouter.media.MediaRouter;
+// import androidx.mediarouter.media.MediaRouteSelector;
+
 /**
- * A View that contains the controls for {@link android.media.MediaPlayer}.
- * It provides a wide range of buttons that serve the following functions: play/pause,
- * rewind/fast-forward, skip to next/previous, select subtitle track, enter/exit full screen mode,
- * adjust video quality, select audio track, mute/unmute, and adjust playback speed.
+ * @hide
+ * A View that contains the controls for MediaPlayer2.
+ * It provides a wide range of UI including buttons such as "Play/Pause", "Rewind", "Fast Forward",
+ * "Subtitle", "Full Screen", and it is also possible to add multiple custom buttons.
  *
  * <p>
  * <em> MediaControlView2 can be initialized in two different ways: </em>
- * 1) When initializing {@link VideoView2} a default MediaControlView2 is created.
- * 2) Initialize MediaControlView2 programmatically and add it to a {@link ViewGroup} instance.
+ * 1) When VideoView2 is initialized, it automatically initializes a MediaControlView2 instance and
+ * adds it to the view.
+ * 2) Initialize MediaControlView2 programmatically and add it to a ViewGroup instance.
  *
  * In the first option, VideoView2 automatically connects MediaControlView2 to MediaController,
- * which is necessary to communicate with MediaSession. In the second option, however, the
- * developer needs to manually retrieve a MediaController instance from MediaSession and set it to
- * MediaControlView2.
+ * which is necessary to communicate with MediaSession2. In the second option, however, the
+ * developer needs to manually retrieve a MediaController instance and set it to MediaControlView2
+ * by calling setController(MediaController controller).
  *
  * <p>
  * There is no separate method that handles the show/hide behavior for MediaControlView2. Instead,
- * one can directly change the visibility of this view by calling {@link View#setVisibility(int)}.
- * The values supported are View.VISIBLE and View.GONE.
+ * one can directly change the visibility of this view by calling View.setVisibility(int). The
+ * values supported are View.VISIBLE and View.GONE.
+ * In addition, the following customization is supported:
+ * Set focus to the play/pause button by calling requestPlayButtonFocus().
  *
  * <p>
- * In addition, the following customizations are supported:
- * 1) Set focus to the play/pause button by calling requestPlayButtonFocus().
- * 2) Set full screen mode
- *
+ * It is also possible to add custom buttons with custom icons and actions inside MediaControlView2.
+ * Those buttons will be shown when the overflow button is clicked.
+ * See VideoView2#setCustomActions for more details on how to add.
  */
 @RequiresApi(21) // TODO correct minSdk API use incompatibilities and remove before release.
+@RestrictTo(LIBRARY_GROUP)
 public class MediaControlView2 extends BaseLayout {
     /**
      * @hide
@@ -181,6 +185,10 @@
 
     private static final String TAG = "MediaControlView2";
 
+    static final String ARGUMENT_KEY_FULLSCREEN = "fullScreen";
+
+    // TODO: Make these constants public api to support custom video view.
+    // TODO: Combine these constants into one regarding TrackInfo.
     static final String KEY_VIDEO_TRACK_COUNT = "VideoTrackCount";
     static final String KEY_AUDIO_TRACK_COUNT = "AudioTrackCount";
     static final String KEY_SUBTITLE_TRACK_COUNT = "SubtitleTrackCount";
@@ -188,6 +196,8 @@
     static final String KEY_SELECTED_AUDIO_INDEX = "SelectedAudioIndex";
     static final String KEY_SELECTED_SUBTITLE_INDEX = "SelectedSubtitleIndex";
     static final String EVENT_UPDATE_TRACK_STATUS = "UpdateTrackStatus";
+
+    // TODO: Remove this once integrating with MediaSession2 & MediaMetadata2
     static final String KEY_STATE_IS_ADVERTISEMENT = "MediaTypeAdvertisement";
     static final String EVENT_UPDATE_MEDIA_TYPE_STATUS = "UpdateMediaTypeStatus";
 
@@ -195,6 +205,8 @@
     static final String COMMAND_SHOW_SUBTITLE = "showSubtitle";
     // String for sending command to hide subtitle to MediaSession.
     static final String COMMAND_HIDE_SUBTITLE = "hideSubtitle";
+    // TODO: remove once the implementation is revised
+    public static final String COMMAND_SET_FULLSCREEN = "setFullscreen";
     // String for sending command to select audio track to MediaSession.
     static final String COMMAND_SELECT_AUDIO_TRACK = "SelectTrack";
     // String for sending command to set playback speed to MediaSession.
@@ -218,6 +230,7 @@
 
     private static final int SIZE_TYPE_EMBEDDED = 0;
     private static final int SIZE_TYPE_FULL = 1;
+    // TODO: add support for Minimal size type.
     private static final int SIZE_TYPE_MINIMAL = 2;
 
     private static final int MAX_PROGRESS = 1000;
@@ -233,7 +246,6 @@
     private MediaControllerCompat.TransportControls mControls;
     private PlaybackStateCompat mPlaybackState;
     private MediaMetadataCompat mMetadata;
-    private OnFullScreenListener mOnFullScreenListener;
     private int mDuration;
     private int mPrevState;
     private int mPrevWidth;
@@ -249,7 +261,8 @@
     private int mSelectedSpeedIndex;
     private int mEmbeddedSettingsItemWidth;
     private int mFullSettingsItemWidth;
-    private int mSettingsItemHeight;
+    private int mEmbeddedSettingsItemHeight;
+    private int mFullSettingsItemHeight;
     private int mSettingsWindowMargin;
     private int mMediaType;
     private int mSizeType;
@@ -271,8 +284,9 @@
     private TextView mTitleView;
     private View mAdExternalLink;
     private ImageButton mBackButton;
-    private MediaRouteButton mRouteButton;
-    private MediaRouteSelector mRouteSelector;
+    // TODO (b/77158231) revive
+    // private MediaRouteButton mRouteButton;
+    // private MediaRouteSelector mRouteSelector;
 
     // Relating to Center View
     private ViewGroup mCenterView;
@@ -340,9 +354,20 @@
 
     public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs,
             int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
+        this(context, attrs, defStyleAttr, 0);
+    }
 
-        mResources = context.getResources();
+    public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+//        super((instance, superProvider, privateProvider) ->
+//                ApiLoader.getProvider().createMediaControlView2(
+//                        (MediaControlView2) instance, superProvider, privateProvider,
+//                        attrs, defStyleAttr, defStyleRes),
+//                context, attrs, defStyleAttr, defStyleRes);
+//        mProvider.initialize(attrs, defStyleAttr, defStyleRes);
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        mResources = getContext().getResources();
         // Inflate MediaControlView2 from XML
         mRoot = makeControllerView();
         addView(mRoot);
@@ -350,10 +375,9 @@
 
     /**
      * Sets MediaSession2 token to control corresponding MediaSession2.
-     * @hide
      */
-    @RestrictTo(LIBRARY_GROUP)
     public void setMediaSessionToken(SessionToken2 token) {
+        //mProvider.setMediaSessionToken_impl(token);
     }
 
     /**
@@ -361,20 +385,17 @@
      * @param l The callback that will be run
      */
     public void setOnFullScreenListener(OnFullScreenListener l) {
-        mOnFullScreenListener = l;
+        //mProvider.setOnFullScreenListener_impl(l);
     }
 
     /**
-     * Sets MediaController instance to MediaControlView2, which makes it possible to send and
-     * receive data between MediaControlView2 and VideoView2. This method does not need to be called
-     * when MediaControlView2 is initialized with VideoView2.
      * @hide TODO: remove once the implementation is revised
      */
     @RestrictTo(LIBRARY_GROUP)
     public void setController(MediaControllerCompat controller) {
         mController = controller;
         if (controller != null) {
-            mControls = mController.getTransportControls();
+            mControls = controller.getTransportControls();
             // Set mMetadata and mPlaybackState to existing MediaSession variables since they may
             // be called before the callback is called
             mPlaybackState = mController.getPlaybackState();
@@ -408,6 +429,8 @@
      */
     @RestrictTo(LIBRARY_GROUP)
     public void setButtonVisibility(@Button int button, /*@Visibility*/ int visibility) {
+        // TODO: add member variables for Fast-Forward/Prvious/Rewind buttons to save visibility in
+        // order to prevent being overriden inside updateLayout().
         switch (button) {
             case MediaControlView2.BUTTON_PLAY_PAUSE:
                 if (mPlayPauseButton != null && canPause()) {
@@ -494,6 +517,7 @@
         return false;
     }
 
+    // TODO: Should this function be removed?
     @Override
     public boolean onTrackballEvent(MotionEvent ev) {
         return false;
@@ -522,13 +546,17 @@
             manager.getDefaultDisplay().getSize(screenSize);
             int screenWidth = screenSize.x;
             int screenHeight = screenSize.y;
-            int iconSize = mResources.getDimensionPixelSize(R.dimen.mcv2_icon_size);
+            int fullIconSize = mResources.getDimensionPixelSize(R.dimen.mcv2_full_icon_size);
+            int embeddedIconSize = mResources.getDimensionPixelSize(
+                    R.dimen.mcv2_embedded_icon_size);
+            int marginSize = mResources.getDimensionPixelSize(R.dimen.mcv2_icon_margin);
 
+            // TODO: add support for Advertisement Mode.
             if (mMediaType == MEDIA_TYPE_DEFAULT) {
                 // Max number of icons inside BottomBarRightView for Music mode is 4.
                 int maxIconCount = 4;
-                updateLayout(maxIconCount, iconSize, currWidth, currHeight, screenWidth,
-                        screenHeight);
+                updateLayout(maxIconCount, fullIconSize, embeddedIconSize, marginSize, currWidth,
+                        currHeight, screenWidth, screenHeight);
 
             } else if (mMediaType == MEDIA_TYPE_MUSIC) {
                 if (mNeedUXUpdate) {
@@ -547,12 +575,13 @@
 
                 // Max number of icons inside BottomBarRightView for Music mode is 3.
                 int maxIconCount = 3;
-                updateLayout(maxIconCount, iconSize, currWidth, currHeight, screenWidth,
-                        screenHeight);
+                updateLayout(maxIconCount, fullIconSize, embeddedIconSize, marginSize, currWidth,
+                        currHeight, screenWidth, screenHeight);
             }
             mPrevWidth = currWidth;
             mPrevHeight = currHeight;
         }
+        // TODO: move this to a different location.
         // Update title bar parameters in order to avoid overlap between title view and the right
         // side of the title bar.
         updateTitleBarLayout();
@@ -562,6 +591,7 @@
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
 
+        // TODO: Merge the below code with disableUnsupportedButtons().
         if (mPlayPauseButton != null) {
             mPlayPauseButton.setEnabled(enabled);
         }
@@ -596,16 +626,19 @@
         }
     }
 
+    // TODO (b/77158231) revive once androidx.mediarouter.* packagaes are available.
+    /*
     void setRouteSelector(MediaRouteSelector selector) {
         mRouteSelector = selector;
         if (mRouteSelector != null && !mRouteSelector.isEmpty()) {
-            mRouteButton.setRouteSelector(selector);
+            mRouteButton.setRouteSelector(selector, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
             mRouteButton.setVisibility(View.VISIBLE);
         } else {
             mRouteButton.setRouteSelector(MediaRouteSelector.EMPTY);
             mRouteButton.setVisibility(View.GONE);
         }
     }
+    */
 
     ///////////////////////////////////////////////////
     // Protected or private methods
@@ -665,12 +698,14 @@
      *
      * @return The controller view.
      */
+    // TODO: This was "protected". Determine if it should be protected in MCV2.
     private ViewGroup makeControllerView() {
         ViewGroup root = (ViewGroup) inflateLayout(getContext(), R.layout.media_controller);
         initControllerView(root);
         return root;
     }
 
+    // TODO(b/76444971) make sure this is compatible with ApiHelper's one in updatable.
     private View inflateLayout(Context context, int resId) {
         LayoutInflater inflater = (LayoutInflater) context
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -688,7 +723,8 @@
             mBackButton.setOnClickListener(mBackListener);
             mBackButton.setVisibility(View.GONE);
         }
-        mRouteButton = v.findViewById(R.id.cast);
+        // TODO (b/77158231) revive
+        // mRouteButton = v.findViewById(R.id.cast);
 
         // Relating to Center View
         mCenterView = v.findViewById(R.id.center_view);
@@ -699,7 +735,7 @@
         mMinimalExtraView = (LinearLayout) v.findViewById(R.id.minimal_extra_view);
         LinearLayout.LayoutParams params =
                 (LinearLayout.LayoutParams) mMinimalExtraView.getLayoutParams();
-        int iconSize = mResources.getDimensionPixelSize(R.dimen.mcv2_icon_size);
+        int iconSize = mResources.getDimensionPixelSize(R.dimen.mcv2_embedded_icon_size);
         int marginSize = mResources.getDimensionPixelSize(R.dimen.mcv2_icon_margin);
         params.setMargins(0, (iconSize + marginSize * 2) * (-1), 0, 0);
         mMinimalExtraView.setLayoutParams(params);
@@ -742,6 +778,7 @@
         mFullScreenButton = v.findViewById(R.id.fullscreen);
         if (mFullScreenButton != null) {
             mFullScreenButton.setOnClickListener(mFullScreenListener);
+            // TODO: Show Fullscreen button when only it is possible.
         }
         mOverflowButtonRight = v.findViewById(R.id.overflow_right);
         if (mOverflowButtonRight != null) {
@@ -778,8 +815,10 @@
         mEmbeddedSettingsItemWidth = mResources.getDimensionPixelSize(
                 R.dimen.mcv2_embedded_settings_width);
         mFullSettingsItemWidth = mResources.getDimensionPixelSize(R.dimen.mcv2_full_settings_width);
-        mSettingsItemHeight = mResources.getDimensionPixelSize(
-                R.dimen.mcv2_settings_height);
+        mEmbeddedSettingsItemHeight = mResources.getDimensionPixelSize(
+                R.dimen.mcv2_embedded_settings_height);
+        mFullSettingsItemHeight = mResources.getDimensionPixelSize(
+                R.dimen.mcv2_full_settings_height);
         mSettingsWindowMargin = (-1) * mResources.getDimensionPixelSize(
                 R.dimen.mcv2_settings_offset);
         mSettingsWindow = new PopupWindow(mSettingsListView, mEmbeddedSettingsItemWidth,
@@ -801,6 +840,13 @@
             if (mFfwdButton != null && !canSeekForward()) {
                 mFfwdButton.setEnabled(false);
             }
+            // TODO What we really should do is add a canSeek to the MediaPlayerControl interface;
+            // this scheme can break the case when applications want to allow seek through the
+            // progress bar but disable forward/backward buttons.
+            //
+            // However, currently the flags SEEK_BACKWARD_AVAILABLE, SEEK_FORWARD_AVAILABLE,
+            // and SEEK_AVAILABLE are all (un)set together; as such the aforementioned issue
+            // shouldn't arise in existing applications.
             if (mProgress != null && !canSeekBackward() && !canSeekForward()) {
                 mProgress.setEnabled(false);
             }
@@ -1032,11 +1078,7 @@
     private final OnClickListener mBackListener = new OnClickListener() {
         @Override
         public void onClick(View v) {
-            View parent = (View) getParent();
-            if (parent != null) {
-                parent.onKeyDown(KeyEvent.KEYCODE_BACK,
-                        new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
-            }
+            // TODO: implement
         }
     };
 
@@ -1063,11 +1105,8 @@
     private final OnClickListener mFullScreenListener = new OnClickListener() {
         @Override
         public void onClick(View v) {
-            if (mOnFullScreenListener == null) {
-                return;
-            }
-
             final boolean isEnteringFullScreen = !mIsFullScreen;
+            // TODO: Re-arrange the button layouts according to the UX.
             if (isEnteringFullScreen) {
                 mFullScreenButton.setImageDrawable(
                         mResources.getDrawable(R.drawable.ic_fullscreen_exit, null));
@@ -1075,9 +1114,11 @@
                 mFullScreenButton.setImageDrawable(
                         mResources.getDrawable(R.drawable.ic_fullscreen, null));
             }
+            Bundle args = new Bundle();
+            args.putBoolean(ARGUMENT_KEY_FULLSCREEN, isEnteringFullScreen);
+            mController.sendCommand(COMMAND_SET_FULLSCREEN, args, null);
+
             mIsFullScreen = isEnteringFullScreen;
-            mOnFullScreenListener.onFullScreen(MediaControlView2.this,
-                    mIsFullScreen);
         }
     };
 
@@ -1142,6 +1183,7 @@
                         mSubSettingsAdapter.setCheckPosition(mSelectedSpeedIndex);
                         mSettingsMode = SETTINGS_MODE_PLAYBACK_SPEED;
                     } else if (position == SETTINGS_MODE_HELP) {
+                        // TODO: implement this.
                         mSettingsWindow.dismiss();
                         return;
                     }
@@ -1172,6 +1214,7 @@
                     mSettingsWindow.dismiss();
                     break;
                 case SETTINGS_MODE_HELP:
+                    // TODO: implement this.
                     break;
                 case SETTINGS_MODE_SUBTITLE_TRACK:
                     if (position != mSelectedSubtitleTrackIndex) {
@@ -1197,6 +1240,7 @@
                     mSettingsWindow.dismiss();
                     break;
                 case SETTINGS_MODE_VIDEO_QUALITY:
+                    // TODO: add support for video quality
                     mSelectedVideoQualityIndex = position;
                     mSettingsWindow.dismiss();
                     break;
@@ -1306,14 +1350,21 @@
         }
     }
 
-    private void updateLayout(int maxIconCount, int iconSize, int currWidth,
-             int currHeight, int screenWidth, int screenHeight) {
-        int bottomBarRightWidthMax = iconSize * maxIconCount;
+    private void updateLayout(int maxIconCount, int fullIconSize, int embeddedIconSize,
+             int marginSize, int currWidth, int currHeight, int screenWidth, int screenHeight) {
+        int fullBottomBarRightWidthMax = fullIconSize * maxIconCount
+                + marginSize * (maxIconCount * 2);
+        int embeddedBottomBarRightWidthMax = embeddedIconSize * maxIconCount
+                + marginSize * (maxIconCount * 2);
         int fullWidth = mTransportControls.getWidth() + mTimeView.getWidth()
-                + bottomBarRightWidthMax;
-        int embeddedWidth = mTimeView.getWidth() + bottomBarRightWidthMax;
+                + fullBottomBarRightWidthMax;
+        int embeddedWidth = mTimeView.getWidth() + embeddedBottomBarRightWidthMax;
         int screenMaxLength = Math.max(screenWidth, screenHeight);
 
+        if (fullWidth > screenMaxLength) {
+            // TODO: screen may be smaller than the length needed for Full size.
+        }
+
         boolean isFullSize = (mMediaType == MEDIA_TYPE_DEFAULT) ? (currWidth == screenMaxLength) :
                 (currWidth == screenWidth && currHeight == screenHeight);
 
@@ -1352,11 +1403,6 @@
                 // Relating to Title Bar
                 mTitleBar.setVisibility(View.VISIBLE);
                 mBackButton.setVisibility(View.GONE);
-                mTitleView.setPadding(
-                        mResources.getDimensionPixelSize(R.dimen.mcv2_embedded_icon_padding),
-                        mTitleView.getPaddingTop(),
-                        mTitleView.getPaddingRight(),
-                        mTitleView.getPaddingBottom());
 
                 // Relating to Full Screen Button
                 mMinimalExtraView.setVisibility(View.GONE);
@@ -1385,11 +1431,6 @@
                 // Relating to Title Bar
                 mTitleBar.setVisibility(View.VISIBLE);
                 mBackButton.setVisibility(View.VISIBLE);
-                mTitleView.setPadding(
-                        0,
-                        mTitleView.getPaddingTop(),
-                        mTitleView.getPaddingRight(),
-                        mTitleView.getPaddingBottom());
 
                 // Relating to Full Screen Button
                 mMinimalExtraView.setVisibility(View.GONE);
@@ -1482,6 +1523,7 @@
                 mRewButton.setVisibility(View.GONE);
             }
         }
+        // TODO: Add support for Next and Previous buttons
         mNextButton = v.findViewById(R.id.next);
         if (mNextButton != null) {
             mNextButton.setOnClickListener(mNextListener);
@@ -1548,12 +1590,15 @@
         mSettingsWindow.setWidth(itemWidth);
 
         // Calculate height of window and show
-        int totalHeight = adapter.getCount() * mSettingsItemHeight;
+        int itemHeight = (mSizeType == SIZE_TYPE_EMBEDDED)
+                ? mEmbeddedSettingsItemHeight : mFullSettingsItemHeight;
+        int totalHeight = adapter.getCount() * itemHeight;
         mSettingsWindow.dismiss();
         mSettingsWindow.showAsDropDown(this, mSettingsWindowMargin,
                 mSettingsWindowMargin - totalHeight, Gravity.BOTTOM | Gravity.RIGHT);
     }
 
+    @RequiresApi(26) // TODO correct minSdk API use incompatibilities and remove before release.
     private class MediaControllerCallback extends MediaControllerCompat.Callback {
         @Override
         public void onPlaybackStateChanged(PlaybackStateCompat state) {
@@ -1625,12 +1670,16 @@
                 for (final PlaybackStateCompat.CustomAction action : customActions) {
                     ImageButton button = new ImageButton(getContext(),
                             null /* AttributeSet */, 0 /* Style */);
+                    // TODO: Apply R.style.BottomBarButton to this button using library context.
                     // Refer Constructor with argument (int defStyleRes) of View.java
                     button.setImageResource(action.getIcon());
+                    button.setTooltipText(action.getName());
                     final String actionString = action.getAction().toString();
                     button.setOnClickListener(new OnClickListener() {
                         @Override
                         public void onClick(View v) {
+                            // TODO: Currently, we are just sending extras that came from session.
+                            // Is it the right behavior?
                             mControls.sendCustomAction(actionString, action.getExtras());
                             setVisibility(View.VISIBLE);
                         }
@@ -1659,6 +1708,7 @@
                     mAudioTrackCount = extras.getInt(KEY_AUDIO_TRACK_COUNT);
                     mAudioTrackList = new ArrayList<String>();
                     if (mAudioTrackCount > 0) {
+                        // TODO: add more text about track info.
                         for (int i = 0; i < mAudioTrackCount; i++) {
                             String track = mResources.getString(
                                     R.string.MediaControlView2_audio_track_number_text, i + 1);
@@ -1737,12 +1787,14 @@
         @Override
         public long getItemId(int position) {
             // Auto-generated method stub--does not have any purpose here
+            // TODO: implement this.
             return 0;
         }
 
         @Override
         public Object getItem(int position) {
             // Auto-generated method stub--does not have any purpose here
+            // TODO: implement this.
             return null;
         }
 
@@ -1786,6 +1838,7 @@
         }
     }
 
+    // TODO: extend this class from SettingsAdapter
     private class SubSettingsAdapter extends BaseAdapter {
         private List<String> mTexts;
         private int mCheckPosition;
@@ -1812,12 +1865,14 @@
         @Override
         public long getItemId(int position) {
             // Auto-generated method stub--does not have any purpose here
+            // TODO: implement this.
             return 0;
         }
 
         @Override
         public Object getItem(int position) {
             // Auto-generated method stub--does not have any purpose here
+            // TODO: implement this.
             return null;
         }
 
diff --git a/media-widget/src/main/java/androidx/media/widget/RoutePlayer.java b/media-widget/src/main/java/androidx/media/widget/RoutePlayer.java
deleted file mode 100644
index 00ac36a..0000000
--- a/media-widget/src/main/java/androidx/media/widget/RoutePlayer.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.widget;
-
-import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.content.Context;
-import android.media.session.MediaSession;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.v4.media.session.PlaybackStateCompat;
-
-import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
-import androidx.mediarouter.media.MediaItemStatus;
-import androidx.mediarouter.media.MediaRouter;
-import androidx.mediarouter.media.MediaSessionStatus;
-import androidx.mediarouter.media.RemotePlaybackClient;
-import androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback;
-import androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback;
-import androidx.mediarouter.media.RemotePlaybackClient.StatusCallback;
-
-/**
- * @hide
- */
-@RestrictTo(LIBRARY_GROUP)
-@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
-public class RoutePlayer extends MediaSession.Callback {
-    public static final long PLAYBACK_ACTIONS = PlaybackStateCompat.ACTION_PAUSE
-            | PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_SEEK_TO
-            | PlaybackStateCompat.ACTION_FAST_FORWARD | PlaybackStateCompat.ACTION_REWIND;
-
-    private RemotePlaybackClient mClient;
-    private String mSessionId;
-    private String mItemId;
-    private PlayerEventCallback mCallback;
-
-    private StatusCallback mStatusCallback = new StatusCallback() {
-        @Override
-        public void onItemStatusChanged(Bundle data,
-                                        String sessionId, MediaSessionStatus sessionStatus,
-                                        String itemId, MediaItemStatus itemStatus) {
-            updateSessionStatus(sessionId, sessionStatus);
-            updateItemStatus(itemId, itemStatus);
-        }
-    };
-
-    public RoutePlayer(Context context, MediaRouter.RouteInfo route) {
-        mClient = new RemotePlaybackClient(context, route);
-        mClient.setStatusCallback(mStatusCallback);
-        if (mClient.isSessionManagementSupported()) {
-            mClient.startSession(null, new SessionActionCallback() {
-                @Override
-                public void onResult(Bundle data,
-                                     String sessionId, MediaSessionStatus sessionStatus) {
-                    updateSessionStatus(sessionId, sessionStatus);
-                }
-            });
-        }
-    }
-
-    @Override
-    public void onPlay() {
-        if (mClient.isSessionManagementSupported()) {
-            mClient.resume(null, new SessionActionCallback() {
-                @Override
-                public void onResult(Bundle data,
-                                     String sessionId, MediaSessionStatus sessionStatus) {
-                    updateSessionStatus(sessionId, sessionStatus);
-                }
-            });
-        }
-    }
-
-    @Override
-    public void onPause() {
-        if (mClient.isSessionManagementSupported()) {
-            mClient.pause(null, new SessionActionCallback() {
-                @Override
-                public void onResult(Bundle data,
-                                     String sessionId, MediaSessionStatus sessionStatus) {
-                    updateSessionStatus(sessionId, sessionStatus);
-                }
-            });
-        }
-    }
-
-    @Override
-    public void onSeekTo(long pos) {
-        if (mClient.isSessionManagementSupported()) {
-            mClient.seek(mItemId, pos, null, new ItemActionCallback() {
-                @Override
-                public void onResult(Bundle data,
-                                     String sessionId, MediaSessionStatus sessionStatus,
-                                     String itemId, MediaItemStatus itemStatus) {
-                    updateSessionStatus(sessionId, sessionStatus);
-                    updateItemStatus(itemId, itemStatus);
-                }
-            });
-        }
-    }
-
-    @Override
-    public void onStop() {
-        if (mClient.isSessionManagementSupported()) {
-            mClient.stop(null, new SessionActionCallback() {
-                @Override
-                public void onResult(Bundle data,
-                                     String sessionId, MediaSessionStatus sessionStatus) {
-                    updateSessionStatus(sessionId, sessionStatus);
-                }
-            });
-        }
-    }
-
-    /**
-     * Sets a callback to be notified of events for this player.
-     * @param callback the callback to receive the events.
-     */
-    public void setPlayerEventCallback(PlayerEventCallback callback) {
-        mCallback = callback;
-    }
-
-    // b/77556429
-//    public void openVideo(DataSourceDesc dsd) {
-//        mClient.play(dsd.getUri(), "video/mp4", null, 0, null, new ItemActionCallback() {
-//            @Override
-//            public void onResult(Bundle data,
-//                                 String sessionId, MediaSessionStatus sessionStatus,
-//                                 String itemId, MediaItemStatus itemStatus) {
-//                updateSessionStatus(sessionId, sessionStatus);
-//                updateItemStatus(itemId, itemStatus);
-//                playInternal(dsd.getUri());
-//            }
-//        });
-//    }
-
-    /**
-     * Opens the video based on the given uri and updates the media session and item statuses.
-     * @param uri link to the video
-     */
-    public void openVideo(Uri uri) {
-        mClient.play(uri, "video/mp4", null, 0, null, new ItemActionCallback() {
-            @Override
-            public void onResult(Bundle data,
-                                 String sessionId, MediaSessionStatus sessionStatus,
-                                 String itemId, MediaItemStatus itemStatus) {
-                updateSessionStatus(sessionId, sessionStatus);
-                updateItemStatus(itemId, itemStatus);
-            }
-        });
-    }
-
-    /**
-     * Releases the {@link RemotePlaybackClient} and {@link PlayerEventCallback} instances.
-     */
-    public void release() {
-        if (mClient != null) {
-            mClient.release();
-            mClient = null;
-        }
-        if (mCallback != null) {
-            mCallback = null;
-        }
-    }
-
-    private void playInternal(Uri uri) {
-        mClient.play(uri, "video/mp4", null, 0, null, new ItemActionCallback() {
-            @Override
-            public void onResult(Bundle data,
-                                 String sessionId, MediaSessionStatus sessionStatus,
-                                 String itemId, MediaItemStatus itemStatus) {
-                updateSessionStatus(sessionId, sessionStatus);
-                updateItemStatus(itemId, itemStatus);
-            }
-        });
-    }
-
-    private void updateSessionStatus(String sessionId, MediaSessionStatus sessionStatus) {
-        mSessionId = sessionId;
-    }
-
-    private void updateItemStatus(String itemId, MediaItemStatus itemStatus) {
-        mItemId = itemId;
-        if (itemStatus == null || mCallback == null) return;
-        mCallback.onPlayerStateChanged(itemStatus);
-    }
-
-    /**
-     * A callback class to receive notifications for events on the route player.
-     */
-    public abstract static class PlayerEventCallback {
-        /**
-         * Override to handle changes in playback state.
-         *
-         * @param itemStatus The new MediaItemStatus of the RoutePlayer
-         */
-        public void onPlayerStateChanged(MediaItemStatus itemStatus) { }
-    }
-}
diff --git a/media-widget/src/main/java/androidx/media/widget/SubtitleView.java b/media-widget/src/main/java/androidx/media/widget/SubtitleView.java
deleted file mode 100644
index 1faff2f..0000000
--- a/media-widget/src/main/java/androidx/media/widget/SubtitleView.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.widget;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.os.Looper;
-import android.util.AttributeSet;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.media.subtitle.SubtitleController.Anchor;
-import androidx.media.subtitle.SubtitleTrack.RenderingWidget;
-
-@RequiresApi(21)
-class SubtitleView extends BaseLayout implements Anchor {
-    private static final String TAG = "SubtitleView";
-
-    private RenderingWidget mSubtitleWidget;
-    private RenderingWidget.OnChangedListener mSubtitlesChangedListener;
-
-    SubtitleView(Context context) {
-        this(context, null);
-    }
-
-    SubtitleView(Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    SubtitleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    SubtitleView(
-            Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    @Override
-    public void setSubtitleWidget(RenderingWidget subtitleWidget) {
-        if (mSubtitleWidget == subtitleWidget) {
-            return;
-        }
-
-        final boolean attachedToWindow = isAttachedToWindow();
-        if (mSubtitleWidget != null) {
-            if (attachedToWindow) {
-                mSubtitleWidget.onDetachedFromWindow();
-            }
-
-            mSubtitleWidget.setOnChangedListener(null);
-        }
-        mSubtitleWidget = subtitleWidget;
-
-        if (subtitleWidget != null) {
-            if (mSubtitlesChangedListener == null) {
-                mSubtitlesChangedListener = new RenderingWidget.OnChangedListener() {
-                    @Override
-                    public void onChanged(RenderingWidget renderingWidget) {
-                        invalidate();
-                    }
-                };
-            }
-
-            setWillNotDraw(false);
-            subtitleWidget.setOnChangedListener(mSubtitlesChangedListener);
-
-            if (attachedToWindow) {
-                subtitleWidget.onAttachedToWindow();
-                requestLayout();
-            }
-        } else {
-            setWillNotDraw(true);
-        }
-
-        invalidate();
-    }
-
-    @Override
-    public Looper getSubtitleLooper() {
-        return Looper.getMainLooper();
-    }
-
-    @Override
-    public void onAttachedToWindow() {
-        super.onAttachedToWindow();
-
-        if (mSubtitleWidget != null) {
-            mSubtitleWidget.onAttachedToWindow();
-        }
-    }
-
-    @Override
-    public void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-
-        if (mSubtitleWidget != null) {
-            mSubtitleWidget.onDetachedFromWindow();
-        }
-    }
-
-    @Override
-    public void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-
-        if (mSubtitleWidget != null) {
-            final int width = getWidth() - getPaddingLeft() - getPaddingRight();
-            final int height = getHeight() - getPaddingTop() - getPaddingBottom();
-
-            mSubtitleWidget.setSize(width, height);
-        }
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        super.draw(canvas);
-
-        if (mSubtitleWidget != null) {
-            final int saveCount = canvas.save();
-            canvas.translate(getPaddingLeft(), getPaddingTop());
-            mSubtitleWidget.draw(canvas);
-            canvas.restoreToCount(saveCount);
-        }
-    }
-
-    @Override
-    public CharSequence getAccessibilityClassName() {
-        return SubtitleView.class.getName();
-    }
-}
diff --git a/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoSurfaceViewWithMp1.java b/media-widget/src/main/java/androidx/media/widget/VideoSurfaceView.java
similarity index 82%
rename from media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoSurfaceViewWithMp1.java
rename to media-widget/src/main/java/androidx/media/widget/VideoSurfaceView.java
index 740d908..d417bd2 100644
--- a/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoSurfaceViewWithMp1.java
+++ b/media-widget/src/main/java/androidx/media/widget/VideoSurfaceView.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.media.MediaPlayer;
+import android.util.AttributeSet;
 import android.util.Log;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
@@ -30,24 +31,39 @@
 import androidx.annotation.RequiresApi;
 
 @RequiresApi(21)
-class VideoSurfaceViewWithMp1 extends SurfaceView
-        implements VideoViewInterfaceWithMp1, SurfaceHolder.Callback {
-    private static final String TAG = "VideoSurfaceViewWithMp1";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+class VideoSurfaceView extends SurfaceView implements VideoViewInterface, SurfaceHolder.Callback {
+    private static final String TAG = "VideoSurfaceView";
+    private static final boolean DEBUG = true; // STOPSHIP: Log.isLoggable(TAG, Log.DEBUG);
     private SurfaceHolder mSurfaceHolder = null;
     private SurfaceListener mSurfaceListener = null;
     private MediaPlayer mMediaPlayer;
     // A flag to indicate taking over other view should be proceed.
     private boolean mIsTakingOverOldView;
-    private VideoViewInterfaceWithMp1 mOldView;
+    private VideoViewInterface mOldView;
 
-    VideoSurfaceViewWithMp1(Context context) {
-        super(context, null);
+
+    VideoSurfaceView(Context context) {
+        this(context, null);
+    }
+
+    VideoSurfaceView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        getHolder().addCallback(this);
+    }
+
+    @RequiresApi(21)
+    VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr,
+                            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
         getHolder().addCallback(this);
     }
 
     ////////////////////////////////////////////////////
-    // implements VideoViewInterfaceWithMp1
+    // implements VideoViewInterface
     ////////////////////////////////////////////////////
 
     @Override
@@ -79,7 +95,7 @@
     }
 
     @Override
-    public void takeOver(@NonNull VideoViewInterfaceWithMp1 oldView) {
+    public void takeOver(@NonNull VideoViewInterface oldView) {
         if (assignSurfaceToMediaPlayer(mMediaPlayer)) {
             ((View) oldView).setVisibility(GONE);
             mIsTakingOverOldView = false;
@@ -134,6 +150,7 @@
         }
     }
 
+    // TODO: Investigate the way to move onMeasure() code into FrameLayout.
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int videoWidth = (mMediaPlayer == null) ? 0 : mMediaPlayer.getVideoWidth();
@@ -177,4 +194,10 @@
             Log.i(TAG, " measuredSize: " + getMeasuredWidth() + "/" + getMeasuredHeight());
         }
     }
+
+    @Override
+    public String toString() {
+        return "ViewType: SurfaceView / Visibility: " + getVisibility()
+                + " / surfaceHolder: " + mSurfaceHolder;
+    }
 }
diff --git a/media-widget/src/main/java/androidx/media/widget/impl/VideoTextureView.java b/media-widget/src/main/java/androidx/media/widget/VideoTextureView.java
similarity index 87%
rename from media-widget/src/main/java/androidx/media/widget/impl/VideoTextureView.java
rename to media-widget/src/main/java/androidx/media/widget/VideoTextureView.java
index 3726047..cdc833b 100644
--- a/media-widget/src/main/java/androidx/media/widget/impl/VideoTextureView.java
+++ b/media-widget/src/main/java/androidx/media/widget/VideoTextureView.java
@@ -20,6 +20,8 @@
 
 import android.content.Context;
 import android.graphics.SurfaceTexture;
+import android.media.MediaPlayer;
+import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Surface;
 import android.view.TextureView;
@@ -27,32 +29,44 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
-import androidx.media.MediaPlayer2;
 
 @RequiresApi(21)
 class VideoTextureView extends TextureView
         implements VideoViewInterface, TextureView.SurfaceTextureListener {
-    private static final String TAG = "VideoTextureViewWithMp1";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final String TAG = "VideoTextureView";
+    private static final boolean DEBUG = true; // STOPSHIP: Log.isLoggable(TAG, Log.DEBUG);
 
     private Surface mSurface;
     private SurfaceListener mSurfaceListener;
-    private MediaPlayer2 mMediaPlayer;
+    private MediaPlayer mMediaPlayer;
     // A flag to indicate taking over other view should be proceed.
     private boolean mIsTakingOverOldView;
     private VideoViewInterface mOldView;
 
     VideoTextureView(Context context) {
-        super(context, null);
+        this(context, null);
+    }
+
+    VideoTextureView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    VideoTextureView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    VideoTextureView(
+            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
         setSurfaceTextureListener(this);
     }
 
     ////////////////////////////////////////////////////
-    // implements VideoViewInterfaceWithMp1
+    // implements VideoViewInterface
     ////////////////////////////////////////////////////
 
     @Override
-    public boolean assignSurfaceToMediaPlayer(MediaPlayer2 mp) {
+    public boolean assignSurfaceToMediaPlayer(MediaPlayer mp) {
         if (mp == null || !hasAvailableSurface()) {
             // Surface is not ready.
             return false;
@@ -72,7 +86,7 @@
     }
 
     @Override
-    public void setMediaPlayer(MediaPlayer2 mp) {
+    public void setMediaPlayer(MediaPlayer mp) {
         mMediaPlayer = mp;
         if (mIsTakingOverOldView) {
             takeOver(mOldView);
diff --git a/media-widget/src/main/java/androidx/media/widget/VideoView2.java b/media-widget/src/main/java/androidx/media/widget/VideoView2.java
index a851370..a8ea450 100644
--- a/media-widget/src/main/java/androidx/media/widget/VideoView2.java
+++ b/media-widget/src/main/java/androidx/media/widget/VideoView2.java
@@ -19,17 +19,38 @@
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
 import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Point;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.media.AudioAttributes;
+import android.media.AudioFocusRequest;
 import android.media.AudioManager;
+import android.media.MediaMetadataRetriever;
 import android.media.MediaPlayer;
+import android.media.PlaybackParams;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.ResultReceiver;
+import android.support.v4.media.MediaMetadataCompat;
 import android.support.v4.media.session.MediaControllerCompat;
+import android.support.v4.media.session.MediaControllerCompat.PlaybackInfo;
+import android.support.v4.media.session.MediaSessionCompat;
 import android.support.v4.media.session.PlaybackStateCompat;
 import android.util.AttributeSet;
+import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.Pair;
+import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.ImageView;
+import android.widget.TextView;
 import android.widget.VideoView;
 
 import androidx.annotation.IntDef;
@@ -38,21 +59,25 @@
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
-import androidx.media.AudioAttributesCompat;
 import androidx.media.DataSourceDesc;
 import androidx.media.MediaItem2;
 import androidx.media.MediaMetadata2;
 import androidx.media.SessionToken2;
+import androidx.palette.graphics.Palette;
 
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Executor;
 
+// TODO: Replace MediaSession wtih MediaSession2 once MediaSession2 is submitted.
 /**
- * Displays a video file.  VideoView2 class is a ViewGroup class which is wrapping
- * {@link MediaPlayer} so that developers can easily implement a video rendering application.
+ * @hide
+ * Displays a video file.  VideoView2 class is a View class which is wrapping {@link MediaPlayer}
+ * so that developers can easily implement a video rendering application.
  *
  * <p>
  * <em> Data sources that VideoView2 supports : </em>
@@ -73,12 +98,20 @@
  * VideoView2 covers and inherits the most of
  * VideoView's functionalities. The main differences are
  * <ul>
- * <li> VideoView2 inherits ViewGroup and renders videos using SurfaceView and TextureView
+ * <li> VideoView2 inherits FrameLayout and renders videos using SurfaceView and TextureView
  * selectively while VideoView inherits SurfaceView class.
  * <li> VideoView2 is integrated with MediaControlView2 and a default MediaControlView2 instance is
- * attached to VideoView2 by default.
- * <li> If a developer wants to attach a customed MediaControlView2,
- * assign the customed media control widget using {@link #setMediaControlView2}.
+ * attached to VideoView2 by default. If a developer does not want to use the default
+ * MediaControlView2, needs to set enableControlView attribute to false. For instance,
+ * <pre>
+ * &lt;VideoView2
+ *     android:id="@+id/video_view"
+ *     xmlns:widget="http://schemas.android.com/apk/com.android.media.update"
+ *     widget:enableControlView="false" /&gt;
+ * </pre>
+ * If a developer wants to attach a customed MediaControlView2, then set enableControlView attribute
+ * to false and assign the customed media control widget using {@link #setMediaControlView2}.
+ * <li> VideoView2 is integrated with MediaPlayer while VideoView is integrated with MediaPlayer.
  * <li> VideoView2 is integrated with MediaSession and so it responses with media key events.
  * A VideoView2 keeps a MediaSession instance internally and connects it to a corresponding
  * MediaControlView2 instance.
@@ -101,7 +134,8 @@
  * {@link android.app.Activity#onRestoreInstanceState}.
  */
 @RequiresApi(21) // TODO correct minSdk API use incompatibilities and remove before release.
-public class VideoView2 extends BaseLayout {
+@RestrictTo(LIBRARY_GROUP)
+public class VideoView2 extends BaseLayout implements VideoViewInterface.SurfaceListener {
     /** @hide */
     @RestrictTo(LIBRARY_GROUP)
     @IntDef({
@@ -126,10 +160,171 @@
     public static final int VIEW_TYPE_TEXTUREVIEW = 1;
 
     private static final String TAG = "VideoView2";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final boolean USE_MP2 = Log.isLoggable("VV2MP2", Log.DEBUG);
+    private static final boolean DEBUG = true; // STOPSHIP: Log.isLoggable(TAG, Log.DEBUG);
+    private static final long DEFAULT_SHOW_CONTROLLER_INTERVAL_MS = 2000;
 
-    private VideoView2Impl mImpl;
+    private static final int STATE_ERROR = -1;
+    private static final int STATE_IDLE = 0;
+    private static final int STATE_PREPARING = 1;
+    private static final int STATE_PREPARED = 2;
+    private static final int STATE_PLAYING = 3;
+    private static final int STATE_PAUSED = 4;
+    private static final int STATE_PLAYBACK_COMPLETED = 5;
+
+    private static final int INVALID_TRACK_INDEX = -1;
+    private static final float INVALID_SPEED = 0f;
+
+    private static final int SIZE_TYPE_EMBEDDED = 0;
+    private static final int SIZE_TYPE_FULL = 1;
+    // TODO: add support for Minimal size type.
+    private static final int SIZE_TYPE_MINIMAL = 2;
+
+    private AccessibilityManager mAccessibilityManager;
+    private AudioManager mAudioManager;
+    private AudioAttributes mAudioAttributes;
+    private int mAudioFocusType = AudioManager.AUDIOFOCUS_GAIN; // legacy focus gain
+    private boolean mAudioFocused = false;
+
+    private Pair<Executor, OnCustomActionListener> mCustomActionListenerRecord;
+    private OnViewTypeChangedListener mViewTypeChangedListener;
+    private OnFullScreenRequestListener mFullScreenRequestListener;
+
+    private VideoViewInterface mCurrentView;
+    private VideoTextureView mTextureView;
+    private VideoSurfaceView mSurfaceView;
+
+    private MediaPlayer mMediaPlayer;
+    private DataSourceDesc mDsd;
+    private MediaControlView2 mMediaControlView;
+    private MediaSessionCompat mMediaSession;
+    private MediaControllerCompat mMediaController;
+    private MediaMetadata2 mMediaMetadata;
+    private MediaMetadataRetriever mRetriever;
+    private boolean mNeedUpdateMediaType;
+    private Bundle mMediaTypeData;
+    private String mTitle;
+
+    // TODO: move music view inside SurfaceView/TextureView or implement VideoViewInterface.
+    private WindowManager mManager;
+    private Resources mResources;
+    private View mMusicView;
+    private Drawable mMusicAlbumDrawable;
+    private String mMusicTitleText;
+    private String mMusicArtistText;
+    private boolean mIsMusicMediaType;
+    private int mPrevWidth;
+    private int mPrevHeight;
+    private int mDominantColor;
+    private int mSizeType;
+
+    private PlaybackStateCompat.Builder mStateBuilder;
+    private List<PlaybackStateCompat.CustomAction> mCustomActionList;
+
+    private int mTargetState = STATE_IDLE;
+    private int mCurrentState = STATE_IDLE;
+    private int mCurrentBufferPercentage;
+    private long mSeekWhenPrepared;  // recording the seek position while preparing
+
+    private int mVideoWidth;
+    private int mVideoHeight;
+
+    private ArrayList<Integer> mVideoTrackIndices;
+    private ArrayList<Integer> mAudioTrackIndices;
+    // private ArrayList<Pair<Integer, SubtitleTrack>> mSubtitleTrackIndices;
+    // private SubtitleController mSubtitleController;
+
+    // selected video/audio/subtitle track index as MediaPlayer returns
+    private int mSelectedVideoTrackIndex;
+    private int mSelectedAudioTrackIndex;
+    private int mSelectedSubtitleTrackIndex;
+
+    // private SubtitleView mSubtitleView;
+    private boolean mSubtitleEnabled;
+
+    private float mSpeed;
+    // TODO: Remove mFallbackSpeed when integration with MediaPlayer's new setPlaybackParams().
+    // Refer: https://docs.google.com/document/d/1nzAfns6i2hJ3RkaUre3QMT6wsDedJ5ONLiA_OOBFFX8/edit
+    private float mFallbackSpeed;  // keep the original speed before 'pause' is called.
+    private float mVolumeLevelFloat;
+    private int mVolumeLevel;
+
+    private long mShowControllerIntervalMs;
+
+    // private MediaRouter mMediaRouter;
+    // private MediaRouteSelector mRouteSelector;
+    // private MediaRouter.RouteInfo mRoute;
+    // private RoutePlayer mRoutePlayer;
+
+    // TODO (b/77158231)
+    /*
+    private final MediaRouter.Callback mRouterCallback = new MediaRouter.Callback() {
+        @Override
+        public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo route) {
+            if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
+                // Stop local playback (if necessary)
+                resetPlayer();
+                mRoute = route;
+                mRoutePlayer = new RoutePlayer(getContext(), route);
+                mRoutePlayer.setPlayerEventCallback(new RoutePlayer.PlayerEventCallback() {
+                    @Override
+                    public void onPlayerStateChanged(MediaItemStatus itemStatus) {
+                        PlaybackStateCompat.Builder psBuilder = new PlaybackStateCompat.Builder();
+                        psBuilder.setActions(RoutePlayer.PLAYBACK_ACTIONS);
+                        long position = itemStatus.getContentPosition();
+                        switch (itemStatus.getPlaybackState()) {
+                            case MediaItemStatus.PLAYBACK_STATE_PENDING:
+                                psBuilder.setState(PlaybackStateCompat.STATE_NONE, position, 0);
+                                mCurrentState = STATE_IDLE;
+                                break;
+                            case MediaItemStatus.PLAYBACK_STATE_PLAYING:
+                                psBuilder.setState(PlaybackStateCompat.STATE_PLAYING, position, 1);
+                                mCurrentState = STATE_PLAYING;
+                                break;
+                            case MediaItemStatus.PLAYBACK_STATE_PAUSED:
+                                psBuilder.setState(PlaybackStateCompat.STATE_PAUSED, position, 0);
+                                mCurrentState = STATE_PAUSED;
+                                break;
+                            case MediaItemStatus.PLAYBACK_STATE_BUFFERING:
+                                psBuilder.setState(
+                                        PlaybackStateCompat.STATE_BUFFERING, position, 0);
+                                mCurrentState = STATE_PAUSED;
+                                break;
+                            case MediaItemStatus.PLAYBACK_STATE_FINISHED:
+                                psBuilder.setState(PlaybackStateCompat.STATE_STOPPED, position, 0);
+                                mCurrentState = STATE_PLAYBACK_COMPLETED;
+                                break;
+                        }
+
+                        PlaybackStateCompat pbState = psBuilder.build();
+                        mMediaSession.setPlaybackState(pbState);
+
+                        MediaMetadataCompat.Builder mmBuilder = new MediaMetadataCompat.Builder();
+                        mmBuilder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION,
+                                itemStatus.getContentDuration());
+                        mMediaSession.setMetadata(mmBuilder.build());
+                    }
+                });
+                // Start remote playback (if necessary)
+                mRoutePlayer.openVideo(mDsd);
+            }
+        }
+
+        @Override
+        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route, int reason) {
+            if (mRoute != null && mRoutePlayer != null) {
+                mRoutePlayer.release();
+                mRoutePlayer = null;
+            }
+            if (mRoute == route) {
+                mRoute = null;
+            }
+            if (reason != MediaRouter.UNSELECT_REASON_ROUTE_CHANGED) {
+                // TODO: Resume local playback  (if necessary)
+                openVideo(mDsd);
+            }
+        }
+    };
+    */
 
     public VideoView2(@NonNull Context context) {
         this(context, null);
@@ -140,20 +335,86 @@
     }
 
     public VideoView2(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        if (android.os.Build.VERSION.SDK_INT >= 28) {
-            if (USE_MP2) {
-                Log.d(TAG, "Create VideoView2ImplBase");
-                mImpl = new VideoView2ImplBase();
-            } else {
-                Log.d(TAG, "Create VideoView2ImplApi28WithMp1");
-                mImpl = new VideoView2ImplApi28WithMp1();
-            }
-        } else {
-            Log.d(TAG, "Create VideoView2ImplBaseWithMp1");
-            mImpl = new VideoView2ImplBaseWithMp1();
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public VideoView2(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        mVideoWidth = 0;
+        mVideoHeight = 0;
+        mSpeed = 1.0f;
+        mFallbackSpeed = mSpeed;
+        mSelectedSubtitleTrackIndex = INVALID_TRACK_INDEX;
+        // TODO: add attributes to get this value.
+        mShowControllerIntervalMs = DEFAULT_SHOW_CONTROLLER_INTERVAL_MS;
+
+        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
+
+        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        mAudioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA)
+                .setContentType(AudioAttributes.CONTENT_TYPE_MOVIE).build();
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+        requestFocus();
+
+        // TODO: try to keep a single child at a time rather than always having both.
+        mTextureView = new VideoTextureView(getContext());
+        mSurfaceView = new VideoSurfaceView(getContext());
+        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT);
+        mTextureView.setLayoutParams(params);
+        mSurfaceView.setLayoutParams(params);
+        mTextureView.setSurfaceListener(this);
+        mSurfaceView.setSurfaceListener(this);
+
+        addView(mTextureView);
+        addView(mSurfaceView);
+
+        // mSubtitleView = new SubtitleView(getContext());
+        // mSubtitleView.setLayoutParams(params);
+        // mSubtitleView.setBackgroundColor(0);
+        // addView(mSubtitleView);
+
+        boolean enableControlView = (attrs == null) || attrs.getAttributeBooleanValue(
+                "http://schemas.android.com/apk/res/android",
+                "enableControlView", true);
+        if (enableControlView) {
+            mMediaControlView = new MediaControlView2(getContext());
         }
-        mImpl.initialize(this, context, attrs, defStyleAttr);
+
+        mSubtitleEnabled = (attrs == null) || attrs.getAttributeBooleanValue(
+                "http://schemas.android.com/apk/res/android",
+                "enableSubtitle", false);
+
+        // TODO: Choose TextureView when SurfaceView cannot be created.
+        // Choose surface view by default
+        int viewType = (attrs == null) ? VideoView2.VIEW_TYPE_SURFACEVIEW
+                : attrs.getAttributeIntValue(
+                "http://schemas.android.com/apk/res/android",
+                "viewType", VideoView2.VIEW_TYPE_SURFACEVIEW);
+        if (viewType == VideoView2.VIEW_TYPE_SURFACEVIEW) {
+            Log.d(TAG, "viewType attribute is surfaceView.");
+            mTextureView.setVisibility(View.GONE);
+            mSurfaceView.setVisibility(View.VISIBLE);
+            mCurrentView = mSurfaceView;
+        } else if (viewType == VideoView2.VIEW_TYPE_TEXTUREVIEW) {
+            Log.d(TAG, "viewType attribute is textureView.");
+            mTextureView.setVisibility(View.VISIBLE);
+            mSurfaceView.setVisibility(View.GONE);
+            mCurrentView = mTextureView;
+        }
+
+        // TODO (b/77158231)
+        /*
+        MediaRouteSelector.Builder builder = new MediaRouteSelector.Builder();
+        builder.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+        builder.addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO);
+        builder.addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO);
+        mRouteSelector = builder.build();
+        */
     }
 
     /**
@@ -164,7 +425,15 @@
      * @param intervalMs a time interval in milliseconds until VideoView2 hides MediaControlView2.
      */
     public void setMediaControlView2(MediaControlView2 mediaControlView, long intervalMs) {
-        mImpl.setMediaControlView2(mediaControlView, intervalMs);
+        mMediaControlView = mediaControlView;
+        mShowControllerIntervalMs = intervalMs;
+        // TODO: Call MediaControlView2.setRouteSelector only when cast availalbe.
+        // TODO (b/77158231)
+        // mMediaControlView.setRouteSelector(mRouteSelector);
+
+        if (isAttachedToWindow()) {
+            attachMediaControlView();
+        }
     }
 
     /**
@@ -172,7 +441,7 @@
      * {@link #setMediaControlView2} method.
      */
     public MediaControlView2 getMediaControlView2() {
-        return mImpl.getMediaControlView2();
+        return mMediaControlView;
     }
 
     /**
@@ -194,7 +463,7 @@
      */
     @RestrictTo(LIBRARY_GROUP)
     public MediaMetadata2 getMediaMetadata() {
-        return mImpl.getMediaMetadata();
+        return mMediaMetadata;
     }
 
     /**
@@ -209,7 +478,10 @@
      */
     @RestrictTo(LIBRARY_GROUP)
     public MediaControllerCompat getMediaController() {
-        return mImpl.getMediaController();
+        if (mMediaSession == null) {
+            throw new IllegalStateException("MediaSession instance is not available.");
+        }
+        return mMediaController;
     }
 
     /**
@@ -222,6 +494,7 @@
      */
     @RestrictTo(LIBRARY_GROUP)
     public SessionToken2 getMediaSessionToken() {
+        //return mProvider.getMediaSessionToken_impl();
         return null;
     }
 
@@ -232,7 +505,10 @@
      * @param enable shows closed caption or subtitles if this value is true, or hides.
      */
     public void setSubtitleEnabled(boolean enable) {
-        mImpl.setSubtitleEnabled(enable);
+        if (enable != mSubtitleEnabled) {
+            selectOrDeselectSubtitle(enable);
+        }
+        mSubtitleEnabled = enable;
     }
 
     /**
@@ -241,7 +517,7 @@
      * has been enabled by {@link #setSubtitleEnabled}.
      */
     public boolean isSubtitleEnabled() {
-        return mImpl.isSubtitleEnabled();
+        return mSubtitleEnabled;
     }
 
     /**
@@ -253,18 +529,17 @@
      * be reset to the normal speed 1.0f.
      * @param speed the playback speed. It should be positive.
      */
+    // TODO: Support this via MediaController2.
     public void setSpeed(float speed) {
-        mImpl.setSpeed(speed);
-    }
-
-    /**
-     * Returns playback speed.
-     *
-     * It returns the same value that has been set by {@link #setSpeed}, if it was available value.
-     * If {@link #setSpeed} has not been called before, then the normal speed 1.0f will be returned.
-     */
-    public float getSpeed() {
-        return mImpl.getSpeed();
+        if (speed <= 0.0f) {
+            Log.e(TAG, "Unsupported speed (" + speed + ") is ignored.");
+            return;
+        }
+        mSpeed = speed;
+        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
+            applySpeed();
+        }
+        updatePlaybackState();
     }
 
     /**
@@ -283,7 +558,14 @@
      *                  playback.
      */
     public void setAudioFocusRequest(int focusGain) {
-        mImpl.setAudioFocusRequest(focusGain);
+        if (focusGain != AudioManager.AUDIOFOCUS_NONE
+                && focusGain != AudioManager.AUDIOFOCUS_GAIN
+                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
+                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
+                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) {
+            throw new IllegalArgumentException("Illegal audio focus type " + focusGain);
+        }
+        mAudioFocusType = focusGain;
     }
 
     /**
@@ -292,19 +574,10 @@
      * @param attributes non-null <code>AudioAttributes</code>.
      */
     public void setAudioAttributes(@NonNull AudioAttributes attributes) {
-        mImpl.setAudioAttributes(AudioAttributesCompat.wrap(attributes));
-    }
-
-    /**
-     * Sets the {@link AudioAttributesCompat} to be used during the playback of the video.
-     *
-     * @param attributes non-null <code>AudioAttributesCompat</code>.
-     *
-     * @hide TODO unhide and remove setAudioAttributes with framework attributes
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    public void setAudioAttributes(@NonNull AudioAttributesCompat attributes) {
-        mImpl.setAudioAttributes(attributes);
+        if (attributes == null) {
+            throw new IllegalArgumentException("Illegal null AudioAttributes");
+        }
+        mAudioAttributes = attributes;
     }
 
     /**
@@ -312,11 +585,11 @@
      *
      * @param path the path of the video.
      *
-     * @hide
+     * @hide TODO remove
      */
     @RestrictTo(LIBRARY_GROUP)
     public void setVideoPath(String path) {
-        mImpl.setVideoUri(Uri.parse(path));
+        setVideoUri(Uri.parse(path));
     }
 
     /**
@@ -324,11 +597,11 @@
      *
      * @param uri the URI of the video.
      *
-     * @hide
+     * @hide TODO remove
      */
     @RestrictTo(LIBRARY_GROUP)
     public void setVideoUri(Uri uri) {
-        mImpl.setVideoUri(uri, null);
+        setVideoUri(uri, null);
     }
 
     /**
@@ -340,9 +613,13 @@
      *                changed with key/value pairs through the headers parameter with
      *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
      *                to disallow or allow cross domain redirection.
+     *
+     * @hide TODO remove
      */
-    public void setVideoUri(Uri uri, @Nullable Map<String, String> headers) {
-        mImpl.setVideoUri(uri, headers);
+    @RestrictTo(LIBRARY_GROUP)
+    public void setVideoUri(Uri uri, Map<String, String> headers) {
+        mSeekWhenPrepared = 0;
+        openVideo(uri, headers);
     }
 
     /**
@@ -350,11 +627,9 @@
      * object to VideoView2 is {@link #setDataSource}.
      * @param mediaItem the MediaItem2 to play
      * @see #setDataSource
-     *
-     * @hide
      */
-    @RestrictTo(LIBRARY_GROUP)
     public void setMediaItem(@NonNull MediaItem2 mediaItem) {
+        //mProvider.setMediaItem_impl(mediaItem);
     }
 
     /**
@@ -365,6 +640,7 @@
      */
     @RestrictTo(LIBRARY_GROUP)
     public void setDataSource(@NonNull DataSourceDesc dataSource) {
+        //mProvider.setDataSource_impl(dataSource);
     }
 
     /**
@@ -377,7 +653,22 @@
      * </ul>
      */
     public void setViewType(@ViewType int viewType) {
-        mImpl.setViewType(viewType);
+        if (viewType == mCurrentView.getViewType()) {
+            return;
+        }
+        VideoViewInterface targetView;
+        if (viewType == VideoView2.VIEW_TYPE_TEXTUREVIEW) {
+            Log.d(TAG, "switching to TextureView");
+            targetView = mTextureView;
+        } else if (viewType == VideoView2.VIEW_TYPE_SURFACEVIEW) {
+            Log.d(TAG, "switching to SurfaceView");
+            targetView = mSurfaceView;
+        } else {
+            throw new IllegalArgumentException("Unknown view type: " + viewType);
+        }
+        ((View) targetView).setVisibility(View.VISIBLE);
+        targetView.takeOver(mCurrentView);
+        requestLayout();
     }
 
     /**
@@ -387,7 +678,7 @@
      */
     @ViewType
     public int getViewType() {
-        return mImpl.getViewType();
+        return mCurrentView.getViewType();
     }
 
     /**
@@ -398,12 +689,17 @@
      *                   buttons in {@link MediaControlView2}.
      * @param executor executor to run callbacks on.
      * @param listener A listener to be called when a custom button is clicked.
-     * @hide
+     * @hide  TODO remove
      */
     @RestrictTo(LIBRARY_GROUP)
     public void setCustomActions(List<PlaybackStateCompat.CustomAction> actionList,
             Executor executor, OnCustomActionListener listener) {
-        mImpl.setCustomActions(actionList, executor, listener);
+        mCustomActionList = actionList;
+        mCustomActionListenerRecord = new Pair<>(executor, listener);
+
+        // Create a new playback builder in order to clear existing the custom actions.
+        mStateBuilder = null;
+        updatePlaybackState();
     }
 
     /**
@@ -415,19 +711,54 @@
     @VisibleForTesting
     @RestrictTo(LIBRARY_GROUP)
     public void setOnViewTypeChangedListener(OnViewTypeChangedListener l) {
-        mImpl.setOnViewTypeChangedListener(l);
+        mViewTypeChangedListener = l;
+    }
+
+    /**
+     * Registers a callback to be invoked when the fullscreen mode should be changed.
+     * @param l The callback that will be run
+     * @hide  TODO remove
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    public void setFullScreenRequestListener(OnFullScreenRequestListener l) {
+        mFullScreenRequestListener = l;
     }
 
     @Override
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
-        mImpl.onAttachedToWindowImpl();
+
+        // Create MediaSession
+        mMediaSession = new MediaSessionCompat(getContext(), "VideoView2MediaSession");
+        mMediaSession.setCallback(new MediaSessionCallback());
+        mMediaSession.setActive(true);
+        mMediaController = mMediaSession.getController();
+        // TODO (b/77158231)
+        // mMediaRouter = MediaRouter.getInstance(getContext());
+        // mMediaRouter.setMediaSession(mMediaSession);
+        // mMediaRouter.addCallback(mRouteSelector, mRouterCallback);
+        attachMediaControlView();
+        // TODO: remove this after moving MediaSession creating code inside initializing VideoView2
+        if (mCurrentState == STATE_PREPARED) {
+            extractTracks();
+            extractMetadata();
+            extractAudioMetadata();
+            if (mNeedUpdateMediaType) {
+                mMediaSession.sendSessionEvent(
+                        MediaControlView2.EVENT_UPDATE_MEDIA_TYPE_STATUS,
+                        mMediaTypeData);
+                mNeedUpdateMediaType = false;
+            }
+        }
     }
 
     @Override
     public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        mImpl.onDetachedFromWindowImpl();
+
+        mMediaSession.release();
+        mMediaSession = null;
+        mMediaController = null;
     }
 
     @Override
@@ -437,25 +768,76 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        mImpl.onTouchEventImpl(ev);
+        if (DEBUG) {
+            Log.d(TAG, "onTouchEvent(). mCurrentState=" + mCurrentState
+                    + ", mTargetState=" + mTargetState);
+        }
+        if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
+            if (!mIsMusicMediaType || mSizeType != SIZE_TYPE_FULL) {
+                toggleMediaControlViewVisibility();
+            }
+        }
+
         return super.onTouchEvent(ev);
     }
 
     @Override
     public boolean onTrackballEvent(MotionEvent ev) {
-        mImpl.onTrackballEventImpl(ev);
+        if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
+            if (!mIsMusicMediaType || mSizeType != SIZE_TYPE_FULL) {
+                toggleMediaControlViewVisibility();
+            }
+        }
+
         return super.onTrackballEvent(ev);
     }
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
+        // TODO: Test touch event handling logic thoroughly and simplify the logic.
         return super.dispatchTouchEvent(ev);
     }
 
     @Override
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        mImpl.onMeasureImpl(widthMeasureSpec, heightMeasureSpec);
+
+        if (mIsMusicMediaType) {
+            if (mPrevWidth != getMeasuredWidth()
+                    || mPrevHeight != getMeasuredHeight()) {
+                int currWidth = getMeasuredWidth();
+                int currHeight = getMeasuredHeight();
+                Point screenSize = new Point();
+                mManager.getDefaultDisplay().getSize(screenSize);
+                int screenWidth = screenSize.x;
+                int screenHeight = screenSize.y;
+
+                if (currWidth == screenWidth && currHeight == screenHeight) {
+                    int orientation = retrieveOrientation();
+                    if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
+                        inflateMusicView(R.layout.full_landscape_music);
+                    } else {
+                        inflateMusicView(R.layout.full_portrait_music);
+                    }
+
+                    if (mSizeType != SIZE_TYPE_FULL) {
+                        mSizeType = SIZE_TYPE_FULL;
+                        // Remove existing mFadeOut callback
+                        mMediaControlView.removeCallbacks(mFadeOut);
+                        mMediaControlView.setVisibility(View.VISIBLE);
+                    }
+                } else {
+                    if (mSizeType != SIZE_TYPE_EMBEDDED) {
+                        mSizeType = SIZE_TYPE_EMBEDDED;
+                        inflateMusicView(R.layout.embedded_music);
+                        // Add new mFadeOut callback
+                        mMediaControlView.postDelayed(mFadeOut, mShowControllerIntervalMs);
+                    }
+                }
+                mPrevWidth = currWidth;
+                mPrevHeight = currHeight;
+            }
+        }
     }
 
     /**
@@ -463,6 +845,7 @@
      *
      * @hide
      */
+    @VisibleForTesting
     @RestrictTo(LIBRARY_GROUP)
     public interface OnViewTypeChangedListener {
         /**
@@ -479,6 +862,19 @@
     }
 
     /**
+     * Interface definition of a callback to be invoked to inform the fullscreen mode is changed.
+     * Application should handle the fullscreen mode accordingly.
+     * @hide  TODO remove
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    public interface OnFullScreenRequestListener {
+        /**
+         * Called to indicate a fullscreen mode change.
+         */
+        void onFullScreenRequest(View view, boolean fullScreen);
+    }
+
+    /**
      * Interface definition of a callback to be invoked to inform that a custom action is performed.
      * @hide  TODO remove
      */
@@ -493,4 +889,901 @@
          */
         void onCustomAction(String action, Bundle extras);
     }
+
+    ///////////////////////////////////////////////////
+    // Implements VideoViewInterface.SurfaceListener
+    ///////////////////////////////////////////////////
+
+    @Override
+    public void onSurfaceCreated(View view, int width, int height) {
+        if (DEBUG) {
+            Log.d(TAG, "onSurfaceCreated(). mCurrentState=" + mCurrentState
+                    + ", mTargetState=" + mTargetState + ", width/height: " + width + "/" + height
+                    + ", " + view.toString());
+        }
+        if (needToStart()) {
+            mMediaController.getTransportControls().play();
+        }
+    }
+
+    @Override
+    public void onSurfaceDestroyed(View view) {
+        if (DEBUG) {
+            Log.d(TAG, "onSurfaceDestroyed(). mCurrentState=" + mCurrentState
+                    + ", mTargetState=" + mTargetState + ", " + view.toString());
+        }
+    }
+
+    @Override
+    public void onSurfaceChanged(View view, int width, int height) {
+        // TODO: Do we need to call requestLayout here?
+        if (DEBUG) {
+            Log.d(TAG, "onSurfaceChanged(). width/height: " + width + "/" + height
+                    + ", " + view.toString());
+        }
+    }
+
+    @Override
+    public void onSurfaceTakeOverDone(VideoViewInterface view) {
+        if (DEBUG) {
+            Log.d(TAG, "onSurfaceTakeOverDone(). Now current view is: " + view);
+        }
+        mCurrentView = view;
+        if (mViewTypeChangedListener != null) {
+            mViewTypeChangedListener.onViewTypeChanged(this, view.getViewType());
+        }
+        if (needToStart()) {
+            mMediaController.getTransportControls().play();
+        }
+    }
+
+    ///////////////////////////////////////////////////
+    // Protected or private methods
+    ///////////////////////////////////////////////////
+
+    private void attachMediaControlView() {
+        // Get MediaController from MediaSession and set it inside MediaControlView
+        mMediaControlView.setController(mMediaSession.getController());
+
+        LayoutParams params =
+                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+        addView(mMediaControlView, params);
+    }
+
+    private boolean isInPlaybackState() {
+        // TODO (b/77158231)
+        // return (mMediaPlayer != null || mRoutePlayer != null)
+        return (mMediaPlayer != null)
+                && mCurrentState != STATE_ERROR
+                && mCurrentState != STATE_IDLE
+                && mCurrentState != STATE_PREPARING;
+    }
+
+    private boolean needToStart() {
+        // TODO (b/77158231)
+        // return (mMediaPlayer != null || mRoutePlayer != null)
+        return (mMediaPlayer != null)
+                && isAudioGranted()
+                && isWaitingPlayback();
+    }
+
+    private boolean isWaitingPlayback() {
+        return mCurrentState != STATE_PLAYING && mTargetState == STATE_PLAYING;
+    }
+
+    private boolean isAudioGranted() {
+        return mAudioFocused || mAudioFocusType == AudioManager.AUDIOFOCUS_NONE;
+    }
+
+    AudioManager.OnAudioFocusChangeListener mAudioFocusListener =
+            new AudioManager.OnAudioFocusChangeListener() {
+        @Override
+        public void onAudioFocusChange(int focusChange) {
+            switch (focusChange) {
+                case AudioManager.AUDIOFOCUS_GAIN:
+                    mAudioFocused = true;
+                    if (needToStart()) {
+                        mMediaController.getTransportControls().play();
+                    }
+                    break;
+                case AudioManager.AUDIOFOCUS_LOSS:
+                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
+                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
+                    // There is no way to distinguish pause() by transient
+                    // audio focus loss and by other explicit actions.
+                    // TODO: If we can distinguish those cases, change the code to resume when it
+                    // gains audio focus again for AUDIOFOCUS_LOSS_TRANSIENT and
+                    // AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
+                    mAudioFocused = false;
+                    if (isInPlaybackState() && mMediaPlayer.isPlaying()) {
+                        mMediaController.getTransportControls().pause();
+                    } else {
+                        mTargetState = STATE_PAUSED;
+                    }
+            }
+        }
+    };
+
+    @SuppressWarnings("deprecation")
+    private void requestAudioFocus(int focusType) {
+        int result;
+        if (android.os.Build.VERSION.SDK_INT >= 26) {
+            AudioFocusRequest focusRequest;
+            focusRequest = new AudioFocusRequest.Builder(focusType)
+                    .setAudioAttributes(mAudioAttributes)
+                    .setOnAudioFocusChangeListener(mAudioFocusListener)
+                    .build();
+            result = mAudioManager.requestAudioFocus(focusRequest);
+        } else {
+            result = mAudioManager.requestAudioFocus(mAudioFocusListener,
+                    AudioManager.STREAM_MUSIC,
+                    focusType);
+        }
+        if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
+            mAudioFocused = false;
+        } else if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
+            mAudioFocused = true;
+        } else if (result == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
+            mAudioFocused = false;
+        }
+    }
+
+    // Creates a MediaPlayer instance and prepare playback.
+    private void openVideo(Uri uri, Map<String, String> headers) {
+        resetPlayer();
+        if (isRemotePlayback()) {
+            // TODO (b/77158231)
+            // mRoutePlayer.openVideo(dsd);
+            return;
+        }
+
+        try {
+            Log.d(TAG, "openVideo(): creating new MediaPlayer instance.");
+            mMediaPlayer = new MediaPlayer();
+            mSurfaceView.setMediaPlayer(mMediaPlayer);
+            mTextureView.setMediaPlayer(mMediaPlayer);
+            mCurrentView.assignSurfaceToMediaPlayer(mMediaPlayer);
+
+            final Context context = getContext();
+            // TODO: Add timely firing logic for more accurate sync between CC and video frame
+            // mSubtitleController = new SubtitleController(context);
+            // mSubtitleController.registerRenderer(new ClosedCaptionRenderer(context));
+            // mSubtitleController.setAnchor((SubtitleController.Anchor) mSubtitleView);
+
+            mMediaPlayer.setOnPreparedListener(mPreparedListener);
+            mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
+            mMediaPlayer.setOnCompletionListener(mCompletionListener);
+            mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
+            mMediaPlayer.setOnErrorListener(mErrorListener);
+            mMediaPlayer.setOnInfoListener(mInfoListener);
+            mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
+
+            mCurrentBufferPercentage = -1;
+            mMediaPlayer.setDataSource(getContext(), uri, headers);
+            mMediaPlayer.setAudioAttributes(mAudioAttributes);
+            // mMediaPlayer.setOnSubtitleDataListener(mSubtitleListener);
+            // we don't set the target state here either, but preserve the
+            // target state that was there before.
+            mCurrentState = STATE_PREPARING;
+            mMediaPlayer.prepareAsync();
+
+            // Save file name as title since the file may not have a title Metadata.
+            mTitle = uri.getPath();
+            String scheme = uri.getScheme();
+            if (scheme != null && scheme.equals("file")) {
+                mTitle = uri.getLastPathSegment();
+            }
+            mRetriever = new MediaMetadataRetriever();
+            mRetriever.setDataSource(getContext(), uri);
+
+            if (DEBUG) {
+                Log.d(TAG, "openVideo(). mCurrentState=" + mCurrentState
+                        + ", mTargetState=" + mTargetState);
+            }
+        } catch (IOException | IllegalArgumentException ex) {
+            Log.w(TAG, "Unable to open content: " + uri, ex);
+            mCurrentState = STATE_ERROR;
+            mTargetState = STATE_ERROR;
+            mErrorListener.onError(mMediaPlayer,
+                    MediaPlayer.MEDIA_ERROR_UNKNOWN, MediaPlayer.MEDIA_ERROR_IO);
+        }
+    }
+
+    /*
+     * Reset the media player in any state
+     */
+    @SuppressWarnings("deprecation")
+    private void resetPlayer() {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.reset();
+            mMediaPlayer.release();
+            mMediaPlayer = null;
+            mTextureView.setMediaPlayer(null);
+            mSurfaceView.setMediaPlayer(null);
+            mCurrentState = STATE_IDLE;
+            mTargetState = STATE_IDLE;
+            if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
+                mAudioManager.abandonAudioFocus(null);
+            }
+        }
+        mVideoWidth = 0;
+        mVideoHeight = 0;
+    }
+
+    private void updatePlaybackState() {
+        if (mStateBuilder == null) {
+            /*
+            // Get the capabilities of the player for this stream
+            mMetadata = mMediaPlayer.getMetadata(MediaPlayer.METADATA_ALL,
+                    MediaPlayer.BYPASS_METADATA_FILTER);
+
+            // Add Play action as default
+            long playbackActions = PlaybackStateCompat.ACTION_PLAY;
+            if (mMetadata != null) {
+                if (!mMetadata.has(Metadata.PAUSE_AVAILABLE)
+                        || mMetadata.getBoolean(Metadata.PAUSE_AVAILABLE)) {
+                    playbackActions |= PlaybackStateCompat.ACTION_PAUSE;
+                }
+                if (!mMetadata.has(Metadata.SEEK_BACKWARD_AVAILABLE)
+                        || mMetadata.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE)) {
+                    playbackActions |= PlaybackStateCompat.ACTION_REWIND;
+                }
+                if (!mMetadata.has(Metadata.SEEK_FORWARD_AVAILABLE)
+                        || mMetadata.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE)) {
+                    playbackActions |= PlaybackStateCompat.ACTION_FAST_FORWARD;
+                }
+                if (!mMetadata.has(Metadata.SEEK_AVAILABLE)
+                        || mMetadata.getBoolean(Metadata.SEEK_AVAILABLE)) {
+                    playbackActions |= PlaybackStateCompat.ACTION_SEEK_TO;
+                }
+            } else {
+                playbackActions |= (PlaybackStateCompat.ACTION_PAUSE
+                        | PlaybackStateCompat.ACTION_REWIND
+                        | PlaybackStateCompat.ACTION_FAST_FORWARD
+                        | PlaybackStateCompat.ACTION_SEEK_TO);
+            }
+            */
+            // TODO determine the actionable list based the metadata info.
+            long playbackActions = PlaybackStateCompat.ACTION_PLAY
+                    | PlaybackStateCompat.ACTION_PAUSE
+                    | PlaybackStateCompat.ACTION_REWIND | PlaybackStateCompat.ACTION_FAST_FORWARD
+                    | PlaybackStateCompat.ACTION_SEEK_TO;
+            mStateBuilder = new PlaybackStateCompat.Builder();
+            mStateBuilder.setActions(playbackActions);
+
+            if (mCustomActionList != null) {
+                for (PlaybackStateCompat.CustomAction action : mCustomActionList) {
+                    mStateBuilder.addCustomAction(action);
+                }
+            }
+        }
+        mStateBuilder.setState(getCorrespondingPlaybackState(),
+                mMediaPlayer.getCurrentPosition(), mSpeed);
+        if (mCurrentState != STATE_ERROR
+                && mCurrentState != STATE_IDLE
+                && mCurrentState != STATE_PREPARING) {
+            // TODO: this should be replaced with MediaPlayer2.getBufferedPosition() once it is
+            // implemented.
+            if (mCurrentBufferPercentage == -1) {
+                mStateBuilder.setBufferedPosition(-1);
+            } else {
+                mStateBuilder.setBufferedPosition(
+                        (long) (mCurrentBufferPercentage / 100.0 * mMediaPlayer.getDuration()));
+            }
+        }
+
+        // Set PlaybackState for MediaSession
+        if (mMediaSession != null) {
+            PlaybackStateCompat state = mStateBuilder.build();
+            mMediaSession.setPlaybackState(state);
+        }
+    }
+
+    private int getCorrespondingPlaybackState() {
+        switch (mCurrentState) {
+            case STATE_ERROR:
+                return PlaybackStateCompat.STATE_ERROR;
+            case STATE_IDLE:
+                return PlaybackStateCompat.STATE_NONE;
+            case STATE_PREPARING:
+                return PlaybackStateCompat.STATE_CONNECTING;
+            case STATE_PREPARED:
+                return PlaybackStateCompat.STATE_PAUSED;
+            case STATE_PLAYING:
+                return PlaybackStateCompat.STATE_PLAYING;
+            case STATE_PAUSED:
+                return PlaybackStateCompat.STATE_PAUSED;
+            case STATE_PLAYBACK_COMPLETED:
+                return PlaybackStateCompat.STATE_STOPPED;
+            default:
+                return -1;
+        }
+    }
+
+    private final Runnable mFadeOut = new Runnable() {
+        @Override
+        public void run() {
+            if (mCurrentState == STATE_PLAYING) {
+                mMediaControlView.setVisibility(View.GONE);
+            }
+        }
+    };
+
+    private void showController() {
+        // TODO: Decide what to show when the state is not in playback state
+        if (mMediaControlView == null || !isInPlaybackState()
+                || (mIsMusicMediaType && mSizeType == SIZE_TYPE_FULL)) {
+            return;
+        }
+        mMediaControlView.removeCallbacks(mFadeOut);
+        mMediaControlView.setVisibility(View.VISIBLE);
+        if (mShowControllerIntervalMs != 0
+                && !mAccessibilityManager.isTouchExplorationEnabled()) {
+            mMediaControlView.postDelayed(mFadeOut, mShowControllerIntervalMs);
+        }
+    }
+
+    private void toggleMediaControlViewVisibility() {
+        if (mMediaControlView.getVisibility() == View.VISIBLE) {
+            mMediaControlView.removeCallbacks(mFadeOut);
+            mMediaControlView.setVisibility(View.GONE);
+        } else {
+            showController();
+        }
+    }
+
+    private void applySpeed() {
+        if (android.os.Build.VERSION.SDK_INT < 23) {
+            // TODO: MediaPlayer2 will cover this, or implement with SoundPool.
+            return;
+        }
+        PlaybackParams params = mMediaPlayer.getPlaybackParams().allowDefaults();
+        if (mSpeed != params.getSpeed()) {
+            try {
+                params.setSpeed(mSpeed);
+                mMediaPlayer.setPlaybackParams(params);
+                mFallbackSpeed = mSpeed;
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "PlaybackParams has unsupported value: " + e);
+                // TODO: should revise this part after integrating with MP2.
+                // If mSpeed had an illegal value for speed rate, system will determine best
+                // handling (see PlaybackParams.AUDIO_FALLBACK_MODE_DEFAULT).
+                // Note: The pre-MP2 returns 0.0f when it is paused. In this case, VideoView2 will
+                // use mFallbackSpeed instead.
+                float fallbackSpeed = mMediaPlayer.getPlaybackParams().allowDefaults().getSpeed();
+                if (fallbackSpeed > 0.0f) {
+                    mFallbackSpeed = fallbackSpeed;
+                }
+                mSpeed = mFallbackSpeed;
+            }
+        }
+    }
+
+    private boolean isRemotePlayback() {
+        if (mMediaController == null) {
+            return false;
+        }
+        PlaybackInfo playbackInfo = mMediaController.getPlaybackInfo();
+        return playbackInfo != null
+                && playbackInfo.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE;
+    }
+
+    private void selectOrDeselectSubtitle(boolean select) {
+        if (!isInPlaybackState()) {
+            return;
+        }
+    /*
+        if (select) {
+            if (mSubtitleTrackIndices.size() > 0) {
+                // TODO: make this selection dynamic
+                mSelectedSubtitleTrackIndex = mSubtitleTrackIndices.get(0).first;
+                mSubtitleController.selectTrack(mSubtitleTrackIndices.get(0).second);
+                mMediaPlayer.selectTrack(mSelectedSubtitleTrackIndex);
+                mSubtitleView.setVisibility(View.VISIBLE);
+            }
+        } else {
+            if (mSelectedSubtitleTrackIndex != INVALID_TRACK_INDEX) {
+                mMediaPlayer.deselectTrack(mSelectedSubtitleTrackIndex);
+                mSelectedSubtitleTrackIndex = INVALID_TRACK_INDEX;
+                mSubtitleView.setVisibility(View.GONE);
+            }
+        }
+    */
+    }
+
+    private void extractTracks() {
+        MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo();
+        mVideoTrackIndices = new ArrayList<>();
+        mAudioTrackIndices = new ArrayList<>();
+        /*
+        mSubtitleTrackIndices = new ArrayList<>();
+        mSubtitleController.reset();
+        */
+        for (int i = 0; i < trackInfos.length; ++i) {
+            int trackType = trackInfos[i].getTrackType();
+            if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) {
+                mVideoTrackIndices.add(i);
+            } else if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
+                mAudioTrackIndices.add(i);
+                /*
+            } else if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE
+                    || trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) {
+                SubtitleTrack track = mSubtitleController.addTrack(trackInfos[i].getFormat());
+                if (track != null) {
+                    mSubtitleTrackIndices.add(new Pair<>(i, track));
+                }
+                */
+            }
+        }
+        // Select first tracks as default
+        if (mVideoTrackIndices.size() > 0) {
+            mSelectedVideoTrackIndex = 0;
+        }
+        if (mAudioTrackIndices.size() > 0) {
+            mSelectedAudioTrackIndex = 0;
+        }
+        if (mVideoTrackIndices.size() == 0 && mAudioTrackIndices.size() > 0) {
+            mIsMusicMediaType = true;
+        }
+
+        Bundle data = new Bundle();
+        data.putInt(MediaControlView2.KEY_VIDEO_TRACK_COUNT, mVideoTrackIndices.size());
+        data.putInt(MediaControlView2.KEY_AUDIO_TRACK_COUNT, mAudioTrackIndices.size());
+        /*
+        data.putInt(MediaControlView2.KEY_SUBTITLE_TRACK_COUNT, mSubtitleTrackIndices.size());
+        if (mSubtitleTrackIndices.size() > 0) {
+            selectOrDeselectSubtitle(mSubtitleEnabled);
+        }
+        */
+        mMediaSession.sendSessionEvent(MediaControlView2.EVENT_UPDATE_TRACK_STATUS, data);
+    }
+
+    private void extractMetadata() {
+        // Get and set duration and title values as MediaMetadata for MediaControlView2
+        MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
+        String title = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
+        if (title != null) {
+            mTitle = title;
+        }
+        builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mTitle);
+        builder.putLong(
+                MediaMetadataCompat.METADATA_KEY_DURATION, mMediaPlayer.getDuration());
+
+        if (mMediaSession != null) {
+            mMediaSession.setMetadata(builder.build());
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void extractAudioMetadata() {
+        if (!mIsMusicMediaType) {
+            return;
+        }
+
+        mResources = getResources();
+        mManager = (WindowManager) getContext().getApplicationContext()
+                .getSystemService(Context.WINDOW_SERVICE);
+
+        byte[] album = mRetriever.getEmbeddedPicture();
+        if (album != null) {
+            Bitmap bitmap = BitmapFactory.decodeByteArray(album, 0, album.length);
+            mMusicAlbumDrawable = new BitmapDrawable(bitmap);
+
+            // TODO: replace with visualizer
+            Palette.Builder builder = Palette.from(bitmap);
+            builder.generate(new Palette.PaletteAsyncListener() {
+                @Override
+                public void onGenerated(Palette palette) {
+                    // TODO: add dominant color for default album image.
+                    mDominantColor = palette.getDominantColor(0);
+                    if (mMusicView != null) {
+                        mMusicView.setBackgroundColor(mDominantColor);
+                    }
+                }
+            });
+        } else {
+            mMusicAlbumDrawable = mResources.getDrawable(R.drawable.ic_default_album_image);
+        }
+
+        String title = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
+        if (title != null) {
+            mMusicTitleText = title;
+        } else {
+            mMusicTitleText = mResources.getString(R.string.mcv2_music_title_unknown_text);
+        }
+
+        String artist = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
+        if (artist != null) {
+            mMusicArtistText = artist;
+        } else {
+            mMusicArtistText = mResources.getString(R.string.mcv2_music_artist_unknown_text);
+        }
+
+        // Send title and artist string to MediaControlView2
+        MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
+        builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mMusicTitleText);
+        builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, mMusicArtistText);
+        mMediaSession.setMetadata(builder.build());
+
+        // Display Embedded mode as default
+        removeView(mSurfaceView);
+        removeView(mTextureView);
+        inflateMusicView(R.layout.embedded_music);
+    }
+
+    private int retrieveOrientation() {
+        DisplayMetrics dm = Resources.getSystem().getDisplayMetrics();
+        int width = dm.widthPixels;
+        int height = dm.heightPixels;
+
+        return (height > width)
+                ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+                : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+    }
+
+    private void inflateMusicView(int layoutId) {
+        removeView(mMusicView);
+
+        LayoutInflater inflater = (LayoutInflater) getContext()
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        View v = inflater.inflate(layoutId, null);
+        v.setBackgroundColor(mDominantColor);
+
+        ImageView albumView = v.findViewById(R.id.album);
+        if (albumView != null) {
+            albumView.setImageDrawable(mMusicAlbumDrawable);
+        }
+
+        TextView titleView = v.findViewById(R.id.title);
+        if (titleView != null) {
+            titleView.setText(mMusicTitleText);
+        }
+
+        TextView artistView = v.findViewById(R.id.artist);
+        if (artistView != null) {
+            artistView.setText(mMusicArtistText);
+        }
+
+        mMusicView = v;
+        addView(mMusicView, 0);
+    }
+
+    /*
+    OnSubtitleDataListener mSubtitleListener =
+            new OnSubtitleDataListener() {
+                @Override
+                public void onSubtitleData(MediaPlayer mp, SubtitleData data) {
+                    if (DEBUG) {
+                        Log.d(TAG, "onSubtitleData(): getTrackIndex: " + data.getTrackIndex()
+                                + ", getCurrentPosition: " + mp.getCurrentPosition()
+                                + ", getStartTimeUs(): " + data.getStartTimeUs()
+                                + ", diff: "
+                                + (data.getStartTimeUs() / 1000 - mp.getCurrentPosition())
+                                + "ms, getDurationUs(): " + data.getDurationUs());
+
+                    }
+                    final int index = data.getTrackIndex();
+                    if (index != mSelectedSubtitleTrackIndex) {
+                        Log.d(TAG, "onSubtitleData(): getTrackIndex: " + data.getTrackIndex()
+                                + ", selected track index: " + mSelectedSubtitleTrackIndex);
+                        return;
+                    }
+                    for (Pair<Integer, SubtitleTrack> p : mSubtitleTrackIndices) {
+                        if (p.first == index) {
+                            SubtitleTrack track = p.second;
+                            track.onData(data);
+                        }
+                    }
+                }
+            };
+            */
+
+    MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
+            new MediaPlayer.OnVideoSizeChangedListener() {
+                @Override
+                public void onVideoSizeChanged(
+                        MediaPlayer mp, int width, int height) {
+                    if (DEBUG) {
+                        Log.d(TAG, "onVideoSizeChanged(): size: " + width + "/" + height);
+                    }
+                    mVideoWidth = mp.getVideoWidth();
+                    mVideoHeight = mp.getVideoHeight();
+                    if (DEBUG) {
+                        Log.d(TAG, "onVideoSizeChanged(): mVideoSize:" + mVideoWidth + "/"
+                                + mVideoHeight);
+                    }
+                    if (mVideoWidth != 0 && mVideoHeight != 0) {
+                        requestLayout();
+                    }
+                }
+            };
+    MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
+        @Override
+        public void onPrepared(MediaPlayer mp) {
+            if (DEBUG) {
+                Log.d(TAG, "OnPreparedListener(). mCurrentState=" + mCurrentState
+                        + ", mTargetState=" + mTargetState);
+            }
+            mCurrentState = STATE_PREPARED;
+            // Create and set playback state for MediaControlView2
+            updatePlaybackState();
+
+            // TODO: change this to send TrackInfos to MediaControlView2
+            // TODO: create MediaSession when initializing VideoView2
+            if (mMediaSession != null) {
+                extractTracks();
+            }
+
+            if (mMediaControlView != null) {
+                mMediaControlView.setEnabled(true);
+            }
+            int videoWidth = mp.getVideoWidth();
+            int videoHeight = mp.getVideoHeight();
+
+            // mSeekWhenPrepared may be changed after seekTo() call
+            long seekToPosition = mSeekWhenPrepared;
+            if (seekToPosition != 0) {
+                mMediaController.getTransportControls().seekTo(seekToPosition);
+            }
+
+            if (videoWidth != 0 && videoHeight != 0) {
+                if (videoWidth != mVideoWidth || videoHeight != mVideoHeight) {
+                    if (DEBUG) {
+                        Log.i(TAG, "OnPreparedListener() : ");
+                        Log.i(TAG, " video size: " + videoWidth + "/" + videoHeight);
+                        Log.i(TAG, " measuredSize: " + getMeasuredWidth() + "/"
+                                + getMeasuredHeight());
+                        Log.i(TAG, " viewSize: " + getWidth() + "/" + getHeight());
+                    }
+                    mVideoWidth = videoWidth;
+                    mVideoHeight = videoHeight;
+                    requestLayout();
+                }
+
+                if (needToStart()) {
+                    mMediaController.getTransportControls().play();
+                }
+            } else {
+                // We don't know the video size yet, but should start anyway.
+                // The video size might be reported to us later.
+                if (needToStart()) {
+                    mMediaController.getTransportControls().play();
+                }
+            }
+            // Get and set duration and title values as MediaMetadata for MediaControlView2
+            MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
+
+            // TODO: Get title via other public APIs.
+            /*
+            if (mMetadata != null && mMetadata.has(Metadata.TITLE)) {
+                mTitle = mMetadata.getString(Metadata.TITLE);
+            }
+            */
+            builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mTitle);
+            builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, mMediaPlayer.getDuration());
+
+            if (mMediaSession != null) {
+                mMediaSession.setMetadata(builder.build());
+
+                // TODO: merge this code with the above code when integrating with
+                // MediaSession2.
+                if (mNeedUpdateMediaType) {
+                    mMediaSession.sendSessionEvent(
+                            MediaControlView2.EVENT_UPDATE_MEDIA_TYPE_STATUS, mMediaTypeData);
+                    mNeedUpdateMediaType = false;
+                }
+            }
+        }
+    };
+
+    MediaPlayer.OnSeekCompleteListener mSeekCompleteListener =
+            new MediaPlayer.OnSeekCompleteListener() {
+                @Override
+                public void onSeekComplete(MediaPlayer mp) {
+                    updatePlaybackState();
+                }
+    };
+
+    MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
+        @Override
+        @SuppressWarnings("deprecation")
+        public void onCompletion(MediaPlayer mp) {
+            mCurrentState = STATE_PLAYBACK_COMPLETED;
+            mTargetState = STATE_PLAYBACK_COMPLETED;
+            updatePlaybackState();
+            if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
+                mAudioManager.abandonAudioFocus(null);
+            }
+        }
+    };
+
+    MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {
+        @Override
+        public boolean onInfo(MediaPlayer mp, int what, int extra) {
+            if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
+                extractTracks();
+            }
+            return true;
+        }
+    };
+
+    MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() {
+        @Override
+        public boolean onError(MediaPlayer mp, int frameworkErr, int implErr) {
+            if (DEBUG) {
+                Log.d(TAG, "Error: " + frameworkErr + "," + implErr);
+            }
+            mCurrentState = STATE_ERROR;
+            mTargetState = STATE_ERROR;
+            updatePlaybackState();
+
+            if (mMediaControlView != null) {
+                mMediaControlView.setVisibility(View.GONE);
+            }
+            return true;
+        }
+    };
+
+    MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
+            new MediaPlayer.OnBufferingUpdateListener() {
+        @Override
+        public void onBufferingUpdate(MediaPlayer mp, int percent) {
+            mCurrentBufferPercentage = percent;
+            updatePlaybackState();
+        }
+    };
+
+    private class MediaSessionCallback extends MediaSessionCompat.Callback {
+        @Override
+        public void onCommand(String command, Bundle args, ResultReceiver receiver) {
+            if (isRemotePlayback()) {
+                // TODO (b/77158231)
+                // mRoutePlayer.onCommand(command, args, receiver);
+            } else {
+                switch (command) {
+                    case MediaControlView2.COMMAND_SHOW_SUBTITLE:
+                        /*
+                        int subtitleIndex = args.getInt(
+                                MediaControlView2.KEY_SELECTED_SUBTITLE_INDEX,
+                                INVALID_TRACK_INDEX);
+                        if (subtitleIndex != INVALID_TRACK_INDEX) {
+                            int subtitleTrackIndex = mSubtitleTrackIndices.get(subtitleIndex).first;
+                            if (subtitleTrackIndex != mSelectedSubtitleTrackIndex) {
+                                mSelectedSubtitleTrackIndex = subtitleTrackIndex;
+                                setSubtitleEnabled(true);
+                            }
+                        }
+                        */
+                        break;
+                    case MediaControlView2.COMMAND_HIDE_SUBTITLE:
+                        setSubtitleEnabled(false);
+                        break;
+                    case MediaControlView2.COMMAND_SET_FULLSCREEN:
+                        if (mFullScreenRequestListener != null) {
+                            mFullScreenRequestListener.onFullScreenRequest(
+                                    VideoView2.this,
+                                    args.getBoolean(MediaControlView2.ARGUMENT_KEY_FULLSCREEN));
+                        }
+                        break;
+                    case MediaControlView2.COMMAND_SELECT_AUDIO_TRACK:
+                        int audioIndex = args.getInt(MediaControlView2.KEY_SELECTED_AUDIO_INDEX,
+                                INVALID_TRACK_INDEX);
+                        if (audioIndex != INVALID_TRACK_INDEX) {
+                            int audioTrackIndex = mAudioTrackIndices.get(audioIndex);
+                            if (audioTrackIndex != mSelectedAudioTrackIndex) {
+                                mSelectedAudioTrackIndex = audioTrackIndex;
+                                mMediaPlayer.selectTrack(mSelectedAudioTrackIndex);
+                            }
+                        }
+                        break;
+                    case MediaControlView2.COMMAND_SET_PLAYBACK_SPEED:
+                        float speed = args.getFloat(
+                                MediaControlView2.KEY_PLAYBACK_SPEED, INVALID_SPEED);
+                        if (speed != INVALID_SPEED && speed != mSpeed) {
+                            setSpeed(speed);
+                            mSpeed = speed;
+                        }
+                        break;
+                    case MediaControlView2.COMMAND_MUTE:
+                        mVolumeLevel = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
+                        break;
+                    case MediaControlView2.COMMAND_UNMUTE:
+                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mVolumeLevel, 0);
+                        break;
+                }
+            }
+            showController();
+        }
+
+        @Override
+        public void onCustomAction(final String action, final Bundle extras) {
+            mCustomActionListenerRecord.first.execute(new Runnable() {
+                @Override
+                public void run() {
+                    mCustomActionListenerRecord.second.onCustomAction(action, extras);
+                }
+            });
+            showController();
+        }
+
+        @Override
+        public void onPlay() {
+            if (!isAudioGranted()) {
+                requestAudioFocus(mAudioFocusType);
+            }
+
+            if ((isInPlaybackState() && mCurrentView.hasAvailableSurface()) || mIsMusicMediaType) {
+                if (isRemotePlayback()) {
+                    // TODO (b/77158231)
+                    // mRoutePlayer.onPlay();
+                } else {
+                    applySpeed();
+                    mMediaPlayer.start();
+                    mCurrentState = STATE_PLAYING;
+                    updatePlaybackState();
+                }
+                mCurrentState = STATE_PLAYING;
+            }
+            mTargetState = STATE_PLAYING;
+            if (DEBUG) {
+                Log.d(TAG, "onPlay(). mCurrentState=" + mCurrentState
+                        + ", mTargetState=" + mTargetState);
+            }
+            showController();
+        }
+
+        @Override
+        public void onPause() {
+            if (isInPlaybackState()) {
+                if (isRemotePlayback()) {
+                    // TODO (b/77158231)
+                    // mRoutePlayer.onPause();
+                    mCurrentState = STATE_PAUSED;
+                } else if (mMediaPlayer.isPlaying()) {
+                    mMediaPlayer.pause();
+                    mCurrentState = STATE_PAUSED;
+                    updatePlaybackState();
+                }
+            }
+            mTargetState = STATE_PAUSED;
+            if (DEBUG) {
+                Log.d(TAG, "onPause(). mCurrentState=" + mCurrentState
+                        + ", mTargetState=" + mTargetState);
+            }
+            showController();
+        }
+
+        @Override
+        public void onSeekTo(long pos) {
+            if (isInPlaybackState()) {
+                if (isRemotePlayback()) {
+                    // TODO (b/77158231)
+                    // mRoutePlayer.onSeekTo(pos);
+                } else {
+                    // TODO Refactor VideoView2 with FooImplBase and FooImplApiXX.
+                    if (android.os.Build.VERSION.SDK_INT < 26) {
+                        mMediaPlayer.seekTo((int) pos);
+                    } else {
+                        mMediaPlayer.seekTo(pos, MediaPlayer.SEEK_PREVIOUS_SYNC);
+                    }
+                    mSeekWhenPrepared = 0;
+                }
+            } else {
+                mSeekWhenPrepared = pos;
+            }
+            showController();
+        }
+
+        @Override
+        public void onStop() {
+            if (isRemotePlayback()) {
+                // TODO (b/77158231)
+                // mRoutePlayer.onStop();
+            } else {
+                resetPlayer();
+            }
+            showController();
+        }
+    }
 }
diff --git a/media-widget/src/main/java/androidx/media/widget/VideoView2Impl.java b/media-widget/src/main/java/androidx/media/widget/VideoView2Impl.java
deleted file mode 100644
index 7632490..0000000
--- a/media-widget/src/main/java/androidx/media/widget/VideoView2Impl.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.widget;
-
-import android.content.Context;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.support.v4.media.session.MediaControllerCompat;
-import android.support.v4.media.session.PlaybackStateCompat;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.media.AudioAttributesCompat;
-import androidx.media.DataSourceDesc;
-import androidx.media.MediaItem2;
-import androidx.media.MediaMetadata2;
-import androidx.media.SessionToken2;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-/**
- * Interface for impl classes.
- */
-interface VideoView2Impl {
-    void initialize(
-            VideoView2 instance, Context context,
-            @Nullable AttributeSet attrs, int defStyleAttr);
-
-    /**
-     * Sets MediaControlView2 instance. It will replace the previously assigned MediaControlView2
-     * instance if any.
-     *
-     * @param mediaControlView a media control view2 instance.
-     * @param intervalMs a time interval in milliseconds until VideoView2 hides MediaControlView2.
-     */
-    void setMediaControlView2(MediaControlView2 mediaControlView, long intervalMs);
-
-    /**
-     * Returns MediaControlView2 instance which is currently attached to VideoView2 by default or by
-     * {@link #setMediaControlView2} method.
-     */
-    MediaControlView2 getMediaControlView2();
-
-    /**
-     * Sets MediaMetadata2 instance. It will replace the previously assigned MediaMetadata2 instance
-     * if any.
-     *
-     * @param metadata a MediaMetadata2 instance.
-     */
-    void setMediaMetadata(MediaMetadata2 metadata);
-
-    /**
-     * Returns MediaMetadata2 instance which is retrieved from MediaPlayer inside VideoView2 by
-     * default or by {@link #setMediaMetadata} method.
-     */
-    MediaMetadata2 getMediaMetadata();
-
-    /**
-     * Returns MediaController instance which is connected with MediaSession that VideoView2 is
-     * using. This method should be called when VideoView2 is attached to window, or it throws
-     * IllegalStateException, since internal MediaSession instance is not available until
-     * this view is attached to window. Please check {@link View#isAttachedToWindow}
-     * before calling this method.
-     *
-     * @throws IllegalStateException if interal MediaSession is not created yet.
-     */
-    MediaControllerCompat getMediaController();
-
-    /**
-     * Returns {@link SessionToken2} so that developers create their own
-     * {@link androidx.media.MediaController2} instance. This method should be called when
-     * VideoView2 is attached to window, or it throws IllegalStateException.
-     *
-     * @throws IllegalStateException if interal MediaSession is not created yet.
-     */
-    SessionToken2 getMediaSessionToken();
-
-    /**
-     * Shows or hides closed caption or subtitles if there is any.
-     * The first subtitle track will be chosen if there multiple subtitle tracks exist.
-     * Default behavior of VideoView2 is not showing subtitle.
-     * @param enable shows closed caption or subtitles if this value is true, or hides.
-     */
-    void setSubtitleEnabled(boolean enable);
-
-    /**
-     * Returns true if showing subtitle feature is enabled or returns false.
-     * Although there is no subtitle track or closed caption, it can return true, if the feature
-     * has been enabled by {@link #setSubtitleEnabled}.
-     */
-    boolean isSubtitleEnabled();
-
-    /**
-     * Sets playback speed.
-     *
-     * It is expressed as a multiplicative factor, where normal speed is 1.0f. If it is less than
-     * or equal to zero, it will be just ignored and nothing will be changed. If it exceeds the
-     * maximum speed that internal engine supports, system will determine best handling or it will
-     * be reset to the normal speed 1.0f.
-     * @param speed the playback speed. It should be positive.
-     */
-    void setSpeed(float speed);
-
-    /**
-     * Returns playback speed.
-     *
-     * It returns the same value that has been set by {@link #setSpeed}, if it was available value.
-     * If {@link #setSpeed} has not been called before, then the normal speed 1.0f will be returned.
-     */
-    float getSpeed();
-
-    /**
-     * Sets which type of audio focus will be requested during the playback, or configures playback
-     * to not request audio focus. Valid values for focus requests are
-     * {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
-     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
-     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}. Or use
-     * {@link AudioManager#AUDIOFOCUS_NONE} to express that audio focus should not be
-     * requested when playback starts. You can for instance use this when playing a silent animation
-     * through this class, and you don't want to affect other audio applications playing in the
-     * background.
-     *
-     * @param focusGain the type of audio focus gain that will be requested, or
-     *                  {@link AudioManager#AUDIOFOCUS_NONE} to disable the use audio focus during
-     *                  playback.
-     */
-    void setAudioFocusRequest(int focusGain);
-
-    /**
-     * Sets the {@link AudioAttributesCompat} to be used during the playback of the video.
-     *
-     * @param attributes non-null <code>AudioAttributesCompat</code>.
-     */
-    void setAudioAttributes(@NonNull AudioAttributesCompat attributes);
-
-    /**
-     * Sets video path.
-     *
-     * @param path the path of the video.
-     */
-    void setVideoPath(String path);
-
-    /**
-     * Sets video URI.
-     *
-     * @param uri the URI of the video.
-     */
-    void setVideoUri(Uri uri);
-
-    /**
-     * Sets video URI using specific headers.
-     *
-     * @param uri     the URI of the video.
-     * @param headers the headers for the URI request.
-     *                Note that the cross domain redirection is allowed by default, but that can be
-     *                changed with key/value pairs through the headers parameter with
-     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
-     *                to disallow or allow cross domain redirection.
-     */
-    void setVideoUri(Uri uri, @Nullable Map<String, String> headers);
-
-    /**
-     * Sets {@link MediaItem2} object to render using VideoView2. Alternative way to set media
-     * object to VideoView2 is {@link #setDataSource}.
-     * @param mediaItem the MediaItem2 to play
-     * @see #setDataSource
-     */
-    void setMediaItem(@NonNull MediaItem2 mediaItem);
-
-    /**
-     * Sets {@link DataSourceDesc} object to render using VideoView2.
-     * @param dataSource the {@link DataSourceDesc} object to play.
-     * @see #setMediaItem
-     */
-    void setDataSource(@NonNull DataSourceDesc dataSource);
-
-    /**
-     * Selects which view will be used to render video between SurfacView and TextureView.
-     *
-     * @param viewType the view type to render video
-     * <ul>
-     * <li>{@link #VideoView2.VIEW_TYPE_SURFACEVIEW}
-     * <li>{@link #VideoView2.VIEW_TYPE_TEXTUREVIEW}
-     * </ul>
-     */
-    void setViewType(@VideoView2.ViewType int viewType);
-
-    /**
-     * Returns view type.
-     *
-     * @return view type. See {@see setViewType}.
-     */
-    @VideoView2.ViewType
-    int getViewType();
-
-    /**
-     * Sets custom actions which will be shown as custom buttons in {@link MediaControlView2}.
-     *
-     * @param actionList A list of {@link PlaybackStateCompat.CustomAction}. The return value of
-     *                   {@link PlaybackStateCompat.CustomAction#getIcon()} will be used to draw
-     *                   buttons in {@link MediaControlView2}.
-     * @param executor executor to run callbacks on.
-     * @param listener A listener to be called when a custom button is clicked.
-     */
-    void setCustomActions(List<PlaybackStateCompat.CustomAction> actionList,
-            Executor executor, VideoView2.OnCustomActionListener listener);
-
-    /**
-     * Registers a callback to be invoked when a view type change is done.
-     * {@see #setViewType(int)}
-     * @param l The callback that will be run
-     */
-    void setOnViewTypeChangedListener(VideoView2.OnViewTypeChangedListener l);
-
-    void onAttachedToWindowImpl();
-
-    void onDetachedFromWindowImpl();
-
-    void onTouchEventImpl(MotionEvent ev);
-
-    void onTrackballEventImpl(MotionEvent ev);
-
-    void onMeasureImpl(int widthMeasureSpec, int heightMeasureSpec);
-}
diff --git a/media-widget/src/main/java/androidx/media/widget/impl/VideoViewInterface.java b/media-widget/src/main/java/androidx/media/widget/VideoViewInterface.java
similarity index 94%
rename from media-widget/src/main/java/androidx/media/widget/impl/VideoViewInterface.java
rename to media-widget/src/main/java/androidx/media/widget/VideoViewInterface.java
index a497e32..81b40a9 100644
--- a/media-widget/src/main/java/androidx/media/widget/impl/VideoViewInterface.java
+++ b/media-widget/src/main/java/androidx/media/widget/VideoViewInterface.java
@@ -16,10 +16,10 @@
 
 package androidx.media.widget;
 
+import android.media.MediaPlayer;
 import android.view.View;
 
 import androidx.annotation.NonNull;
-import androidx.media.MediaPlayer2;
 
 interface VideoViewInterface {
     /**
@@ -29,10 +29,10 @@
      * @return true if the surface is successfully assigned, false if not. It will fail to assign
      *         if any of MediaPlayer or surface is unavailable.
      */
-    boolean assignSurfaceToMediaPlayer(MediaPlayer2 mp);
+    boolean assignSurfaceToMediaPlayer(MediaPlayer mp);
     void setSurfaceListener(SurfaceListener l);
     int getViewType();
-    void setMediaPlayer(MediaPlayer2 mp);
+    void setMediaPlayer(MediaPlayer mp);
 
     /**
      * Takes over oldView. It means that the MediaPlayer will start rendering on this view.
diff --git a/media-widget/src/main/java/androidx/media/widget/impl/VideoSurfaceView.java b/media-widget/src/main/java/androidx/media/widget/impl/VideoSurfaceView.java
deleted file mode 100644
index 5c140c8..0000000
--- a/media-widget/src/main/java/androidx/media/widget/impl/VideoSurfaceView.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.widget;
-
-import static androidx.media.widget.VideoView2.VIEW_TYPE_SURFACEVIEW;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.media.MediaPlayer2;
-
-@RequiresApi(21)
-class VideoSurfaceView extends SurfaceView
-        implements VideoViewInterface, SurfaceHolder.Callback {
-    private static final String TAG = "VideoSurfaceView";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private Surface mSurface = null;
-    private SurfaceListener mSurfaceListener = null;
-    private MediaPlayer2 mMediaPlayer;
-    // A flag to indicate taking over other view should be proceed.
-    private boolean mIsTakingOverOldView;
-    private VideoViewInterface mOldView;
-
-    VideoSurfaceView(Context context) {
-        super(context, null);
-        getHolder().addCallback(this);
-    }
-
-    ////////////////////////////////////////////////////
-    // implements VideoViewInterfaceWithMp1
-    ////////////////////////////////////////////////////
-
-    @Override
-    public boolean assignSurfaceToMediaPlayer(MediaPlayer2 mp) {
-        Log.d(TAG, "assignSurfaceToMediaPlayer(): mSurface: " + mSurface);
-        if (mp == null || !hasAvailableSurface()) {
-            return false;
-        }
-        mp.setSurface(mSurface);
-        return true;
-    }
-
-    @Override
-    public void setSurfaceListener(SurfaceListener l) {
-        mSurfaceListener = l;
-    }
-
-    @Override
-    public int getViewType() {
-        return VIEW_TYPE_SURFACEVIEW;
-    }
-
-    @Override
-    public void setMediaPlayer(MediaPlayer2 mp) {
-        mMediaPlayer = mp;
-        if (mIsTakingOverOldView) {
-            takeOver(mOldView);
-        }
-    }
-
-    @Override
-    public void takeOver(@NonNull VideoViewInterface oldView) {
-        if (assignSurfaceToMediaPlayer(mMediaPlayer)) {
-            ((View) oldView).setVisibility(GONE);
-            mIsTakingOverOldView = false;
-            mOldView = null;
-            if (mSurfaceListener != null) {
-                mSurfaceListener.onSurfaceTakeOverDone(this);
-            }
-        } else {
-            mIsTakingOverOldView = true;
-            mOldView = oldView;
-        }
-    }
-
-    @Override
-    public boolean hasAvailableSurface() {
-        return mSurface != null && mSurface.isValid();
-    }
-
-    ////////////////////////////////////////////////////
-    // implements SurfaceHolder.Callback
-    ////////////////////////////////////////////////////
-
-    @Override
-    public void surfaceCreated(SurfaceHolder holder) {
-        Log.d(TAG, "surfaceCreated: mSurface: " + mSurface + ", new : " + holder.getSurface());
-        mSurface = holder.getSurface();
-        if (mIsTakingOverOldView) {
-            takeOver(mOldView);
-        } else {
-            assignSurfaceToMediaPlayer(mMediaPlayer);
-        }
-
-        if (mSurfaceListener != null) {
-            Rect rect = holder.getSurfaceFrame();
-            mSurfaceListener.onSurfaceCreated(this, rect.width(), rect.height());
-        }
-    }
-
-    @Override
-    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-        if (mSurfaceListener != null) {
-            mSurfaceListener.onSurfaceChanged(this, width, height);
-        }
-    }
-
-    @Override
-    public void surfaceDestroyed(SurfaceHolder holder) {
-        // After we return from this we can't use the surface any more
-        mSurface = null;
-        if (mSurfaceListener != null) {
-            mSurfaceListener.onSurfaceDestroyed(this);
-        }
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int videoWidth = (mMediaPlayer == null) ? 0 : mMediaPlayer.getVideoWidth();
-        int videoHeight = (mMediaPlayer == null) ? 0 : mMediaPlayer.getVideoHeight();
-        if (DEBUG) {
-            Log.d(TAG, "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
-                    + MeasureSpec.toString(heightMeasureSpec) + ")");
-            Log.i(TAG, " measuredSize: " + getMeasuredWidth() + "/" + getMeasuredHeight());
-            Log.i(TAG, " viewSize: " + getWidth() + "/" + getHeight());
-            Log.i(TAG, " mVideoWidth/height: " + videoWidth + ", " + videoHeight);
-        }
-
-        int width = getDefaultSize(videoWidth, widthMeasureSpec);
-        int height = getDefaultSize(videoHeight, heightMeasureSpec);
-
-        if (videoWidth > 0 && videoHeight > 0) {
-            int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
-            int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
-
-            width = widthSpecSize;
-            height = heightSpecSize;
-
-            // for compatibility, we adjust size based on aspect ratio
-            if (videoWidth * height < width * videoHeight) {
-                width = height * videoWidth / videoHeight;
-                if (DEBUG) {
-                    Log.d(TAG, "image too wide, correcting. width: " + width);
-                }
-            } else if (videoWidth * height > width * videoHeight) {
-                height = width * videoHeight / videoWidth;
-                if (DEBUG) {
-                    Log.d(TAG, "image too tall, correcting. height: " + height);
-                }
-            }
-        } else {
-            // no size yet, just adopt the given spec sizes
-        }
-        setMeasuredDimension(width, height);
-        if (DEBUG) {
-            Log.i(TAG, "end of onMeasure()");
-            Log.i(TAG, " measuredSize: " + getMeasuredWidth() + "/" + getMeasuredHeight());
-        }
-    }
-}
diff --git a/media-widget/src/main/java/androidx/media/widget/impl/VideoView2ImplBase.java b/media-widget/src/main/java/androidx/media/widget/impl/VideoView2ImplBase.java
deleted file mode 100644
index 68477f8..0000000
--- a/media-widget/src/main/java/androidx/media/widget/impl/VideoView2ImplBase.java
+++ /dev/null
@@ -1,1570 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.widget;
-
-import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Point;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.media.AudioAttributes;
-import android.media.AudioFocusRequest;
-import android.media.AudioManager;
-import android.media.MediaMetadataRetriever;
-import android.media.PlaybackParams;
-import android.media.SubtitleData;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.ResultReceiver;
-import android.support.v4.media.MediaMetadataCompat;
-import android.support.v4.media.session.MediaControllerCompat;
-import android.support.v4.media.session.MediaControllerCompat.PlaybackInfo;
-import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v4.media.session.PlaybackStateCompat;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.Pair;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
-import androidx.media.AudioAttributesCompat;
-import androidx.media.DataSourceDesc;
-import androidx.media.MediaItem2;
-import androidx.media.MediaMetadata2;
-import androidx.media.MediaPlayer2;
-import androidx.media.MediaPlayer2.MediaPlayer2EventCallback;
-import androidx.media.SessionToken2;
-import androidx.media.subtitle.ClosedCaptionRenderer;
-import androidx.media.subtitle.SubtitleController;
-import androidx.media.subtitle.SubtitleTrack;
-import androidx.mediarouter.media.MediaControlIntent;
-import androidx.mediarouter.media.MediaItemStatus;
-import androidx.mediarouter.media.MediaRouteSelector;
-import androidx.mediarouter.media.MediaRouter;
-import androidx.palette.graphics.Palette;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-/**
- * Base implementation of VideoView2.
- */
-@RequiresApi(28) // TODO correct minSdk API use incompatibilities and remove before release.
-class VideoView2ImplBase implements VideoView2Impl, VideoViewInterface.SurfaceListener {
-    private static final String TAG = "VideoView2ImplBase";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final long DEFAULT_SHOW_CONTROLLER_INTERVAL_MS = 2000;
-
-    private static final int STATE_ERROR = -1;
-    private static final int STATE_IDLE = 0;
-    private static final int STATE_PREPARING = 1;
-    private static final int STATE_PREPARED = 2;
-    private static final int STATE_PLAYING = 3;
-    private static final int STATE_PAUSED = 4;
-    private static final int STATE_PLAYBACK_COMPLETED = 5;
-
-    private static final int INVALID_TRACK_INDEX = -1;
-    private static final float INVALID_SPEED = 0f;
-
-    private static final int SIZE_TYPE_EMBEDDED = 0;
-    private static final int SIZE_TYPE_FULL = 1;
-    private static final int SIZE_TYPE_MINIMAL = 2;
-
-    private AccessibilityManager mAccessibilityManager;
-    private AudioManager mAudioManager;
-    private AudioAttributesCompat mAudioAttributes;
-    private int mAudioFocusType = AudioManager.AUDIOFOCUS_GAIN; // legacy focus gain
-    private boolean mAudioFocused = false;
-
-    private Pair<Executor, VideoView2.OnCustomActionListener> mCustomActionListenerRecord;
-    private VideoView2.OnViewTypeChangedListener mViewTypeChangedListener;
-
-    private VideoViewInterface mCurrentView;
-    private VideoTextureView mTextureView;
-    private VideoSurfaceView mSurfaceView;
-
-    private MediaPlayer2 mMediaPlayer;
-    private DataSourceDesc mDsd;
-    private Uri mUri;
-    private Map<String, String> mHeaders;
-    private MediaControlView2 mMediaControlView;
-    private MediaSessionCompat mMediaSession;
-    private MediaControllerCompat mMediaController;
-    private MediaMetadata2 mMediaMetadata;
-    private MediaMetadataRetriever mRetriever;
-    private boolean mNeedUpdateMediaType;
-    private Bundle mMediaTypeData;
-    private String mTitle;
-
-    private WindowManager mManager;
-    private Resources mResources;
-    private View mMusicView;
-    private Drawable mMusicAlbumDrawable;
-    private String mMusicTitleText;
-    private String mMusicArtistText;
-    private boolean mIsMusicMediaType;
-    private int mPrevWidth;
-    private int mPrevHeight;
-    private int mDominantColor;
-    private int mSizeType;
-
-    private PlaybackStateCompat.Builder mStateBuilder;
-    private List<PlaybackStateCompat.CustomAction> mCustomActionList;
-
-    private int mTargetState = STATE_IDLE;
-    private int mCurrentState = STATE_IDLE;
-    private int mCurrentBufferPercentage;
-    private long mSeekWhenPrepared;  // recording the seek position while preparing
-
-    private int mVideoWidth;
-    private int mVideoHeight;
-
-    private ArrayList<Integer> mVideoTrackIndices;
-    private ArrayList<Integer> mAudioTrackIndices;
-    private ArrayList<Pair<Integer, SubtitleTrack>> mSubtitleTrackIndices;
-    private SubtitleController mSubtitleController;
-
-    // selected video/audio/subtitle track index as MediaPlayer returns
-    private int mSelectedVideoTrackIndex;
-    private int mSelectedAudioTrackIndex;
-    private int mSelectedSubtitleTrackIndex;
-
-    private SubtitleView mSubtitleView;
-    private boolean mSubtitleEnabled;
-
-    private float mSpeed;
-    private float mFallbackSpeed;  // keep the original speed before 'pause' is called.
-    private float mVolumeLevelFloat;
-    private int mVolumeLevel;
-    private VideoView2 mInstance;
-
-    private long mShowControllerIntervalMs;
-
-    private MediaRouter mMediaRouter;
-    private MediaRouteSelector mRouteSelector;
-    private MediaRouter.RouteInfo mRoute;
-    private RoutePlayer mRoutePlayer;
-
-    private final MediaRouter.Callback mRouterCallback = new MediaRouter.Callback() {
-        @Override
-        public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo route) {
-            if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
-                // Stop local playback (if necessary)
-                resetPlayer();
-                mRoute = route;
-                mRoutePlayer = new RoutePlayer(mInstance.getContext(), route);
-                mRoutePlayer.setPlayerEventCallback(new RoutePlayer.PlayerEventCallback() {
-                    @Override
-                    public void onPlayerStateChanged(MediaItemStatus itemStatus) {
-                        PlaybackStateCompat.Builder psBuilder = new PlaybackStateCompat.Builder();
-                        psBuilder.setActions(RoutePlayer.PLAYBACK_ACTIONS);
-                        long position = itemStatus.getContentPosition();
-                        switch (itemStatus.getPlaybackState()) {
-                            case MediaItemStatus.PLAYBACK_STATE_PENDING:
-                                psBuilder.setState(PlaybackStateCompat.STATE_NONE, position, 0);
-                                mCurrentState = STATE_IDLE;
-                                break;
-                            case MediaItemStatus.PLAYBACK_STATE_PLAYING:
-                                psBuilder.setState(PlaybackStateCompat.STATE_PLAYING, position, 1);
-                                mCurrentState = STATE_PLAYING;
-                                break;
-                            case MediaItemStatus.PLAYBACK_STATE_PAUSED:
-                                psBuilder.setState(PlaybackStateCompat.STATE_PAUSED, position, 0);
-                                mCurrentState = STATE_PAUSED;
-                                break;
-                            case MediaItemStatus.PLAYBACK_STATE_BUFFERING:
-                                psBuilder.setState(
-                                        PlaybackStateCompat.STATE_BUFFERING, position, 0);
-                                mCurrentState = STATE_PAUSED;
-                                break;
-                            case MediaItemStatus.PLAYBACK_STATE_FINISHED:
-                                psBuilder.setState(PlaybackStateCompat.STATE_STOPPED, position, 0);
-                                mCurrentState = STATE_PLAYBACK_COMPLETED;
-                                break;
-                        }
-
-                        PlaybackStateCompat pbState = psBuilder.build();
-                        mMediaSession.setPlaybackState(pbState);
-
-                        MediaMetadataCompat.Builder mmBuilder = new MediaMetadataCompat.Builder();
-                        mmBuilder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION,
-                                itemStatus.getContentDuration());
-                        mMediaSession.setMetadata(mmBuilder.build());
-                    }
-                });
-                // Start remote playback (if necessary)
-                // TODO: b/77556429
-                mRoutePlayer.openVideo(mUri);
-            }
-        }
-
-        @Override
-        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route, int reason) {
-            if (mRoute != null && mRoutePlayer != null) {
-                mRoutePlayer.release();
-                mRoutePlayer = null;
-            }
-            if (mRoute == route) {
-                mRoute = null;
-            }
-            if (reason != MediaRouter.UNSELECT_REASON_ROUTE_CHANGED) {
-                // TODO: Resume local playback  (if necessary)
-                // TODO: b/77556429
-                openVideo(mDsd);
-            }
-        }
-    };
-
-    @Override
-    public void initialize(
-            VideoView2 instance, Context context,
-            @Nullable AttributeSet attrs, int defStyleAttr) {
-        mInstance = instance;
-
-        mVideoWidth = 0;
-        mVideoHeight = 0;
-        mSpeed = 1.0f;
-        mFallbackSpeed = mSpeed;
-        mSelectedSubtitleTrackIndex = INVALID_TRACK_INDEX;
-        mShowControllerIntervalMs = DEFAULT_SHOW_CONTROLLER_INTERVAL_MS;
-
-        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
-                Context.ACCESSIBILITY_SERVICE);
-
-        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        mAudioAttributes = new AudioAttributesCompat.Builder()
-                .setUsage(AudioAttributesCompat.USAGE_MEDIA)
-                .setContentType(AudioAttributesCompat.CONTENT_TYPE_MOVIE).build();
-
-        mInstance.setFocusable(true);
-        mInstance.setFocusableInTouchMode(true);
-        mInstance.requestFocus();
-
-        mTextureView = new VideoTextureView(context);
-        mSurfaceView = new VideoSurfaceView(context);
-        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
-                LayoutParams.MATCH_PARENT);
-        mTextureView.setLayoutParams(params);
-        mSurfaceView.setLayoutParams(params);
-        mTextureView.setSurfaceListener(this);
-        mSurfaceView.setSurfaceListener(this);
-
-        mInstance.addView(mTextureView);
-        mInstance.addView(mSurfaceView);
-
-        mSubtitleView = new SubtitleView(context);
-        mSubtitleView.setLayoutParams(params);
-        mSubtitleView.setBackgroundColor(0);
-        mInstance.addView(mSubtitleView);
-
-        boolean enableControlView = (attrs == null) || attrs.getAttributeBooleanValue(
-                "http://schemas.android.com/apk/res/android",
-                "enableControlView", true);
-        if (enableControlView) {
-            mMediaControlView = new MediaControlView2(context);
-        }
-
-        mSubtitleEnabled = (attrs == null) || attrs.getAttributeBooleanValue(
-                "http://schemas.android.com/apk/res/android",
-                "enableSubtitle", false);
-
-        // Choose surface view by default
-        int viewType = (attrs == null) ? VideoView2.VIEW_TYPE_SURFACEVIEW
-                : attrs.getAttributeIntValue(
-                "http://schemas.android.com/apk/res/android",
-                "viewType", VideoView2.VIEW_TYPE_SURFACEVIEW);
-        if (viewType == VideoView2.VIEW_TYPE_SURFACEVIEW) {
-            Log.d(TAG, "viewType attribute is surfaceView.");
-            mTextureView.setVisibility(View.GONE);
-            mSurfaceView.setVisibility(View.VISIBLE);
-            mCurrentView = mSurfaceView;
-        } else if (viewType == VideoView2.VIEW_TYPE_TEXTUREVIEW) {
-            Log.d(TAG, "viewType attribute is textureView.");
-            mTextureView.setVisibility(View.VISIBLE);
-            mSurfaceView.setVisibility(View.GONE);
-            mCurrentView = mTextureView;
-        }
-
-        MediaRouteSelector.Builder builder = new MediaRouteSelector.Builder();
-        builder.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
-        builder.addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO);
-        builder.addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO);
-        mRouteSelector = builder.build();
-    }
-
-    /**
-     * Sets MediaControlView2 instance. It will replace the previously assigned MediaControlView2
-     * instance if any.
-     *
-     * @param mediaControlView a media control view2 instance.
-     * @param intervalMs a time interval in milliseconds until VideoView2 hides MediaControlView2.
-     */
-    @Override
-    public void setMediaControlView2(MediaControlView2 mediaControlView, long intervalMs) {
-        mMediaControlView = mediaControlView;
-        mShowControllerIntervalMs = intervalMs;
-        mMediaControlView.setRouteSelector(mRouteSelector);
-
-        if (mInstance.isAttachedToWindow()) {
-            attachMediaControlView();
-        }
-    }
-
-    /**
-     * Returns MediaControlView2 instance which is currently attached to VideoView2 by default or by
-     * {@link #setMediaControlView2} method.
-     */
-    @Override
-    public MediaControlView2 getMediaControlView2() {
-        return mMediaControlView;
-    }
-
-    /**
-     * Sets MediaMetadata2 instance. It will replace the previously assigned MediaMetadata2 instance
-     * if any.
-     *
-     * @param metadata a MediaMetadata2 instance.
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setMediaMetadata(MediaMetadata2 metadata) {
-      //mProvider.setMediaMetadata_impl(metadata);
-    }
-
-    /**
-     * Returns MediaMetadata2 instance which is retrieved from MediaPlayer inside VideoView2 by
-     * default or by {@link #setMediaMetadata} method.
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public MediaMetadata2 getMediaMetadata() {
-        return mMediaMetadata;
-    }
-
-    /**
-     * Returns MediaController instance which is connected with MediaSession that VideoView2 is
-     * using. This method should be called when VideoView2 is attached to window, or it throws
-     * IllegalStateException, since internal MediaSession instance is not available until
-     * this view is attached to window. Please check {@link View#isAttachedToWindow}
-     * before calling this method.
-     *
-     * @throws IllegalStateException if interal MediaSession is not created yet.
-     * @hide  TODO: remove
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public MediaControllerCompat getMediaController() {
-        if (mMediaSession == null) {
-            throw new IllegalStateException("MediaSession instance is not available.");
-        }
-        return mMediaController;
-    }
-
-    /**
-     * Returns {@link SessionToken2} so that developers create their own
-     * {@link androidx.media.MediaController2} instance. This method should be called when
-     * VideoView2 is attached to window, or it throws IllegalStateException.
-     *
-     * @throws IllegalStateException if interal MediaSession is not created yet.
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public SessionToken2 getMediaSessionToken() {
-        //return mProvider.getMediaSessionToken_impl();
-        return null;
-    }
-
-    /**
-     * Shows or hides closed caption or subtitles if there is any.
-     * The first subtitle track will be chosen if there multiple subtitle tracks exist.
-     * Default behavior of VideoView2 is not showing subtitle.
-     * @param enable shows closed caption or subtitles if this value is true, or hides.
-     */
-    @Override
-    public void setSubtitleEnabled(boolean enable) {
-        // No-op on API < 28
-    }
-
-    /**
-     * Returns true if showing subtitle feature is enabled or returns false.
-     * Although there is no subtitle track or closed caption, it can return true, if the feature
-     * has been enabled by {@link #setSubtitleEnabled}.
-     */
-    @Override
-    public boolean isSubtitleEnabled() {
-        // Not supported on API < 28
-        return false;
-    }
-
-    /**
-     * Sets playback speed.
-     *
-     * It is expressed as a multiplicative factor, where normal speed is 1.0f. If it is less than
-     * or equal to zero, it will be just ignored and nothing will be changed. If it exceeds the
-     * maximum speed that internal engine supports, system will determine best handling or it will
-     * be reset to the normal speed 1.0f.
-     * @param speed the playback speed. It should be positive.
-     */
-    @Override
-    public void setSpeed(float speed) {
-        if (speed <= 0.0f) {
-            Log.e(TAG, "Unsupported speed (" + speed + ") is ignored.");
-            return;
-        }
-        mSpeed = speed;
-        if (isPlaying()) {
-            applySpeed();
-        }
-        updatePlaybackState();
-    }
-
-    /**
-     * Returns playback speed.
-     *
-     * It returns the same value that has been set by {@link #setSpeed}, if it was available value.
-     * If {@link #setSpeed} has not been called before, then the normal speed 1.0f will be returned.
-     */
-    @Override
-    public float getSpeed() {
-        return mSpeed;
-    }
-
-    /**
-     * Sets which type of audio focus will be requested during the playback, or configures playback
-     * to not request audio focus. Valid values for focus requests are
-     * {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
-     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
-     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}. Or use
-     * {@link AudioManager#AUDIOFOCUS_NONE} to express that audio focus should not be
-     * requested when playback starts. You can for instance use this when playing a silent animation
-     * through this class, and you don't want to affect other audio applications playing in the
-     * background.
-     *
-     * @param focusGain the type of audio focus gain that will be requested, or
-     *                  {@link AudioManager#AUDIOFOCUS_NONE} to disable the use audio focus during
-     *                  playback.
-     */
-    @Override
-    public void setAudioFocusRequest(int focusGain) {
-        if (focusGain != AudioManager.AUDIOFOCUS_NONE
-                && focusGain != AudioManager.AUDIOFOCUS_GAIN
-                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
-                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
-                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) {
-            throw new IllegalArgumentException("Illegal audio focus type " + focusGain);
-        }
-        mAudioFocusType = focusGain;
-    }
-
-    /**
-     * Sets the {@link AudioAttributesCompat} to be used during the playback of the video.
-     *
-     * @param attributes non-null <code>AudioAttributesCompat</code>.
-     */
-    @Override
-    public void setAudioAttributes(@NonNull AudioAttributesCompat attributes) {
-        if (attributes == null) {
-            throw new IllegalArgumentException("Illegal null AudioAttributes");
-        }
-        mAudioAttributes = attributes;
-    }
-
-    /**
-     * Sets video path.
-     *
-     * @param path the path of the video.
-     *
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setVideoPath(String path) {
-        setVideoUri(Uri.parse(path));
-    }
-
-    /**
-     * Sets video URI.
-     *
-     * @param uri the URI of the video.
-     *
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setVideoUri(Uri uri) {
-        setVideoUri(uri, null);
-    }
-
-    /**
-     * Sets video URI using specific headers.
-     *
-     * @param uri     the URI of the video.
-     * @param headers the headers for the URI request.
-     *                Note that the cross domain redirection is allowed by default, but that can be
-     *                changed with key/value pairs through the headers parameter with
-     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
-     *                to disallow or allow cross domain redirection.
-     */
-    @Override
-    public void setVideoUri(Uri uri, @Nullable Map<String, String> headers) {
-        DataSourceDesc.Builder builder = new DataSourceDesc.Builder();
-        builder.setDataSource(mInstance.getContext(), uri, headers, null);
-        setDataSource(builder.build());
-    }
-
-    /**
-     * Sets {@link MediaItem2} object to render using VideoView2. Alternative way to set media
-     * object to VideoView2 is {@link #setDataSource}.
-     * @param mediaItem the MediaItem2 to play
-     * @see #setDataSource
-     *
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setMediaItem(@NonNull MediaItem2 mediaItem) {
-    }
-
-    /**
-     * Sets {@link DataSourceDesc} object to render using VideoView2.
-     * @param dataSource the {@link DataSourceDesc} object to play.
-     * @see #setMediaItem
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setDataSource(@NonNull DataSourceDesc dataSource) {
-        mDsd = dataSource;
-        mSeekWhenPrepared = 0;
-        openVideo(dataSource);
-    }
-
-    /**
-     * Selects which view will be used to render video between SurfacView and TextureView.
-     *
-     * @param viewType the view type to render video
-     * <ul>
-     * <li>{@link #VideoView2.VIEW_TYPE_SURFACEVIEW}
-     * <li>{@link #VideoView2.VIEW_TYPE_TEXTUREVIEW}
-     * </ul>
-     */
-    @Override
-    public void setViewType(@VideoView2.ViewType int viewType) {
-        if (viewType == mCurrentView.getViewType()) {
-            return;
-        }
-        VideoViewInterface targetView;
-        if (viewType == VideoView2.VIEW_TYPE_TEXTUREVIEW) {
-            Log.d(TAG, "switching to TextureView");
-            targetView = mTextureView;
-        } else if (viewType == VideoView2.VIEW_TYPE_SURFACEVIEW) {
-            Log.d(TAG, "switching to SurfaceView");
-            targetView = mSurfaceView;
-        } else {
-            throw new IllegalArgumentException("Unknown view type: " + viewType);
-        }
-        ((View) targetView).setVisibility(View.VISIBLE);
-        targetView.takeOver(mCurrentView);
-        mInstance.requestLayout();
-    }
-
-    /**
-     * Returns view type.
-     *
-     * @return view type. See {@see setViewType}.
-     */
-    @VideoView2.ViewType
-    @Override
-    public int getViewType() {
-        return mCurrentView.getViewType();
-    }
-
-    /**
-     * Sets custom actions which will be shown as custom buttons in {@link MediaControlView2}.
-     *
-     * @param actionList A list of {@link PlaybackStateCompat.CustomAction}. The return value of
-     *                   {@link PlaybackStateCompat.CustomAction#getIcon()} will be used to draw
-     *                   buttons in {@link MediaControlView2}.
-     * @param executor executor to run callbacks on.
-     * @param listener A listener to be called when a custom button is clicked.
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setCustomActions(List<PlaybackStateCompat.CustomAction> actionList,
-            Executor executor, VideoView2.OnCustomActionListener listener) {
-        mCustomActionList = actionList;
-        mCustomActionListenerRecord = new Pair<>(executor, listener);
-
-        // Create a new playback builder in order to clear existing the custom actions.
-        mStateBuilder = null;
-        updatePlaybackState();
-    }
-
-    /**
-     * Registers a callback to be invoked when a view type change is done.
-     * {@see #setViewType(int)}
-     * @param l The callback that will be run
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setOnViewTypeChangedListener(VideoView2.OnViewTypeChangedListener l) {
-        mViewTypeChangedListener = l;
-    }
-
-    @Override
-    public void onAttachedToWindowImpl() {
-        // Create MediaSession
-        mMediaSession = new MediaSessionCompat(mInstance.getContext(), "VideoView2MediaSession");
-        mMediaSession.setCallback(new MediaSessionCallback());
-        mMediaSession.setActive(true);
-        mMediaController = mMediaSession.getController();
-        attachMediaControlView();
-        if (mCurrentState == STATE_PREPARED) {
-            extractTracks();
-            extractMetadata();
-            extractAudioMetadata();
-            if (mNeedUpdateMediaType) {
-                mMediaSession.sendSessionEvent(
-                        MediaControlView2.EVENT_UPDATE_MEDIA_TYPE_STATUS,
-                        mMediaTypeData);
-                mNeedUpdateMediaType = false;
-            }
-        }
-
-        mMediaRouter = MediaRouter.getInstance(mInstance.getContext());
-        mMediaRouter.setMediaSessionCompat(mMediaSession);
-        mMediaRouter.addCallback(mRouteSelector, mRouterCallback,
-                MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
-    }
-
-    @Override
-    public void onDetachedFromWindowImpl() {
-        mMediaSession.release();
-        mMediaSession = null;
-        mMediaController = null;
-    }
-
-    @Override
-    public void onTouchEventImpl(MotionEvent ev) {
-        if (DEBUG) {
-            Log.d(TAG, "onTouchEvent(). mCurrentState=" + mCurrentState
-                    + ", mTargetState=" + mTargetState);
-        }
-        if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
-            if (!mIsMusicMediaType || mSizeType != SIZE_TYPE_FULL) {
-                toggleMediaControlViewVisibility();
-            }
-        }
-    }
-
-    @Override
-    public void onTrackballEventImpl(MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
-            if (!mIsMusicMediaType || mSizeType != SIZE_TYPE_FULL) {
-                toggleMediaControlViewVisibility();
-            }
-        }
-    }
-
-    @Override
-    public void onMeasureImpl(int widthMeasureSpec, int heightMeasureSpec) {
-        if (mIsMusicMediaType) {
-            int currWidth = mInstance.getMeasuredWidth();
-            int currHeight = mInstance.getMeasuredHeight();
-            if (mPrevWidth != currWidth || mPrevHeight != currHeight) {
-                Point screenSize = new Point();
-                mManager.getDefaultDisplay().getSize(screenSize);
-                int screenWidth = screenSize.x;
-                int screenHeight = screenSize.y;
-
-                if (currWidth == screenWidth && currHeight == screenHeight) {
-                    int orientation = retrieveOrientation();
-                    if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
-                        inflateMusicView(R.layout.full_landscape_music);
-                    } else {
-                        inflateMusicView(R.layout.full_portrait_music);
-                    }
-
-                    if (mSizeType != SIZE_TYPE_FULL) {
-                        mSizeType = SIZE_TYPE_FULL;
-                        // Remove existing mFadeOut callback
-                        mMediaControlView.removeCallbacks(mFadeOut);
-                        mMediaControlView.setVisibility(View.VISIBLE);
-                    }
-                } else {
-                    if (mSizeType != SIZE_TYPE_EMBEDDED) {
-                        mSizeType = SIZE_TYPE_EMBEDDED;
-                        inflateMusicView(R.layout.embedded_music);
-                        // Add new mFadeOut callback
-                        mMediaControlView.postDelayed(mFadeOut, mShowControllerIntervalMs);
-                    }
-                }
-                mPrevWidth = currWidth;
-                mPrevHeight = currHeight;
-            }
-        }
-    }
-
-    ///////////////////////////////////////////////////
-    // Implements VideoViewInterface.SurfaceListener
-    ///////////////////////////////////////////////////
-
-    /**
-     * @hide
-     */
-    @Override
-    @RestrictTo(LIBRARY_GROUP)
-    public void onSurfaceCreated(View view, int width, int height) {
-        if (DEBUG) {
-            Log.d(TAG, "onSurfaceCreated(). mCurrentState=" + mCurrentState
-                    + ", mTargetState=" + mTargetState + ", width/height: " + width + "/" + height
-                    + ", " + view.toString());
-        }
-        if (needToStart()) {
-            mMediaController.getTransportControls().play();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    @RestrictTo(LIBRARY_GROUP)
-    public void onSurfaceDestroyed(View view) {
-        if (DEBUG) {
-            Log.d(TAG, "onSurfaceDestroyed(). mCurrentState=" + mCurrentState
-                    + ", mTargetState=" + mTargetState + ", " + view.toString());
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    @RestrictTo(LIBRARY_GROUP)
-    public void onSurfaceChanged(View view, int width, int height) {
-        if (DEBUG) {
-            Log.d(TAG, "onSurfaceChanged(). width/height: " + width + "/" + height
-                    + ", " + view.toString());
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    @RestrictTo(LIBRARY_GROUP)
-    public void onSurfaceTakeOverDone(VideoViewInterface view) {
-        if (DEBUG) {
-            Log.d(TAG, "onSurfaceTakeOverDone(). Now current view is: " + view);
-        }
-        mCurrentView = view;
-        if (mViewTypeChangedListener != null) {
-            mViewTypeChangedListener.onViewTypeChanged(mInstance, view.getViewType());
-        }
-        if (needToStart()) {
-            mMediaController.getTransportControls().play();
-        }
-    }
-
-    ///////////////////////////////////////////////////
-    // Protected or private methods
-    ///////////////////////////////////////////////////
-
-    private void attachMediaControlView() {
-        // Get MediaController from MediaSession and set it inside MediaControlView
-        mMediaControlView.setController(mMediaSession.getController());
-
-        LayoutParams params =
-                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
-        mInstance.addView(mMediaControlView, params);
-    }
-
-    private boolean isInPlaybackState() {
-        return (mMediaPlayer != null || mRoutePlayer != null)
-                && mCurrentState != STATE_ERROR
-                && mCurrentState != STATE_IDLE
-                && mCurrentState != STATE_PREPARING;
-    }
-
-    private boolean needToStart() {
-        return (mMediaPlayer != null || mRoutePlayer != null)
-                && isAudioGranted()
-                && isWaitingPlayback();
-    }
-
-    private boolean isPlaying() {
-        return mMediaPlayer != null
-                && mMediaPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING;
-    }
-
-    private boolean isWaitingPlayback() {
-        return mCurrentState != STATE_PLAYING && mTargetState == STATE_PLAYING;
-    }
-
-    private boolean isAudioGranted() {
-        return mAudioFocused || mAudioFocusType == AudioManager.AUDIOFOCUS_NONE;
-    }
-
-    private AudioManager.OnAudioFocusChangeListener mAudioFocusListener =
-            new AudioManager.OnAudioFocusChangeListener() {
-        @Override
-        public void onAudioFocusChange(int focusChange) {
-            switch (focusChange) {
-                case AudioManager.AUDIOFOCUS_GAIN:
-                    mAudioFocused = true;
-                    if (needToStart()) {
-                        mMediaController.getTransportControls().play();
-                    }
-                    break;
-                case AudioManager.AUDIOFOCUS_LOSS:
-                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
-                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
-                    mAudioFocused = false;
-                    if (isInPlaybackState() && isPlaying()) {
-                        mMediaController.getTransportControls().pause();
-                    } else {
-                        mTargetState = STATE_PAUSED;
-                    }
-            }
-        }
-    };
-
-    @SuppressWarnings("deprecation")
-    private void requestAudioFocus(int focusType) {
-        int result;
-        if (android.os.Build.VERSION.SDK_INT >= 26) {
-            AudioFocusRequest focusRequest;
-            focusRequest = new AudioFocusRequest.Builder(focusType)
-                    .setAudioAttributes((AudioAttributes) mAudioAttributes.unwrap())
-                    .setOnAudioFocusChangeListener(mAudioFocusListener)
-                    .build();
-            result = mAudioManager.requestAudioFocus(focusRequest);
-        } else {
-            result = mAudioManager.requestAudioFocus(mAudioFocusListener,
-                    AudioManager.STREAM_MUSIC,
-                    focusType);
-        }
-        if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
-            mAudioFocused = false;
-        } else if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
-            mAudioFocused = true;
-        } else if (result == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
-            mAudioFocused = false;
-        }
-    }
-
-    // Creates a MediaPlayer instance and prepare playback.
-    private void openVideo(DataSourceDesc dsd) {
-        Uri uri = dsd.getUri();
-        Map<String, String> headers = dsd.getUriHeaders();
-        resetPlayer();
-        if (isRemotePlayback()) {
-            // TODO: b/77556429
-            mRoutePlayer.openVideo(uri);
-            return;
-        }
-
-        try {
-            Log.d(TAG, "openVideo(): creating new MediaPlayer instance.");
-            mMediaPlayer = MediaPlayer2.create();
-            mSurfaceView.setMediaPlayer(mMediaPlayer);
-            mTextureView.setMediaPlayer(mMediaPlayer);
-            mCurrentView.assignSurfaceToMediaPlayer(mMediaPlayer);
-
-            final Context context = mInstance.getContext();
-            mSubtitleController = new SubtitleController(context);
-            mSubtitleController.registerRenderer(new ClosedCaptionRenderer(context));
-            mSubtitleController.setAnchor((SubtitleController.Anchor) mSubtitleView);
-            Executor executor = new Executor() {
-                @Override
-                public void execute(Runnable runnable) {
-                    runnable.run();
-                }
-            };
-            mMediaPlayer.setMediaPlayer2EventCallback(executor, mMediaPlayer2Callback);
-
-            mCurrentBufferPercentage = -1;
-            mMediaPlayer.setDataSource(dsd);
-            mMediaPlayer.setAudioAttributes(mAudioAttributes);
-            // we don't set the target state here either, but preserve the
-            // target state that was there before.
-            mCurrentState = STATE_PREPARING;
-            mMediaPlayer.prepare();
-
-            // Save file name as title since the file may not have a title Metadata.
-            mTitle = uri.getPath();
-            String scheme = uri.getScheme();
-            if (scheme != null && scheme.equals("file")) {
-                mTitle = uri.getLastPathSegment();
-                mRetriever = new MediaMetadataRetriever();
-                mRetriever.setDataSource(context, uri);
-            }
-
-            if (DEBUG) {
-                Log.d(TAG, "openVideo(). mCurrentState=" + mCurrentState
-                        + ", mTargetState=" + mTargetState);
-            }
-        } catch (IllegalArgumentException ex) {
-            Log.w(TAG, "Unable to open content: " + uri, ex);
-            mCurrentState = STATE_ERROR;
-            mTargetState = STATE_ERROR;
-            mMediaPlayer2Callback.onError(mMediaPlayer, dsd,
-                    MediaPlayer2.MEDIA_ERROR_UNKNOWN, MediaPlayer2.MEDIA_ERROR_IO);
-        }
-    }
-
-    /*
-     * Reset the media player in any state
-     */
-    @SuppressWarnings("deprecation")
-    private void resetPlayer() {
-        if (mMediaPlayer != null) {
-            final MediaPlayer2 player = mMediaPlayer;
-            new AsyncTask<MediaPlayer2, Void, Void>() {
-                @Override
-                protected Void doInBackground(MediaPlayer2... players) {
-                    // TODO: Fix NPE while MediaPlayer2.close()
-                    //players[0].close();
-                    return null;
-                }
-            }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, player);
-            mMediaPlayer = null;
-            mTextureView.setMediaPlayer(null);
-            mSurfaceView.setMediaPlayer(null);
-            mCurrentState = STATE_IDLE;
-            mTargetState = STATE_IDLE;
-            if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
-                mAudioManager.abandonAudioFocus(null);
-            }
-        }
-        mVideoWidth = 0;
-        mVideoHeight = 0;
-    }
-
-    private void updatePlaybackState() {
-        if (mStateBuilder == null) {
-            long playbackActions = PlaybackStateCompat.ACTION_PLAY
-                    | PlaybackStateCompat.ACTION_PAUSE
-                    | PlaybackStateCompat.ACTION_REWIND | PlaybackStateCompat.ACTION_FAST_FORWARD
-                    | PlaybackStateCompat.ACTION_SEEK_TO;
-            mStateBuilder = new PlaybackStateCompat.Builder();
-            mStateBuilder.setActions(playbackActions);
-
-            if (mCustomActionList != null) {
-                for (PlaybackStateCompat.CustomAction action : mCustomActionList) {
-                    mStateBuilder.addCustomAction(action);
-                }
-            }
-        }
-        mStateBuilder.setState(getCorrespondingPlaybackState(),
-                mMediaPlayer.getCurrentPosition(), mSpeed);
-        if (mCurrentState != STATE_ERROR
-                && mCurrentState != STATE_IDLE
-                && mCurrentState != STATE_PREPARING) {
-            if (mCurrentBufferPercentage == -1) {
-                mStateBuilder.setBufferedPosition(-1);
-            } else {
-                mStateBuilder.setBufferedPosition(
-                        (long) (mCurrentBufferPercentage / 100.0 * mMediaPlayer.getDuration()));
-            }
-        }
-
-        // Set PlaybackState for MediaSession
-        if (mMediaSession != null) {
-            PlaybackStateCompat state = mStateBuilder.build();
-            mMediaSession.setPlaybackState(state);
-        }
-    }
-
-    private int getCorrespondingPlaybackState() {
-        switch (mCurrentState) {
-            case STATE_ERROR:
-                return PlaybackStateCompat.STATE_ERROR;
-            case STATE_IDLE:
-                return PlaybackStateCompat.STATE_NONE;
-            case STATE_PREPARING:
-                return PlaybackStateCompat.STATE_CONNECTING;
-            case STATE_PREPARED:
-                return PlaybackStateCompat.STATE_PAUSED;
-            case STATE_PLAYING:
-                return PlaybackStateCompat.STATE_PLAYING;
-            case STATE_PAUSED:
-                return PlaybackStateCompat.STATE_PAUSED;
-            case STATE_PLAYBACK_COMPLETED:
-                return PlaybackStateCompat.STATE_STOPPED;
-            default:
-                return -1;
-        }
-    }
-
-    private final Runnable mFadeOut = new Runnable() {
-        @Override
-        public void run() {
-            if (mCurrentState == STATE_PLAYING) {
-                mMediaControlView.setVisibility(View.GONE);
-            }
-        }
-    };
-
-    private void showController() {
-        if (mMediaControlView == null || !isInPlaybackState()
-                || (mIsMusicMediaType && mSizeType == SIZE_TYPE_FULL)) {
-            return;
-        }
-        mMediaControlView.removeCallbacks(mFadeOut);
-        mMediaControlView.setVisibility(View.VISIBLE);
-        if (mShowControllerIntervalMs != 0
-                && !mAccessibilityManager.isTouchExplorationEnabled()) {
-            mMediaControlView.postDelayed(mFadeOut, mShowControllerIntervalMs);
-        }
-    }
-
-    private void toggleMediaControlViewVisibility() {
-        if (mMediaControlView.getVisibility() == View.VISIBLE) {
-            mMediaControlView.removeCallbacks(mFadeOut);
-            mMediaControlView.setVisibility(View.GONE);
-        } else {
-            showController();
-        }
-    }
-
-    private void applySpeed() {
-        if (android.os.Build.VERSION.SDK_INT < 23) {
-            return;
-        }
-        PlaybackParams params = mMediaPlayer.getPlaybackParams().allowDefaults();
-        if (mSpeed != params.getSpeed()) {
-            try {
-                params.setSpeed(mSpeed);
-                mMediaPlayer.setPlaybackParams(params);
-                mFallbackSpeed = mSpeed;
-            } catch (IllegalArgumentException e) {
-                Log.e(TAG, "PlaybackParams has unsupported value: " + e);
-                float fallbackSpeed = mMediaPlayer.getPlaybackParams().allowDefaults().getSpeed();
-                if (fallbackSpeed > 0.0f) {
-                    mFallbackSpeed = fallbackSpeed;
-                }
-                mSpeed = mFallbackSpeed;
-            }
-        }
-    }
-
-    private boolean isRemotePlayback() {
-        if (mMediaController == null) {
-            return false;
-        }
-        PlaybackInfo playbackInfo = mMediaController.getPlaybackInfo();
-        return playbackInfo != null
-                && playbackInfo.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE;
-    }
-
-    private void selectOrDeselectSubtitle(boolean select) {
-        if (!isInPlaybackState()) {
-            return;
-        }
-        if (select) {
-            if (mSubtitleTrackIndices.size() > 0) {
-                mSelectedSubtitleTrackIndex = mSubtitleTrackIndices.get(0).first;
-                mSubtitleController.selectTrack(mSubtitleTrackIndices.get(0).second);
-                mMediaPlayer.selectTrack(mSelectedSubtitleTrackIndex);
-                mSubtitleView.setVisibility(View.VISIBLE);
-            }
-        } else {
-            if (mSelectedSubtitleTrackIndex != INVALID_TRACK_INDEX) {
-                mMediaPlayer.deselectTrack(mSelectedSubtitleTrackIndex);
-                mSelectedSubtitleTrackIndex = INVALID_TRACK_INDEX;
-                mSubtitleView.setVisibility(View.GONE);
-            }
-        }
-    }
-
-    private void extractTracks() {
-        List<MediaPlayer2.TrackInfo> trackInfos = mMediaPlayer.getTrackInfo();
-        mVideoTrackIndices = new ArrayList<>();
-        mAudioTrackIndices = new ArrayList<>();
-        mSubtitleTrackIndices = new ArrayList<>();
-        mSubtitleController.reset();
-        for (int i = 0; i < trackInfos.size(); ++i) {
-            int trackType = trackInfos.get(i).getTrackType();
-            if (trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) {
-                mVideoTrackIndices.add(i);
-            } else if (trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
-                mAudioTrackIndices.add(i);
-            } else if (trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
-                SubtitleTrack track = mSubtitleController.addTrack(trackInfos.get(i).getFormat());
-                if (track != null) {
-                    mSubtitleTrackIndices.add(new Pair<>(i, track));
-                }
-            }
-        }
-        // Select first tracks as default
-        if (mVideoTrackIndices.size() > 0) {
-            mSelectedVideoTrackIndex = 0;
-        }
-        if (mAudioTrackIndices.size() > 0) {
-            mSelectedAudioTrackIndex = 0;
-        }
-        if (mVideoTrackIndices.size() == 0 && mAudioTrackIndices.size() > 0) {
-            mIsMusicMediaType = true;
-        }
-
-        Bundle data = new Bundle();
-        data.putInt(MediaControlView2.KEY_VIDEO_TRACK_COUNT, mVideoTrackIndices.size());
-        data.putInt(MediaControlView2.KEY_AUDIO_TRACK_COUNT, mAudioTrackIndices.size());
-        data.putInt(MediaControlView2.KEY_SUBTITLE_TRACK_COUNT, mSubtitleTrackIndices.size());
-        if (mSubtitleTrackIndices.size() > 0) {
-            selectOrDeselectSubtitle(mSubtitleEnabled);
-        }
-        mMediaSession.sendSessionEvent(MediaControlView2.EVENT_UPDATE_TRACK_STATUS, data);
-    }
-
-    private void extractMetadata() {
-        if (mRetriever == null) {
-            return;
-        }
-        // Get and set duration and title values as MediaMetadata for MediaControlView2
-        MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
-        String title = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
-        if (title != null) {
-            mTitle = title;
-        }
-        builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mTitle);
-        builder.putLong(
-                MediaMetadataCompat.METADATA_KEY_DURATION, mMediaPlayer.getDuration());
-
-        if (mMediaSession != null) {
-            mMediaSession.setMetadata(builder.build());
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    private void extractAudioMetadata() {
-        if (mRetriever == null || !mIsMusicMediaType) {
-            return;
-        }
-
-        mResources = mInstance.getResources();
-        mManager = (WindowManager) mInstance.getContext().getApplicationContext()
-                .getSystemService(Context.WINDOW_SERVICE);
-
-        byte[] album = mRetriever.getEmbeddedPicture();
-        if (album != null) {
-            Bitmap bitmap = BitmapFactory.decodeByteArray(album, 0, album.length);
-            mMusicAlbumDrawable = new BitmapDrawable(bitmap);
-
-            Palette.Builder builder = Palette.from(bitmap);
-            builder.generate(new Palette.PaletteAsyncListener() {
-                @Override
-                public void onGenerated(Palette palette) {
-                    mDominantColor = palette.getDominantColor(0);
-                    if (mMusicView != null) {
-                        mMusicView.setBackgroundColor(mDominantColor);
-                    }
-                }
-            });
-        } else {
-            mMusicAlbumDrawable = mResources.getDrawable(R.drawable.ic_default_album_image);
-        }
-
-        String title = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
-        if (title != null) {
-            mMusicTitleText = title;
-        } else {
-            mMusicTitleText = mResources.getString(R.string.mcv2_music_title_unknown_text);
-        }
-
-        String artist = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
-        if (artist != null) {
-            mMusicArtistText = artist;
-        } else {
-            mMusicArtistText = mResources.getString(R.string.mcv2_music_artist_unknown_text);
-        }
-
-        // Send title and artist string to MediaControlView2
-        MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
-        builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mMusicTitleText);
-        builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, mMusicArtistText);
-        mMediaSession.setMetadata(builder.build());
-
-        // Display Embedded mode as default
-        mInstance.removeView(mSurfaceView);
-        mInstance.removeView(mTextureView);
-        inflateMusicView(R.layout.embedded_music);
-    }
-
-    private int retrieveOrientation() {
-        DisplayMetrics dm = Resources.getSystem().getDisplayMetrics();
-        int width = dm.widthPixels;
-        int height = dm.heightPixels;
-
-        return (height > width)
-                ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
-                : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-    }
-
-    private void inflateMusicView(int layoutId) {
-        mInstance.removeView(mMusicView);
-
-        LayoutInflater inflater = (LayoutInflater) mInstance.getContext()
-                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View v = inflater.inflate(layoutId, null);
-        v.setBackgroundColor(mDominantColor);
-
-        ImageView albumView = v.findViewById(R.id.album);
-        if (albumView != null) {
-            albumView.setImageDrawable(mMusicAlbumDrawable);
-        }
-
-        TextView titleView = v.findViewById(R.id.title);
-        if (titleView != null) {
-            titleView.setText(mMusicTitleText);
-        }
-
-        TextView artistView = v.findViewById(R.id.artist);
-        if (artistView != null) {
-            artistView.setText(mMusicArtistText);
-        }
-
-        mMusicView = v;
-        mInstance.addView(mMusicView, 0);
-    }
-
-    MediaPlayer2EventCallback mMediaPlayer2Callback =
-            new MediaPlayer2EventCallback() {
-                @Override
-                public void onVideoSizeChanged(
-                        MediaPlayer2 mp, DataSourceDesc dsd, int width, int height) {
-                    if (DEBUG) {
-                        Log.d(TAG, "onVideoSizeChanged(): size: " + width + "/" + height);
-                    }
-                    mVideoWidth = mp.getVideoWidth();
-                    mVideoHeight = mp.getVideoHeight();
-                    if (DEBUG) {
-                        Log.d(TAG, "onVideoSizeChanged(): mVideoSize:" + mVideoWidth + "/"
-                                + mVideoHeight);
-                    }
-                    if (mVideoWidth != 0 && mVideoHeight != 0) {
-                        mInstance.requestLayout();
-                    }
-                }
-
-                @Override
-                public void onInfo(
-                        MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
-                    if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) {
-                        extractTracks();
-                    } else if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
-                        this.onPrepared(mp, dsd);
-                    } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
-                        this.onCompletion(mp, dsd);
-                    } else if (what == MediaPlayer2.MEDIA_INFO_BUFFERING_UPDATE) {
-                        this.onBufferingUpdate(mp, dsd, extra);
-                    }
-                }
-
-                @Override
-                public void onError(
-                        MediaPlayer2 mp, DataSourceDesc dsd, int frameworkErr, int implErr) {
-                    if (DEBUG) {
-                        Log.d(TAG, "Error: " + frameworkErr + "," + implErr);
-                    }
-                    mCurrentState = STATE_ERROR;
-                    mTargetState = STATE_ERROR;
-                    updatePlaybackState();
-
-                    if (mMediaControlView != null) {
-                        mMediaControlView.setVisibility(View.GONE);
-                    }
-                }
-
-                @Override
-                public void onCallCompleted(
-                        MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
-                    if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
-                        updatePlaybackState();
-                    }
-                }
-
-                @Override
-                public void onSubtitleData(MediaPlayer2 mp, DataSourceDesc dsd, SubtitleData data) {
-                    if (DEBUG) {
-                        Log.d(TAG, "onSubtitleData(): getTrackIndex: " + data.getTrackIndex()
-                                + ", getCurrentPosition: " + mp.getCurrentPosition()
-                                + ", getStartTimeUs(): " + data.getStartTimeUs()
-                                + ", diff: "
-                                + (data.getStartTimeUs() / 1000 - mp.getCurrentPosition())
-                                + "ms, getDurationUs(): " + data.getDurationUs());
-
-                    }
-                    final int index = data.getTrackIndex();
-                    if (index != mSelectedSubtitleTrackIndex) {
-                        Log.d(TAG, "onSubtitleData(): getTrackIndex: " + data.getTrackIndex()
-                                + ", selected track index: " + mSelectedSubtitleTrackIndex);
-                        return;
-                    }
-                    for (Pair<Integer, SubtitleTrack> p : mSubtitleTrackIndices) {
-                        if (p.first == index) {
-                            SubtitleTrack track = p.second;
-                            track.onData(data);
-                        }
-                    }
-                }
-
-                private void onPrepared(MediaPlayer2 mp, DataSourceDesc dsd) {
-                    if (DEBUG) {
-                        Log.d(TAG, "OnPreparedListener(). mCurrentState=" + mCurrentState
-                                + ", mTargetState=" + mTargetState);
-                    }
-                    mCurrentState = STATE_PREPARED;
-                    // Create and set playback state for MediaControlView2
-                    updatePlaybackState();
-
-                    if (mMediaSession != null) {
-                        extractTracks();
-                        extractMetadata();
-                        extractAudioMetadata();
-                    }
-
-                    if (mMediaControlView != null) {
-                        mMediaControlView.setEnabled(true);
-                    }
-                    int videoWidth = mp.getVideoWidth();
-                    int videoHeight = mp.getVideoHeight();
-
-                    // mSeekWhenPrepared may be changed after seekTo() call
-                    long seekToPosition = mSeekWhenPrepared;
-                    if (seekToPosition != 0) {
-                        mMediaController.getTransportControls().seekTo(seekToPosition);
-                    }
-
-                    if (videoWidth != 0 && videoHeight != 0) {
-                        if (videoWidth != mVideoWidth || videoHeight != mVideoHeight) {
-                            mVideoWidth = videoWidth;
-                            mVideoHeight = videoHeight;
-                            mInstance.requestLayout();
-                        }
-
-                        if (needToStart()) {
-                            mMediaController.getTransportControls().play();
-                        }
-
-                    } else {
-                        // We don't know the video size yet, but should start anyway.
-                        // The video size might be reported to us later.
-                        if (needToStart()) {
-                            mMediaController.getTransportControls().play();
-                        }
-                    }
-                    // Get and set duration and title values as MediaMetadata for MediaControlView2
-                    MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
-
-                    builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mTitle);
-                    builder.putLong(
-                            MediaMetadataCompat.METADATA_KEY_DURATION, mMediaPlayer.getDuration());
-
-                    if (mMediaSession != null) {
-                        mMediaSession.setMetadata(builder.build());
-
-                        if (mNeedUpdateMediaType) {
-                            mMediaSession.sendSessionEvent(
-                                    MediaControlView2.EVENT_UPDATE_MEDIA_TYPE_STATUS,
-                                    mMediaTypeData);
-                            mNeedUpdateMediaType = false;
-                        }
-                    }
-                }
-
-                @SuppressWarnings("deprecation")
-                private void onCompletion(MediaPlayer2 mp, DataSourceDesc dsd) {
-                    mCurrentState = STATE_PLAYBACK_COMPLETED;
-                    mTargetState = STATE_PLAYBACK_COMPLETED;
-                    updatePlaybackState();
-                    if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
-                        mAudioManager.abandonAudioFocus(null);
-                    }
-                }
-
-                private void onBufferingUpdate(MediaPlayer2 mp, DataSourceDesc dsd, int percent) {
-                    mCurrentBufferPercentage = percent;
-                    updatePlaybackState();
-                }
-            };
-
-    private class MediaSessionCallback extends MediaSessionCompat.Callback {
-        @Override
-        public void onCommand(String command, Bundle args, ResultReceiver receiver) {
-            if (isRemotePlayback()) {
-                mRoutePlayer.onCommand(command, args, receiver);
-            } else {
-                switch (command) {
-                    case MediaControlView2.COMMAND_SHOW_SUBTITLE:
-                        int subtitleIndex = args.getInt(
-                                MediaControlView2.KEY_SELECTED_SUBTITLE_INDEX,
-                                INVALID_TRACK_INDEX);
-                        if (subtitleIndex != INVALID_TRACK_INDEX) {
-                            int subtitleTrackIndex = mSubtitleTrackIndices.get(subtitleIndex).first;
-                            if (subtitleTrackIndex != mSelectedSubtitleTrackIndex) {
-                                mSelectedSubtitleTrackIndex = subtitleTrackIndex;
-                                mInstance.setSubtitleEnabled(true);
-                            }
-                        }
-                        break;
-                    case MediaControlView2.COMMAND_HIDE_SUBTITLE:
-                        mInstance.setSubtitleEnabled(false);
-                        break;
-                    case MediaControlView2.COMMAND_SELECT_AUDIO_TRACK:
-                        int audioIndex = args.getInt(MediaControlView2.KEY_SELECTED_AUDIO_INDEX,
-                                INVALID_TRACK_INDEX);
-                        if (audioIndex != INVALID_TRACK_INDEX) {
-                            int audioTrackIndex = mAudioTrackIndices.get(audioIndex);
-                            if (audioTrackIndex != mSelectedAudioTrackIndex) {
-                                mSelectedAudioTrackIndex = audioTrackIndex;
-                                mMediaPlayer.selectTrack(mSelectedAudioTrackIndex);
-                            }
-                        }
-                        break;
-                    case MediaControlView2.COMMAND_SET_PLAYBACK_SPEED:
-                        float speed = args.getFloat(
-                                MediaControlView2.KEY_PLAYBACK_SPEED, INVALID_SPEED);
-                        if (speed != INVALID_SPEED && speed != mSpeed) {
-                            setSpeed(speed);
-                            mSpeed = speed;
-                        }
-                        break;
-                    case MediaControlView2.COMMAND_MUTE:
-                        mVolumeLevel = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
-                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
-                        break;
-                    case MediaControlView2.COMMAND_UNMUTE:
-                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mVolumeLevel, 0);
-                        break;
-                }
-            }
-            showController();
-        }
-
-        @Override
-        public void onCustomAction(final String action, final Bundle extras) {
-            mCustomActionListenerRecord.first.execute(new Runnable() {
-                @Override
-                public void run() {
-                    mCustomActionListenerRecord.second.onCustomAction(action, extras);
-                }
-            });
-            showController();
-        }
-
-        @Override
-        public void onPlay() {
-            if (!isAudioGranted()) {
-                requestAudioFocus(mAudioFocusType);
-            }
-
-            if ((isInPlaybackState() && mCurrentView.hasAvailableSurface()) || mIsMusicMediaType) {
-                if (isRemotePlayback()) {
-                    mRoutePlayer.onPlay();
-                } else {
-                    applySpeed();
-                    mMediaPlayer.play();
-                    mCurrentState = STATE_PLAYING;
-                    updatePlaybackState();
-                }
-                mCurrentState = STATE_PLAYING;
-            }
-            mTargetState = STATE_PLAYING;
-            if (DEBUG) {
-                Log.d(TAG, "onPlay(). mCurrentState=" + mCurrentState
-                        + ", mTargetState=" + mTargetState);
-            }
-            showController();
-        }
-
-        @Override
-        public void onPause() {
-            if (isInPlaybackState()) {
-                if (isRemotePlayback()) {
-                    mRoutePlayer.onPlay();
-                    mCurrentState = STATE_PAUSED;
-                } else if (isPlaying()) {
-                    mMediaPlayer.pause();
-                    mCurrentState = STATE_PAUSED;
-                    updatePlaybackState();
-                }
-            }
-            mTargetState = STATE_PAUSED;
-            if (DEBUG) {
-                Log.d(TAG, "onPause(). mCurrentState=" + mCurrentState
-                        + ", mTargetState=" + mTargetState);
-            }
-            showController();
-        }
-
-        @Override
-        public void onSeekTo(long pos) {
-            if (isInPlaybackState()) {
-                if (isRemotePlayback()) {
-                    mRoutePlayer.onPlay();
-                } else {
-                    if (android.os.Build.VERSION.SDK_INT < 26) {
-                        mMediaPlayer.seekTo((int) pos);
-                    } else {
-                        mMediaPlayer.seekTo(pos, MediaPlayer2.SEEK_PREVIOUS_SYNC);
-                    }
-                    mSeekWhenPrepared = 0;
-                }
-            } else {
-                mSeekWhenPrepared = pos;
-            }
-            showController();
-        }
-
-        @Override
-        public void onStop() {
-            if (isRemotePlayback()) {
-                mRoutePlayer.onPlay();
-            } else {
-                resetPlayer();
-            }
-            showController();
-        }
-    }
-}
diff --git a/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoTextureViewWithMp1.java b/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoTextureViewWithMp1.java
deleted file mode 100644
index e20d78f..0000000
--- a/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoTextureViewWithMp1.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.widget;
-
-import static androidx.media.widget.VideoView2.VIEW_TYPE_TEXTUREVIEW;
-
-import android.content.Context;
-import android.graphics.SurfaceTexture;
-import android.media.MediaPlayer;
-import android.util.Log;
-import android.view.Surface;
-import android.view.TextureView;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-
-@RequiresApi(21)
-class VideoTextureViewWithMp1 extends TextureView
-        implements VideoViewInterfaceWithMp1, TextureView.SurfaceTextureListener {
-    private static final String TAG = "VideoTextureViewWithMp1";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private Surface mSurface;
-    private SurfaceListener mSurfaceListener;
-    private MediaPlayer mMediaPlayer;
-    // A flag to indicate taking over other view should be proceed.
-    private boolean mIsTakingOverOldView;
-    private VideoViewInterfaceWithMp1 mOldView;
-
-    VideoTextureViewWithMp1(Context context) {
-        super(context, null);
-        setSurfaceTextureListener(this);
-    }
-
-    ////////////////////////////////////////////////////
-    // implements VideoViewInterfaceWithMp1
-    ////////////////////////////////////////////////////
-
-    @Override
-    public boolean assignSurfaceToMediaPlayer(MediaPlayer mp) {
-        if (mp == null || !hasAvailableSurface()) {
-            // Surface is not ready.
-            return false;
-        }
-        mp.setSurface(mSurface);
-        return true;
-    }
-
-    @Override
-    public void setSurfaceListener(SurfaceListener l) {
-        mSurfaceListener = l;
-    }
-
-    @Override
-    public int getViewType() {
-        return VIEW_TYPE_TEXTUREVIEW;
-    }
-
-    @Override
-    public void setMediaPlayer(MediaPlayer mp) {
-        mMediaPlayer = mp;
-        if (mIsTakingOverOldView) {
-            takeOver(mOldView);
-        }
-    }
-
-    @Override
-    public void takeOver(@NonNull VideoViewInterfaceWithMp1 oldView) {
-        if (assignSurfaceToMediaPlayer(mMediaPlayer)) {
-            ((View) oldView).setVisibility(GONE);
-            mIsTakingOverOldView = false;
-            mOldView = null;
-            if (mSurfaceListener != null) {
-                mSurfaceListener.onSurfaceTakeOverDone(this);
-            }
-        } else {
-            mIsTakingOverOldView = true;
-            mOldView = oldView;
-        }
-    }
-
-    @Override
-    public boolean hasAvailableSurface() {
-        return mSurface != null && mSurface.isValid();
-    }
-
-    ////////////////////////////////////////////////////
-    // implements TextureView.SurfaceTextureListener
-    ////////////////////////////////////////////////////
-
-    @Override
-    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
-        mSurface = new Surface(surfaceTexture);
-        if (mIsTakingOverOldView) {
-            takeOver(mOldView);
-        } else {
-            assignSurfaceToMediaPlayer(mMediaPlayer);
-        }
-        if (mSurfaceListener != null) {
-            mSurfaceListener.onSurfaceCreated(this, width, height);
-        }
-    }
-
-    @Override
-    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
-        if (mSurfaceListener != null) {
-            mSurfaceListener.onSurfaceChanged(this, width, height);
-        }
-        // requestLayout();  // TODO: figure out if it should be called here?
-    }
-
-    @Override
-    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
-        // no-op
-    }
-
-    @Override
-    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
-        if (mSurfaceListener != null) {
-            mSurfaceListener.onSurfaceDestroyed(this);
-        }
-        mSurface = null;
-        return true;
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int videoWidth = (mMediaPlayer == null) ? 0 : mMediaPlayer.getVideoWidth();
-        int videoHeight = (mMediaPlayer == null) ? 0 : mMediaPlayer.getVideoHeight();
-        if (DEBUG) {
-            Log.d(TAG, "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
-                    + MeasureSpec.toString(heightMeasureSpec) + ")");
-            Log.i(TAG, " measuredSize: " + getMeasuredWidth() + "/" + getMeasuredHeight());
-            Log.i(TAG, " viewSize: " + getWidth() + "/" + getHeight());
-            Log.i(TAG, " mVideoWidth/height: " + videoWidth + ", " + videoHeight);
-        }
-
-        int width = getDefaultSize(videoWidth, widthMeasureSpec);
-        int height = getDefaultSize(videoHeight, heightMeasureSpec);
-
-        if (videoWidth > 0 && videoHeight > 0) {
-            int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
-            int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
-
-            width = widthSpecSize;
-            height = heightSpecSize;
-
-            // for compatibility, we adjust size based on aspect ratio
-            if (videoWidth * height < width * videoHeight) {
-                width = height * videoWidth / videoHeight;
-                if (DEBUG) {
-                    Log.d(TAG, "image too wide, correcting. width: " + width);
-                }
-            } else if (videoWidth * height > width * videoHeight) {
-                height = width * videoHeight / videoWidth;
-                if (DEBUG) {
-                    Log.d(TAG, "image too tall, correcting. height: " + height);
-                }
-            }
-        } else {
-            // no size yet, just adopt the given spec sizes
-        }
-        setMeasuredDimension(width, height);
-        if (DEBUG) {
-            Log.i(TAG, "end of onMeasure()");
-            Log.i(TAG, " measuredSize: " + getMeasuredWidth() + "/" + getMeasuredHeight());
-        }
-    }
-}
diff --git a/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoView2ImplApi28WithMp1.java b/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoView2ImplApi28WithMp1.java
deleted file mode 100644
index e0f6d36..0000000
--- a/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoView2ImplApi28WithMp1.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.widget;
-
-import android.content.Context;
-import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnSubtitleDataListener;
-import android.media.SubtitleData;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Pair;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.media.subtitle.ClosedCaptionRenderer;
-import androidx.media.subtitle.SubtitleController;
-import androidx.media.subtitle.SubtitleTrack;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Map;
-
-/**
- * Base implementation of VideoView2.
- */
-@RequiresApi(28)
-class VideoView2ImplApi28WithMp1 extends VideoView2ImplBaseWithMp1 {
-    private static final String TAG = "VideoView2ImplApi28_1";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private static final int INVALID_TRACK_INDEX = -1;
-
-    private ArrayList<Pair<Integer, SubtitleTrack>> mSubtitleTrackIndices;
-    private SubtitleController mSubtitleController;
-
-    // selected video/audio/subtitle track index as MediaPlayer returns
-    private int mSelectedSubtitleTrackIndex;
-
-    private SubtitleView mSubtitleView;
-    private boolean mSubtitleEnabled;
-
-    @Override
-    public void initialize(
-            VideoView2 instance, Context context,
-            @Nullable AttributeSet attrs, int defStyleAttr) {
-        super.initialize(instance, context, attrs, defStyleAttr);
-        mSelectedSubtitleTrackIndex = INVALID_TRACK_INDEX;
-
-        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
-                LayoutParams.MATCH_PARENT);
-        mSubtitleView = new SubtitleView(context);
-        mSubtitleView.setLayoutParams(params);
-        mSubtitleView.setBackgroundColor(0);
-        mInstance.addView(mSubtitleView);
-
-        mSubtitleEnabled = (attrs == null) || attrs.getAttributeBooleanValue(
-                "http://schemas.android.com/apk/res/android",
-                "enableSubtitle", false);
-    }
-
-    /**
-     * Shows or hides closed caption or subtitles if there is any.
-     * The first subtitle track will be chosen if there multiple subtitle tracks exist.
-     * Default behavior of VideoView2 is not showing subtitle.
-     * @param enable shows closed caption or subtitles if this value is true, or hides.
-     */
-    @Override
-    public void setSubtitleEnabled(boolean enable) {
-        if (enable != mSubtitleEnabled) {
-            selectOrDeselectSubtitle(enable);
-        }
-        mSubtitleEnabled = enable;
-    }
-
-    /**
-     * Returns true if showing subtitle feature is enabled or returns false.
-     * Although there is no subtitle track or closed caption, it can return true, if the feature
-     * has been enabled by {@link #setSubtitleEnabled}.
-     */
-    @Override
-    public boolean isSubtitleEnabled() {
-        return mSubtitleEnabled;
-    }
-
-    ///////////////////////////////////////////////////
-    // Protected or private methods
-    ///////////////////////////////////////////////////
-
-    /**
-     * Used in openVideo(). Setup MediaPlayer and related objects before calling prepare.
-     */
-    @Override
-    protected void setupMediaPlayer(Context context, Uri uri, Map<String, String> headers)
-            throws IOException {
-        super.setupMediaPlayer(context, uri, headers);
-
-        mSubtitleController = new SubtitleController(context);
-        mSubtitleController.registerRenderer(new ClosedCaptionRenderer(context));
-        mSubtitleController.setAnchor((SubtitleController.Anchor) mSubtitleView);
-
-        mMediaPlayer.setOnSubtitleDataListener(mSubtitleListener);
-    }
-
-    private void selectOrDeselectSubtitle(boolean select) {
-        if (!isInPlaybackState()) {
-            return;
-        }
-        if (select) {
-            if (mSubtitleTrackIndices.size() > 0) {
-                mSelectedSubtitleTrackIndex = mSubtitleTrackIndices.get(0).first;
-                mSubtitleController.selectTrack(mSubtitleTrackIndices.get(0).second);
-                mMediaPlayer.selectTrack(mSelectedSubtitleTrackIndex);
-                mSubtitleView.setVisibility(View.VISIBLE);
-            }
-        } else {
-            if (mSelectedSubtitleTrackIndex != INVALID_TRACK_INDEX) {
-                mMediaPlayer.deselectTrack(mSelectedSubtitleTrackIndex);
-                mSelectedSubtitleTrackIndex = INVALID_TRACK_INDEX;
-                mSubtitleView.setVisibility(View.GONE);
-            }
-        }
-    }
-
-    @Override
-    protected void extractTracks() {
-        MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo();
-        mVideoTrackIndices = new ArrayList<>();
-        mAudioTrackIndices = new ArrayList<>();
-        mSubtitleTrackIndices = new ArrayList<>();
-        mSubtitleController.reset();
-        for (int i = 0; i < trackInfos.length; ++i) {
-            int trackType = trackInfos[i].getTrackType();
-            if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) {
-                mVideoTrackIndices.add(i);
-            } else if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
-                mAudioTrackIndices.add(i);
-            } else if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
-                SubtitleTrack track = mSubtitleController.addTrack(trackInfos[i].getFormat());
-                if (track != null) {
-                    mSubtitleTrackIndices.add(new Pair<>(i, track));
-                }
-            }
-        }
-        // Select first tracks as default
-        if (mVideoTrackIndices.size() > 0) {
-            mSelectedVideoTrackIndex = 0;
-        }
-        if (mAudioTrackIndices.size() > 0) {
-            mSelectedAudioTrackIndex = 0;
-        }
-
-        Bundle data = new Bundle();
-        data.putInt(MediaControlView2.KEY_VIDEO_TRACK_COUNT, mVideoTrackIndices.size());
-        data.putInt(MediaControlView2.KEY_AUDIO_TRACK_COUNT, mAudioTrackIndices.size());
-        data.putInt(MediaControlView2.KEY_SUBTITLE_TRACK_COUNT, mSubtitleTrackIndices.size());
-        if (mSubtitleTrackIndices.size() > 0) {
-            selectOrDeselectSubtitle(mSubtitleEnabled);
-        }
-        mMediaSession.sendSessionEvent(MediaControlView2.EVENT_UPDATE_TRACK_STATUS, data);
-    }
-
-    private OnSubtitleDataListener mSubtitleListener =
-            new OnSubtitleDataListener() {
-                @Override
-                public void onSubtitleData(MediaPlayer mp, SubtitleData data) {
-                    if (DEBUG) {
-                        Log.d(TAG, "onSubtitleData(): getTrackIndex: " + data.getTrackIndex()
-                                + ", getCurrentPosition: " + mp.getCurrentPosition()
-                                + ", getStartTimeUs(): " + data.getStartTimeUs()
-                                + ", diff: "
-                                + (data.getStartTimeUs() / 1000 - mp.getCurrentPosition())
-                                + "ms, getDurationUs(): " + data.getDurationUs());
-
-                    }
-                    final int index = data.getTrackIndex();
-                    if (index != mSelectedSubtitleTrackIndex) {
-                        Log.d(TAG, "onSubtitleData(): getTrackIndex: " + data.getTrackIndex()
-                                + ", selected track index: " + mSelectedSubtitleTrackIndex);
-                        return;
-                    }
-                    for (Pair<Integer, SubtitleTrack> p : mSubtitleTrackIndices) {
-                        if (p.first == index) {
-                            SubtitleTrack track = p.second;
-                            track.onData(data);
-                        }
-                    }
-                }
-            };
-
-    @Override
-    protected void doShowSubtitleCommand(Bundle args) {
-        int subtitleIndex = args.getInt(
-                MediaControlView2.KEY_SELECTED_SUBTITLE_INDEX,
-                INVALID_TRACK_INDEX);
-        if (subtitleIndex != INVALID_TRACK_INDEX) {
-            int subtitleTrackIndex = mSubtitleTrackIndices.get(subtitleIndex).first;
-            if (subtitleTrackIndex != mSelectedSubtitleTrackIndex) {
-                mSelectedSubtitleTrackIndex = subtitleTrackIndex;
-                mInstance.setSubtitleEnabled(true);
-            }
-        }
-    }
-
-    @Override
-    protected void doHideSubtitleCommand() {
-        mInstance.setSubtitleEnabled(false);
-    }
-}
diff --git a/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoView2ImplBaseWithMp1.java b/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoView2ImplBaseWithMp1.java
deleted file mode 100644
index 8fdb1b1..0000000
--- a/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoView2ImplBaseWithMp1.java
+++ /dev/null
@@ -1,1473 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.widget;
-
-import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Point;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.media.AudioAttributes;
-import android.media.AudioFocusRequest;
-import android.media.AudioManager;
-import android.media.MediaMetadataRetriever;
-import android.media.MediaPlayer;
-import android.media.PlaybackParams;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.ResultReceiver;
-import android.support.v4.media.MediaMetadataCompat;
-import android.support.v4.media.session.MediaControllerCompat;
-import android.support.v4.media.session.MediaControllerCompat.PlaybackInfo;
-import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v4.media.session.PlaybackStateCompat;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.Pair;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
-import androidx.media.AudioAttributesCompat;
-import androidx.media.DataSourceDesc;
-import androidx.media.MediaItem2;
-import androidx.media.MediaMetadata2;
-import androidx.media.SessionToken2;
-import androidx.mediarouter.media.MediaControlIntent;
-import androidx.mediarouter.media.MediaItemStatus;
-import androidx.mediarouter.media.MediaRouteSelector;
-import androidx.mediarouter.media.MediaRouter;
-import androidx.palette.graphics.Palette;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-/**
- * Base implementation of VideoView2.
- */
-@RequiresApi(21) // TODO correct minSdk API use incompatibilities and remove before release.
-class VideoView2ImplBaseWithMp1
-        implements VideoView2Impl, VideoViewInterfaceWithMp1.SurfaceListener {
-    private static final String TAG = "VideoView2ImplBase_1";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final long DEFAULT_SHOW_CONTROLLER_INTERVAL_MS = 2000;
-
-    private static final int STATE_ERROR = -1;
-    private static final int STATE_IDLE = 0;
-    private static final int STATE_PREPARING = 1;
-    private static final int STATE_PREPARED = 2;
-    private static final int STATE_PLAYING = 3;
-    private static final int STATE_PAUSED = 4;
-    private static final int STATE_PLAYBACK_COMPLETED = 5;
-
-    private static final int INVALID_TRACK_INDEX = -1;
-    private static final float INVALID_SPEED = 0f;
-
-    private static final int SIZE_TYPE_EMBEDDED = 0;
-    private static final int SIZE_TYPE_FULL = 1;
-    private static final int SIZE_TYPE_MINIMAL = 2;
-
-    private AccessibilityManager mAccessibilityManager;
-    private AudioManager mAudioManager;
-    private AudioAttributes mAudioAttributes;
-    private int mAudioFocusType = AudioManager.AUDIOFOCUS_GAIN; // legacy focus gain
-    private boolean mAudioFocused = false;
-
-    private Pair<Executor, VideoView2.OnCustomActionListener> mCustomActionListenerRecord;
-    private VideoView2.OnViewTypeChangedListener mViewTypeChangedListener;
-
-    private VideoViewInterfaceWithMp1 mCurrentView;
-    private VideoTextureViewWithMp1 mTextureView;
-    private VideoSurfaceViewWithMp1 mSurfaceView;
-
-    protected MediaPlayer mMediaPlayer;
-    private DataSourceDesc mDsd;
-    private Uri mUri;
-    private Map<String, String> mHeaders;
-    private MediaControlView2 mMediaControlView;
-    protected MediaSessionCompat mMediaSession;
-    private MediaControllerCompat mMediaController;
-    private MediaMetadata2 mMediaMetadata;
-    private MediaMetadataRetriever mRetriever;
-    private boolean mNeedUpdateMediaType;
-    private Bundle mMediaTypeData;
-    private String mTitle;
-
-    private WindowManager mManager;
-    private Resources mResources;
-    private View mMusicView;
-    private Drawable mMusicAlbumDrawable;
-    private String mMusicTitleText;
-    private String mMusicArtistText;
-    private int mPrevWidth;
-    private int mPrevHeight;
-    private int mDominantColor;
-    private int mSizeType;
-
-    private PlaybackStateCompat.Builder mStateBuilder;
-    private List<PlaybackStateCompat.CustomAction> mCustomActionList;
-
-    private int mTargetState = STATE_IDLE;
-    private int mCurrentState = STATE_IDLE;
-    private int mCurrentBufferPercentage;
-    private long mSeekWhenPrepared;  // recording the seek position while preparing
-
-    private int mVideoWidth;
-    private int mVideoHeight;
-
-    protected ArrayList<Integer> mVideoTrackIndices;
-    protected ArrayList<Integer> mAudioTrackIndices;
-
-    // selected video/audio/subtitle track index as MediaPlayer returns
-    protected int mSelectedVideoTrackIndex;
-    protected int mSelectedAudioTrackIndex;
-
-    private float mSpeed;
-    private float mFallbackSpeed;  // keep the original speed before 'pause' is called.
-    private float mVolumeLevelFloat;
-    private int mVolumeLevel;
-    protected VideoView2 mInstance;
-
-    private long mShowControllerIntervalMs;
-
-    private MediaRouter mMediaRouter;
-    private MediaRouteSelector mRouteSelector;
-    private MediaRouter.RouteInfo mRoute;
-    private RoutePlayer mRoutePlayer;
-
-    private final MediaRouter.Callback mRouterCallback = new MediaRouter.Callback() {
-        @Override
-        public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo route) {
-            if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
-                // Stop local playback (if necessary)
-                resetPlayer();
-                mRoute = route;
-                mRoutePlayer = new RoutePlayer(mInstance.getContext(), route);
-                mRoutePlayer.setPlayerEventCallback(new RoutePlayer.PlayerEventCallback() {
-                    @Override
-                    public void onPlayerStateChanged(MediaItemStatus itemStatus) {
-                        PlaybackStateCompat.Builder psBuilder = new PlaybackStateCompat.Builder();
-                        psBuilder.setActions(RoutePlayer.PLAYBACK_ACTIONS);
-                        long position = itemStatus.getContentPosition();
-                        switch (itemStatus.getPlaybackState()) {
-                            case MediaItemStatus.PLAYBACK_STATE_PENDING:
-                                psBuilder.setState(PlaybackStateCompat.STATE_NONE, position, 0);
-                                mCurrentState = STATE_IDLE;
-                                break;
-                            case MediaItemStatus.PLAYBACK_STATE_PLAYING:
-                                psBuilder.setState(PlaybackStateCompat.STATE_PLAYING, position, 1);
-                                mCurrentState = STATE_PLAYING;
-                                break;
-                            case MediaItemStatus.PLAYBACK_STATE_PAUSED:
-                                psBuilder.setState(PlaybackStateCompat.STATE_PAUSED, position, 0);
-                                mCurrentState = STATE_PAUSED;
-                                break;
-                            case MediaItemStatus.PLAYBACK_STATE_BUFFERING:
-                                psBuilder.setState(
-                                        PlaybackStateCompat.STATE_BUFFERING, position, 0);
-                                mCurrentState = STATE_PAUSED;
-                                break;
-                            case MediaItemStatus.PLAYBACK_STATE_FINISHED:
-                                psBuilder.setState(PlaybackStateCompat.STATE_STOPPED, position, 0);
-                                mCurrentState = STATE_PLAYBACK_COMPLETED;
-                                break;
-                        }
-
-                        PlaybackStateCompat pbState = psBuilder.build();
-                        mMediaSession.setPlaybackState(pbState);
-
-                        MediaMetadataCompat.Builder mmBuilder = new MediaMetadataCompat.Builder();
-                        mmBuilder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION,
-                                itemStatus.getContentDuration());
-                        mMediaSession.setMetadata(mmBuilder.build());
-                    }
-                });
-                // Start remote playback (if necessary)
-                // TODO: b/77556429
-                mRoutePlayer.openVideo(mUri);
-            }
-        }
-
-        @Override
-        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route, int reason) {
-            if (mRoute != null && mRoutePlayer != null) {
-                mRoutePlayer.release();
-                mRoutePlayer = null;
-            }
-            if (mRoute == route) {
-                mRoute = null;
-            }
-            if (reason != MediaRouter.UNSELECT_REASON_ROUTE_CHANGED) {
-                // TODO: Resume local playback  (if necessary)
-                // TODO: b/77556429
-                openVideo(mUri, mHeaders);
-            }
-        }
-    };
-
-    @Override
-    public void initialize(
-            VideoView2 instance, Context context,
-            @Nullable AttributeSet attrs, int defStyleAttr) {
-        mInstance = instance;
-
-        mVideoWidth = 0;
-        mVideoHeight = 0;
-        mSpeed = 1.0f;
-        mFallbackSpeed = mSpeed;
-        mShowControllerIntervalMs = DEFAULT_SHOW_CONTROLLER_INTERVAL_MS;
-
-        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
-                Context.ACCESSIBILITY_SERVICE);
-
-        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        mAudioAttributes = new AudioAttributes.Builder()
-                .setUsage(AudioAttributes.USAGE_MEDIA)
-                .setContentType(AudioAttributes.CONTENT_TYPE_MOVIE).build();
-
-        mInstance.setFocusable(true);
-        mInstance.setFocusableInTouchMode(true);
-        mInstance.requestFocus();
-
-        mTextureView = new VideoTextureViewWithMp1(context);
-        mSurfaceView = new VideoSurfaceViewWithMp1(context);
-        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
-                LayoutParams.MATCH_PARENT);
-        mTextureView.setLayoutParams(params);
-        mSurfaceView.setLayoutParams(params);
-        mTextureView.setSurfaceListener(this);
-        mSurfaceView.setSurfaceListener(this);
-
-        mInstance.addView(mTextureView);
-        mInstance.addView(mSurfaceView);
-
-        boolean enableControlView = (attrs == null) || attrs.getAttributeBooleanValue(
-                "http://schemas.android.com/apk/res/android",
-                "enableControlView", true);
-        if (enableControlView) {
-            mMediaControlView = new MediaControlView2(context);
-        }
-
-        // Choose surface view by default
-        int viewType = (attrs == null) ? VideoView2.VIEW_TYPE_SURFACEVIEW
-                : attrs.getAttributeIntValue(
-                "http://schemas.android.com/apk/res/android",
-                "viewType", VideoView2.VIEW_TYPE_SURFACEVIEW);
-        if (viewType == VideoView2.VIEW_TYPE_SURFACEVIEW) {
-            Log.d(TAG, "viewType attribute is surfaceView.");
-            mTextureView.setVisibility(View.GONE);
-            mSurfaceView.setVisibility(View.VISIBLE);
-            mCurrentView = mSurfaceView;
-        } else if (viewType == VideoView2.VIEW_TYPE_TEXTUREVIEW) {
-            Log.d(TAG, "viewType attribute is textureView.");
-            mTextureView.setVisibility(View.VISIBLE);
-            mSurfaceView.setVisibility(View.GONE);
-            mCurrentView = mTextureView;
-        }
-
-        MediaRouteSelector.Builder builder = new MediaRouteSelector.Builder();
-        builder.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
-        builder.addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO);
-        builder.addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO);
-        mRouteSelector = builder.build();
-    }
-
-    /**
-     * Sets MediaControlView2 instance. It will replace the previously assigned MediaControlView2
-     * instance if any.
-     *
-     * @param mediaControlView a media control view2 instance.
-     * @param intervalMs a time interval in milliseconds until VideoView2 hides MediaControlView2.
-     */
-    @Override
-    public void setMediaControlView2(MediaControlView2 mediaControlView, long intervalMs) {
-        mMediaControlView = mediaControlView;
-        mShowControllerIntervalMs = intervalMs;
-        mMediaControlView.setRouteSelector(mRouteSelector);
-
-        if (mInstance.isAttachedToWindow()) {
-            attachMediaControlView();
-        }
-    }
-
-    /**
-     * Returns MediaControlView2 instance which is currently attached to VideoView2 by default or by
-     * {@link #setMediaControlView2} method.
-     */
-    @Override
-    public MediaControlView2 getMediaControlView2() {
-        return mMediaControlView;
-    }
-
-    /**
-     * Sets MediaMetadata2 instance. It will replace the previously assigned MediaMetadata2 instance
-     * if any.
-     *
-     * @param metadata a MediaMetadata2 instance.
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setMediaMetadata(MediaMetadata2 metadata) {
-      //mProvider.setMediaMetadata_impl(metadata);
-    }
-
-    /**
-     * Returns MediaMetadata2 instance which is retrieved from MediaPlayer inside VideoView2 by
-     * default or by {@link #setMediaMetadata} method.
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public MediaMetadata2 getMediaMetadata() {
-        return mMediaMetadata;
-    }
-
-    /**
-     * Returns MediaController instance which is connected with MediaSession that VideoView2 is
-     * using. This method should be called when VideoView2 is attached to window, or it throws
-     * IllegalStateException, since internal MediaSession instance is not available until
-     * this view is attached to window. Please check {@link View#isAttachedToWindow}
-     * before calling this method.
-     *
-     * @throws IllegalStateException if interal MediaSession is not created yet.
-     * @hide  TODO: remove
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public MediaControllerCompat getMediaController() {
-        if (mMediaSession == null) {
-            throw new IllegalStateException("MediaSession instance is not available.");
-        }
-        return mMediaController;
-    }
-
-    /**
-     * Returns {@link SessionToken2} so that developers create their own
-     * {@link androidx.media.MediaController2} instance. This method should be called when
-     * VideoView2 is attached to window, or it throws IllegalStateException.
-     *
-     * @throws IllegalStateException if interal MediaSession is not created yet.
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public SessionToken2 getMediaSessionToken() {
-        //return mProvider.getMediaSessionToken_impl();
-        return null;
-    }
-
-    /**
-     * Shows or hides closed caption or subtitles if there is any.
-     * The first subtitle track will be chosen if there multiple subtitle tracks exist.
-     * Default behavior of VideoView2 is not showing subtitle.
-     * @param enable shows closed caption or subtitles if this value is true, or hides.
-     */
-    @Override
-    public void setSubtitleEnabled(boolean enable) {
-        // No-op on API < 28
-    }
-
-    /**
-     * Returns true if showing subtitle feature is enabled or returns false.
-     * Although there is no subtitle track or closed caption, it can return true, if the feature
-     * has been enabled by {@link #setSubtitleEnabled}.
-     */
-    @Override
-    public boolean isSubtitleEnabled() {
-        // Not supported on API < 28
-        return false;
-    }
-
-    /**
-     * Sets playback speed.
-     *
-     * It is expressed as a multiplicative factor, where normal speed is 1.0f. If it is less than
-     * or equal to zero, it will be just ignored and nothing will be changed. If it exceeds the
-     * maximum speed that internal engine supports, system will determine best handling or it will
-     * be reset to the normal speed 1.0f.
-     * @param speed the playback speed. It should be positive.
-     */
-    @Override
-    public void setSpeed(float speed) {
-        if (speed <= 0.0f) {
-            Log.e(TAG, "Unsupported speed (" + speed + ") is ignored.");
-            return;
-        }
-        mSpeed = speed;
-        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
-            applySpeed();
-        }
-        updatePlaybackState();
-    }
-
-    /**
-     * Returns playback speed.
-     *
-     * It returns the same value that has been set by {@link #setSpeed}, if it was available value.
-     * If {@link #setSpeed} has not been called before, then the normal speed 1.0f will be returned.
-     */
-    @Override
-    public float getSpeed() {
-        return mSpeed;
-    }
-
-    /**
-     * Sets which type of audio focus will be requested during the playback, or configures playback
-     * to not request audio focus. Valid values for focus requests are
-     * {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
-     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
-     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}. Or use
-     * {@link AudioManager#AUDIOFOCUS_NONE} to express that audio focus should not be
-     * requested when playback starts. You can for instance use this when playing a silent animation
-     * through this class, and you don't want to affect other audio applications playing in the
-     * background.
-     *
-     * @param focusGain the type of audio focus gain that will be requested, or
-     *                  {@link AudioManager#AUDIOFOCUS_NONE} to disable the use audio focus during
-     *                  playback.
-     */
-    @Override
-    public void setAudioFocusRequest(int focusGain) {
-        if (focusGain != AudioManager.AUDIOFOCUS_NONE
-                && focusGain != AudioManager.AUDIOFOCUS_GAIN
-                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
-                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
-                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) {
-            throw new IllegalArgumentException("Illegal audio focus type " + focusGain);
-        }
-        mAudioFocusType = focusGain;
-    }
-
-    /**
-     * Sets the {@link AudioAttributesCompat} to be used during the playback of the video.
-     *
-     * @param attributes non-null <code>AudioAttributesCompat</code>.
-     */
-    @Override
-    public void setAudioAttributes(@NonNull AudioAttributesCompat attributes) {
-        if (attributes == null) {
-            throw new IllegalArgumentException("Illegal null AudioAttributesCompat");
-        }
-        mAudioAttributes = (AudioAttributes) attributes.unwrap();
-    }
-
-    /**
-     * Sets video path.
-     *
-     * @param path the path of the video.
-     *
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setVideoPath(String path) {
-        setVideoUri(Uri.parse(path));
-    }
-
-    /**
-     * Sets video URI.
-     *
-     * @param uri the URI of the video.
-     *
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setVideoUri(Uri uri) {
-        setVideoUri(uri, null);
-    }
-
-    /**
-     * Sets video URI using specific headers.
-     *
-     * @param uri     the URI of the video.
-     * @param headers the headers for the URI request.
-     *                Note that the cross domain redirection is allowed by default, but that can be
-     *                changed with key/value pairs through the headers parameter with
-     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
-     *                to disallow or allow cross domain redirection.
-     */
-    @Override
-    public void setVideoUri(Uri uri, @Nullable Map<String, String> headers) {
-        mSeekWhenPrepared = 0;
-        openVideo(uri, headers);
-    }
-
-    /**
-     * Sets {@link MediaItem2} object to render using VideoView2. Alternative way to set media
-     * object to VideoView2 is {@link #setDataSource}.
-     * @param mediaItem the MediaItem2 to play
-     * @see #setDataSource
-     *
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setMediaItem(@NonNull MediaItem2 mediaItem) {
-    }
-
-    /**
-     * Sets {@link DataSourceDesc} object to render using VideoView2.
-     * @param dataSource the {@link DataSourceDesc} object to play.
-     * @see #setMediaItem
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setDataSource(@NonNull DataSourceDesc dataSource) {
-    }
-
-    /**
-     * Selects which view will be used to render video between SurfacView and TextureView.
-     *
-     * @param viewType the view type to render video
-     * <ul>
-     * <li>{@link #VideoView2.VIEW_TYPE_SURFACEVIEW}
-     * <li>{@link #VideoView2.VIEW_TYPE_TEXTUREVIEW}
-     * </ul>
-     */
-    @Override
-    public void setViewType(@VideoView2.ViewType int viewType) {
-        if (viewType == mCurrentView.getViewType()) {
-            return;
-        }
-        VideoViewInterfaceWithMp1 targetView;
-        if (viewType == VideoView2.VIEW_TYPE_TEXTUREVIEW) {
-            Log.d(TAG, "switching to TextureView");
-            targetView = mTextureView;
-        } else if (viewType == VideoView2.VIEW_TYPE_SURFACEVIEW) {
-            Log.d(TAG, "switching to SurfaceView");
-            targetView = mSurfaceView;
-        } else {
-            throw new IllegalArgumentException("Unknown view type: " + viewType);
-        }
-        ((View) targetView).setVisibility(View.VISIBLE);
-        targetView.takeOver(mCurrentView);
-        mInstance.requestLayout();
-    }
-
-    /**
-     * Returns view type.
-     *
-     * @return view type. See {@see setViewType}.
-     */
-    @Override
-    @VideoView2.ViewType
-    public int getViewType() {
-        return mCurrentView.getViewType();
-    }
-
-    /**
-     * Sets custom actions which will be shown as custom buttons in {@link MediaControlView2}.
-     *
-     * @param actionList A list of {@link PlaybackStateCompat.CustomAction}. The return value of
-     *                   {@link PlaybackStateCompat.CustomAction#getIcon()} will be used to draw
-     *                   buttons in {@link MediaControlView2}.
-     * @param executor executor to run callbacks on.
-     * @param listener A listener to be called when a custom button is clicked.
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setCustomActions(List<PlaybackStateCompat.CustomAction> actionList,
-            Executor executor, VideoView2.OnCustomActionListener listener) {
-        mCustomActionList = actionList;
-        mCustomActionListenerRecord = new Pair<>(executor, listener);
-
-        // Create a new playback builder in order to clear existing the custom actions.
-        mStateBuilder = null;
-        updatePlaybackState();
-    }
-
-    /**
-     * Registers a callback to be invoked when a view type change is done.
-     * {@see #setViewType(int)}
-     * @param l The callback that will be run
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void setOnViewTypeChangedListener(VideoView2.OnViewTypeChangedListener l) {
-        mViewTypeChangedListener = l;
-    }
-
-    @Override
-    public void onAttachedToWindowImpl() {
-        // Create MediaSession
-        mMediaSession = new MediaSessionCompat(mInstance.getContext(), "VideoView2MediaSession");
-        mMediaSession.setCallback(new MediaSessionCallback());
-        mMediaSession.setActive(true);
-        mMediaController = mMediaSession.getController();
-        attachMediaControlView();
-        if (mCurrentState == STATE_PREPARED) {
-            extractTracks();
-            extractMetadata();
-            extractAudioMetadata();
-            if (mNeedUpdateMediaType) {
-                mMediaSession.sendSessionEvent(
-                        MediaControlView2.EVENT_UPDATE_MEDIA_TYPE_STATUS,
-                        mMediaTypeData);
-                mNeedUpdateMediaType = false;
-            }
-        }
-
-        mMediaRouter = MediaRouter.getInstance(mInstance.getContext());
-        mMediaRouter.setMediaSessionCompat(mMediaSession);
-        mMediaRouter.addCallback(mRouteSelector, mRouterCallback,
-                MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
-    }
-
-    @Override
-    public void onDetachedFromWindowImpl() {
-        mMediaSession.release();
-        mMediaSession = null;
-        mMediaController = null;
-    }
-
-    @Override
-    public void onTouchEventImpl(MotionEvent ev) {
-        if (DEBUG) {
-            Log.d(TAG, "onTouchEvent(). mCurrentState=" + mCurrentState
-                    + ", mTargetState=" + mTargetState);
-        }
-        if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
-            if (!isMusicMediaType() || mSizeType != SIZE_TYPE_FULL) {
-                toggleMediaControlViewVisibility();
-            }
-        }
-    }
-
-    @Override
-    public void onTrackballEventImpl(MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
-            if (!isMusicMediaType() || mSizeType != SIZE_TYPE_FULL) {
-                toggleMediaControlViewVisibility();
-            }
-        }
-    }
-
-    @Override
-    public void onMeasureImpl(int widthMeasureSpec, int heightMeasureSpec) {
-        if (isMusicMediaType()) {
-            int currWidth = mInstance.getMeasuredWidth();
-            int currHeight = mInstance.getMeasuredHeight();
-            if (mPrevWidth != currWidth || mPrevHeight != currHeight) {
-                Point screenSize = new Point();
-                mManager.getDefaultDisplay().getSize(screenSize);
-                int screenWidth = screenSize.x;
-                int screenHeight = screenSize.y;
-
-                if (currWidth == screenWidth && currHeight == screenHeight) {
-                    int orientation = retrieveOrientation();
-                    if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
-                        inflateMusicView(R.layout.full_landscape_music);
-                    } else {
-                        inflateMusicView(R.layout.full_portrait_music);
-                    }
-
-                    if (mSizeType != SIZE_TYPE_FULL) {
-                        mSizeType = SIZE_TYPE_FULL;
-                        // Remove existing mFadeOut callback
-                        mMediaControlView.removeCallbacks(mFadeOut);
-                        mMediaControlView.setVisibility(View.VISIBLE);
-                    }
-                } else {
-                    if (mSizeType != SIZE_TYPE_EMBEDDED) {
-                        mSizeType = SIZE_TYPE_EMBEDDED;
-                        inflateMusicView(R.layout.embedded_music);
-                        // Add new mFadeOut callback
-                        mMediaControlView.postDelayed(mFadeOut, mShowControllerIntervalMs);
-                    }
-                }
-                mPrevWidth = currWidth;
-                mPrevHeight = currHeight;
-            }
-        }
-    }
-
-    ///////////////////////////////////////////////////
-    // Implements VideoViewInterfaceWithMp1.SurfaceListener
-    ///////////////////////////////////////////////////
-
-    @Override
-    public void onSurfaceCreated(View view, int width, int height) {
-        if (DEBUG) {
-            Log.d(TAG, "onSurfaceCreated(). mCurrentState=" + mCurrentState
-                    + ", mTargetState=" + mTargetState + ", width/height: " + width + "/" + height
-                    + ", " + view.toString());
-        }
-        if (needToStart()) {
-            mMediaController.getTransportControls().play();
-        }
-    }
-
-    @Override
-    public void onSurfaceDestroyed(View view) {
-        if (DEBUG) {
-            Log.d(TAG, "onSurfaceDestroyed(). mCurrentState=" + mCurrentState
-                    + ", mTargetState=" + mTargetState + ", " + view.toString());
-        }
-    }
-
-    @Override
-    public void onSurfaceChanged(View view, int width, int height) {
-        if (DEBUG) {
-            Log.d(TAG, "onSurfaceChanged(). width/height: " + width + "/" + height
-                    + ", " + view.toString());
-        }
-    }
-
-    @Override
-    public void onSurfaceTakeOverDone(VideoViewInterfaceWithMp1 view) {
-        if (DEBUG) {
-            Log.d(TAG, "onSurfaceTakeOverDone(). Now current view is: " + view);
-        }
-        mCurrentView = view;
-        if (mViewTypeChangedListener != null) {
-            mViewTypeChangedListener.onViewTypeChanged(mInstance, view.getViewType());
-        }
-        if (needToStart()) {
-            mMediaController.getTransportControls().play();
-        }
-    }
-
-    ///////////////////////////////////////////////////
-    // Protected or private methods
-    ///////////////////////////////////////////////////
-
-    private void attachMediaControlView() {
-        // Get MediaController from MediaSession and set it inside MediaControlView
-        mMediaControlView.setController(mMediaSession.getController());
-
-        LayoutParams params =
-                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
-        mInstance.addView(mMediaControlView, params);
-    }
-
-    protected boolean isInPlaybackState() {
-        return (mMediaPlayer != null || mRoutePlayer != null)
-                && mCurrentState != STATE_ERROR
-                && mCurrentState != STATE_IDLE
-                && mCurrentState != STATE_PREPARING;
-    }
-
-    private boolean needToStart() {
-        return (mMediaPlayer != null || mRoutePlayer != null)
-                && isAudioGranted()
-                && isWaitingPlayback();
-    }
-
-    private boolean isMusicMediaType() {
-        return mVideoTrackIndices != null && mVideoTrackIndices.size() == 0;
-    }
-
-    private boolean isWaitingPlayback() {
-        return mCurrentState != STATE_PLAYING && mTargetState == STATE_PLAYING;
-    }
-
-    private boolean isAudioGranted() {
-        return mAudioFocused || mAudioFocusType == AudioManager.AUDIOFOCUS_NONE;
-    }
-
-    private AudioManager.OnAudioFocusChangeListener mAudioFocusListener =
-            new AudioManager.OnAudioFocusChangeListener() {
-        @Override
-        public void onAudioFocusChange(int focusChange) {
-            switch (focusChange) {
-                case AudioManager.AUDIOFOCUS_GAIN:
-                    mAudioFocused = true;
-                    if (needToStart()) {
-                        mMediaController.getTransportControls().play();
-                    }
-                    break;
-                case AudioManager.AUDIOFOCUS_LOSS:
-                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
-                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
-                    mAudioFocused = false;
-                    if (isInPlaybackState() && mMediaPlayer.isPlaying()) {
-                        mMediaController.getTransportControls().pause();
-                    } else {
-                        mTargetState = STATE_PAUSED;
-                    }
-            }
-        }
-    };
-
-    @SuppressWarnings("deprecation")
-    private void requestAudioFocus(int focusType) {
-        int result;
-        if (android.os.Build.VERSION.SDK_INT >= 26) {
-            AudioFocusRequest focusRequest;
-            focusRequest = new AudioFocusRequest.Builder(focusType)
-                    .setAudioAttributes(mAudioAttributes)
-                    .setOnAudioFocusChangeListener(mAudioFocusListener)
-                    .build();
-            result = mAudioManager.requestAudioFocus(focusRequest);
-        } else {
-            result = mAudioManager.requestAudioFocus(mAudioFocusListener,
-                    AudioManager.STREAM_MUSIC,
-                    focusType);
-        }
-        if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
-            mAudioFocused = false;
-        } else if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
-            mAudioFocused = true;
-        } else if (result == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
-            mAudioFocused = false;
-        }
-    }
-
-    // Creates a MediaPlayer instance and prepare playback.
-    private void openVideo(Uri uri, Map<String, String> headers) {
-        resetPlayer();
-        mUri = uri;
-        if (isRemotePlayback()) {
-            // TODO: b/77556429
-            mRoutePlayer.openVideo(uri);
-            return;
-        }
-
-        try {
-            Log.d(TAG, "openVideo(): creating new MediaPlayer instance.");
-            mMediaPlayer = new MediaPlayer();
-            final Context context = mInstance.getContext();
-            setupMediaPlayer(context, uri, headers);
-
-            // we don't set the target state here either, but preserve the
-            // target state that was there before.
-            mCurrentState = STATE_PREPARING;
-            mMediaPlayer.prepareAsync();
-
-            // Save file name as title since the file may not have a title Metadata.
-            mTitle = uri.getPath();
-            String scheme = uri.getScheme();
-            if (scheme != null && scheme.equals("file")) {
-                mTitle = uri.getLastPathSegment();
-                mRetriever = new MediaMetadataRetriever();
-                mRetriever.setDataSource(context, uri);
-            }
-
-            if (DEBUG) {
-                Log.d(TAG, "openVideo(). mCurrentState=" + mCurrentState
-                        + ", mTargetState=" + mTargetState);
-            }
-        } catch (IOException | IllegalArgumentException ex) {
-            Log.w(TAG, "Unable to open content: " + uri, ex);
-            mCurrentState = STATE_ERROR;
-            mTargetState = STATE_ERROR;
-            mErrorListener.onError(mMediaPlayer,
-                    MediaPlayer.MEDIA_ERROR_UNKNOWN, MediaPlayer.MEDIA_ERROR_IO);
-        }
-    }
-
-    /**
-     * Used in openVideo(). Setup MediaPlayer and related objects before calling prepare.
-     */
-    protected void setupMediaPlayer(Context context, Uri uri, Map<String, String> headers)
-            throws IOException {
-        mSurfaceView.setMediaPlayer(mMediaPlayer);
-        mTextureView.setMediaPlayer(mMediaPlayer);
-        mCurrentView.assignSurfaceToMediaPlayer(mMediaPlayer);
-
-        mMediaPlayer.setOnPreparedListener(mPreparedListener);
-        mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
-        mMediaPlayer.setOnCompletionListener(mCompletionListener);
-        mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
-        mMediaPlayer.setOnErrorListener(mErrorListener);
-        mMediaPlayer.setOnInfoListener(mInfoListener);
-        mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
-
-        mCurrentBufferPercentage = -1;
-        mMediaPlayer.setDataSource(context, uri, headers);
-        mMediaPlayer.setAudioAttributes(mAudioAttributes);
-    }
-
-    /*
-     * Reset the media player in any state
-     */
-    @SuppressWarnings("deprecation")
-    private void resetPlayer() {
-        if (mMediaPlayer != null) {
-            mMediaPlayer.reset();
-            mMediaPlayer.release();
-            mMediaPlayer = null;
-            mTextureView.setMediaPlayer(null);
-            mSurfaceView.setMediaPlayer(null);
-            mCurrentState = STATE_IDLE;
-            mTargetState = STATE_IDLE;
-            if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
-                mAudioManager.abandonAudioFocus(null);
-            }
-        }
-        mVideoWidth = 0;
-        mVideoHeight = 0;
-    }
-
-    private void updatePlaybackState() {
-        if (mStateBuilder == null) {
-            long playbackActions = PlaybackStateCompat.ACTION_PLAY
-                    | PlaybackStateCompat.ACTION_PAUSE
-                    | PlaybackStateCompat.ACTION_REWIND | PlaybackStateCompat.ACTION_FAST_FORWARD
-                    | PlaybackStateCompat.ACTION_SEEK_TO;
-            mStateBuilder = new PlaybackStateCompat.Builder();
-            mStateBuilder.setActions(playbackActions);
-
-            if (mCustomActionList != null) {
-                for (PlaybackStateCompat.CustomAction action : mCustomActionList) {
-                    mStateBuilder.addCustomAction(action);
-                }
-            }
-        }
-        mStateBuilder.setState(getCorrespondingPlaybackState(),
-                mMediaPlayer.getCurrentPosition(), mSpeed);
-        if (mCurrentState != STATE_ERROR
-                && mCurrentState != STATE_IDLE
-                && mCurrentState != STATE_PREPARING) {
-            if (mCurrentBufferPercentage == -1) {
-                mStateBuilder.setBufferedPosition(-1);
-            } else {
-                mStateBuilder.setBufferedPosition(
-                        (long) (mCurrentBufferPercentage / 100.0 * mMediaPlayer.getDuration()));
-            }
-        }
-
-        // Set PlaybackState for MediaSession
-        if (mMediaSession != null) {
-            PlaybackStateCompat state = mStateBuilder.build();
-            mMediaSession.setPlaybackState(state);
-        }
-    }
-
-    private int getCorrespondingPlaybackState() {
-        switch (mCurrentState) {
-            case STATE_ERROR:
-                return PlaybackStateCompat.STATE_ERROR;
-            case STATE_IDLE:
-                return PlaybackStateCompat.STATE_NONE;
-            case STATE_PREPARING:
-                return PlaybackStateCompat.STATE_CONNECTING;
-            case STATE_PREPARED:
-                return PlaybackStateCompat.STATE_PAUSED;
-            case STATE_PLAYING:
-                return PlaybackStateCompat.STATE_PLAYING;
-            case STATE_PAUSED:
-                return PlaybackStateCompat.STATE_PAUSED;
-            case STATE_PLAYBACK_COMPLETED:
-                return PlaybackStateCompat.STATE_STOPPED;
-            default:
-                return -1;
-        }
-    }
-
-    private final Runnable mFadeOut = new Runnable() {
-        @Override
-        public void run() {
-            if (mCurrentState == STATE_PLAYING) {
-                mMediaControlView.setVisibility(View.GONE);
-            }
-        }
-    };
-
-    private void showController() {
-        if (mMediaControlView == null || !isInPlaybackState()
-                || (isMusicMediaType() && mSizeType == SIZE_TYPE_FULL)) {
-            return;
-        }
-        mMediaControlView.removeCallbacks(mFadeOut);
-        mMediaControlView.setVisibility(View.VISIBLE);
-        if (mShowControllerIntervalMs != 0
-                && !mAccessibilityManager.isTouchExplorationEnabled()) {
-            mMediaControlView.postDelayed(mFadeOut, mShowControllerIntervalMs);
-        }
-    }
-
-    private void toggleMediaControlViewVisibility() {
-        if (mMediaControlView.getVisibility() == View.VISIBLE) {
-            mMediaControlView.removeCallbacks(mFadeOut);
-            mMediaControlView.setVisibility(View.GONE);
-        } else {
-            showController();
-        }
-    }
-
-    private void applySpeed() {
-        if (android.os.Build.VERSION.SDK_INT < 23) {
-            return;
-        }
-        PlaybackParams params = mMediaPlayer.getPlaybackParams().allowDefaults();
-        if (mSpeed != params.getSpeed()) {
-            try {
-                params.setSpeed(mSpeed);
-                mMediaPlayer.setPlaybackParams(params);
-                mFallbackSpeed = mSpeed;
-            } catch (IllegalArgumentException e) {
-                Log.e(TAG, "PlaybackParams has unsupported value: " + e);
-                float fallbackSpeed = mMediaPlayer.getPlaybackParams().allowDefaults().getSpeed();
-                if (fallbackSpeed > 0.0f) {
-                    mFallbackSpeed = fallbackSpeed;
-                }
-                mSpeed = mFallbackSpeed;
-            }
-        }
-    }
-
-    private boolean isRemotePlayback() {
-        if (mMediaController == null) {
-            return false;
-        }
-        PlaybackInfo playbackInfo = mMediaController.getPlaybackInfo();
-        return playbackInfo != null
-                && playbackInfo.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE;
-    }
-
-    protected void extractTracks() {
-        MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo();
-        mVideoTrackIndices = new ArrayList<>();
-        mAudioTrackIndices = new ArrayList<>();
-        for (int i = 0; i < trackInfos.length; ++i) {
-            int trackType = trackInfos[i].getTrackType();
-            if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) {
-                mVideoTrackIndices.add(i);
-            } else if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
-                mAudioTrackIndices.add(i);
-            }
-        }
-        // Select first tracks as default
-        if (mVideoTrackIndices.size() > 0) {
-            mSelectedVideoTrackIndex = 0;
-        }
-        if (mAudioTrackIndices.size() > 0) {
-            mSelectedAudioTrackIndex = 0;
-        }
-
-        Bundle data = new Bundle();
-        data.putInt(MediaControlView2.KEY_VIDEO_TRACK_COUNT, mVideoTrackIndices.size());
-        data.putInt(MediaControlView2.KEY_AUDIO_TRACK_COUNT, mAudioTrackIndices.size());
-        mMediaSession.sendSessionEvent(MediaControlView2.EVENT_UPDATE_TRACK_STATUS, data);
-    }
-
-    protected void doShowSubtitleCommand(Bundle args) {
-        // No-op
-    }
-
-    protected void doHideSubtitleCommand() {
-        // No-op
-    }
-
-    private void extractMetadata() {
-        if (mRetriever == null) {
-            return;
-        }
-        // Get and set duration and title values as MediaMetadata for MediaControlView2
-        MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
-        String title = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
-        if (title != null) {
-            mTitle = title;
-        }
-        builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mTitle);
-        builder.putLong(
-                MediaMetadataCompat.METADATA_KEY_DURATION, mMediaPlayer.getDuration());
-
-        if (mMediaSession != null) {
-            mMediaSession.setMetadata(builder.build());
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    private void extractAudioMetadata() {
-        if (mRetriever == null || !isMusicMediaType()) {
-            return;
-        }
-
-        mResources = mInstance.getResources();
-        mManager = (WindowManager) mInstance.getContext().getApplicationContext()
-                .getSystemService(Context.WINDOW_SERVICE);
-
-        byte[] album = mRetriever.getEmbeddedPicture();
-        if (album != null) {
-            Bitmap bitmap = BitmapFactory.decodeByteArray(album, 0, album.length);
-            mMusicAlbumDrawable = new BitmapDrawable(bitmap);
-
-            Palette.Builder builder = Palette.from(bitmap);
-            builder.generate(new Palette.PaletteAsyncListener() {
-                @Override
-                public void onGenerated(Palette palette) {
-                    mDominantColor = palette.getDominantColor(0);
-                    if (mMusicView != null) {
-                        mMusicView.setBackgroundColor(mDominantColor);
-                    }
-                }
-            });
-        } else {
-            mMusicAlbumDrawable = mResources.getDrawable(R.drawable.ic_default_album_image);
-        }
-
-        String title = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
-        if (title != null) {
-            mMusicTitleText = title;
-        } else {
-            mMusicTitleText = mResources.getString(R.string.mcv2_music_title_unknown_text);
-        }
-
-        String artist = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
-        if (artist != null) {
-            mMusicArtistText = artist;
-        } else {
-            mMusicArtistText = mResources.getString(R.string.mcv2_music_artist_unknown_text);
-        }
-
-        // Send title and artist string to MediaControlView2
-        MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
-        builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mMusicTitleText);
-        builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, mMusicArtistText);
-        mMediaSession.setMetadata(builder.build());
-
-        // Display Embedded mode as default
-        mInstance.removeView(mSurfaceView);
-        mInstance.removeView(mTextureView);
-        inflateMusicView(R.layout.embedded_music);
-    }
-
-    private int retrieveOrientation() {
-        DisplayMetrics dm = Resources.getSystem().getDisplayMetrics();
-        int width = dm.widthPixels;
-        int height = dm.heightPixels;
-
-        return (height > width)
-                ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
-                : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-    }
-
-    private void inflateMusicView(int layoutId) {
-        mInstance.removeView(mMusicView);
-
-        LayoutInflater inflater = (LayoutInflater) mInstance.getContext()
-                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View v = inflater.inflate(layoutId, null);
-        v.setBackgroundColor(mDominantColor);
-
-        ImageView albumView = v.findViewById(R.id.album);
-        if (albumView != null) {
-            albumView.setImageDrawable(mMusicAlbumDrawable);
-        }
-
-        TextView titleView = v.findViewById(R.id.title);
-        if (titleView != null) {
-            titleView.setText(mMusicTitleText);
-        }
-
-        TextView artistView = v.findViewById(R.id.artist);
-        if (artistView != null) {
-            artistView.setText(mMusicArtistText);
-        }
-
-        mMusicView = v;
-        mInstance.addView(mMusicView, 0);
-    }
-
-    private MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
-            new MediaPlayer.OnVideoSizeChangedListener() {
-                @Override
-                public void onVideoSizeChanged(
-                        MediaPlayer mp, int width, int height) {
-                    if (DEBUG) {
-                        Log.d(TAG, "onVideoSizeChanged(): size: " + width + "/" + height);
-                    }
-                    mVideoWidth = mp.getVideoWidth();
-                    mVideoHeight = mp.getVideoHeight();
-                    if (DEBUG) {
-                        Log.d(TAG, "onVideoSizeChanged(): mVideoSize:" + mVideoWidth + "/"
-                                + mVideoHeight);
-                    }
-                    if (mVideoWidth != 0 && mVideoHeight != 0) {
-                        mInstance.requestLayout();
-                    }
-                }
-            };
-
-    private MediaPlayer.OnPreparedListener mPreparedListener =
-            new MediaPlayer.OnPreparedListener() {
-        @Override
-        public void onPrepared(MediaPlayer mp) {
-            if (DEBUG) {
-                Log.d(TAG, "OnPreparedListener(). mCurrentState=" + mCurrentState
-                        + ", mTargetState=" + mTargetState);
-            }
-            mCurrentState = STATE_PREPARED;
-            // Create and set playback state for MediaControlView2
-            updatePlaybackState();
-
-            if (mMediaSession != null) {
-                extractTracks();
-                extractMetadata();
-                extractAudioMetadata();
-            }
-
-            if (mMediaControlView != null) {
-                mMediaControlView.setEnabled(true);
-            }
-            int videoWidth = mp.getVideoWidth();
-            int videoHeight = mp.getVideoHeight();
-
-            // mSeekWhenPrepared may be changed after seekTo() call
-            long seekToPosition = mSeekWhenPrepared;
-            if (seekToPosition != 0) {
-                mMediaController.getTransportControls().seekTo(seekToPosition);
-            }
-
-            if (videoWidth != 0 && videoHeight != 0) {
-                if (videoWidth != mVideoWidth || videoHeight != mVideoHeight) {
-                    mVideoWidth = videoWidth;
-                    mVideoHeight = videoHeight;
-                    mInstance.requestLayout();
-                }
-
-                if (needToStart()) {
-                    mMediaController.getTransportControls().play();
-                }
-            } else {
-                // We don't know the video size yet, but should start anyway.
-                // The video size might be reported to us later.
-                if (needToStart()) {
-                    mMediaController.getTransportControls().play();
-                }
-            }
-            // Get and set duration and title values as MediaMetadata for MediaControlView2
-            MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
-
-            builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mTitle);
-            builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, mMediaPlayer.getDuration());
-
-            if (mMediaSession != null) {
-                mMediaSession.setMetadata(builder.build());
-
-                if (mNeedUpdateMediaType) {
-                    mMediaSession.sendSessionEvent(
-                            MediaControlView2.EVENT_UPDATE_MEDIA_TYPE_STATUS, mMediaTypeData);
-                    mNeedUpdateMediaType = false;
-                }
-            }
-        }
-    };
-
-    private MediaPlayer.OnSeekCompleteListener mSeekCompleteListener =
-            new MediaPlayer.OnSeekCompleteListener() {
-                @Override
-                public void onSeekComplete(MediaPlayer mp) {
-                    updatePlaybackState();
-                }
-    };
-
-    private MediaPlayer.OnCompletionListener mCompletionListener =
-            new MediaPlayer.OnCompletionListener() {
-        @Override
-        @SuppressWarnings("deprecation")
-        public void onCompletion(MediaPlayer mp) {
-            mCurrentState = STATE_PLAYBACK_COMPLETED;
-            mTargetState = STATE_PLAYBACK_COMPLETED;
-            updatePlaybackState();
-            if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
-                mAudioManager.abandonAudioFocus(null);
-            }
-        }
-    };
-
-    private MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {
-        @Override
-        public boolean onInfo(MediaPlayer mp, int what, int extra) {
-            if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
-                extractTracks();
-            }
-            return true;
-        }
-    };
-
-    private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() {
-        @Override
-        public boolean onError(MediaPlayer mp, int frameworkErr, int implErr) {
-            if (DEBUG) {
-                Log.d(TAG, "Error: " + frameworkErr + "," + implErr);
-            }
-            mCurrentState = STATE_ERROR;
-            mTargetState = STATE_ERROR;
-            updatePlaybackState();
-
-            if (mMediaControlView != null) {
-                mMediaControlView.setVisibility(View.GONE);
-            }
-            return true;
-        }
-    };
-
-    private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
-            new MediaPlayer.OnBufferingUpdateListener() {
-        @Override
-        public void onBufferingUpdate(MediaPlayer mp, int percent) {
-            mCurrentBufferPercentage = percent;
-            updatePlaybackState();
-        }
-    };
-
-    private class MediaSessionCallback extends MediaSessionCompat.Callback {
-        @Override
-        public void onCommand(String command, Bundle args, ResultReceiver receiver) {
-            if (isRemotePlayback()) {
-                mRoutePlayer.onCommand(command, args, receiver);
-            } else {
-                switch (command) {
-                    case MediaControlView2.COMMAND_SHOW_SUBTITLE:
-                        doShowSubtitleCommand(args);
-                        break;
-                    case MediaControlView2.COMMAND_HIDE_SUBTITLE:
-                        doHideSubtitleCommand();
-                        break;
-                    case MediaControlView2.COMMAND_SELECT_AUDIO_TRACK:
-                        int audioIndex = args.getInt(MediaControlView2.KEY_SELECTED_AUDIO_INDEX,
-                                INVALID_TRACK_INDEX);
-                        if (audioIndex != INVALID_TRACK_INDEX) {
-                            int audioTrackIndex = mAudioTrackIndices.get(audioIndex);
-                            if (audioTrackIndex != mSelectedAudioTrackIndex) {
-                                mSelectedAudioTrackIndex = audioTrackIndex;
-                                mMediaPlayer.selectTrack(mSelectedAudioTrackIndex);
-                            }
-                        }
-                        break;
-                    case MediaControlView2.COMMAND_SET_PLAYBACK_SPEED:
-                        float speed = args.getFloat(
-                                MediaControlView2.KEY_PLAYBACK_SPEED, INVALID_SPEED);
-                        if (speed != INVALID_SPEED && speed != mSpeed) {
-                            setSpeed(speed);
-                            mSpeed = speed;
-                        }
-                        break;
-                    case MediaControlView2.COMMAND_MUTE:
-                        mVolumeLevel = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
-                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
-                        break;
-                    case MediaControlView2.COMMAND_UNMUTE:
-                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mVolumeLevel, 0);
-                        break;
-                }
-            }
-            showController();
-        }
-
-        @Override
-        public void onCustomAction(final String action, final Bundle extras) {
-            mCustomActionListenerRecord.first.execute(new Runnable() {
-                @Override
-                public void run() {
-                    mCustomActionListenerRecord.second.onCustomAction(action, extras);
-                }
-            });
-            showController();
-        }
-
-        @Override
-        public void onPlay() {
-            if (!isAudioGranted()) {
-                requestAudioFocus(mAudioFocusType);
-            }
-
-            if ((isInPlaybackState() && mCurrentView.hasAvailableSurface()) || isMusicMediaType()) {
-                if (isRemotePlayback()) {
-                    mRoutePlayer.onPlay();
-                } else {
-                    applySpeed();
-                    mMediaPlayer.start();
-                    mCurrentState = STATE_PLAYING;
-                    updatePlaybackState();
-                }
-                mCurrentState = STATE_PLAYING;
-            }
-            mTargetState = STATE_PLAYING;
-            if (DEBUG) {
-                Log.d(TAG, "onPlay(). mCurrentState=" + mCurrentState
-                        + ", mTargetState=" + mTargetState);
-            }
-            showController();
-        }
-
-        @Override
-        public void onPause() {
-            if (isInPlaybackState()) {
-                if (isRemotePlayback()) {
-                    mRoutePlayer.onPlay();
-                    mCurrentState = STATE_PAUSED;
-                } else if (mMediaPlayer.isPlaying()) {
-                    mMediaPlayer.pause();
-                    mCurrentState = STATE_PAUSED;
-                    updatePlaybackState();
-                }
-            }
-            mTargetState = STATE_PAUSED;
-            if (DEBUG) {
-                Log.d(TAG, "onPause(). mCurrentState=" + mCurrentState
-                        + ", mTargetState=" + mTargetState);
-            }
-            showController();
-        }
-
-        @Override
-        public void onSeekTo(long pos) {
-            if (isInPlaybackState()) {
-                if (isRemotePlayback()) {
-                    mRoutePlayer.onPlay();
-                } else {
-                    if (android.os.Build.VERSION.SDK_INT < 26) {
-                        mMediaPlayer.seekTo((int) pos);
-                    } else {
-                        mMediaPlayer.seekTo(pos, MediaPlayer.SEEK_PREVIOUS_SYNC);
-                    }
-                    mSeekWhenPrepared = 0;
-                }
-            } else {
-                mSeekWhenPrepared = pos;
-            }
-            showController();
-        }
-
-        @Override
-        public void onStop() {
-            if (isRemotePlayback()) {
-                mRoutePlayer.onPlay();
-            } else {
-                resetPlayer();
-            }
-            showController();
-        }
-    }
-}
diff --git a/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoViewInterfaceWithMp1.java b/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoViewInterfaceWithMp1.java
deleted file mode 100644
index a3bac28..0000000
--- a/media-widget/src/main/java/androidx/media/widget/impl_with_mp1/VideoViewInterfaceWithMp1.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.widget;
-
-import android.media.MediaPlayer;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-
-interface VideoViewInterfaceWithMp1 {
-    /**
-     * Assigns the view's surface to the given MediaPlayer instance.
-     *
-     * @param mp MediaPlayer
-     * @return true if the surface is successfully assigned, false if not. It will fail to assign
-     *         if any of MediaPlayer or surface is unavailable.
-     */
-    boolean assignSurfaceToMediaPlayer(MediaPlayer mp);
-    void setSurfaceListener(SurfaceListener l);
-    int getViewType();
-    void setMediaPlayer(MediaPlayer mp);
-
-    /**
-     * Takes over oldView. It means that the MediaPlayer will start rendering on this view.
-     * The visibility of oldView will be set as {@link View.GONE}. If the view doesn't have a
-     * MediaPlayer instance or its surface is not available, the actual execution is deferred until
-     * a MediaPlayer instance is set by {@link #setMediaPlayer} or its surface becomes available.
-     * {@link SurfaceListener.onSurfaceTakeOverDone} will be called when the actual execution is
-     * done.
-     *
-     * @param oldView The view that MediaPlayer is currently rendering on.
-     */
-    void takeOver(@NonNull VideoViewInterfaceWithMp1 oldView);
-
-    /**
-     * Indicates if the view's surface is available.
-     *
-     * @return true if the surface is available.
-     */
-    boolean hasAvailableSurface();
-
-    /**
-     * An instance of VideoViewInterface calls these surface notification methods accordingly if
-     * a listener has been registered via {@link #setSurfaceListener(SurfaceListener)}.
-     */
-    interface SurfaceListener {
-        void onSurfaceCreated(View view, int width, int height);
-        void onSurfaceDestroyed(View view);
-        void onSurfaceChanged(View view, int width, int height);
-        void onSurfaceTakeOverDone(VideoViewInterfaceWithMp1 view);
-    }
-}
diff --git a/media-widget/src/main/res/layout/embedded_settings_list_item.xml b/media-widget/src/main/res/layout/embedded_settings_list_item.xml
index c690c48..1156dca 100644
--- a/media-widget/src/main/res/layout/embedded_settings_list_item.xml
+++ b/media-widget/src/main/res/layout/embedded_settings_list_item.xml
@@ -16,50 +16,48 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
-    android:layout_height="@dimen/mcv2_settings_height"
+    android:layout_height="@dimen/mcv2_embedded_settings_height"
     android:orientation="horizontal"
     android:background="@color/black_opacity_70">
 
     <LinearLayout
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/mcv2_settings_height"
+        android:layout_height="@dimen/mcv2_embedded_settings_height"
         android:gravity="center"
         android:orientation="horizontal">
 
         <ImageView
             android:id="@+id/icon"
-            android:layout_width="@dimen/mcv2_settings_icon_size"
-            android:layout_height="@dimen/mcv2_settings_icon_size"
+            android:layout_width="@dimen/mcv2_embedded_settings_icon_size"
+            android:layout_height="@dimen/mcv2_embedded_settings_icon_size"
             android:layout_margin="8dp"
             android:gravity="center" />
     </LinearLayout>
 
-    <LinearLayout
+    <RelativeLayout
         android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:gravity="center|left">
+        android:layout_height="@dimen/mcv2_embedded_settings_height"
+        android:gravity="center"
+        android:orientation="vertical">
 
-        <LinearLayout
+        <TextView
+            android:id="@+id/main_text"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:gravity="center|left"
-            android:orientation="vertical">
+            android:layout_height="@dimen/mcv2_embedded_settings_text_height"
+            android:gravity="center"
+            android:paddingLeft="2dp"
+            android:textColor="@color/white"
+            android:textSize="@dimen/mcv2_embedded_settings_main_text_size"/>
 
-            <TextView
-                android:id="@+id/main_text"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:paddingLeft="2dp"
-                android:textColor="@color/white"
-                android:textSize="@dimen/mcv2_settings_main_text_size"/>
-
-            <TextView
-                android:id="@+id/sub_text"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:paddingLeft="2dp"
-                android:textColor="@color/white_opacity_70"
-                android:textSize="@dimen/mcv2_settings_sub_text_size"/>
-        </LinearLayout>
-    </LinearLayout>
+        <TextView
+            android:id="@+id/sub_text"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/mcv2_embedded_settings_text_height"
+            android:layout_below="@id/main_text"
+            android:gravity="center"
+            android:paddingLeft="2dp"
+            android:textColor="@color/white_opacity_70"
+            android:textSize="@dimen/mcv2_embedded_settings_sub_text_size"/>
+    </RelativeLayout>
 </LinearLayout>
+
diff --git a/media-widget/src/main/res/layout/embedded_sub_settings_list_item.xml b/media-widget/src/main/res/layout/embedded_sub_settings_list_item.xml
index c455504..5947a72 100644
--- a/media-widget/src/main/res/layout/embedded_sub_settings_list_item.xml
+++ b/media-widget/src/main/res/layout/embedded_sub_settings_list_item.xml
@@ -16,20 +16,20 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
-    android:layout_height="@dimen/mcv2_settings_height"
+    android:layout_height="@dimen/mcv2_embedded_settings_height"
     android:orientation="horizontal"
     android:background="@color/black_opacity_70">
 
     <LinearLayout
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/mcv2_settings_height"
+        android:layout_height="@dimen/mcv2_embedded_settings_height"
         android:gravity="center"
         android:orientation="horizontal">
 
         <ImageView
             android:id="@+id/check"
-            android:layout_width="@dimen/mcv2_settings_icon_size"
-            android:layout_height="@dimen/mcv2_settings_icon_size"
+            android:layout_width="@dimen/mcv2_embedded_settings_icon_size"
+            android:layout_height="@dimen/mcv2_embedded_settings_icon_size"
             android:layout_margin="8dp"
             android:gravity="center"
             android:src="@drawable/ic_check"/>
@@ -37,17 +37,17 @@
 
     <RelativeLayout
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/mcv2_settings_height"
+        android:layout_height="@dimen/mcv2_embedded_settings_height"
         android:gravity="center"
         android:orientation="vertical">
 
         <TextView
             android:id="@+id/text"
             android:layout_width="wrap_content"
-            android:layout_height="@dimen/mcv2_settings_text_height"
+            android:layout_height="@dimen/mcv2_embedded_settings_text_height"
             android:gravity="center"
             android:paddingLeft="2dp"
             android:textColor="@color/white"
-            android:textSize="@dimen/mcv2_settings_main_text_size"/>
+            android:textSize="@dimen/mcv2_embedded_settings_main_text_size"/>
     </RelativeLayout>
 </LinearLayout>
diff --git a/media-widget/src/main/res/layout/embedded_transport_controls.xml b/media-widget/src/main/res/layout/embedded_transport_controls.xml
index 89b98b7..a3a5957 100644
--- a/media-widget/src/main/res/layout/embedded_transport_controls.xml
+++ b/media-widget/src/main/res/layout/embedded_transport_controls.xml
@@ -15,10 +15,12 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:gravity="center"
     android:orientation="horizontal"
+    android:paddingLeft="@dimen/mcv2_transport_controls_padding"
+    android:paddingRight="@dimen/mcv2_transport_controls_padding"
     android:visibility="visible">
 
     <ImageButton android:id="@+id/prev" style="@style/EmbeddedTransportControlsButton.Previous" />
diff --git a/media-widget/src/main/res/layout/full_settings_list_item.xml b/media-widget/src/main/res/layout/full_settings_list_item.xml
index c4406d9..f92ea5e 100644
--- a/media-widget/src/main/res/layout/full_settings_list_item.xml
+++ b/media-widget/src/main/res/layout/full_settings_list_item.xml
@@ -16,50 +16,47 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
-    android:layout_height="@dimen/mcv2_settings_height"
+    android:layout_height="@dimen/mcv2_full_settings_height"
     android:orientation="horizontal"
     android:background="@color/black_opacity_70">
 
     <LinearLayout
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/mcv2_settings_height"
+        android:layout_height="@dimen/mcv2_full_settings_height"
         android:gravity="center"
         android:orientation="horizontal">
 
         <ImageView
             android:id="@+id/icon"
-            android:layout_width="@dimen/mcv2_settings_icon_size"
-            android:layout_height="@dimen/mcv2_settings_icon_size"
+            android:layout_width="@dimen/mcv2_full_settings_icon_size"
+            android:layout_height="@dimen/mcv2_full_settings_icon_size"
             android:layout_margin="8dp"
             android:gravity="center"/>
     </LinearLayout>
 
-    <LinearLayout
+    <RelativeLayout
         android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:gravity="center|left">
+        android:layout_height="@dimen/mcv2_full_settings_height"
+        android:gravity="center"
+        android:orientation="vertical">
 
-        <LinearLayout
+        <TextView
+            android:id="@+id/main_text"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:gravity="center|left"
-            android:orientation="vertical">
+            android:layout_height="@dimen/mcv2_full_settings_text_height"
+            android:paddingLeft="2dp"
+            android:gravity="center"
+            android:textColor="@color/white"
+            android:textSize="@dimen/mcv2_full_settings_main_text_size"/>
 
-            <TextView
-                android:id="@+id/main_text"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:paddingLeft="2dp"
-                android:textColor="@color/white"
-                android:textSize="@dimen/mcv2_settings_main_text_size"/>
-
-            <TextView
-                android:id="@+id/sub_text"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:paddingLeft="2dp"
-                android:textColor="@color/white_opacity_70"
-                android:textSize="@dimen/mcv2_settings_sub_text_size"/>
-        </LinearLayout>
-    </LinearLayout>
+        <TextView
+            android:id="@+id/sub_text"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/mcv2_full_settings_text_height"
+            android:layout_below="@id/main_text"
+            android:gravity="center"
+            android:paddingLeft="2dp"
+            android:textColor="@color/white_opacity_70"
+            android:textSize="@dimen/mcv2_full_settings_sub_text_size"/>
+    </RelativeLayout>
 </LinearLayout>
diff --git a/media-widget/src/main/res/layout/full_sub_settings_list_item.xml b/media-widget/src/main/res/layout/full_sub_settings_list_item.xml
index 3bd4ed1..49128d0 100644
--- a/media-widget/src/main/res/layout/full_sub_settings_list_item.xml
+++ b/media-widget/src/main/res/layout/full_sub_settings_list_item.xml
@@ -16,20 +16,20 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
-    android:layout_height="@dimen/mcv2_settings_height"
+    android:layout_height="@dimen/mcv2_full_settings_height"
     android:orientation="horizontal"
     android:background="@color/black_opacity_70">
 
     <LinearLayout
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/mcv2_settings_height"
+        android:layout_height="@dimen/mcv2_full_settings_height"
         android:gravity="center"
         android:orientation="horizontal">
 
         <ImageView
             android:id="@+id/check"
-            android:layout_width="@dimen/mcv2_settings_icon_size"
-            android:layout_height="@dimen/mcv2_settings_icon_size"
+            android:layout_width="@dimen/mcv2_full_settings_icon_size"
+            android:layout_height="@dimen/mcv2_full_settings_icon_size"
             android:layout_margin="8dp"
             android:gravity="center"
             android:src="@drawable/ic_check"/>
@@ -37,17 +37,17 @@
 
     <RelativeLayout
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/mcv2_settings_height"
+        android:layout_height="@dimen/mcv2_full_settings_height"
         android:gravity="center"
         android:orientation="vertical">
 
         <TextView
             android:id="@+id/text"
             android:layout_width="wrap_content"
-            android:layout_height="@dimen/mcv2_settings_text_height"
+            android:layout_height="@dimen/mcv2_full_settings_text_height"
             android:gravity="center"
             android:paddingLeft="2dp"
             android:textColor="@color/white"
-            android:textSize="@dimen/mcv2_settings_main_text_size"/>
+            android:textSize="@dimen/mcv2_full_settings_main_text_size"/>
     </RelativeLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/media-widget/src/main/res/layout/full_transport_controls.xml b/media-widget/src/main/res/layout/full_transport_controls.xml
index f5d8b00..0914785 100644
--- a/media-widget/src/main/res/layout/full_transport_controls.xml
+++ b/media-widget/src/main/res/layout/full_transport_controls.xml
@@ -15,10 +15,12 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:gravity="center"
     android:orientation="horizontal"
+    android:paddingLeft="@dimen/mcv2_transport_controls_padding"
+    android:paddingRight="@dimen/mcv2_transport_controls_padding"
     android:visibility="visible">
 
     <ImageButton android:id="@+id/prev" style="@style/FullTransportControlsButton.Previous" />
diff --git a/media-widget/src/main/res/layout/media_controller.xml b/media-widget/src/main/res/layout/media_controller.xml
index 7fec8cc..8749a7b 100644
--- a/media-widget/src/main/res/layout/media_controller.xml
+++ b/media-widget/src/main/res/layout/media_controller.xml
@@ -29,16 +29,19 @@
             android:id="@+id/title_bar_left"
             android:gravity="center"
             android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_alignParentStart="true"
+            android:layout_height="wrap_content"
+            android:layout_alignParentLeft="true"
             android:layout_centerVertical="true"
             android:orientation="horizontal">
 
             <ImageButton
                 android:id="@+id/back"
                 android:clickable="true"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
                 android:layout_alignParentStart="true"
                 android:layout_centerVertical="true"
+                android:paddingLeft="5dip"
                 android:visibility="visible"
                 style="@style/TitleBarButton.Back"/>
 
@@ -50,7 +53,8 @@
                 android:layout_toRightOf="@id/back"
                 android:layout_centerVertical="true"
                 android:maxLines="1"
-                android:paddingStart="@dimen/mcv2_embedded_icon_padding"
+                android:paddingLeft="5dip"
+                android:paddingRight="5dip"
                 android:textSize="15sp"
                 android:textColor="#FFFFFFFF"/>
         </LinearLayout>
@@ -95,12 +99,13 @@
                     style="@style/TitleBarButton.Launch" />
             </LinearLayout>
 
-            <view class="androidx.mediarouter.app.MediaRouteButton"
+            <!-- TODO (b/77158231): Causes java.lang.ClassNotFoundException as of Apr 02 2018 -->
+            <!--view class="androidx.mediarouter.app.MediaRouteButton"
                 android:id="@+id/cast"
                 android:layout_centerVertical="true"
                 android:visibility="gone"
                 android:contentDescription="@string/mr_button_content_description"
-                style="@style/TitleBarButton" />
+                style="@style/TitleBarButton" /-->
         </LinearLayout>
 
     </RelativeLayout>
@@ -152,9 +157,9 @@
     <RelativeLayout
         android:id="@+id/bottom_bar"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/mcv2_bottom_bar_height"
-        android:background="@color/bottom_bar_background"
-        android:orientation="horizontal">
+        android:layout_height="44dp"
+        android:orientation="horizontal"
+        android:background="@color/bottom_bar_background">
 
         <LinearLayout
             android:id="@+id/bottom_bar_left"
@@ -165,12 +170,12 @@
 
             <TextView
                 android:id="@+id/ad_skip_time"
+                android:gravity="center"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:layout_marginLeft="4dp"
-                android:gravity="center"
-                android:textColor="#FFFFFF"
                 android:textSize="12sp"
+                android:textColor="#FFFFFF"
                 android:visibility="gone" />
         </LinearLayout>
 
@@ -179,21 +184,19 @@
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:layout_toRightOf="@id/bottom_bar_left"
-            android:gravity="center"
             android:paddingLeft="10dp"
-            android:paddingRight="10dp">
+            android:paddingRight="10dp"
+            android:gravity="center" >
 
             <TextView
                 android:id="@+id/time_current"
-                style="@style/TimeText.Current" />
-
+                style="@style/TimeText.Current"/>
             <TextView
                 android:id="@+id/time_interpunct"
-                style="@style/TimeText.Interpunct" />
-
+                style="@style/TimeText.Interpunct"/>
             <TextView
                 android:id="@+id/time_end"
-                style="@style/TimeText.End" />
+                style="@style/TimeText.End"/>
         </LinearLayout>
 
         <LinearLayout
@@ -201,68 +204,63 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_alignParentEnd="true"
-            android:layout_centerVertical="true">
+            android:gravity="right">
 
             <LinearLayout
                 android:id="@+id/basic_controls"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:gravity="center"
-                android:orientation="horizontal">
+                android:gravity="center_vertical"
+                android:orientation="horizontal" >
 
                 <TextView
                     android:id="@+id/ad_remaining"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:gravity="center"
-                    android:textColor="#FFFFFF"
                     android:textSize="12sp"
+                    android:textColor="#FFFFFF"
                     android:visibility="gone" />
 
                 <ImageButton
                     android:id="@+id/mute"
                     style="@style/BottomBarButton.Mute" />
-
                 <ImageButton
                     android:id="@+id/subtitle"
-                    style="@style/BottomBarButton.CC"
                     android:scaleType="fitCenter"
-                    android:visibility="gone" />
-
+                    android:visibility="gone"
+                    style="@style/BottomBarButton.CC" />
                 <ImageButton
                     android:id="@+id/fullscreen"
-                    style="@style/BottomBarButton.FullScreen" />
-
+                    style="@style/BottomBarButton.FullScreen"/>
                 <ImageButton
                     android:id="@+id/overflow_right"
-                    style="@style/BottomBarButton.OverflowRight" />
+                    style="@style/BottomBarButton.OverflowRight"/>
             </LinearLayout>
 
             <LinearLayout
                 android:id="@+id/extra_controls"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:gravity="center"
+                android:visibility="gone"
                 android:orientation="horizontal"
-                android:visibility="gone">
+                android:gravity="center_vertical">
 
                 <LinearLayout
                     android:id="@+id/custom_buttons"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:orientation="horizontal" />
+                    android:orientation="horizontal"/>
 
                 <ImageButton
                     android:id="@+id/video_quality"
                     style="@style/BottomBarButton.VideoQuality" />
-
                 <ImageButton
                     android:id="@+id/settings"
                     style="@style/BottomBarButton.Settings" />
-
                 <ImageButton
                     android:id="@+id/overflow_left"
-                    style="@style/BottomBarButton.OverflowLeft" />
+                    style="@style/BottomBarButton.OverflowLeft"/>
             </LinearLayout>
         </LinearLayout>
     </RelativeLayout>
diff --git a/media-widget/src/main/res/layout/minimal_transport_controls.xml b/media-widget/src/main/res/layout/minimal_transport_controls.xml
index a72adc7..800c80b 100644
--- a/media-widget/src/main/res/layout/minimal_transport_controls.xml
+++ b/media-widget/src/main/res/layout/minimal_transport_controls.xml
@@ -15,8 +15,8 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:gravity="center"
     android:orientation="horizontal">
 
diff --git a/media-widget/src/main/res/layout/settings_list.xml b/media-widget/src/main/res/layout/settings_list.xml
index f08f81b..ea30538 100644
--- a/media-widget/src/main/res/layout/settings_list.xml
+++ b/media-widget/src/main/res/layout/settings_list.xml
@@ -16,8 +16,7 @@
 
 <ListView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="@dimen/mcv2_embedded_settings_width"
-    android:layout_height="@dimen/mcv2_settings_height"
-    android:layout_gravity="center_vertical"
+    android:layout_height="@dimen/mcv2_embedded_settings_height"
     android:divider="@null"
     android:dividerHeight="0dp">
 </ListView>
\ No newline at end of file
diff --git a/media-widget/src/main/res/values/dimens.xml b/media-widget/src/main/res/values/dimens.xml
index f03c871..796f345 100644
--- a/media-widget/src/main/res/values/dimens.xml
+++ b/media-widget/src/main/res/values/dimens.xml
@@ -17,19 +17,25 @@
 
 <resources>
     <dimen name="mcv2_embedded_settings_width">150dp</dimen>
+    <dimen name="mcv2_embedded_settings_height">36dp</dimen>
+    <dimen name="mcv2_embedded_settings_icon_size">20dp</dimen>
+    <dimen name="mcv2_embedded_settings_text_height">18dp</dimen>
+    <dimen name="mcv2_embedded_settings_main_text_size">12sp</dimen>
+    <dimen name="mcv2_embedded_settings_sub_text_size">10sp</dimen>
     <dimen name="mcv2_full_settings_width">225dp</dimen>
-    <dimen name="mcv2_settings_height">48dp</dimen>
-    <dimen name="mcv2_settings_icon_size">24dp</dimen>
-    <dimen name="mcv2_settings_text_height">24dp</dimen>
-    <dimen name="mcv2_settings_main_text_size">14sp</dimen>
-    <dimen name="mcv2_settings_sub_text_size">12sp</dimen>
+    <dimen name="mcv2_full_settings_height">54dp</dimen>
+    <dimen name="mcv2_full_settings_icon_size">30dp</dimen>
+    <dimen name="mcv2_full_settings_text_height">27dp</dimen>
+    <dimen name="mcv2_full_settings_main_text_size">16sp</dimen>
+    <dimen name="mcv2_full_settings_sub_text_size">13sp</dimen>
     <dimen name="mcv2_settings_offset">8dp</dimen>
 
-    <dimen name="mcv2_icon_size">48dp</dimen>
+    <dimen name="mcv2_transport_controls_padding">4dp</dimen>
+    <dimen name="mcv2_pause_icon_size">36dp</dimen>
+    <dimen name="mcv2_full_icon_size">28dp</dimen>
+    <dimen name="mcv2_embedded_icon_size">24dp</dimen>
+    <dimen name="mcv2_minimal_icon_size">24dp</dimen>
     <dimen name="mcv2_icon_margin">10dp</dimen>
-    <dimen name="mcv2_pause_icon_padding">6dp</dimen>
-    <dimen name="mcv2_full_icon_padding">10dp</dimen>
-    <dimen name="mcv2_embedded_icon_padding">12dp</dimen>
 
     <dimen name="mcv2_full_album_image_portrait_size">232dp</dimen>
     <dimen name="mcv2_full_album_image_landscape_size">176dp</dimen>
@@ -37,7 +43,4 @@
     <dimen name="mcv2_custom_progress_max_size">2dp</dimen>
     <dimen name="mcv2_custom_progress_thumb_size">12dp</dimen>
     <dimen name="mcv2_buffer_view_height">5dp</dimen>
-
-    <dimen name="mcv2_title_bar_height">54dp</dimen>
-    <dimen name="mcv2_bottom_bar_height">58dp</dimen>
 </resources>
diff --git a/media-widget/src/main/res/values/styles.xml b/media-widget/src/main/res/values/styles.xml
index 2e03acb..fc42bd4 100644
--- a/media-widget/src/main/res/values/styles.xml
+++ b/media-widget/src/main/res/values/styles.xml
@@ -2,99 +2,91 @@
 <resources>
     <style name="FullTransportControlsButton">
         <item name="android:background">@null</item>
+        <item name="android:layout_margin">@dimen/mcv2_icon_margin</item>
         <item name="android:scaleType">fitXY</item>
     </style>
 
     <style name="FullTransportControlsButton.Previous">
         <item name="android:src">@drawable/ic_skip_previous</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_full_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_full_icon_size</item>
         <item name="android:contentDescription">@string/mcv2_previous_button_desc</item>
-        <item name="android:padding">@dimen/mcv2_full_icon_padding</item>
     </style>
 
     <style name="FullTransportControlsButton.Next">
         <item name="android:src">@drawable/ic_skip_next</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_full_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_full_icon_size</item>
         <item name="android:contentDescription">@string/mcv2_next_button_desc</item>
-        <item name="android:padding">@dimen/mcv2_full_icon_padding</item>
     </style>
 
     <style name="FullTransportControlsButton.Pause">
         <item name="android:src">@drawable/ic_pause_circle_filled</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_pause_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_pause_icon_size</item>
         <item name="android:contentDescription">@string/mcv2_pause_button_desc</item>
-        <item name="android:padding">@dimen/mcv2_pause_icon_padding</item>
     </style>
 
     <style name="FullTransportControlsButton.Ffwd">
         <item name="android:src">@drawable/ic_forward_30</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_full_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_full_icon_size</item>
         <item name="android:contentDescription">@string/mcv2_ffwd_button_desc</item>
-        <item name="android:padding">@dimen/mcv2_full_icon_padding</item>
     </style>
 
     <style name="FullTransportControlsButton.Rew">
         <item name="android:src">@drawable/ic_rewind_10</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_full_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_full_icon_size</item>
         <item name="android:contentDescription">@string/mcv2_rewind_button_desc</item>
-        <item name="android:padding">@dimen/mcv2_full_icon_padding</item>
     </style>
 
     <style name="EmbeddedTransportControlsButton">
         <item name="android:background">@null</item>
+        <item name="android:layout_margin">@dimen/mcv2_icon_margin</item>
         <item name="android:scaleType">fitXY</item>
     </style>
 
     <style name="EmbeddedTransportControlsButton.Previous">
         <item name="android:src">@drawable/ic_skip_previous</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_embedded_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_embedded_icon_size</item>
         <item name="android:contentDescription">@string/mcv2_previous_button_desc</item>
-        <item name="android:padding">@dimen/mcv2_embedded_icon_padding</item>
     </style>
 
     <style name="EmbeddedTransportControlsButton.Next">
         <item name="android:src">@drawable/ic_skip_next</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_embedded_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_embedded_icon_size</item>
         <item name="android:contentDescription">@string/mcv2_next_button_desc</item>
-        <item name="android:padding">@dimen/mcv2_embedded_icon_padding</item>
     </style>
 
     <style name="EmbeddedTransportControlsButton.Pause">
         <item name="android:src">@drawable/ic_pause_circle_filled</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_pause_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_pause_icon_size</item>
         <item name="android:contentDescription">@string/mcv2_pause_button_desc</item>
-        <item name="android:padding">@dimen/mcv2_pause_icon_padding</item>
     </style>
 
     <style name="EmbeddedTransportControlsButton.Ffwd">
         <item name="android:src">@drawable/ic_forward_30</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_embedded_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_embedded_icon_size</item>
         <item name="android:contentDescription">@string/mcv2_ffwd_button_desc</item>
-        <item name="android:padding">@dimen/mcv2_embedded_icon_padding</item>
     </style>
 
     <style name="EmbeddedTransportControlsButton.Rew">
         <item name="android:src">@drawable/ic_rewind_10</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_embedded_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_embedded_icon_size</item>
         <item name="android:contentDescription">@string/mcv2_rewind_button_desc</item>
-        <item name="android:padding">@dimen/mcv2_embedded_icon_padding</item>
     </style>
 
     <style name="MinimalTransportControlsButton">
         <item name="android:background">@null</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
-        <item name="android:padding">@dimen/mcv2_pause_icon_padding</item>
+        <item name="android:layout_width">@dimen/mcv2_pause_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_pause_icon_size</item>
+        <item name="android:layout_margin">@dimen/mcv2_icon_margin</item>
         <item name="android:scaleType">fitXY</item>
         <item name="android:src">@drawable/ic_pause_circle_filled</item>
         <item name="android:contentDescription">@string/mcv2_pause_button_desc</item>
@@ -102,15 +94,15 @@
 
     <style name="TitleBar">
         <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">@dimen/mcv2_title_bar_height</item>
+        <item name="android:layout_height">46dp</item>
+        <item name="android:paddingLeft">5dp</item>
+        <item name="android:paddingRight">5dp</item>
     </style>
 
     <style name="TitleBarButton">
         <item name="android:background">@null</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
-        <item name="android:padding">@dimen/mcv2_embedded_icon_padding</item>
-        <item name="android:scaleType">fitXY</item>
+        <item name="android:layout_width">36dp</item>
+        <item name="android:layout_height">36dp</item>
     </style>
 
     <style name="TitleBarButton.Back">
@@ -150,10 +142,10 @@
 
     <style name="BottomBarButton">
         <item name="android:background">@null</item>
-        <item name="android:layout_width">@dimen/mcv2_icon_size</item>
-        <item name="android:layout_height">@dimen/mcv2_icon_size</item>
+        <item name="android:layout_width">@dimen/mcv2_embedded_icon_size</item>
+        <item name="android:layout_height">@dimen/mcv2_embedded_icon_size</item>
+        <item name="android:layout_margin">@dimen/mcv2_icon_margin</item>
         <item name="android:gravity">center_horizontal</item>
-        <item name="android:padding">@dimen/mcv2_embedded_icon_padding</item>
         <item name="android:scaleType">fitXY</item>
     </style>
 
diff --git a/media/api/current.txt b/media/api/current.txt
index c3c28f5..a9e2161 100644
--- a/media/api/current.txt
+++ b/media/api/current.txt
@@ -300,7 +300,6 @@
     method public void addOnActiveChangeListener(android.support.v4.media.session.MediaSessionCompat.OnActiveChangeListener);
     method public static android.support.v4.media.session.MediaSessionCompat fromMediaSession(android.content.Context, java.lang.Object);
     method public android.support.v4.media.session.MediaControllerCompat getController();
-    method public final androidx.media.MediaSessionManager.RemoteUserInfo getCurrentControllerInfo();
     method public java.lang.Object getMediaSession();
     method public java.lang.Object getRemoteControlClient();
     method public android.support.v4.media.session.MediaSessionCompat.Token getSessionToken();
@@ -601,38 +600,10 @@
     method public androidx.media.DataSourceDesc.Builder setStartPosition(long);
   }
 
-  public abstract class Media2DataSource implements java.io.Closeable {
-    ctor public Media2DataSource();
-    method public abstract long getSize() throws java.io.IOException;
-    method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
-  }
-
-  public class MediaBrowser2 extends androidx.media.MediaController2 {
-    ctor public MediaBrowser2(android.content.Context, androidx.media.SessionToken2, java.util.concurrent.Executor, androidx.media.MediaBrowser2.BrowserCallback);
-    method public void getChildren(java.lang.String, int, int, android.os.Bundle);
-    method public void getItem(java.lang.String);
-    method public void getLibraryRoot(android.os.Bundle);
-    method public void getSearchResult(java.lang.String, int, int, android.os.Bundle);
-    method public void search(java.lang.String, android.os.Bundle);
-    method public void subscribe(java.lang.String, android.os.Bundle);
-    method public void unsubscribe(java.lang.String);
-  }
-
-  public static class MediaBrowser2.BrowserCallback extends androidx.media.MediaController2.ControllerCallback {
-    ctor public MediaBrowser2.BrowserCallback();
-    method public void onChildrenChanged(androidx.media.MediaBrowser2, java.lang.String, int, android.os.Bundle);
-    method public void onGetChildrenDone(androidx.media.MediaBrowser2, java.lang.String, int, int, java.util.List<androidx.media.MediaItem2>, android.os.Bundle);
-    method public void onGetItemDone(androidx.media.MediaBrowser2, java.lang.String, androidx.media.MediaItem2);
-    method public void onGetLibraryRootDone(androidx.media.MediaBrowser2, android.os.Bundle, java.lang.String, android.os.Bundle);
-    method public void onGetSearchResultDone(androidx.media.MediaBrowser2, java.lang.String, int, int, java.util.List<androidx.media.MediaItem2>, android.os.Bundle);
-    method public void onSearchResultChanged(androidx.media.MediaBrowser2, java.lang.String, int, android.os.Bundle);
-  }
-
   public abstract class MediaBrowserServiceCompat extends android.app.Service {
     ctor public MediaBrowserServiceCompat();
     method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public final android.os.Bundle getBrowserRootHints();
-    method public final androidx.media.MediaSessionManager.RemoteUserInfo getCurrentBrowserInfo();
     method public android.support.v4.media.session.MediaSessionCompat.Token getSessionToken();
     method public void notifyChildrenChanged(java.lang.String);
     method public void notifyChildrenChanged(java.lang.String, android.os.Bundle);
@@ -768,48 +739,6 @@
     method public androidx.media.MediaItem2.Builder setMetadata(androidx.media.MediaMetadata2);
   }
 
-  public abstract class MediaLibraryService2 extends androidx.media.MediaSessionService2 {
-    ctor public MediaLibraryService2();
-    method public abstract androidx.media.MediaLibraryService2.MediaLibrarySession onCreateSession(java.lang.String);
-    field public static final java.lang.String SERVICE_INTERFACE = "android.media.MediaLibraryService2";
-  }
-
-  public static final class MediaLibraryService2.LibraryRoot {
-    ctor public MediaLibraryService2.LibraryRoot(java.lang.String, android.os.Bundle);
-    method public android.os.Bundle getExtras();
-    method public java.lang.String getRootId();
-    field public static final java.lang.String EXTRA_OFFLINE = "android.media.extra.OFFLINE";
-    field public static final java.lang.String EXTRA_RECENT = "android.media.extra.RECENT";
-    field public static final java.lang.String EXTRA_SUGGESTED = "android.media.extra.SUGGESTED";
-  }
-
-  public static final class MediaLibraryService2.MediaLibrarySession extends androidx.media.MediaSession2 {
-    method public void notifyChildrenChanged(androidx.media.MediaSession2.ControllerInfo, java.lang.String, int, android.os.Bundle);
-    method public void notifyChildrenChanged(java.lang.String, int, android.os.Bundle);
-    method public void notifySearchResultChanged(androidx.media.MediaSession2.ControllerInfo, java.lang.String, int, android.os.Bundle);
-  }
-
-  public static final class MediaLibraryService2.MediaLibrarySession.Builder {
-    ctor public MediaLibraryService2.MediaLibrarySession.Builder(androidx.media.MediaLibraryService2, java.util.concurrent.Executor, androidx.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback);
-    method public androidx.media.MediaLibraryService2.MediaLibrarySession build();
-    method public androidx.media.MediaLibraryService2.MediaLibrarySession.Builder setId(java.lang.String);
-    method public androidx.media.MediaLibraryService2.MediaLibrarySession.Builder setPlayer(androidx.media.MediaPlayerInterface);
-    method public androidx.media.MediaLibraryService2.MediaLibrarySession.Builder setPlaylistAgent(androidx.media.MediaPlaylistAgent);
-    method public androidx.media.MediaLibraryService2.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent);
-    method public androidx.media.MediaLibraryService2.MediaLibrarySession.Builder setVolumeProvider(androidx.media.VolumeProviderCompat);
-  }
-
-  public static class MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback extends androidx.media.MediaSession2.SessionCallback {
-    ctor public MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback();
-    method public java.util.List<androidx.media.MediaItem2> onGetChildren(androidx.media.MediaLibraryService2.MediaLibrarySession, androidx.media.MediaSession2.ControllerInfo, java.lang.String, int, int, android.os.Bundle);
-    method public androidx.media.MediaItem2 onGetItem(androidx.media.MediaLibraryService2.MediaLibrarySession, androidx.media.MediaSession2.ControllerInfo, java.lang.String);
-    method public androidx.media.MediaLibraryService2.LibraryRoot onGetLibraryRoot(androidx.media.MediaLibraryService2.MediaLibrarySession, androidx.media.MediaSession2.ControllerInfo, android.os.Bundle);
-    method public java.util.List<androidx.media.MediaItem2> onGetSearchResult(androidx.media.MediaLibraryService2.MediaLibrarySession, androidx.media.MediaSession2.ControllerInfo, java.lang.String, int, int, android.os.Bundle);
-    method public void onSearch(androidx.media.MediaLibraryService2.MediaLibrarySession, androidx.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
-    method public void onSubscribe(androidx.media.MediaLibraryService2.MediaLibrarySession, androidx.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
-    method public void onUnsubscribe(androidx.media.MediaLibraryService2.MediaLibrarySession, androidx.media.MediaSession2.ControllerInfo, java.lang.String);
-  }
-
   public final class MediaMetadata2 {
     method public boolean containsKey(java.lang.String);
     method public static androidx.media.MediaMetadata2 fromBundle(android.os.Bundle);
@@ -881,201 +810,8 @@
     method public androidx.media.MediaMetadata2.Builder setExtras(android.os.Bundle);
   }
 
-  public abstract class MediaPlayer2 {
-    method public abstract void attachAuxEffect(int);
-    method public abstract void clearDrmEventCallback();
-    method public abstract void clearMediaPlayer2EventCallback();
-    method public abstract void clearPendingCommands();
-    method public abstract void close();
-    method public static final androidx.media.MediaPlayer2 create();
-    method public abstract void deselectTrack(int);
-    method public abstract androidx.media.AudioAttributesCompat getAudioAttributes();
-    method public abstract int getAudioSessionId();
-    method public abstract long getBufferedPosition();
-    method public abstract androidx.media.DataSourceDesc getCurrentDataSource();
-    method public abstract long getCurrentPosition();
-    method public abstract androidx.media.MediaPlayer2.DrmInfo getDrmInfo();
-    method public abstract android.media.MediaDrm.KeyRequest getDrmKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws androidx.media.MediaPlayer2.NoDrmSchemeException;
-    method public abstract java.lang.String getDrmPropertyString(java.lang.String) throws androidx.media.MediaPlayer2.NoDrmSchemeException;
-    method public abstract long getDuration();
-    method public float getMaxPlayerVolume();
-    method public abstract int getMediaPlayer2State();
-    method public abstract androidx.media.MediaPlayerInterface getMediaPlayerInterface();
-    method public abstract android.os.PersistableBundle getMetrics();
-    method public abstract android.media.PlaybackParams getPlaybackParams();
-    method public float getPlaybackSpeed();
-    method public abstract float getPlayerVolume();
-    method public abstract int getSelectedTrack(int);
-    method public abstract android.media.SyncParams getSyncParams();
-    method public abstract android.media.MediaTimestamp getTimestamp();
-    method public abstract java.util.List<androidx.media.MediaPlayer2.TrackInfo> getTrackInfo();
-    method public abstract int getVideoHeight();
-    method public abstract int getVideoWidth();
-    method public boolean isReversePlaybackSupported();
-    method public abstract void loopCurrent(boolean);
-    method public void notifyWhenCommandLabelReached(java.lang.Object);
-    method public abstract void pause();
-    method public abstract void play();
-    method public abstract void prepare();
-    method public abstract void prepareDrm(java.util.UUID) throws androidx.media.MediaPlayer2.ProvisioningNetworkErrorException, androidx.media.MediaPlayer2.ProvisioningServerErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
-    method public abstract byte[] provideDrmKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, androidx.media.MediaPlayer2.NoDrmSchemeException;
-    method public abstract void releaseDrm() throws androidx.media.MediaPlayer2.NoDrmSchemeException;
-    method public abstract void reset();
-    method public abstract void restoreDrmKeys(byte[]) throws androidx.media.MediaPlayer2.NoDrmSchemeException;
-    method public void seekTo(long);
-    method public abstract void seekTo(long, int);
-    method public abstract void selectTrack(int);
-    method public abstract void setAudioAttributes(androidx.media.AudioAttributesCompat);
-    method public abstract void setAudioSessionId(int);
-    method public abstract void setAuxEffectSendLevel(float);
-    method public abstract void setDataSource(androidx.media.DataSourceDesc);
-    method public abstract void setDrmEventCallback(java.util.concurrent.Executor, androidx.media.MediaPlayer2.DrmEventCallback);
-    method public abstract void setDrmPropertyString(java.lang.String, java.lang.String) throws androidx.media.MediaPlayer2.NoDrmSchemeException;
-    method public abstract void setMediaPlayer2EventCallback(java.util.concurrent.Executor, androidx.media.MediaPlayer2.MediaPlayer2EventCallback);
-    method public abstract void setNextDataSource(androidx.media.DataSourceDesc);
-    method public abstract void setNextDataSources(java.util.List<androidx.media.DataSourceDesc>);
-    method public abstract void setOnDrmConfigHelper(androidx.media.MediaPlayer2.OnDrmConfigHelper);
-    method public abstract void setPlaybackParams(android.media.PlaybackParams);
-    method public abstract void setPlaybackSpeed(float);
-    method public abstract void setPlayerVolume(float);
-    method public abstract void setSurface(android.view.Surface);
-    method public abstract void setSyncParams(android.media.SyncParams);
-    method public abstract void skipToNext();
-    field public static final int CALL_COMPLETED_ATTACH_AUX_EFFECT = 1; // 0x1
-    field public static final int CALL_COMPLETED_DESELECT_TRACK = 2; // 0x2
-    field public static final int CALL_COMPLETED_LOOP_CURRENT = 3; // 0x3
-    field public static final int CALL_COMPLETED_PAUSE = 4; // 0x4
-    field public static final int CALL_COMPLETED_PLAY = 5; // 0x5
-    field public static final int CALL_COMPLETED_PREPARE = 6; // 0x6
-    field public static final int CALL_COMPLETED_SEEK_TO = 14; // 0xe
-    field public static final int CALL_COMPLETED_SELECT_TRACK = 15; // 0xf
-    field public static final int CALL_COMPLETED_SET_AUDIO_ATTRIBUTES = 16; // 0x10
-    field public static final int CALL_COMPLETED_SET_AUDIO_SESSION_ID = 17; // 0x11
-    field public static final int CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL = 18; // 0x12
-    field public static final int CALL_COMPLETED_SET_DATA_SOURCE = 19; // 0x13
-    field public static final int CALL_COMPLETED_SET_NEXT_DATA_SOURCE = 22; // 0x16
-    field public static final int CALL_COMPLETED_SET_NEXT_DATA_SOURCES = 23; // 0x17
-    field public static final int CALL_COMPLETED_SET_PLAYBACK_PARAMS = 24; // 0x18
-    field public static final int CALL_COMPLETED_SET_PLAYBACK_SPEED = 25; // 0x19
-    field public static final int CALL_COMPLETED_SET_PLAYER_VOLUME = 26; // 0x1a
-    field public static final int CALL_COMPLETED_SET_SURFACE = 27; // 0x1b
-    field public static final int CALL_COMPLETED_SET_SYNC_PARAMS = 28; // 0x1c
-    field public static final int CALL_COMPLETED_SKIP_TO_NEXT = 29; // 0x1d
-    field public static final int CALL_STATUS_BAD_VALUE = 2; // 0x2
-    field public static final int CALL_STATUS_ERROR_IO = 4; // 0x4
-    field public static final int CALL_STATUS_ERROR_UNKNOWN = -2147483648; // 0x80000000
-    field public static final int CALL_STATUS_INVALID_OPERATION = 1; // 0x1
-    field public static final int CALL_STATUS_NO_ERROR = 0; // 0x0
-    field public static final int CALL_STATUS_PERMISSION_DENIED = 3; // 0x3
-    field public static final int MEDIAPLAYER2_STATE_ERROR = 1005; // 0x3ed
-    field public static final int MEDIAPLAYER2_STATE_IDLE = 1001; // 0x3e9
-    field public static final int MEDIAPLAYER2_STATE_PAUSED = 1003; // 0x3eb
-    field public static final int MEDIAPLAYER2_STATE_PLAYING = 1004; // 0x3ec
-    field public static final int MEDIAPLAYER2_STATE_PREPARED = 1002; // 0x3ea
-    field public static final int MEDIA_ERROR_IO = -1004; // 0xfffffc14
-    field public static final int MEDIA_ERROR_MALFORMED = -1007; // 0xfffffc11
-    field public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200; // 0xc8
-    field public static final int MEDIA_ERROR_TIMED_OUT = -110; // 0xffffff92
-    field public static final int MEDIA_ERROR_UNKNOWN = 1; // 0x1
-    field public static final int MEDIA_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
-    field public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
-    field public static final int MEDIA_INFO_AUDIO_RENDERING_START = 4; // 0x4
-    field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
-    field public static final int MEDIA_INFO_BUFFERING_END = 702; // 0x2be
-    field public static final int MEDIA_INFO_BUFFERING_START = 701; // 0x2bd
-    field public static final int MEDIA_INFO_BUFFERING_UPDATE = 704; // 0x2c0
-    field public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
-    field public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
-    field public static final int MEDIA_INFO_PLAYBACK_COMPLETE = 5; // 0x5
-    field public static final int MEDIA_INFO_PLAYLIST_END = 6; // 0x6
-    field public static final int MEDIA_INFO_PREPARED = 100; // 0x64
-    field public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902; // 0x386
-    field public static final int MEDIA_INFO_UNKNOWN = 1; // 0x1
-    field public static final int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901; // 0x385
-    field public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
-    field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
-    field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
-    field public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3; // 0x3
-    field public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1; // 0x1
-    field public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2; // 0x2
-    field public static final int PREPARE_DRM_STATUS_SUCCESS = 0; // 0x0
-    field public static final int SEEK_CLOSEST = 3; // 0x3
-    field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
-    field public static final int SEEK_NEXT_SYNC = 1; // 0x1
-    field public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0
-    field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
-  }
-
-  public static abstract class MediaPlayer2.DrmEventCallback {
-    ctor public MediaPlayer2.DrmEventCallback();
-    method public void onDrmInfo(androidx.media.MediaPlayer2, androidx.media.DataSourceDesc, androidx.media.MediaPlayer2.DrmInfo);
-    method public void onDrmPrepared(androidx.media.MediaPlayer2, androidx.media.DataSourceDesc, int);
-  }
-
-  public static abstract class MediaPlayer2.DrmInfo {
-    ctor public MediaPlayer2.DrmInfo();
-    method public abstract java.util.Map<java.util.UUID, byte[]> getPssh();
-    method public abstract java.util.List<java.util.UUID> getSupportedSchemes();
-  }
-
-  public static abstract class MediaPlayer2.MediaPlayer2EventCallback {
-    ctor public MediaPlayer2.MediaPlayer2EventCallback();
-    method public void onCallCompleted(androidx.media.MediaPlayer2, androidx.media.DataSourceDesc, int, int);
-    method public void onCommandLabelReached(androidx.media.MediaPlayer2, java.lang.Object);
-    method public void onError(androidx.media.MediaPlayer2, androidx.media.DataSourceDesc, int, int);
-    method public void onInfo(androidx.media.MediaPlayer2, androidx.media.DataSourceDesc, int, int);
-    method public void onMediaTimeDiscontinuity(androidx.media.MediaPlayer2, androidx.media.DataSourceDesc, android.media.MediaTimestamp);
-    method public void onSubtitleData(androidx.media.MediaPlayer2, androidx.media.DataSourceDesc, android.media.SubtitleData);
-    method public void onTimedMetaDataAvailable(androidx.media.MediaPlayer2, androidx.media.DataSourceDesc, android.media.TimedMetaData);
-    method public void onVideoSizeChanged(androidx.media.MediaPlayer2, androidx.media.DataSourceDesc, int, int);
-  }
-
-  public static final class MediaPlayer2.MetricsConstants {
-    field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-    field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-    field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs";
-    field public static final java.lang.String ERRORS = "android.media.mediaplayer.err";
-    field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode";
-    field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames";
-    field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-    field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height";
-    field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
-    field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
-    field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs";
-    field public static final java.lang.String WIDTH = "android.media.mediaplayer.width";
-  }
-
-  public static class MediaPlayer2.NoDrmSchemeException extends android.media.MediaDrmException {
-    ctor public MediaPlayer2.NoDrmSchemeException(java.lang.String);
-  }
-
-  public static abstract interface MediaPlayer2.OnDrmConfigHelper {
-    method public abstract void onDrmConfig(androidx.media.MediaPlayer2, androidx.media.DataSourceDesc);
-  }
-
-  public static class MediaPlayer2.ProvisioningNetworkErrorException extends android.media.MediaDrmException {
-    ctor public MediaPlayer2.ProvisioningNetworkErrorException(java.lang.String);
-  }
-
-  public static class MediaPlayer2.ProvisioningServerErrorException extends android.media.MediaDrmException {
-    ctor public MediaPlayer2.ProvisioningServerErrorException(java.lang.String);
-  }
-
-  public static abstract class MediaPlayer2.TrackInfo {
-    ctor public MediaPlayer2.TrackInfo();
-    method public abstract android.media.MediaFormat getFormat();
-    method public abstract java.lang.String getLanguage();
-    method public abstract int getTrackType();
-    method public abstract java.lang.String toString();
-    field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
-    field public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
-    field public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; // 0x4
-    field public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; // 0x0
-    field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
-  }
-
-  public abstract class MediaPlayerInterface implements java.lang.AutoCloseable {
-    ctor public MediaPlayerInterface();
+  public abstract class MediaPlayerBase implements java.lang.AutoCloseable {
+    ctor public MediaPlayerBase();
     method public abstract androidx.media.AudioAttributesCompat getAudioAttributes();
     method public long getBufferedPosition();
     method public abstract int getBufferingState();
@@ -1091,7 +827,7 @@
     method public abstract void pause();
     method public abstract void play();
     method public abstract void prepare();
-    method public abstract void registerPlayerEventCallback(java.util.concurrent.Executor, androidx.media.MediaPlayerInterface.PlayerEventCallback);
+    method public abstract void registerPlayerEventCallback(java.util.concurrent.Executor, androidx.media.MediaPlayerBase.PlayerEventCallback);
     method public abstract void reset();
     method public abstract void seekTo(long);
     method public abstract void setAudioAttributes(androidx.media.AudioAttributesCompat);
@@ -1101,7 +837,7 @@
     method public abstract void setPlaybackSpeed(float);
     method public abstract void setPlayerVolume(float);
     method public abstract void skipToNext();
-    method public abstract void unregisterPlayerEventCallback(androidx.media.MediaPlayerInterface.PlayerEventCallback);
+    method public abstract void unregisterPlayerEventCallback(androidx.media.MediaPlayerBase.PlayerEventCallback);
     field public static final int BUFFERING_STATE_BUFFERING_AND_PLAYABLE = 1; // 0x1
     field public static final int BUFFERING_STATE_BUFFERING_AND_STARVED = 2; // 0x2
     field public static final int BUFFERING_STATE_BUFFERING_COMPLETE = 3; // 0x3
@@ -1113,14 +849,14 @@
     field public static final long UNKNOWN_TIME = -1L; // 0xffffffffffffffffL
   }
 
-  public static abstract class MediaPlayerInterface.PlayerEventCallback {
-    ctor public MediaPlayerInterface.PlayerEventCallback();
-    method public void onBufferingStateChanged(androidx.media.MediaPlayerInterface, androidx.media.DataSourceDesc, int);
-    method public void onCurrentDataSourceChanged(androidx.media.MediaPlayerInterface, androidx.media.DataSourceDesc);
-    method public void onMediaPrepared(androidx.media.MediaPlayerInterface, androidx.media.DataSourceDesc);
-    method public void onPlaybackSpeedChanged(androidx.media.MediaPlayerInterface, float);
-    method public void onPlayerStateChanged(androidx.media.MediaPlayerInterface, int);
-    method public void onSeekCompleted(androidx.media.MediaPlayerInterface, long);
+  public static abstract class MediaPlayerBase.PlayerEventCallback {
+    ctor public MediaPlayerBase.PlayerEventCallback();
+    method public void onBufferingStateChanged(androidx.media.MediaPlayerBase, androidx.media.DataSourceDesc, int);
+    method public void onCurrentDataSourceChanged(androidx.media.MediaPlayerBase, androidx.media.DataSourceDesc);
+    method public void onMediaPrepared(androidx.media.MediaPlayerBase, androidx.media.DataSourceDesc);
+    method public void onPlaybackSpeedChanged(androidx.media.MediaPlayerBase, float);
+    method public void onPlayerStateChanged(androidx.media.MediaPlayerBase, int);
+    method public void onSeekCompleted(androidx.media.MediaPlayerBase, long);
   }
 
   public abstract class MediaPlaylistAgent {
@@ -1175,7 +911,7 @@
     method public long getCurrentPosition();
     method public long getDuration();
     method public float getPlaybackSpeed();
-    method public androidx.media.MediaPlayerInterface getPlayer();
+    method public androidx.media.MediaPlayerBase getPlayer();
     method public int getPlayerState();
     method public java.util.List<androidx.media.MediaItem2> getPlaylist();
     method public androidx.media.MediaPlaylistAgent getPlaylistAgent();
@@ -1206,7 +942,7 @@
     method public void skipToNextItem();
     method public void skipToPlaylistItem(androidx.media.MediaItem2);
     method public void skipToPreviousItem();
-    method public void updatePlayer(androidx.media.MediaPlayerInterface, androidx.media.MediaPlaylistAgent, androidx.media.VolumeProviderCompat);
+    method public void updatePlayer(androidx.media.MediaPlayerBase, androidx.media.MediaPlaylistAgent, androidx.media.VolumeProviderCompat);
     method public void updatePlaylistMetadata(androidx.media.MediaMetadata2);
     field public static final int ERROR_CODE_ACTION_ABORTED = 10; // 0xa
     field public static final int ERROR_CODE_APP_ERROR = 1; // 0x1
@@ -1227,7 +963,7 @@
     ctor public MediaSession2.Builder(android.content.Context);
     method public androidx.media.MediaSession2 build();
     method public androidx.media.MediaSession2.Builder setId(java.lang.String);
-    method public androidx.media.MediaSession2.Builder setPlayer(androidx.media.MediaPlayerInterface);
+    method public androidx.media.MediaSession2.Builder setPlayer(androidx.media.MediaPlayerBase);
     method public androidx.media.MediaSession2.Builder setPlaylistAgent(androidx.media.MediaPlaylistAgent);
     method public androidx.media.MediaSession2.Builder setSessionActivity(android.app.PendingIntent);
     method public androidx.media.MediaSession2.Builder setSessionCallback(java.util.concurrent.Executor, androidx.media.MediaSession2.SessionCallback);
@@ -1263,19 +999,19 @@
 
   public static abstract class MediaSession2.SessionCallback {
     ctor public MediaSession2.SessionCallback();
-    method public void onBufferingStateChanged(androidx.media.MediaSession2, androidx.media.MediaPlayerInterface, androidx.media.MediaItem2, int);
+    method public void onBufferingStateChanged(androidx.media.MediaSession2, androidx.media.MediaPlayerBase, androidx.media.MediaItem2, int);
     method public boolean onCommandRequest(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo, androidx.media.SessionCommand2);
     method public androidx.media.SessionCommandGroup2 onConnect(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo);
-    method public void onCurrentMediaItemChanged(androidx.media.MediaSession2, androidx.media.MediaPlayerInterface, androidx.media.MediaItem2);
+    method public void onCurrentMediaItemChanged(androidx.media.MediaSession2, androidx.media.MediaPlayerBase, androidx.media.MediaItem2);
     method public void onCustomCommand(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo, androidx.media.SessionCommand2, android.os.Bundle, android.os.ResultReceiver);
     method public void onDisconnected(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo);
     method public void onFastForward(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo);
-    method public void onMediaPrepared(androidx.media.MediaSession2, androidx.media.MediaPlayerInterface, androidx.media.MediaItem2);
+    method public void onMediaPrepared(androidx.media.MediaSession2, androidx.media.MediaPlayerBase, androidx.media.MediaItem2);
     method public void onPlayFromMediaId(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
     method public void onPlayFromSearch(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
     method public void onPlayFromUri(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo, android.net.Uri, android.os.Bundle);
-    method public void onPlaybackSpeedChanged(androidx.media.MediaSession2, androidx.media.MediaPlayerInterface, float);
-    method public void onPlayerStateChanged(androidx.media.MediaSession2, androidx.media.MediaPlayerInterface, int);
+    method public void onPlaybackSpeedChanged(androidx.media.MediaSession2, androidx.media.MediaPlayerBase, float);
+    method public void onPlayerStateChanged(androidx.media.MediaSession2, androidx.media.MediaPlayerBase, int);
     method public void onPlaylistChanged(androidx.media.MediaSession2, androidx.media.MediaPlaylistAgent, java.util.List<androidx.media.MediaItem2>, androidx.media.MediaMetadata2);
     method public void onPlaylistMetadataChanged(androidx.media.MediaSession2, androidx.media.MediaPlaylistAgent, androidx.media.MediaMetadata2);
     method public void onPrepareFromMediaId(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
@@ -1283,7 +1019,7 @@
     method public void onPrepareFromUri(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo, android.net.Uri, android.os.Bundle);
     method public void onRepeatModeChanged(androidx.media.MediaSession2, androidx.media.MediaPlaylistAgent, int);
     method public void onRewind(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo);
-    method public void onSeekCompleted(androidx.media.MediaSession2, androidx.media.MediaPlayerInterface, long);
+    method public void onSeekCompleted(androidx.media.MediaSession2, androidx.media.MediaPlayerBase, long);
     method public void onSelectRoute(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo, android.os.Bundle);
     method public void onSetRating(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo, java.lang.String, androidx.media.Rating2);
     method public void onShuffleModeChanged(androidx.media.MediaSession2, androidx.media.MediaPlaylistAgent, int);
@@ -1291,35 +1027,6 @@
     method public void onUnsubscribeRoutesInfo(androidx.media.MediaSession2, androidx.media.MediaSession2.ControllerInfo);
   }
 
-  public final class MediaSessionManager {
-    method public static androidx.media.MediaSessionManager getSessionManager(android.content.Context);
-    method public boolean isTrustedForMediaControl(androidx.media.MediaSessionManager.RemoteUserInfo);
-  }
-
-  public static final class MediaSessionManager.RemoteUserInfo {
-    ctor public MediaSessionManager.RemoteUserInfo(java.lang.String, int, int);
-    method public java.lang.String getPackageName();
-    method public int getPid();
-    method public int getUid();
-    field public static java.lang.String LEGACY_CONTROLLER;
-  }
-
-  public abstract class MediaSessionService2 extends android.app.Service {
-    ctor public MediaSessionService2();
-    method public final androidx.media.MediaSession2 getSession();
-    method public android.os.IBinder onBind(android.content.Intent);
-    method public abstract androidx.media.MediaSession2 onCreateSession(java.lang.String);
-    method public androidx.media.MediaSessionService2.MediaNotification onUpdateNotification();
-    field public static final java.lang.String SERVICE_INTERFACE = "android.media.MediaSessionService2";
-    field public static final java.lang.String SERVICE_META_DATA = "android.media.session";
-  }
-
-  public static class MediaSessionService2.MediaNotification {
-    ctor public MediaSessionService2.MediaNotification(int, android.app.Notification);
-    method public android.app.Notification getNotification();
-    method public int getNotificationId();
-  }
-
   public final class Rating2 {
     method public static androidx.media.Rating2 fromBundle(android.os.Bundle);
     method public float getPercentRating();
@@ -1350,13 +1057,6 @@
     method public java.lang.String getCustomCommand();
     method public android.os.Bundle getExtras();
     field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
-    field public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 29; // 0x1d
-    field public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 30; // 0x1e
-    field public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 31; // 0x1f
-    field public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 32; // 0x20
-    field public static final int COMMAND_CODE_LIBRARY_SEARCH = 33; // 0x21
-    field public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 34; // 0x22
-    field public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 35; // 0x23
     field public static final int COMMAND_CODE_PLAYBACK_PAUSE = 2; // 0x2
     field public static final int COMMAND_CODE_PLAYBACK_PLAY = 1; // 0x1
     field public static final int COMMAND_CODE_PLAYBACK_PREPARE = 6; // 0x6
@@ -1406,7 +1106,6 @@
   }
 
   public final class SessionToken2 {
-    ctor public SessionToken2(android.content.Context, android.content.ComponentName);
     method public static androidx.media.SessionToken2 fromBundle(android.os.Bundle);
     method public java.lang.String getId();
     method public java.lang.String getPackageName();
@@ -1414,9 +1113,7 @@
     method public int getType();
     method public int getUid();
     method public android.os.Bundle toBundle();
-    field public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2
     field public static final int TYPE_SESSION = 0; // 0x0
-    field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
   }
 
   public abstract class VolumeProviderCompat {
diff --git a/media/src/androidTest/java/androidx/media/MediaBrowser2Test.java b/media/src/androidTest/java/androidx/media/MediaBrowser2Test.java
index 211b5a9..4b75986 100644
--- a/media/src/androidTest/java/androidx/media/MediaBrowser2Test.java
+++ b/media/src/androidTest/java/androidx/media/MediaBrowser2Test.java
@@ -29,12 +29,9 @@
 import static org.junit.Assert.assertNotEquals;
 
 import android.content.Context;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Process;
 import android.os.ResultReceiver;
-import android.support.test.filters.LargeTest;
-import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -68,15 +65,17 @@
  * {@link MediaController2} works cleanly.
  */
 // TODO(jaewan): Implement host-side test so browser and service can run in different processes.
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@Ignore
 public class MediaBrowser2Test extends MediaController2Test {
     private static final String TAG = "MediaBrowser2Test";
 
     @Override
     TestControllerInterface onCreateController(final @NonNull SessionToken2 token,
-            final @Nullable ControllerCallback callback) throws InterruptedException {
+            @Nullable ControllerCallback callback) throws InterruptedException {
+        final BrowserCallback browserCallback =
+                callback != null ? (BrowserCallback) callback : new BrowserCallback() {};
         final AtomicReference<TestControllerInterface> controller = new AtomicReference<>();
         sHandler.postAndSync(new Runnable() {
             @Override
@@ -85,7 +84,7 @@
                 // Looper. Otherwise, MediaBrowserCompat will post all the commands to the handler
                 // and commands wouldn't be run if tests codes waits on the test handler.
                 controller.set(new TestMediaBrowser(
-                        mContext, token, new TestBrowserCallback(callback)));
+                        mContext, token, new TestBrowserCallback(browserCallback)));
             }
         });
         return controller.get();
@@ -121,9 +120,7 @@
                     Bundle rootHints, String rootMediaId, Bundle rootExtra) {
                 assertTrue(TestUtils.equals(param, rootHints));
                 assertEquals(ROOT_ID, rootMediaId);
-                // Note that TestUtils#equals() cannot be used for this because
-                // MediaBrowserServiceCompat adds extra_client_version to the rootHints.
-                assertTrue(TestUtils.contains(rootExtra, EXTRAS));
+                assertTrue(TestUtils.equals(EXTRAS, rootExtra));
                 latch.countDown();
             }
         };
@@ -262,6 +259,7 @@
         assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
     }
 
+    @Ignore
     @Test
     public void testSearch() throws InterruptedException {
         prepareLooper();
@@ -319,7 +317,6 @@
     }
 
     @Test
-    @LargeTest
     public void testSearchTakesTime() throws InterruptedException {
         prepareLooper();
         final String query = MockMediaLibraryService2.SEARCH_QUERY_TAKES_TIME;
@@ -421,201 +418,82 @@
     }
 
     @Test
-    public void testBrowserCallback_onChildrenChangedIsNotCalledWhenNotSubscribed()
-            throws InterruptedException {
-        // This test uses MediaLibrarySession.notifyChildrenChanged().
+    public void testBrowserCallback_notifyChildrenChanged() throws InterruptedException {
         prepareLooper();
-        final String subscribedMediaId = "subscribedMediaId";
-        final String anotherMediaId = "anotherMediaId";
+        // TODO(jaewan): Add test for the notifyChildrenChanged itself.
+        final String testParentId1 = "testBrowserCallback_notifyChildrenChanged_unexpectedParent";
+        final String testParentId2 = "testBrowserCallback_notifyChildrenChanged";
         final int testChildrenCount = 101;
-        final CountDownLatch latch = new CountDownLatch(1);
+        final Bundle testExtras = new Bundle();
+        testExtras.putString(testParentId1, testParentId1);
 
-        final MediaLibrarySessionCallback sessionCallback = new MediaLibrarySessionCallback() {
-            @Override
-            public void onSubscribe(@NonNull MediaLibrarySession session,
-                    @NonNull ControllerInfo controller, @NonNull String parentId,
-                    @Nullable Bundle extras) {
-                if (Process.myUid() == controller.getUid()) {
-                    // Shouldn't trigger onChildrenChanged() for the browser,
-                    // because the browser didn't subscribe this media id.
-                    session.notifyChildrenChanged(anotherMediaId, testChildrenCount, null);
-                }
-            }
+        final CountDownLatch latch = new CountDownLatch(3);
+        final MediaLibrarySessionCallback sessionCallback =
+                new MediaLibrarySessionCallback() {
+                    @Override
+                    public SessionCommandGroup2 onConnect(@NonNull MediaSession2 session,
+                            @NonNull ControllerInfo controller) {
+                        if (Process.myUid() == controller.getUid()) {
+                            assertTrue(session instanceof MediaLibrarySession);
+                            if (mSession != null) {
+                                mSession.close();
+                            }
+                            mSession = session;
+                            // Shouldn't trigger onChildrenChanged() for the browser, because it
+                            // hasn't subscribed.
+                            ((MediaLibrarySession) session).notifyChildrenChanged(
+                                    testParentId1, testChildrenCount, null);
+                            ((MediaLibrarySession) session).notifyChildrenChanged(
+                                    controller, testParentId1, testChildrenCount, null);
+                        }
+                        return super.onConnect(session, controller);
+                    }
 
-            @Override
-            public List<MediaItem2> onGetChildren(MediaLibrarySession session,
-                    ControllerInfo controller, String parentId, int page, int pageSize,
-                    Bundle extras) {
-                return TestUtils.createPlaylist(testChildrenCount);
-            }
+                    @Override
+                    public void onSubscribe(@NonNull MediaLibrarySession session,
+                            @NonNull ControllerInfo info, @NonNull String parentId,
+                            @Nullable Bundle extras) {
+                        if (Process.myUid() == info.getUid()) {
+                            session.notifyChildrenChanged(testParentId2, testChildrenCount, null);
+                            session.notifyChildrenChanged(info, testParentId2, testChildrenCount,
+                                    testExtras);
+                        }
+                    }
         };
-        final BrowserCallback controllerCallbackProxy = new BrowserCallback() {
-            @Override
-            public void onChildrenChanged(MediaBrowser2 browser, String parentId,
-                    int itemCount, Bundle extras) {
-                // Unexpected call.
-                fail();
-            }
-        };
-
+        final BrowserCallback controllerCallbackProxy =
+                new BrowserCallback() {
+                    @Override
+                    public void onChildrenChanged(MediaBrowser2 browser, String parentId,
+                            int itemCount, Bundle extras) {
+                        switch ((int) latch.getCount()) {
+                            case 3:
+                                assertEquals(testParentId2, parentId);
+                                assertEquals(testChildrenCount, itemCount);
+                                assertNull(extras);
+                                latch.countDown();
+                                break;
+                            case 2:
+                                assertEquals(testParentId2, parentId);
+                                assertEquals(testChildrenCount, itemCount);
+                                assertTrue(TestUtils.equals(testExtras, extras));
+                                latch.countDown();
+                                break;
+                            default:
+                                // Unexpected call.
+                                fail();
+                        }
+                    }
+                };
         TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
         final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
         final MediaBrowser2 browser = (MediaBrowser2) createController(
                 token, true, controllerCallbackProxy);
-        browser.subscribe(subscribedMediaId, null);
-
-        // onChildrenChanged() should not be called.
+        assertTrue(mSession instanceof MediaLibrarySession);
+        browser.subscribe(testParentId2, null);
+        // This ensures that onChildrenChanged() is only called for the expected reasons.
         assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
     }
 
-    @Test
-    public void testBrowserCallback_onChildrenChangedIsCalledWhenSubscribed()
-            throws InterruptedException {
-        // This test uses MediaLibrarySession.notifyChildrenChanged().
-        prepareLooper();
-        final String expectedParentId = "expectedParentId";
-        final int testChildrenCount = 101;
-        final Bundle testExtras = TestUtils.createTestBundle();
-
-        final CountDownLatch latch = new CountDownLatch(1);
-        final MediaLibrarySessionCallback sessionCallback = new MediaLibrarySessionCallback() {
-            @Override
-            public void onSubscribe(@NonNull MediaLibrarySession session,
-                    @NonNull ControllerInfo controller, @NonNull String parentId,
-                    @Nullable Bundle extras) {
-                if (Process.myUid() == controller.getUid()) {
-                    // Should trigger onChildrenChanged() for the browser.
-                    session.notifyChildrenChanged(expectedParentId, testChildrenCount, testExtras);
-                }
-            }
-
-            @Override
-            public List<MediaItem2> onGetChildren(MediaLibrarySession session,
-                    ControllerInfo controller, String parentId, int page, int pageSize,
-                    Bundle extras) {
-                return TestUtils.createPlaylist(testChildrenCount);
-            }
-        };
-        final BrowserCallback controllerCallbackProxy = new BrowserCallback() {
-            @Override
-            public void onChildrenChanged(MediaBrowser2 browser, String parentId,
-                    int itemCount, Bundle extras) {
-                assertEquals(expectedParentId, parentId);
-                assertEquals(testChildrenCount, itemCount);
-                assertTrue(TestUtils.equals(testExtras, extras));
-                latch.countDown();
-            }
-        };
-
-        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
-        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
-        final MediaBrowser2 browser = (MediaBrowser2) createController(
-                token, true, controllerCallbackProxy);
-        browser.subscribe(expectedParentId, null);
-
-        // onChildrenChanged() should be called.
-        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testBrowserCallback_onChildrenChangedIsNotCalledWhenNotSubscribed2()
-            throws InterruptedException {
-        // This test uses MediaLibrarySession.notifyChildrenChanged(ControllerInfo).
-        prepareLooper();
-        final String subscribedMediaId = "subscribedMediaId";
-        final String anotherMediaId = "anotherMediaId";
-        final int testChildrenCount = 101;
-        final CountDownLatch latch = new CountDownLatch(1);
-
-        final MediaLibrarySessionCallback sessionCallback = new MediaLibrarySessionCallback() {
-            @Override
-            public void onSubscribe(@NonNull MediaLibrarySession session,
-                    @NonNull ControllerInfo controller, @NonNull String parentId,
-                    @Nullable Bundle extras) {
-                if (Process.myUid() == controller.getUid()) {
-                    // Shouldn't trigger onChildrenChanged() for the browser,
-                    // because the browser didn't subscribe this media id.
-                    session.notifyChildrenChanged(
-                            controller, anotherMediaId, testChildrenCount, null);
-                }
-            }
-
-            @Override
-            public List<MediaItem2> onGetChildren(MediaLibrarySession session,
-                    ControllerInfo controller, String parentId, int page, int pageSize,
-                    Bundle extras) {
-                return TestUtils.createPlaylist(testChildrenCount);
-            }
-        };
-        final BrowserCallback controllerCallbackProxy = new BrowserCallback() {
-            @Override
-            public void onChildrenChanged(MediaBrowser2 browser, String parentId,
-                    int itemCount, Bundle extras) {
-                // Unexpected call.
-                fail();
-            }
-        };
-
-        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
-        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
-        final MediaBrowser2 browser = (MediaBrowser2) createController(
-                token, true, controllerCallbackProxy);
-        browser.subscribe(subscribedMediaId, null);
-
-        // onChildrenChanged() should not be called.
-        assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testBrowserCallback_onChildrenChangedIsCalledWhenSubscribed2()
-            throws InterruptedException {
-        // This test uses MediaLibrarySession.notifyChildrenChanged(ControllerInfo).
-        prepareLooper();
-        final String expectedParentId = "expectedParentId";
-        final int testChildrenCount = 101;
-        final Bundle testExtras = TestUtils.createTestBundle();
-
-        final CountDownLatch latch = new CountDownLatch(1);
-        final MediaLibrarySessionCallback sessionCallback = new MediaLibrarySessionCallback() {
-            @Override
-            public void onSubscribe(@NonNull MediaLibrarySession session,
-                    @NonNull ControllerInfo controller, @NonNull String parentId,
-                    @Nullable Bundle extras) {
-                if (Process.myUid() == controller.getUid()) {
-                    // Should trigger onChildrenChanged() for the browser.
-                    session.notifyChildrenChanged(
-                            controller, expectedParentId, testChildrenCount, testExtras);
-                }
-            }
-
-            @Override
-            public List<MediaItem2> onGetChildren(MediaLibrarySession session,
-                    ControllerInfo controller, String parentId, int page, int pageSize,
-                    Bundle extras) {
-                return TestUtils.createPlaylist(testChildrenCount);
-            }
-        };
-        final BrowserCallback controllerCallbackProxy = new BrowserCallback() {
-            @Override
-            public void onChildrenChanged(MediaBrowser2 browser, String parentId,
-                    int itemCount, Bundle extras) {
-                assertEquals(expectedParentId, parentId);
-                assertEquals(testChildrenCount, itemCount);
-                assertTrue(TestUtils.equals(testExtras, extras));
-                latch.countDown();
-            }
-        };
-
-        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
-        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
-        final MediaBrowser2 browser = (MediaBrowser2) createController(
-                token, true, controllerCallbackProxy);
-        browser.subscribe(expectedParentId, null);
-
-        // onChildrenChanged() should be called.
-        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-    }
-
     public static class TestBrowserCallback extends BrowserCallback
             implements TestControllerCallbackInterface {
         private final ControllerCallback mCallbackProxy;
@@ -626,7 +504,7 @@
 
         TestBrowserCallback(ControllerCallback callbackProxy) {
             if (callbackProxy == null) {
-                callbackProxy = new BrowserCallback() {};
+                throw new IllegalArgumentException("Callback proxy shouldn't be null. Test bug");
             }
             mCallbackProxy = callbackProxy;
         }
@@ -812,9 +690,9 @@
         private final BrowserCallback mCallback;
 
         public TestMediaBrowser(@NonNull Context context, @NonNull SessionToken2 token,
-                @NonNull BrowserCallback callback) {
-            super(context, token, sHandlerExecutor, callback);
-            mCallback = callback;
+                @NonNull ControllerCallback callback) {
+            super(context, token, sHandlerExecutor, (BrowserCallback) callback);
+            mCallback = (BrowserCallback) callback;
         }
 
         @Override
diff --git a/media/src/androidTest/java/androidx/media/MediaController2Test.java b/media/src/androidTest/java/androidx/media/MediaController2Test.java
index 072381e..75c9e50 100644
--- a/media/src/androidTest/java/androidx/media/MediaController2Test.java
+++ b/media/src/androidTest/java/androidx/media/MediaController2Test.java
@@ -25,7 +25,6 @@
 import static org.junit.Assert.fail;
 
 import android.app.PendingIntent;
-import android.content.Context;
 import android.content.Intent;
 import android.media.AudioManager;
 import android.net.Uri;
@@ -42,16 +41,15 @@
 
 import androidx.annotation.NonNull;
 import androidx.media.MediaController2.ControllerCallback;
-import androidx.media.MediaController2.PlaybackInfo;
 import androidx.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
 import androidx.media.MediaSession2.ControllerInfo;
 import androidx.media.MediaSession2.SessionCallback;
 import androidx.media.TestServiceRegistry.SessionServiceCallback;
 import androidx.media.TestUtils.SyncHandler;
-import androidx.testutils.PollingCheck;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -67,7 +65,7 @@
 // TODO(jaewan): Implement host-side test so controller and session can run in different processes.
 // TODO(jaewan): Fix flaky failure -- see MediaController2Impl.getController()
 // TODO(jaeawn): Revisit create/close session in the sHandler. It's no longer necessary.
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 @FlakyTest
@@ -79,7 +77,6 @@
     MediaController2 mController;
     MockPlayer mPlayer;
     MockPlaylistAgent mMockAgent;
-    AudioManager mAudioManager;
 
     @Before
     @Override
@@ -114,7 +111,6 @@
                 .setSessionActivity(mIntent)
                 .setId(TAG).build();
         mController = createController(mSession.getToken());
-        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         TestServiceRegistry.getInstance().setHandler(sHandler);
     }
 
@@ -211,12 +207,11 @@
     @Test
     public void testGettersAfterConnected() throws InterruptedException {
         prepareLooper();
-        final int state = MediaPlayerInterface.PLAYER_STATE_PLAYING;
-        final int bufferingState = MediaPlayerInterface.BUFFERING_STATE_BUFFERING_COMPLETE;
+        final int state = MediaPlayerBase.PLAYER_STATE_PLAYING;
+        final int bufferingState = MediaPlayerBase.BUFFERING_STATE_BUFFERING_COMPLETE;
         final long position = 150000;
         final long bufferedPosition = 900000;
         final float speed = 0.5f;
-        final long timeDiff = 102;
         final MediaItem2 currentMediaItem = TestUtils.createMediaItemWithMetadata();
 
         mPlayer.mLastPlayerState = state;
@@ -226,60 +221,22 @@
         mPlayer.mPlaybackSpeed = speed;
         mMockAgent.mCurrentMediaItem = currentMediaItem;
 
+        long time1 = System.currentTimeMillis();
         MediaController2 controller = createController(mSession.getToken());
-        controller.setTimeDiff(timeDiff);
+        long time2 = System.currentTimeMillis();
         assertEquals(state, controller.getPlayerState());
         assertEquals(bufferedPosition, controller.getBufferedPosition());
         assertEquals(speed, controller.getPlaybackSpeed(), 0.0f);
-        assertEquals(position + (long) (speed * timeDiff), controller.getCurrentPosition());
+        long positionLowerBound = (long) (position + speed * (System.currentTimeMillis() - time2));
+        long currentPosition = controller.getCurrentPosition();
+        long positionUpperBound = (long) (position + speed * (System.currentTimeMillis() - time1));
+        assertTrue("curPos=" + currentPosition + ", lowerBound=" + positionLowerBound
+                        + ", upperBound=" + positionUpperBound,
+                positionLowerBound <= currentPosition && currentPosition <= positionUpperBound);
         assertEquals(currentMediaItem, controller.getCurrentMediaItem());
     }
 
     @Test
-    public void testUpdatePlayer() throws InterruptedException {
-        prepareLooper();
-        final int testState = MediaPlayerInterface.PLAYER_STATE_PLAYING;
-        final List<MediaItem2> testPlaylist = TestUtils.createPlaylist(3);
-        final AudioAttributesCompat testAudioAttributes = new AudioAttributesCompat.Builder()
-                .setLegacyStreamType(AudioManager.STREAM_RING).build();
-        final CountDownLatch latch = new CountDownLatch(3);
-        mController = createController(mSession.getToken(), true, new ControllerCallback() {
-            @Override
-            public void onPlayerStateChanged(MediaController2 controller, int state) {
-                assertEquals(mController, controller);
-                assertEquals(testState, state);
-                latch.countDown();
-            }
-
-            @Override
-            public void onPlaylistChanged(MediaController2 controller, List<MediaItem2> list,
-                    MediaMetadata2 metadata) {
-                assertEquals(mController, controller);
-                assertEquals(testPlaylist, list);
-                assertNull(metadata);
-                latch.countDown();
-            }
-
-            @Override
-            public void onPlaybackInfoChanged(MediaController2 controller, PlaybackInfo info) {
-                assertEquals(mController, controller);
-                assertEquals(testAudioAttributes, info.getAudioAttributes());
-                latch.countDown();
-            }
-        });
-
-        MockPlayer player = new MockPlayer(0);
-        player.mLastPlayerState = testState;
-        player.setAudioAttributes(testAudioAttributes);
-
-        MockPlaylistAgent agent = new MockPlaylistAgent();
-        agent.mPlaylist = testPlaylist;
-
-        mSession.updatePlayer(player, agent, null);
-        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
     public void testGetSessionActivity() {
         prepareLooper();
         PendingIntent sessionActivity = mController.getSessionActivity();
@@ -463,77 +420,6 @@
         }
     }
 
-
-    @Test
-    public void testControllerCallback_onSeekCompleted() throws InterruptedException {
-        prepareLooper();
-        final long testSeekPosition = 400;
-        final long testPosition = 500;
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onSeekCompleted(MediaController2 controller, long position) {
-                controller.setTimeDiff(Long.valueOf(0));
-                assertEquals(testSeekPosition, position);
-                assertEquals(testPosition, controller.getCurrentPosition());
-                latch.countDown();
-            }
-        };
-        final MediaController2 controller = createController(mSession.getToken(), true, callback);
-        mPlayer.mCurrentPosition = testPosition;
-        mPlayer.notifySeekCompleted(testSeekPosition);
-        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testControllerCallback_onBufferingStateChanged() throws InterruptedException {
-        prepareLooper();
-        final List<MediaItem2> testPlaylist = TestUtils.createPlaylist(3);
-        final MediaItem2 testItem = testPlaylist.get(0);
-        final int testBufferingState = MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_PLAYABLE;
-        final long testBufferingPosition = 500;
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onBufferingStateChanged(MediaController2 controller, MediaItem2 item,
-                    int state) {
-                controller.setTimeDiff(Long.valueOf(0));
-                assertEquals(testItem, item);
-                assertEquals(testBufferingState, state);
-                assertEquals(testBufferingState, controller.getBufferingState());
-                assertEquals(testBufferingPosition, controller.getBufferedPosition());
-                latch.countDown();
-            }
-        };
-        final MediaController2 controller = createController(mSession.getToken(), true, callback);
-        mSession.setPlaylist(testPlaylist, null);
-        mPlayer.mBufferedPosition = testBufferingPosition;
-        mPlayer.notifyBufferingStateChanged(testItem.getDataSourceDesc(), testBufferingState);
-        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testControllerCallback_onPlayerStateChanged() throws InterruptedException {
-        prepareLooper();
-        final int testPlayerState = MediaPlayerInterface.PLAYER_STATE_PLAYING;
-        final long testPosition = 500;
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onPlayerStateChanged(MediaController2 controller, int state) {
-                controller.setTimeDiff(Long.valueOf(0));
-                assertEquals(testPlayerState, state);
-                assertEquals(testPlayerState, controller.getPlayerState());
-                assertEquals(testPosition, controller.getCurrentPosition());
-                latch.countDown();
-            }
-        };
-        final MediaController2 controller = createController(mSession.getToken(), true, callback);
-        mPlayer.mCurrentPosition = testPosition;
-        mPlayer.notifyPlaybackState(testPlayerState);
-        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-    }
-
     @Test
     public void testAddPlaylistItem() throws InterruptedException {
         prepareLooper();
@@ -686,6 +572,7 @@
 
     @Test
     public void testSetVolumeTo() throws Exception {
+        // TODO(jaewan): Also test with local volume.
         prepareLooper();
         final int maxVolume = 100;
         final int currentVolume = 23;
@@ -705,6 +592,7 @@
 
     @Test
     public void testAdjustVolume() throws Exception {
+        // TODO(jaewan): Also test with local volume.
         prepareLooper();
         final int maxVolume = 100;
         final int currentVolume = 23;
@@ -723,87 +611,6 @@
     }
 
     @Test
-    public void testSetVolumeWithLocalVolume() throws Exception {
-        prepareLooper();
-        if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
-            // This test is not eligible for this device.
-            return;
-        }
-
-        // Here, we intentionally choose STREAM_ALARM in order not to consider
-        // 'Do Not Disturb' or 'Volume limit'.
-        final int stream = AudioManager.STREAM_ALARM;
-        final int maxVolume = mAudioManager.getStreamMaxVolume(stream);
-        final int minVolume = 0;
-        if (maxVolume <= minVolume) {
-            return;
-        }
-
-        // Set stream of the session.
-        AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
-                .setLegacyStreamType(stream)
-                .build();
-        mPlayer.setAudioAttributes(attrs);
-        mSession.updatePlayer(mPlayer, null, null);
-
-        final int originalVolume = mAudioManager.getStreamVolume(stream);
-        final int targetVolume = originalVolume == minVolume
-                ? originalVolume + 1 : originalVolume - 1;
-
-        mController.setVolumeTo(targetVolume, AudioManager.FLAG_SHOW_UI);
-        new PollingCheck(WAIT_TIME_MS) {
-            @Override
-            protected boolean check() {
-                return targetVolume == mAudioManager.getStreamVolume(stream);
-            }
-        }.run();
-
-        // Set back to original volume.
-        mAudioManager.setStreamVolume(stream, originalVolume, 0 /* flags */);
-    }
-
-    @Test
-    public void testAdjustVolumeWithLocalVolume() throws Exception {
-        prepareLooper();
-        if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
-            // This test is not eligible for this device.
-            return;
-        }
-
-        // Here, we intentionally choose STREAM_ALARM in order not to consider
-        // 'Do Not Disturb' or 'Volume limit'.
-        final int stream = AudioManager.STREAM_ALARM;
-        final int maxVolume = mAudioManager.getStreamMaxVolume(stream);
-        final int minVolume = 0;
-        if (maxVolume <= minVolume) {
-            return;
-        }
-
-        // Set stream of the session.
-        AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
-                .setLegacyStreamType(stream)
-                .build();
-        mPlayer.setAudioAttributes(attrs);
-        mSession.updatePlayer(mPlayer, null, null);
-
-        final int originalVolume = mAudioManager.getStreamVolume(stream);
-        final int direction = originalVolume == minVolume
-                ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER;
-        final int targetVolume = originalVolume + direction;
-
-        mController.adjustVolume(direction, AudioManager.FLAG_SHOW_UI);
-        new PollingCheck(WAIT_TIME_MS) {
-            @Override
-            protected boolean check() {
-                return targetVolume == mAudioManager.getStreamVolume(stream);
-            }
-        }.run();
-
-        // Set back to original volume.
-        mAudioManager.setStreamVolume(stream, originalVolume, 0 /* flags */);
-    }
-
-    @Test
     public void testGetPackageName() {
         prepareLooper();
         assertEquals(mContext.getPackageName(), mController.getSessionToken().getPackageName());
@@ -1172,7 +979,7 @@
             testHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    final int state = MediaPlayerInterface.PLAYER_STATE_ERROR;
+                    final int state = MediaPlayerBase.PLAYER_STATE_ERROR;
                     for (int i = 0; i < 100; i++) {
                         // triggers call from session to controller.
                         player.notifyPlaybackState(state);
@@ -1205,13 +1012,11 @@
                     }
                 });
             }
-
-            if (Build.VERSION.SDK_INT >= 18) {
+            if (sessionThread != null) {
                 sessionThread.quitSafely();
+            }
+            if (testThread != null) {
                 testThread.quitSafely();
-            } else {
-                sessionThread.quit();
-                testThread.quit();
             }
         }
     }
@@ -1260,29 +1065,30 @@
         };
         TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
 
-        final SessionCommand2 testCommand = new SessionCommand2("testConnectToService", null);
-        final CountDownLatch controllerLatch = new CountDownLatch(1);
-        mController = createController(TestUtils.getServiceToken(mContext, id), true,
-                new ControllerCallback() {
-                    @Override
-                    public void onCustomCommand(MediaController2 controller,
-                            SessionCommand2 command, Bundle args, ResultReceiver receiver) {
-                        if (testCommand.equals(command)) {
-                            controllerLatch.countDown();
-                        }
-                    }
-                }
-        );
+        mController = createController(TestUtils.getServiceToken(mContext, id));
         assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
 
-        // Test command from controller to session service.
+        // Test command from controller to session service
+        // TODO: Re enable when transport control works
+        /*
         mController.play();
         assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         assertTrue(mPlayer.mPlayCalled);
+        */
 
-        // Test command from session service to controller.
-        mSession.sendCustomCommand(testCommand, null);
-        assertTrue(controllerLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        // Test command from session service to controller
+        // TODO(jaewan): Add equivalent tests again
+        /*
+        final CountDownLatch latch = new CountDownLatch(1);
+        mController.registerPlayerEventCallback((state) -> {
+            assertNotNull(state);
+            assertEquals(PlaybackState.STATE_REWINDING, state.getState());
+            latch.countDown();
+        }, sHandler);
+        mPlayer.notifyPlaybackState(
+                TestUtils.createPlaybackState(PlaybackState.STATE_REWINDING));
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        */
     }
 
     @Test
@@ -1291,11 +1097,15 @@
         testControllerAfterSessionIsClosed(mSession.getToken().getId());
     }
 
+    // TODO(jaewan): Re-enable this test
+    @Ignore
     @Test
     public void testControllerAfterSessionIsClosed_sessionService() throws InterruptedException {
         prepareLooper();
-        testConnectToService(MockMediaSessionService2.ID);
+        /*
+        connectToService(TestUtils.getServiceToken(mContext, MockMediaSessionService2.ID));
         testControllerAfterSessionIsClosed(MockMediaSessionService2.ID);
+        */
     }
 
     @Test
@@ -1382,12 +1192,14 @@
         testControllerAfterSessionIsClosed(id);
     }
 
+    @Ignore
     @Test
     public void testClose_sessionService() throws InterruptedException {
         prepareLooper();
         testCloseFromService(MockMediaSessionService2.ID);
     }
 
+    @Ignore
     @Test
     public void testClose_libraryService() throws InterruptedException {
         prepareLooper();
diff --git a/media/src/androidTest/java/androidx/media/MediaMetadata2Test.java b/media/src/androidTest/java/androidx/media/MediaMetadata2Test.java
index d583e47..f000f02 100644
--- a/media/src/androidTest/java/androidx/media/MediaMetadata2Test.java
+++ b/media/src/androidTest/java/androidx/media/MediaMetadata2Test.java
@@ -19,9 +19,7 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
 
-import android.os.Build;
 import android.os.Bundle;
-import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -30,7 +28,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class MediaMetadata2Test {
diff --git a/media/src/androidTest/java/androidx/media/MediaPlayer2Test.java b/media/src/androidTest/java/androidx/media/MediaPlayer2Test.java
index 0a35ddb..f565e8a 100644
--- a/media/src/androidTest/java/androidx/media/MediaPlayer2Test.java
+++ b/media/src/androidTest/java/androidx/media/MediaPlayer2Test.java
@@ -29,7 +29,6 @@
 import android.media.MediaRecorder;
 import android.media.MediaTimestamp;
 import android.media.PlaybackParams;
-import android.media.SubtitleData;
 import android.media.SyncParams;
 import android.media.audiofx.AudioEffect;
 import android.media.audiofx.Visualizer;
@@ -37,13 +36,10 @@
 import android.os.Build;
 import android.os.Environment;
 import android.support.test.filters.LargeTest;
-import android.support.test.filters.MediumTest;
 import android.support.test.filters.SdkSuppress;
-import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
-import androidx.media.MediaPlayerInterface.PlayerEventCallback;
 import androidx.media.test.R;
 
 import org.junit.After;
@@ -53,18 +49,14 @@
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Vector;
-import java.util.concurrent.BlockingDeque;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -89,7 +81,7 @@
 
     @Before
     @Override
-    public void setUp() throws Throwable {
+    public void setUp() throws Exception {
         super.setUp();
         mRecordedFilePath = new File(Environment.getExternalStorageDirectory(),
                 "mediaplayer_record.out").getAbsolutePath();
@@ -105,8 +97,61 @@
         }
     }
 
-    @Test
-    @MediumTest
+    // Bug 13652927
+    public void testVorbisCrash() throws Exception {
+        MediaPlayer2 mp = mPlayer;
+        MediaPlayer2 mp2 = mPlayer2;
+        AssetFileDescriptor afd2 = mResources.openRawResourceFd(R.raw.testmp3_2);
+        mp2.setDataSource(new DataSourceDesc.Builder()
+                .setDataSource(afd2.getFileDescriptor(), afd2.getStartOffset(), afd2.getLength())
+                .build());
+        final Monitor onPrepareCalled = new Monitor();
+        final Monitor onErrorCalled = new Monitor();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    onPrepareCalled.signal();
+                }
+            }
+
+            @Override
+            public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                onErrorCalled.signal();
+            }
+        };
+        mp2.setMediaPlayer2EventCallback(mExecutor, ecb);
+        mp2.prepare();
+        onPrepareCalled.waitForSignal();
+        afd2.close();
+        mp2.clearMediaPlayer2EventCallback();
+
+        mp2.loopCurrent(true);
+        mp2.play();
+
+        for (int i = 0; i < 20; i++) {
+            try {
+                AssetFileDescriptor afd = mResources.openRawResourceFd(R.raw.bug13652927);
+                mp.setDataSource(new DataSourceDesc.Builder()
+                        .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
+                            afd.getLength())
+                        .build());
+                mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+                onPrepareCalled.reset();
+                mp.prepare();
+                onErrorCalled.waitForSignal();
+                afd.close();
+            } catch (Exception e) {
+                // expected to fail
+                Log.i("@@@", "failed: " + e);
+            }
+            Thread.sleep(500);
+            assertTrue("media player died",
+                    mp2.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
+            mp.reset();
+        }
+    }
+
     public void testPlayNullSourcePath() throws Exception {
         final Monitor onSetDataSourceCalled = new Monitor();
         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
@@ -127,8 +172,6 @@
         onSetDataSourceCalled.waitForSignal();
     }
 
-    @Test
-    @LargeTest
     public void testPlayAudioFromDataURI() throws Exception {
         final int mp3Duration = 34909;
         final int tolerance = 70;
@@ -177,12 +220,15 @@
                     .setLegacyStreamType(AudioManager.STREAM_MUSIC)
                     .build();
             mp.setAudioAttributes(attributes);
+            /* FIXME: ensure screen is on while testing.
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+            */
 
-            assertFalse(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertFalse(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
             onPlayCalled.reset();
             mp.play();
             onPlayCalled.waitForSignal();
-            assertTrue(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertTrue(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
             /* FIXME: what's API for checking loop state?
             assertFalse(mp.isLooping());
@@ -207,11 +253,11 @@
             // test pause and restart
             mp.pause();
             Thread.sleep(SLEEP_TIME);
-            assertFalse(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertFalse(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
             onPlayCalled.reset();
             mp.play();
             onPlayCalled.waitForSignal();
-            assertTrue(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertTrue(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
             // test stop and restart
             mp.reset();
@@ -223,14 +269,14 @@
             mp.prepare();
             onPrepareCalled.waitForSignal();
 
-            assertFalse(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertFalse(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
             onPlayCalled.reset();
             mp.play();
             onPlayCalled.waitForSignal();
-            assertTrue(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertTrue(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
             // waiting to complete
-            while (mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING) {
+            while (mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING) {
                 Thread.sleep(SLEEP_TIME);
             }
         } finally {
@@ -238,8 +284,6 @@
         }
     }
 
-    @Test
-    @LargeTest
     public void testPlayAudio() throws Exception {
         final int resid = R.raw.testmp3_2;
         final int mp3Duration = 34909;
@@ -279,11 +323,11 @@
                     .build();
             mp.setAudioAttributes(attributes);
 
-            assertFalse(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertFalse(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
             onPlayCalled.reset();
             mp.play();
             onPlayCalled.waitForSignal();
-            assertTrue(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertTrue(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
             //assertFalse(mp.isLooping());
             onLoopCurrentCalled.reset();
@@ -304,11 +348,11 @@
             // test pause and restart
             mp.pause();
             Thread.sleep(SLEEP_TIME);
-            assertFalse(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertFalse(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
             onPlayCalled.reset();
             mp.play();
             onPlayCalled.waitForSignal();
-            assertTrue(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertTrue(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
             // test stop and restart
             mp.reset();
@@ -323,14 +367,14 @@
             onPrepareCalled.waitForSignal();
             afd.close();
 
-            assertFalse(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertFalse(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
             onPlayCalled.reset();
             mp.play();
             onPlayCalled.waitForSignal();
-            assertTrue(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertTrue(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
             // waiting to complete
-            while (mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING) {
+            while (mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING) {
                 Thread.sleep(SLEEP_TIME);
             }
         } catch (Exception e) {
@@ -370,6 +414,7 @@
                         .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
                         .build();
                 mp.setAudioAttributes(attributes);
+                mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
 
                 assertFalse(mp.isPlaying());
                 onPlayCalled.reset();
@@ -400,8 +445,6 @@
     }
     */
 
-    @Test
-    @LargeTest
     public void testPlayAudioLooping() throws Exception {
         final int resid = R.raw.testmp3;
 
@@ -419,10 +462,8 @@
                         @Override
                         public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd,
                                 int what, int extra) {
-                            if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
-                                Log.i("@@@", "got oncompletion");
-                                onCompletionCalled.signal();
-                            }
+                            Log.i("@@@", "got oncompletion");
+                            onCompletionCalled.signal();
                         }
 
                         @Override
@@ -435,21 +476,21 @@
                     };
             mp.setMediaPlayer2EventCallback(mExecutor, ecb);
 
-            assertFalse(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertFalse(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
             onPlayCalled.reset();
             mp.play();
             onPlayCalled.waitForSignal();
-            assertTrue(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertTrue(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
             long duration = mp.getDuration();
             Thread.sleep(duration * 4); // allow for several loops
-            assertTrue(mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+            assertTrue(mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
             assertEquals("wrong number of completion signals", 0,
                     onCompletionCalled.getNumSignal());
             mp.loopCurrent(false);
 
             // wait for playback to finish
-            while (mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING) {
+            while (mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING) {
                 Thread.sleep(SLEEP_TIME);
             }
             assertEquals("wrong number of completion signals", 1,
@@ -459,8 +500,6 @@
         }
     }
 
-    @Test
-    @LargeTest
     public void testPlayMidi() throws Exception {
         final int resid = R.raw.midi8sec;
         final int midiDuration = 8000;
@@ -629,7 +668,7 @@
             mp.play();
             Thread.sleep(SLEEP_TIME);
             assertFalse("player was still playing after " + SLEEP_TIME + " ms",
-                    mp.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+                    mp.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
             assertTrue("nothing heard while test ran", listener.heardSound());
             listener.reset();
             mp.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC);
@@ -691,7 +730,7 @@
          */
         // TODO: uncomment out line below when MediaPlayer2 can seek to requested position.
         // assertEquals(posAfter, posBefore, tolerance);
-        assertTrue(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertTrue(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
         Thread.sleep(SLEEP_TIME);
 
@@ -706,7 +745,7 @@
         posAfter = mPlayer.getCurrentPosition();
         // TODO: uncomment out line below when MediaPlayer2 can seek to requested position.
         // assertEquals(posAfter, posBefore, tolerance);
-        assertTrue(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertTrue(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
         Thread.sleep(SLEEP_TIME);
 
@@ -716,7 +755,7 @@
 
         // TODO: uncomment out line below when MediaPlayer2 can seek to requested position.
         // assertEquals(posAfter, posBefore, tolerance);
-        assertTrue(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertTrue(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
         Thread.sleep(SLEEP_TIME);
     }
@@ -828,19 +867,7 @@
         assertEquals(Integer.parseInt(rotation), angle);
     }
 
-    @Test
-    @LargeTest
-    public void testSkipToNext() throws Exception {
-        testPlaylist(true);
-    }
-
-    @Test
-    @LargeTest
     public void testPlaylist() throws Exception {
-        testPlaylist(false);
-    }
-
-    private void testPlaylist(boolean skip) throws Exception {
         if (!checkLoadResource(
                 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) {
             return; // skip
@@ -888,18 +915,9 @@
 
         mPlayer.play();
 
-        if (skip) {
-            mPlayer.skipToNext();
-            mPlayer.skipToNext();
-        } else {
-            mOnCompletionCalled.waitForSignal();
-            onCompletion2Called.waitForSignal();
-        }
+        mOnCompletionCalled.waitForSignal();
+        onCompletion2Called.waitForSignal();
         onCompletion1Called.waitForSignal();
-        if (skip) {
-            assertFalse("first dsd completed", mOnCompletionCalled.isSignalled());
-            assertFalse("second dsd completed", onCompletion2Called.isSignalled());
-        }
 
         mPlayer.reset();
     }
@@ -1017,7 +1035,7 @@
                     playbackRate, pbp.getSpeed(),
                     FLOAT_TOLERANCE + playbackRate * sync.getTolerance());
             assertTrue("MediaPlayer2 should still be playing",
-                    mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+                    mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
             long playedMediaDurationMs = mPlayer.getCurrentPosition();
             int diff = Math.abs((int) (playedMediaDurationMs / playbackRate) - playTime);
@@ -1434,14 +1452,14 @@
         }
     }
 
-    @Test
-    @LargeTest
     public void testDeselectTrackForSubtitleTracks() throws Throwable {
         if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
             return; // skip;
         }
 
-        mInstrumentation.waitForIdleSync();
+        /* FIXME: find out counter part of waitForIdleSync.
+        getInstrumentation().waitForIdleSync();
+        */
 
         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
             @Override
@@ -1464,19 +1482,22 @@
                     mOnDeselectTrackCalled.signal();
                 }
             }
-
-            @Override
-            public void onSubtitleData(
-                    MediaPlayer2 mp, DataSourceDesc dsd, SubtitleData data) {
-                if (data != null && data.getData() != null) {
-                    mOnSubtitleDataCalled.signal();
-                }
-            }
         };
         synchronized (mEventCbLock) {
             mEventCallbacks.add(ecb);
         }
 
+        /* TODO: uncomment once API is available in supportlib.
+        mPlayer.setOnSubtitleDataListener(new MediaPlayer2.OnSubtitleDataListener() {
+            @Override
+            public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
+                if (data != null && data.getData() != null) {
+                    mOnSubtitleDataCalled.signal();
+                }
+            }
+        });
+        */
+
         mPlayer.setSurface(mActivity.getSurfaceHolder().getSurface());
 
         mOnPrepareCalled.reset();
@@ -1486,7 +1507,7 @@
         mOnPlayCalled.reset();
         mPlayer.play();
         mOnPlayCalled.waitForSignal();
-        assertTrue(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertTrue(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
         // Closed caption tracks are in-band.
         // So, those tracks will be found after processing a number of frames.
@@ -1518,13 +1539,22 @@
         mPlayer.reset();
     }
 
-    @Test
-    @LargeTest
     public void testChangeSubtitleTrack() throws Throwable {
         if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
             return; // skip;
         }
 
+        /* TODO: uncomment once API is available in supportlib.
+        mPlayer.setOnSubtitleDataListener(new MediaPlayer2.OnSubtitleDataListener() {
+            @Override
+            public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
+                if (data != null && data.getData() != null) {
+                    mOnSubtitleDataCalled.signal();
+                }
+            }
+        });
+        */
+
         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
             @Override
             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
@@ -1541,14 +1571,6 @@
                     mOnPlayCalled.signal();
                 }
             }
-
-            @Override
-            public void onSubtitleData(
-                    MediaPlayer2 mp, DataSourceDesc dsd, SubtitleData data) {
-                if (data != null && data.getData() != null) {
-                    mOnSubtitleDataCalled.signal();
-                }
-            }
         };
         synchronized (mEventCbLock) {
             mEventCallbacks.add(ecb);
@@ -1563,7 +1585,7 @@
         mOnPlayCalled.reset();
         mPlayer.play();
         mOnPlayCalled.waitForSignal();
-        assertTrue(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertTrue(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
         // Closed caption tracks are in-band.
         // So, those tracks will be found after processing a number of frames.
@@ -1622,7 +1644,7 @@
         mOnPlayCalled.reset();
         mPlayer.play();
         mOnPlayCalled.waitForSignal();
-        assertTrue(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertTrue(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
         // The media metadata will be changed while playing since closed caption tracks are in-band
         // and those tracks will be found after processing a number of frames. These tracks will be
@@ -1638,77 +1660,10 @@
         mPlayer.reset();
     }
 
-    @Test
-    @LargeTest
-    public void testMediaTimeDiscontinuity() throws Exception {
-        if (!checkLoadResource(
-                R.raw.bbb_s1_320x240_mp4_h264_mp2_800kbps_30fps_aac_lc_5ch_240kbps_44100hz)) {
-            return; // skip
-        }
-
-        final BlockingDeque<MediaTimestamp> timestamps = new LinkedBlockingDeque<>();
-        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
-            @Override
-            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
-                if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
-                    mOnSeekCompleteCalled.signal();
-                }
-            }
-            @Override
-            public void onMediaTimeDiscontinuity(
-                    MediaPlayer2 mp, DataSourceDesc dsd, MediaTimestamp timestamp) {
-                timestamps.add(timestamp);
-                mOnMediaTimeDiscontinuityCalled.signal();
-            }
-        };
-        synchronized (mEventCbLock) {
-            mEventCallbacks.add(ecb);
-        }
-
-        mPlayer.setSurface(mActivity.getSurfaceHolder().getSurface());
-        mPlayer.prepare();
-
-        // Timestamp needs to be reported when playback starts.
-        mOnMediaTimeDiscontinuityCalled.reset();
-        mPlayer.play();
-        do {
-            assertTrue(mOnMediaTimeDiscontinuityCalled.waitForSignal(1000));
-        } while (Math.abs(timestamps.getLast().getMediaClockRate() - 1.0f) > 0.01f);
-
-        // Timestamp needs to be reported when seeking is done.
-        mOnSeekCompleteCalled.reset();
-        mOnMediaTimeDiscontinuityCalled.reset();
-        mPlayer.seekTo(3000);
-        mOnSeekCompleteCalled.waitForSignal();
-        do {
-            assertTrue(mOnMediaTimeDiscontinuityCalled.waitForSignal(1000));
-        } while (Math.abs(timestamps.getLast().getMediaClockRate() - 1.0f) > 0.01f);
-
-        // Timestamp needs to be updated when playback rate changes.
-        mOnMediaTimeDiscontinuityCalled.reset();
-        mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(0.5f));
-        mOnMediaTimeDiscontinuityCalled.waitForSignal();
-        do {
-            assertTrue(mOnMediaTimeDiscontinuityCalled.waitForSignal(1000));
-        } while (Math.abs(timestamps.getLast().getMediaClockRate() - 0.5f) > 0.01f);
-
-        // Timestamp needs to be updated when player is paused.
-        mOnMediaTimeDiscontinuityCalled.reset();
-        mPlayer.pause();
-        mOnMediaTimeDiscontinuityCalled.waitForSignal();
-        do {
-            assertTrue(mOnMediaTimeDiscontinuityCalled.waitForSignal(1000));
-        } while (Math.abs(timestamps.getLast().getMediaClockRate() - 0.0f) > 0.01f);
-
-        mPlayer.reset();
-    }
-
     /*
      *  This test assumes the resources being tested are between 8 and 14 seconds long
      *  The ones being used here are 10 seconds long.
      */
-    @Test
-    @LargeTest
     public void testResumeAtEnd() throws Throwable {
         int testsRun = testResumeAtEnd(R.raw.loudsoftmp3)
                 + testResumeAtEnd(R.raw.loudsoftwav)
@@ -1749,7 +1704,7 @@
         // sleep long enough that we restart playback at least once, but no more
         Thread.sleep(10000);
         assertTrue("MediaPlayer2 should still be playing",
-                mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+                mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
         mPlayer.reset();
         assertEquals("wrong number of repetitions", 1, mOnCompletionCalled.getNumSignal());
         return 1;
@@ -1808,7 +1763,7 @@
         mOnPlayCalled.reset();
         mPlayer.play();
         mOnPlayCalled.waitForSignal();
-        while (mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING) {
+        while (mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING) {
             Log.i("@@@@", "position: " + mPlayer.getCurrentPosition());
             Thread.sleep(500);
         }
@@ -1879,10 +1834,10 @@
         assertFalse(mOnCompletionCalled.isSignalled());
         mPlayer.play();
         mOnPlayCalled.waitForSignal();
-        while (mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING) {
+        while (mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING) {
             Thread.sleep(SLEEP_TIME);
         }
-        assertFalse(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertFalse(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
         mOnCompletionCalled.waitForSignal();
         assertFalse(mOnErrorCalled.isSignalled());
         mPlayer.reset();
@@ -1918,34 +1873,32 @@
             mEventCallbacks.add(ecb);
         }
 
-        MediaPlayerInterface playerBase = mPlayer.getMediaPlayerInterface();
-        assertEquals(MediaPlayerInterface.BUFFERING_STATE_UNKNOWN, playerBase.getBufferingState());
-        assertEquals(MediaPlayerInterface.PLAYER_STATE_IDLE, playerBase.getPlayerState());
+        assertEquals(MediaPlayerBase.BUFFERING_STATE_UNKNOWN, mPlayer.getBufferingState());
+        assertEquals(MediaPlayerBase.PLAYER_STATE_IDLE, mPlayer.getPlayerState());
         prepareCompleted.reset();
-        playerBase.prepare();
+        mPlayer.prepare();
         prepareCompleted.waitForSignal();
-        assertEquals(MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_PLAYABLE,
-                playerBase.getBufferingState());
-        assertEquals(MediaPlayerInterface.PLAYER_STATE_PAUSED, playerBase.getPlayerState());
-        assertEquals(MediaPlayer2.MEDIAPLAYER2_STATE_PREPARED, mPlayer.getMediaPlayer2State());
+        assertEquals(MediaPlayerBase.BUFFERING_STATE_BUFFERING_AND_PLAYABLE,
+                mPlayer.getBufferingState());
+        assertEquals(MediaPlayerBase.PLAYER_STATE_PAUSED, mPlayer.getPlayerState());
 
         playCompleted.reset();
-        playerBase.play();
+        mPlayer.play();
         playCompleted.waitForSignal();
-        assertEquals(MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_PLAYABLE,
-                playerBase.getBufferingState());
-        assertEquals(MediaPlayerInterface.PLAYER_STATE_PLAYING, playerBase.getPlayerState());
+        assertEquals(MediaPlayerBase.BUFFERING_STATE_BUFFERING_AND_PLAYABLE,
+                mPlayer.getBufferingState());
+        assertEquals(MediaPlayerBase.PLAYER_STATE_PLAYING, mPlayer.getPlayerState());
 
         pauseCompleted.reset();
-        playerBase.pause();
+        mPlayer.pause();
         pauseCompleted.waitForSignal();
-        assertEquals(MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_PLAYABLE,
-                playerBase.getBufferingState());
-        assertEquals(MediaPlayerInterface.PLAYER_STATE_PAUSED, playerBase.getPlayerState());
+        assertEquals(MediaPlayerBase.BUFFERING_STATE_BUFFERING_AND_PLAYABLE,
+                mPlayer.getBufferingState());
+        assertEquals(MediaPlayerBase.PLAYER_STATE_PAUSED, mPlayer.getPlayerState());
 
-        playerBase.reset();
-        assertEquals(MediaPlayerInterface.BUFFERING_STATE_UNKNOWN, playerBase.getBufferingState());
-        assertEquals(MediaPlayerInterface.PLAYER_STATE_IDLE, playerBase.getPlayerState());
+        mPlayer.reset();
+        assertEquals(MediaPlayerBase.BUFFERING_STATE_UNKNOWN, mPlayer.getBufferingState());
+        assertEquals(MediaPlayerBase.PLAYER_STATE_IDLE, mPlayer.getPlayerState());
     }
 
     @Test
@@ -1956,13 +1909,9 @@
         if (!checkLoadResource(R.raw.testvideo)) {
             return; // skip;
         }
-        final DataSourceDesc dsd2 = createDataSourceDesc(
-                R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz);
-        mPlayer.setNextDataSource(dsd2);
 
         mPlayer.setSurface(mActivity.getSurfaceHolder().getSurface());
 
-        final Monitor onDsdChangedCalled = new Monitor();
         final Monitor onPrepareCalled = new Monitor();
         final Monitor onSeekCompleteCalled = new Monitor();
         final Monitor onPlayerStateChangedCalled = new Monitor();
@@ -1972,79 +1921,69 @@
         final Monitor onPlaybackSpeedChanged = new Monitor();
         final AtomicReference<Float> playbackSpeed = new AtomicReference<>();
 
-        PlayerEventCallback callback = new PlayerEventCallback() {
+        MediaPlayerBase.PlayerEventCallback callback = new MediaPlayerBase.PlayerEventCallback() {
+            // TODO: implement and add test case for onCurrentDataSourceChanged() callback.
             @Override
-            public void onCurrentDataSourceChanged(MediaPlayerInterface mpb, DataSourceDesc dsd) {
-                onDsdChangedCalled.signal();
-            }
-
-            @Override
-            public void onMediaPrepared(MediaPlayerInterface mpb, DataSourceDesc dsd) {
+            public void onMediaPrepared(MediaPlayerBase mpb, DataSourceDesc dsd) {
                 onPrepareCalled.signal();
             }
 
             @Override
-            public void onPlayerStateChanged(MediaPlayerInterface mpb, int state) {
+            public void onPlayerStateChanged(MediaPlayerBase mpb, int state) {
                 playerState.set(state);
                 onPlayerStateChangedCalled.signal();
             }
 
             @Override
-            public void onBufferingStateChanged(MediaPlayerInterface mpb, DataSourceDesc dsd,
+            public void onBufferingStateChanged(MediaPlayerBase mpb, DataSourceDesc dsd,
                     int state) {
                 bufferingState.set(state);
                 onBufferingStateChangedCalled.signal();
             }
 
             @Override
-            public void onPlaybackSpeedChanged(MediaPlayerInterface mpb, float speed) {
+            public void onPlaybackSpeedChanged(MediaPlayerBase mpb, float speed) {
                 playbackSpeed.set(speed);
                 onPlaybackSpeedChanged.signal();
             }
 
             @Override
-            public void onSeekCompleted(MediaPlayerInterface mpb, long position) {
+            public void onSeekCompleted(MediaPlayerBase mpb, long position) {
                 onSeekCompleteCalled.signal();
             }
         };
-        MediaPlayerInterface basePlayer = mPlayer.getMediaPlayerInterface();
         ExecutorService executor = Executors.newFixedThreadPool(1);
-        basePlayer.registerPlayerEventCallback(executor, callback);
+        mPlayer.registerPlayerEventCallback(executor, callback);
 
         onPrepareCalled.reset();
         onPlayerStateChangedCalled.reset();
         onBufferingStateChangedCalled.reset();
-        basePlayer.prepare();
+        mPlayer.prepare();
         do {
             assertTrue(onBufferingStateChangedCalled.waitForSignal(1000));
-        } while (bufferingState.get()
-                != MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_STARVED);
+        } while (bufferingState.get() != MediaPlayerBase.BUFFERING_STATE_BUFFERING_AND_STARVED);
 
         assertTrue(onPrepareCalled.waitForSignal(1000));
         do {
             assertTrue(onPlayerStateChangedCalled.waitForSignal(1000));
-        } while (playerState.get() != MediaPlayerInterface.PLAYER_STATE_PAUSED);
+        } while (playerState.get() != MediaPlayerBase.PLAYER_STATE_PAUSED);
         do {
             assertTrue(onBufferingStateChangedCalled.waitForSignal(1000));
-        } while (bufferingState.get()
-                != MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_PLAYABLE);
+        } while (bufferingState.get() != MediaPlayerBase.BUFFERING_STATE_BUFFERING_AND_PLAYABLE);
 
         onSeekCompleteCalled.reset();
-        basePlayer.seekTo(mp4Duration >> 1);
+        mPlayer.seekTo(mp4Duration >> 1, MediaPlayer2.SEEK_PREVIOUS_SYNC);
         onSeekCompleteCalled.waitForSignal();
 
         onPlaybackSpeedChanged.reset();
-        basePlayer.setPlaybackSpeed(0.5f);
+        mPlayer.setPlaybackSpeed(0.5f);
         do {
             assertTrue(onPlaybackSpeedChanged.waitForSignal(1000));
         } while (Math.abs(playbackSpeed.get() - 0.5f) > FLOAT_TOLERANCE);
 
-        basePlayer.skipToNext();
-        assertTrue(onDsdChangedCalled.waitForSignal(1000));
+        mPlayer.reset();
 
-        basePlayer.reset();
-
-        basePlayer.unregisterPlayerEventCallback(callback);
+        mPlayer.unregisterPlayerEventCallback(callback);
         executor.shutdown();
     }
 
@@ -2148,12 +2087,12 @@
                 .setDataSource(dataSource)
                 .build());
         playLoadedVideo(null, null, -1);
-        assertTrue(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertTrue(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
         // Test pause and restart.
         mPlayer.pause();
         Thread.sleep(SLEEP_TIME);
-        assertFalse(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertFalse(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
             @Override
@@ -2175,7 +2114,7 @@
         mOnPlayCalled.reset();
         mPlayer.play();
         mOnPlayCalled.waitForSignal();
-        assertTrue(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertTrue(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
         // Test reset.
         mPlayer.reset();
@@ -2192,12 +2131,12 @@
         mOnPlayCalled.reset();
         mPlayer.play();
         mOnPlayCalled.waitForSignal();
-        assertTrue(mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING);
+        assertTrue(mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING);
 
         // Test seek. Note: the seek position is cached and returned as the
         // current position so there's no point in comparing them.
         mPlayer.seekTo(duration - SLEEP_TIME, MediaPlayer2.SEEK_PREVIOUS_SYNC);
-        while (mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING) {
+        while (mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING) {
             Thread.sleep(SLEEP_TIME);
         }
     }
@@ -2320,78 +2259,4 @@
         mPlayer.play();
         assertTrue(mOnErrorCalled.waitForSignal());
     }
-
-    @Test
-    @SmallTest
-    public void testClearPendingCommands() throws Exception {
-        final Monitor readAllowed = new Monitor();
-        Media2DataSource dataSource = new Media2DataSource() {
-            @Override
-            public int readAt(long position, byte[] buffer, int offset, int size)
-                    throws IOException {
-                try {
-                    readAllowed.waitForSignal();
-                } catch (InterruptedException e) {
-                    fail();
-                }
-                return -1;
-            }
-
-            @Override
-            public long getSize() throws IOException {
-                return -1;  // Unknown size
-            }
-
-            @Override
-            public void close() throws IOException {}
-        };
-        final ArrayDeque<Integer> commandsCompleted = new ArrayDeque<>();
-        setOnErrorListener();
-        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
-            @Override
-            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
-                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
-                    mOnPrepareCalled.signal();
-                }
-            }
-
-            @Override
-            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
-                commandsCompleted.add(what);
-            }
-
-            @Override
-            public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
-                mOnErrorCalled.signal();
-            }
-        };
-        synchronized (mEventCbLock) {
-            mEventCallbacks.add(ecb);
-        }
-
-        mOnPrepareCalled.reset();
-        mOnErrorCalled.reset();
-
-        mPlayer.setDataSource(new DataSourceDesc.Builder()
-                .setDataSource(dataSource)
-                .build());
-
-        // prepare() will be pending until readAllowed is signaled.
-        mPlayer.prepare();
-
-        mPlayer.play();
-        mPlayer.pause();
-        mPlayer.play();
-        mPlayer.pause();
-        mPlayer.play();
-        mPlayer.seekTo(1000);
-
-        // Cause a failure on the pending prepare operation.
-        readAllowed.signal();
-        mOnErrorCalled.waitForSignal();
-        assertEquals(0, mOnPrepareCalled.getNumSignal());
-        assertEquals(1, commandsCompleted.size());
-        assertEquals(MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE,
-                (int) commandsCompleted.peekFirst());
-    }
 }
diff --git a/media/src/androidTest/java/androidx/media/MediaPlayer2TestBase.java b/media/src/androidTest/java/androidx/media/MediaPlayer2TestBase.java
index 77c5c04..215993a 100644
--- a/media/src/androidTest/java/androidx/media/MediaPlayer2TestBase.java
+++ b/media/src/androidTest/java/androidx/media/MediaPlayer2TestBase.java
@@ -15,29 +15,20 @@
  */
 package androidx.media;
 
-import static android.content.Context.KEYGUARD_SERVICE;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.app.Instrumentation;
-import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.media.AudioManager;
 import android.media.MediaTimestamp;
-import android.media.SubtitleData;
 import android.media.TimedMetaData;
 import android.net.Uri;
-import android.os.PersistableBundle;
-import android.os.PowerManager;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.view.SurfaceHolder;
-import android.view.WindowManager;
 
 import androidx.annotation.CallSuper;
 
@@ -50,7 +41,6 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.logging.Logger;
@@ -75,7 +65,6 @@
     protected Monitor mOnCompletionCalled = new Monitor();
     protected Monitor mOnInfoCalled = new Monitor();
     protected Monitor mOnErrorCalled = new Monitor();
-    protected Monitor mOnMediaTimeDiscontinuityCalled = new Monitor();
     protected int mCallStatus;
 
     protected Context mContext;
@@ -86,35 +75,34 @@
     protected MediaPlayer2 mPlayer = null;
     protected MediaPlayer2 mPlayer2 = null;
     protected MediaStubActivity mActivity;
-    protected Instrumentation mInstrumentation;
 
     protected final Object mEventCbLock = new Object();
-    protected List<MediaPlayer2.MediaPlayer2EventCallback> mEventCallbacks = new ArrayList<>();
+    protected List<MediaPlayer2.MediaPlayer2EventCallback> mEventCallbacks =
+            new ArrayList<MediaPlayer2.MediaPlayer2EventCallback>();
     protected final Object mEventCbLock2 = new Object();
-    protected List<MediaPlayer2.MediaPlayer2EventCallback> mEventCallbacks2 = new ArrayList<>();
+    protected List<MediaPlayer2.MediaPlayer2EventCallback> mEventCallbacks2 =
+            new ArrayList<MediaPlayer2.MediaPlayer2EventCallback>();
 
     @Rule
     public ActivityTestRule<MediaStubActivity> mActivityRule =
             new ActivityTestRule<>(MediaStubActivity.class);
-    public PowerManager.WakeLock mScreenLock;
-    private KeyguardManager mKeyguardManager;
 
     // convenience functions to create MediaPlayer2
-    protected MediaPlayer2 createMediaPlayer2(Context context, Uri uri) {
+    protected static MediaPlayer2 createMediaPlayer2(Context context, Uri uri) {
         return createMediaPlayer2(context, uri, null);
     }
 
-    protected MediaPlayer2 createMediaPlayer2(Context context, Uri uri,
+    protected static MediaPlayer2 createMediaPlayer2(Context context, Uri uri,
             SurfaceHolder holder) {
         AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
         int s = am.generateAudioSessionId();
         return createMediaPlayer2(context, uri, holder, null, s > 0 ? s : 0);
     }
 
-    protected MediaPlayer2 createMediaPlayer2(Context context, Uri uri, SurfaceHolder holder,
+    protected static MediaPlayer2 createMediaPlayer2(Context context, Uri uri, SurfaceHolder holder,
             AudioAttributesCompat audioAttributes, int audioSessionId) {
         try {
-            MediaPlayer2 mp = createMediaPlayer2OnUiThread();
+            MediaPlayer2 mp = MediaPlayer2.create();
             final AudioAttributesCompat aa = audioAttributes != null ? audioAttributes :
                     new AudioAttributesCompat.Builder().build();
             mp.setAudioAttributes(aa);
@@ -156,13 +144,13 @@
         return null;
     }
 
-    protected MediaPlayer2 createMediaPlayer2(Context context, int resid) {
+    protected static MediaPlayer2 createMediaPlayer2(Context context, int resid) {
         AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
         int s = am.generateAudioSessionId();
         return createMediaPlayer2(context, resid, null, s > 0 ? s : 0);
     }
 
-    protected MediaPlayer2 createMediaPlayer2(Context context, int resid,
+    protected static MediaPlayer2 createMediaPlayer2(Context context, int resid,
             AudioAttributesCompat audioAttributes, int audioSessionId) {
         try {
             AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
@@ -170,7 +158,7 @@
                 return null;
             }
 
-            MediaPlayer2 mp = createMediaPlayer2OnUiThread();
+            MediaPlayer2 mp = MediaPlayer2.create();
 
             final AudioAttributesCompat aa = audioAttributes != null ? audioAttributes :
                     new AudioAttributesCompat.Builder().build();
@@ -216,20 +204,6 @@
         return null;
     }
 
-    private MediaPlayer2 createMediaPlayer2OnUiThread() {
-        final MediaPlayer2[] mp = new MediaPlayer2[1];
-        try {
-            mActivityRule.runOnUiThread(new Runnable() {
-                public void run() {
-                    mp[0] = MediaPlayer2.create();
-                }
-            });
-        } catch (Throwable throwable) {
-            fail("Failed to create MediaPlayer2 instance on UI thread.");
-        }
-        return mp[0];
-    }
-
     public static class Monitor {
         private int mNumSignal;
 
@@ -284,23 +258,8 @@
 
     @Before
     @CallSuper
-    public void setUp() throws Throwable {
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
-        mKeyguardManager = (KeyguardManager)
-                mInstrumentation.getTargetContext().getSystemService(KEYGUARD_SERVICE);
+    public void setUp() throws Exception {
         mActivity = mActivityRule.getActivity();
-        mActivityRule.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                // Keep screen on while testing.
-                mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-                mActivity.setTurnScreenOn(true);
-                mActivity.setShowWhenLocked(true);
-                mKeyguardManager.requestDismissKeyguard(mActivity, null);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
-
         try {
             mActivityRule.runOnUiThread(new Runnable() {
                 public void run() {
@@ -385,11 +344,11 @@
             }
 
             @Override
-            public void onMediaTimeDiscontinuity(MediaPlayer2 mp, DataSourceDesc dsd,
+            public void onMediaTimeChanged(MediaPlayer2 mp, DataSourceDesc dsd,
                     MediaTimestamp timestamp) {
                 synchronized (cbLock) {
                     for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
-                        ecb.onMediaTimeDiscontinuity(mp, dsd, timestamp);
+                        ecb.onMediaTimeChanged(mp, dsd, timestamp);
                     }
                 }
             }
@@ -402,15 +361,6 @@
                     }
                 }
             }
-            @Override
-            public  void onSubtitleData(MediaPlayer2 mp, DataSourceDesc dsd,
-                    final SubtitleData data) {
-                synchronized (cbLock) {
-                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
-                        ecb.onSubtitleData(mp, dsd, data);
-                    }
-                }
-            }
         });
     }
 
@@ -540,7 +490,11 @@
 
         boolean audioOnly = (width != null && width.intValue() == -1)
                 || (height != null && height.intValue() == -1);
+
         mPlayer.setSurface(mActivity.getSurfaceHolder().getSurface());
+        /* FIXME: ensure that screen is on in activity level.
+        mPlayer.setScreenOnWhilePlaying(true);
+        */
 
         synchronized (mEventCbLock) {
             mEventCallbacks.add(new MediaPlayer2.MediaPlayer2EventCallback() {
@@ -605,49 +559,13 @@
         if (playTime == -1) {
             return;
         } else if (playTime == 0) {
-            while (mPlayer.getMediaPlayer2State() == MediaPlayer2.MEDIAPLAYER2_STATE_PLAYING) {
+            while (mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING) {
                 Thread.sleep(SLEEP_TIME);
             }
         } else {
             Thread.sleep(playTime);
         }
 
-        // validate a few MediaMetrics.
-        PersistableBundle metrics = mPlayer.getMetrics();
-        if (metrics == null) {
-            fail("MediaPlayer.getMetrics() returned null metrics");
-        } else if (metrics.isEmpty()) {
-            fail("MediaPlayer.getMetrics() returned empty metrics");
-        } else {
-
-            int size = metrics.size();
-            Set<String> keys = metrics.keySet();
-
-            if (keys == null) {
-                fail("MediaMetricsSet returned no keys");
-            } else if (keys.size() != size) {
-                fail("MediaMetricsSet.keys().size() mismatch MediaMetricsSet.size()");
-            }
-
-            // we played something; so one of these should be non-null
-            String vmime = metrics.getString(MediaPlayer2.MetricsConstants.MIME_TYPE_VIDEO, null);
-            String amime = metrics.getString(MediaPlayer2.MetricsConstants.MIME_TYPE_AUDIO, null);
-            if (vmime == null && amime == null) {
-                fail("getMetrics() returned neither video nor audio mime value");
-            }
-
-            long duration = metrics.getLong(MediaPlayer2.MetricsConstants.DURATION, -2);
-            if (duration == -2) {
-                fail("getMetrics() didn't return a duration");
-            }
-            long playing = metrics.getLong(MediaPlayer2.MetricsConstants.PLAYING, -2);
-            if (playing == -2) {
-                fail("getMetrics() didn't return a playing time");
-            }
-            if (!keys.contains(MediaPlayer2.MetricsConstants.PLAYING)) {
-                fail("MediaMetricsSet.keys() missing: " + MediaPlayer2.MetricsConstants.PLAYING);
-            }
-        }
         mPlayer.reset();
     }
 
diff --git a/media/src/androidTest/java/androidx/media/MediaSession2Test.java b/media/src/androidTest/java/androidx/media/MediaSession2Test.java
index adcba6b..5e7ed0e 100644
--- a/media/src/androidTest/java/androidx/media/MediaSession2Test.java
+++ b/media/src/androidTest/java/androidx/media/MediaSession2Test.java
@@ -65,7 +65,7 @@
 /**
  * Tests {@link MediaSession2}.
  */
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class MediaSession2Test extends MediaSession2TestBase {
@@ -125,7 +125,7 @@
     @Test
     public void testPlayerStateChange() throws Exception {
         prepareLooper();
-        final int targetState = MediaPlayerInterface.PLAYER_STATE_PLAYING;
+        final int targetState = MediaPlayerBase.PLAYER_STATE_PLAYING;
         final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
         sHandler.postAndSync(new Runnable() {
             @Override
@@ -136,7 +136,7 @@
                         .setSessionCallback(sHandlerExecutor, new SessionCallback() {
                             @Override
                             public void onPlayerStateChanged(MediaSession2 session,
-                                    MediaPlayerInterface player, int state) {
+                                    MediaPlayerBase player, int state) {
                                 assertEquals(targetState, state);
                                 latchForSessionCallback.countDown();
                             }
@@ -166,7 +166,7 @@
         final List<MediaItem2> playlist = TestUtils.createPlaylist(5);
 
         final MediaItem2 targetItem = playlist.get(3);
-        final int targetBufferingState = MediaPlayerInterface.BUFFERING_STATE_BUFFERING_COMPLETE;
+        final int targetBufferingState = MediaPlayerBase.BUFFERING_STATE_BUFFERING_COMPLETE;
         final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
         sHandler.postAndSync(new Runnable() {
             @Override
@@ -179,7 +179,7 @@
                         .setSessionCallback(sHandlerExecutor, new SessionCallback() {
                             @Override
                             public void onBufferingStateChanged(MediaSession2 session,
-                                    MediaPlayerInterface player, MediaItem2 item, int state) {
+                                    MediaPlayerBase player, MediaItem2 item, int state) {
                                 assertEquals(targetItem, item);
                                 assertEquals(targetBufferingState, state);
                                 latchForSessionCallback.countDown();
@@ -200,39 +200,13 @@
                     }
                 });
 
-        mPlayer.notifyBufferingStateChanged(targetItem.getDataSourceDesc(), targetBufferingState);
+        mPlayer.notifyBufferingState(targetItem, targetBufferingState);
         assertTrue(latchForSessionCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         assertTrue(latchForControllerCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         assertEquals(targetBufferingState, controller.getBufferingState());
     }
 
     @Test
-    public void testSeekCompleted() throws Exception {
-        prepareLooper();
-        final long testPosition = 1001;
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onSeekCompleted(
-                    MediaSession2 session, MediaPlayerInterface mpb, long position) {
-                assertEquals(mPlayer, mpb);
-                assertEquals(testPosition, position);
-                latch.countDown();
-            }
-        };
-
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setPlaylistAgent(mMockAgent)
-                .setId("testSeekCompleted")
-                .setSessionCallback(sHandlerExecutor, callback).build()) {
-            mPlayer.mCurrentPosition = testPosition;
-            mPlayer.notifySeekCompleted(testPosition);
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
     public void testCurrentDataSourceChanged() throws Exception {
         prepareLooper();
         final int listSize = 5;
@@ -240,7 +214,9 @@
         mMockAgent.setPlaylist(list, null);
 
         final MediaItem2 currentItem = list.get(3);
-        final CountDownLatch latchForSessionCallback = new CountDownLatch(2);
+        mMockAgent.mCurrentMediaItem = currentItem;
+
+        final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
         try (MediaSession2 session = new MediaSession2.Builder(mContext)
                 .setPlayer(mPlayer)
                 .setPlaylistAgent(mMockAgent)
@@ -248,44 +224,27 @@
                 .setSessionCallback(sHandlerExecutor, new SessionCallback() {
                     @Override
                     public void onCurrentMediaItemChanged(MediaSession2 session,
-                            MediaPlayerInterface player, MediaItem2 item) {
-                        switch ((int) latchForSessionCallback.getCount()) {
-                            case 2:
-                                assertEquals(currentItem, item);
-                                break;
-                            case 1:
-                                assertNull(item);
-                        }
+                            MediaPlayerBase player, MediaItem2 itemOut) {
+                        assertSame(currentItem, itemOut);
                         latchForSessionCallback.countDown();
                     }
                 }).build()) {
 
-            final CountDownLatch latchForControllerCallback = new CountDownLatch(2);
+            final CountDownLatch latchForControllerCallback = new CountDownLatch(1);
             final MediaController2 controller =
                     createController(mSession.getToken(), true, new ControllerCallback() {
                         @Override
                         public void onCurrentMediaItemChanged(MediaController2 controller,
                                 MediaItem2 item) {
-                            switch ((int) latchForControllerCallback.getCount()) {
-                                case 2:
-                                    assertEquals(currentItem, item);
-                                    break;
-                                case 1:
-                                    assertNull(item);
-                            }
+                            assertEquals(currentItem, item);
                             latchForControllerCallback.countDown();
                         }
                     });
 
-            // Player notifies with the unknown dsd. Should be ignored.
-            mPlayer.notifyCurrentDataSourceChanged(TestUtils.createMediaItemWithMetadata()
-                    .getDataSourceDesc());
-            // Known DSD should be notified through the onCurrentMediaItemChanged.
             mPlayer.notifyCurrentDataSourceChanged(currentItem.getDataSourceDesc());
-            // Null DSD becomes null MediaItem2.
-            mPlayer.notifyCurrentDataSourceChanged(null);
             assertTrue(latchForSessionCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
             assertTrue(latchForControllerCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+            assertEquals(currentItem, controller.getCurrentMediaItem());
         }
     }
 
@@ -305,7 +264,7 @@
                 .setId("testMediaPrepared")
                 .setSessionCallback(sHandlerExecutor, new SessionCallback() {
                     @Override
-                    public void onMediaPrepared(MediaSession2 session, MediaPlayerInterface player,
+                    public void onMediaPrepared(MediaSession2 session, MediaPlayerBase player,
                             MediaItem2 itemOut) {
                         assertSame(currentItem, itemOut);
                         latchForSessionCallback.countDown();
@@ -326,7 +285,7 @@
         mMockAgent.setPlaylist(list, null);
 
         final MediaItem2 currentItem = list.get(3);
-        final int buffState = MediaPlayerInterface.BUFFERING_STATE_BUFFERING_COMPLETE;
+        final int buffState = MediaPlayerBase.BUFFERING_STATE_BUFFERING_COMPLETE;
 
         final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
         try (MediaSession2 session = new MediaSession2.Builder(mContext)
@@ -336,7 +295,7 @@
                 .setSessionCallback(sHandlerExecutor, new SessionCallback() {
                     @Override
                     public void onBufferingStateChanged(MediaSession2 session,
-                            MediaPlayerInterface player, MediaItem2 itemOut, int stateOut) {
+                            MediaPlayerBase player, MediaItem2 itemOut, int stateOut) {
                         assertSame(currentItem, itemOut);
                         assertEquals(buffState, stateOut);
                         latchForSessionCallback.countDown();
@@ -366,7 +325,7 @@
                 .setSessionCallback(sHandlerExecutor, new SessionCallback() {
                     @Override
                     public void onPlaybackSpeedChanged(MediaSession2 session,
-                            MediaPlayerInterface player, float speedOut) {
+                            MediaPlayerBase player, float speedOut) {
                         assertEquals(speed, speedOut, 0.0f);
                         latchForSessionCallback.countDown();
                     }
@@ -393,7 +352,7 @@
     @Test
     public void testUpdatePlayer() throws Exception {
         prepareLooper();
-        final int targetState = MediaPlayerInterface.PLAYER_STATE_PLAYING;
+        final int targetState = MediaPlayerBase.PLAYER_STATE_PLAYING;
         final CountDownLatch latch = new CountDownLatch(1);
         sHandler.postAndSync(new Runnable() {
             @Override
@@ -403,7 +362,7 @@
                         .setSessionCallback(sHandlerExecutor, new SessionCallback() {
                             @Override
                             public void onPlayerStateChanged(MediaSession2 session,
-                                    MediaPlayerInterface player, int state) {
+                                    MediaPlayerBase player, int state) {
                                 assertEquals(targetState, state);
                                 latch.countDown();
                             }
@@ -424,12 +383,12 @@
         assertNotNull(mSession.getPlaylistAgent());
         assertNotEquals(agent, mSession.getPlaylistAgent());
 
-        player.notifyPlaybackState(MediaPlayerInterface.PLAYER_STATE_PLAYING);
+        player.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_PLAYING);
         assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
     }
 
     @Test
-    public void testUpdatePlayer_playbackInfo() throws Exception {
+    public void testSetPlayer_playbackInfo() throws Exception {
         prepareLooper();
         MockPlayer player = new MockPlayer(0);
         final AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
@@ -523,47 +482,6 @@
     }
 
     @Test
-    public void testGetDuration() throws Exception {
-        prepareLooper();
-        final long testDuration = 9999;
-        mPlayer.mDuration = testDuration;
-        assertEquals(testDuration, mSession.getDuration());
-    }
-
-    @Test
-    public void testSessionCallback_onMediaPrepared() throws Exception {
-        prepareLooper();
-        final long testDuration = 9999;
-        final List<MediaItem2> list = TestUtils.createPlaylist(2);
-        final MediaItem2 testItem = list.get(1);
-        final CountDownLatch latch = new CountDownLatch(1);
-
-        mPlayer.mDuration = testDuration;
-        mMockAgent.setPlaylist(list, null);
-        mMockAgent.mCurrentMediaItem = testItem;
-
-        final SessionCallback sessionCallback = new SessionCallback() {
-            @Override
-            public void onMediaPrepared(MediaSession2 session, MediaPlayerInterface player,
-                    MediaItem2 item) {
-                assertEquals(testItem, item);
-                assertEquals(testDuration,
-                        item.getMetadata().getLong(MediaMetadata2.METADATA_KEY_DURATION));
-                latch.countDown();
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setPlaylistAgent(mMockAgent)
-                .setId("testSessionCallback")
-                .setSessionCallback(sHandlerExecutor, sessionCallback)
-                .build()) {
-            mPlayer.notifyMediaPrepared(testItem.getDataSourceDesc());
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
     public void testSetPlaybackSpeed() throws Exception {
         prepareLooper();
         final float speed = 1.5f;
@@ -614,7 +532,7 @@
     @Test
     public void testGetPlayerState() {
         prepareLooper();
-        final int state = MediaPlayerInterface.PLAYER_STATE_PLAYING;
+        final int state = MediaPlayerBase.PLAYER_STATE_PLAYING;
         mPlayer.mLastPlayerState = state;
         assertEquals(state, mSession.getPlayerState());
     }
@@ -622,7 +540,7 @@
     @Test
     public void testGetBufferingState() {
         prepareLooper();
-        final int bufferingState = MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_PLAYABLE;
+        final int bufferingState = MediaPlayerBase.BUFFERING_STATE_BUFFERING_AND_PLAYABLE;
         mPlayer.mLastBufferingState = bufferingState;
         assertEquals(bufferingState, mSession.getBufferingState());
     }
@@ -826,7 +744,7 @@
 
         mSession.updatePlayer(player, null, null);
         mSession.updatePlayer(mPlayer, null, null);
-        player.notifyPlaybackState(MediaPlayerInterface.PLAYER_STATE_PAUSED);
+        player.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_PAUSED);
         assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
     }
 
@@ -839,7 +757,7 @@
 
         @Override
         public void unregisterPlayerEventCallback(
-                @NonNull MediaPlayerInterface.PlayerEventCallback listener) {
+                @NonNull MediaPlayerBase.PlayerEventCallback listener) {
             // No-op.
         }
     }
diff --git a/media/src/androidTest/java/androidx/media/MediaSession2TestBase.java b/media/src/androidTest/java/androidx/media/MediaSession2TestBase.java
index 9c9fa8e..745ef3a 100644
--- a/media/src/androidTest/java/androidx/media/MediaSession2TestBase.java
+++ b/media/src/androidTest/java/androidx/media/MediaSession2TestBase.java
@@ -20,7 +20,6 @@
 import static junit.framework.Assert.assertTrue;
 
 import android.content.Context;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -122,11 +121,7 @@
             if (sHandler == null) {
                 return;
             }
-            if (Build.VERSION.SDK_INT >= 18) {
-                sHandler.getLooper().quitSafely();
-            } else {
-                sHandler.getLooper().quit();
-            }
+            sHandler.getLooper().quitSafely();
             sHandler = null;
             sHandlerExecutor = null;
         }
diff --git a/media/src/androidTest/java/androidx/media/MediaSession2_PermissionTest.java b/media/src/androidTest/java/androidx/media/MediaSession2_PermissionTest.java
index 0bf93d4..3895ea5 100644
--- a/media/src/androidTest/java/androidx/media/MediaSession2_PermissionTest.java
+++ b/media/src/androidTest/java/androidx/media/MediaSession2_PermissionTest.java
@@ -48,11 +48,9 @@
 import static org.junit.Assert.fail;
 
 import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Process;
 import android.support.test.filters.MediumTest;
-import android.support.test.filters.SdkSuppress;
 import android.support.test.runner.AndroidJUnit4;
 
 import androidx.annotation.NonNull;
@@ -70,7 +68,6 @@
 /**
  * Tests whether {@link MediaSession2} receives commands that hasn't allowed.
  */
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
 @RunWith(AndroidJUnit4.class)
 @MediumTest
 public class MediaSession2_PermissionTest extends MediaSession2TestBase {
diff --git a/media/src/androidTest/java/androidx/media/MediaSessionManager_MediaSession2Test.java b/media/src/androidTest/java/androidx/media/MediaSessionManager_MediaSession2Test.java
index a0ce092..904b768 100644
--- a/media/src/androidTest/java/androidx/media/MediaSessionManager_MediaSession2Test.java
+++ b/media/src/androidTest/java/androidx/media/MediaSessionManager_MediaSession2Test.java
@@ -73,7 +73,7 @@
     public void testGetMediaSession2Tokens_hasMediaController() throws InterruptedException {
         prepareLooper();
         final MockPlayer player = (MockPlayer) mSession.getPlayer();
-        player.notifyPlaybackState(MediaPlayerInterface.PLAYER_STATE_IDLE);
+        player.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_IDLE);
 
         MediaController2 controller = null;
 //        List<SessionToken2> tokens = mManager.getActiveSessionTokens();
@@ -89,7 +89,7 @@
 //        assertNotNull(controller);
 //
 //        // Test if the found controller is correct one.
-//        assertEquals(MediaPlayerInterface.PLAYER_STATE_IDLE, controller.getPlayerState());
+//        assertEquals(MediaPlayerBase.PLAYER_STATE_IDLE, controller.getPlayerState());
 //        controller.play();
 //
 //        assertTrue(player.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
diff --git a/media/src/androidTest/java/androidx/media/MockPlayer.java b/media/src/androidTest/java/androidx/media/MockPlayer.java
index e280ed8..49b1a19 100644
--- a/media/src/androidTest/java/androidx/media/MockPlayer.java
+++ b/media/src/androidTest/java/androidx/media/MockPlayer.java
@@ -16,17 +16,18 @@
 
 package androidx.media;
 
+import android.util.ArrayMap;
+
 import androidx.annotation.NonNull;
-import androidx.collection.ArrayMap;
 
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 
 /**
- * A mock implementation of {@link MediaPlayerInterface} for testing.
+ * A mock implementation of {@link MediaPlayerBase} for testing.
  */
-public class MockPlayer extends MediaPlayerInterface {
+public class MockPlayer extends MediaPlayerBase {
     public final CountDownLatch mCountDownLatch;
 
     public boolean mPlayCalled;
@@ -41,7 +42,6 @@
     public float mPlaybackSpeed = 1.0f;
     public @PlayerState int mLastPlayerState;
     public @BuffState int mLastBufferingState;
-    public long mDuration;
 
     public ArrayMap<PlayerEventCallback, Executor> mCallbacks = new ArrayMap<>();
 
@@ -128,11 +128,6 @@
     }
 
     @Override
-    public long getDuration() {
-        return mDuration;
-    }
-
-    @Override
     public void registerPlayerEventCallback(@NonNull Executor executor,
             @NonNull PlayerEventCallback callback) {
         if (callback == null || executor == null) {
@@ -160,6 +155,21 @@
         }
     }
 
+    public void notifyBufferingState(final MediaItem2 item, final int bufferingState) {
+        mLastBufferingState = bufferingState;
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            final PlayerEventCallback callback = mCallbacks.keyAt(i);
+            final Executor executor = mCallbacks.valueAt(i);
+            executor.execute(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onBufferingStateChanged(
+                            MockPlayer.this, item.getDataSourceDesc(), bufferingState);
+                }
+            });
+        }
+    }
+
     public void notifyCurrentDataSourceChanged(final DataSourceDesc dsd) {
         for (int i = 0; i < mCallbacks.size(); i++) {
             final PlayerEventCallback callback = mCallbacks.keyAt(i);
@@ -213,19 +223,6 @@
         }
     }
 
-    public void notifySeekCompleted(final long position) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onSeekCompleted(MockPlayer.this, position);
-                }
-            });
-        }
-    }
-
     public void notifyError(int what) {
         for (int i = 0; i < mCallbacks.size(); i++) {
             final PlayerEventCallback callback = mCallbacks.keyAt(i);
diff --git a/media/src/androidTest/java/androidx/media/SessionToken2Test.java b/media/src/androidTest/java/androidx/media/SessionToken2Test.java
index bf96eb9..22881a8 100644
--- a/media/src/androidTest/java/androidx/media/SessionToken2Test.java
+++ b/media/src/androidTest/java/androidx/media/SessionToken2Test.java
@@ -20,10 +20,8 @@
 
 import android.content.ComponentName;
 import android.content.Context;
-import android.os.Build;
 import android.os.Process;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -34,7 +32,6 @@
 /**
  * Tests {@link SessionToken2}.
  */
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class SessionToken2Test {
diff --git a/media/src/androidTest/java/androidx/media/TestUtils.java b/media/src/androidTest/java/androidx/media/TestUtils.java
index 2b02b75..1e3ba9b 100644
--- a/media/src/androidTest/java/androidx/media/TestUtils.java
+++ b/media/src/androidTest/java/androidx/media/TestUtils.java
@@ -25,11 +25,10 @@
 import android.os.Handler;
 import android.os.Looper;
 
-import androidx.core.util.ObjectsCompat;
-
 import java.io.FileDescriptor;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -69,29 +68,18 @@
      *     incorrect if any bundle contains a bundle.
      */
     public static boolean equals(Bundle a, Bundle b) {
-        return contains(a, b) && contains(b, a);
-    }
-
-    /**
-     * Checks whether a Bundle contains another bundle.
-     *
-     * @param a a bundle
-     * @param b another bundle
-     * @return {@code true} if a contains b. {@code false} otherwise. This may be incorrect if any
-     *      bundle contains a bundle.
-     */
-    public static boolean contains(Bundle a, Bundle b) {
         if (a == b) {
             return true;
         }
         if (a == null || b == null) {
-            return b == null;
-        }
-        if (!a.keySet().containsAll(b.keySet())) {
             return false;
         }
-        for (String key : b.keySet()) {
-            if (!ObjectsCompat.equals(a.get(key), b.get(key))) {
+        if (!a.keySet().containsAll(b.keySet())
+                || !b.keySet().containsAll(a.keySet())) {
+            return false;
+        }
+        for (String key : a.keySet()) {
+            if (!Objects.equals(a.get(key), b.get(key))) {
                 return false;
             }
         }
@@ -103,7 +91,7 @@
      * <p>
      * Caller's method name will be used for prefix of each media item's media id.
      *
-     * @param size list size
+     * @param size lits size
      * @return the newly created playlist
      */
     public static List<MediaItem2> createPlaylist(int size) {
@@ -112,7 +100,11 @@
         for (int i = 0; i < size; i++) {
             list.add(new MediaItem2.Builder(MediaItem2.FLAG_PLAYABLE)
                     .setMediaId(caller + "_item_" + (size + 1))
-                    .setDataSourceDesc(createDSD()).build());
+                    .setDataSourceDesc(
+                            new DataSourceDesc.Builder()
+                                    .setDataSource(new FileDescriptor())
+                                    .build())
+                    .build());
         }
         return list;
     }
@@ -125,7 +117,7 @@
      */
     public static MediaItem2 createMediaItemWithMetadata() {
         return new MediaItem2.Builder(MediaItem2.FLAG_PLAYABLE)
-                .setMetadata(createMetadata()).setDataSourceDesc(createDSD()).build();
+                .setMetadata(createMetadata()).build();
     }
 
     /**
@@ -141,21 +133,6 @@
                 .putString(MediaMetadata2.METADATA_KEY_MEDIA_ID, mediaId).build();
     }
 
-    private static DataSourceDesc createDSD() {
-        return new DataSourceDesc.Builder().setDataSource(new FileDescriptor()).build();
-    }
-
-    /**
-     * Create a bundle for testing purpose.
-     *
-     * @return the newly created bundle.
-     */
-    public static Bundle createTestBundle() {
-        Bundle bundle = new Bundle();
-        bundle.putString("test_key", "test_value");
-        return bundle;
-    }
-
     /**
      * Handler that always waits until the Runnable finishes.
      */
diff --git a/media/src/main/java/android/support/v4/media/MediaBrowserCompat.java b/media/src/main/java/android/support/v4/media/MediaBrowserCompat.java
index aa039c3..a0e839bd 100644
--- a/media/src/main/java/android/support/v4/media/MediaBrowserCompat.java
+++ b/media/src/main/java/android/support/v4/media/MediaBrowserCompat.java
@@ -15,7 +15,6 @@
  */
 package android.support.v4.media;
 
-import static androidx.annotation.RestrictTo.Scope.LIBRARY;
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_ADD_SUBSCRIPTION;
 import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_CONNECT;
@@ -33,7 +32,6 @@
 import static androidx.media.MediaBrowserProtocol.DATA_MEDIA_ITEM_ID;
 import static androidx.media.MediaBrowserProtocol.DATA_MEDIA_ITEM_LIST;
 import static androidx.media.MediaBrowserProtocol.DATA_MEDIA_SESSION_TOKEN;
-import static androidx.media.MediaBrowserProtocol.DATA_NOTIFY_CHILDREN_CHANGED_OPTIONS;
 import static androidx.media.MediaBrowserProtocol.DATA_OPTIONS;
 import static androidx.media.MediaBrowserProtocol.DATA_PACKAGE_NAME;
 import static androidx.media.MediaBrowserProtocol.DATA_RESULT_RECEIVER;
@@ -430,20 +428,6 @@
     }
 
     /**
-     * Gets the options which is passed to {@link MediaBrowserServiceCompat#notifyChildrenChanged(
-     * String, Bundle)} call that triggered {@link SubscriptionCallback#onChildrenLoaded}.
-     * This should be called inside of {@link SubscriptionCallback#onChildrenLoaded}.
-     *
-     * @return A bundle which is passed to {@link MediaBrowserServiceCompat#notifyChildrenChanged(
-     *         String, Bundle)}
-     * @hide
-     */
-    @RestrictTo(LIBRARY)
-    public @Nullable Bundle getNotifyChildrenChangedOptions() {
-        return mImpl.getNotifyChildrenChangedOptions();
-    }
-
-    /**
      * A class with information on a single media item for use in browsing/searching media.
      * MediaItems are application dependent so we cannot guarantee that they contain the
      * right values.
@@ -967,15 +951,13 @@
         void search(@NonNull String query, Bundle extras, @NonNull SearchCallback callback);
         void sendCustomAction(@NonNull String action, Bundle extras,
                 @Nullable CustomActionCallback callback);
-        @Nullable Bundle getNotifyChildrenChangedOptions();
     }
 
     interface MediaBrowserServiceCallbackImpl {
         void onServiceConnected(Messenger callback, String root, MediaSessionCompat.Token session,
                 Bundle extra);
         void onConnectionFailed(Messenger callback);
-        void onLoadChildren(Messenger callback, String parentId, List list, Bundle options,
-                Bundle notifyChildrenChangedOptions);
+        void onLoadChildren(Messenger callback, String parentId, List list, Bundle options);
     }
 
     static class MediaBrowserImplBase
@@ -1000,7 +982,6 @@
         private String mRootId;
         private MediaSessionCompat.Token mMediaSessionToken;
         private Bundle mExtras;
-        private Bundle mNotifyChildrenChangedOptions;
 
         public MediaBrowserImplBase(Context context, ComponentName serviceComponent,
                 ConnectionCallback callback, Bundle rootHints) {
@@ -1391,7 +1372,7 @@
 
         @Override
         public void onLoadChildren(final Messenger callback, final String parentId,
-                final List list, final Bundle options, final Bundle notifyChildrenChangedOptions) {
+                final List list, final Bundle options) {
             // Check that there hasn't been a disconnect or a different ServiceConnection.
             if (!isCurrent(callback, "onLoadChildren")) {
                 return;
@@ -1417,27 +1398,18 @@
                     if (list == null) {
                         subscriptionCallback.onError(parentId);
                     } else {
-                        mNotifyChildrenChangedOptions = notifyChildrenChangedOptions;
                         subscriptionCallback.onChildrenLoaded(parentId, list);
-                        mNotifyChildrenChangedOptions = null;
                     }
                 } else {
                     if (list == null) {
                         subscriptionCallback.onError(parentId, options);
                     } else {
-                        mNotifyChildrenChangedOptions = notifyChildrenChangedOptions;
                         subscriptionCallback.onChildrenLoaded(parentId, list, options);
-                        mNotifyChildrenChangedOptions = null;
                     }
                 }
             }
         }
 
-        @Override
-        public Bundle getNotifyChildrenChangedOptions() {
-            return mNotifyChildrenChangedOptions;
-        }
-
         /**
          * For debugging.
          */
@@ -1617,7 +1589,6 @@
         protected ServiceBinderWrapper mServiceBinderWrapper;
         protected Messenger mCallbacksMessenger;
         private MediaSessionCompat.Token mMediaSessionToken;
-        private Bundle mNotifyChildrenChangedOptions;
 
         MediaBrowserImplApi21(Context context, ComponentName serviceComponent,
                 ConnectionCallback callback, Bundle rootHints) {
@@ -1891,7 +1862,7 @@
                 mCallbacksMessenger = new Messenger(mHandler);
                 mHandler.setCallbacksMessenger(mCallbacksMessenger);
                 try {
-                    mServiceBinderWrapper.registerCallbackMessenger(mContext, mCallbacksMessenger);
+                    mServiceBinderWrapper.registerCallbackMessenger(mCallbacksMessenger);
                 } catch (RemoteException e) {
                     Log.i(TAG, "Remote error registering client messenger." );
                 }
@@ -1930,8 +1901,7 @@
 
         @Override
         @SuppressWarnings("ReferenceEquality")
-        public void onLoadChildren(Messenger callback, String parentId, List list, Bundle options,
-                Bundle notifyChildrenChangedOptions) {
+        public void onLoadChildren(Messenger callback, String parentId, List list, Bundle options) {
             if (mCallbacksMessenger != callback) {
                 return;
             }
@@ -1952,26 +1922,17 @@
                     if (list == null) {
                         subscriptionCallback.onError(parentId);
                     } else {
-                        mNotifyChildrenChangedOptions = notifyChildrenChangedOptions;
                         subscriptionCallback.onChildrenLoaded(parentId, list);
-                        mNotifyChildrenChangedOptions = null;
                     }
                 } else {
                     if (list == null) {
                         subscriptionCallback.onError(parentId, options);
                     } else {
-                        mNotifyChildrenChangedOptions = notifyChildrenChangedOptions;
                         subscriptionCallback.onChildrenLoaded(parentId, list, options);
-                        mNotifyChildrenChangedOptions = null;
                     }
                 }
             }
         }
-
-        @Override
-        public Bundle getNotifyChildrenChangedOptions() {
-            return mNotifyChildrenChangedOptions;
-        }
     }
 
     @RequiresApi(23)
@@ -2116,8 +2077,7 @@
                         serviceCallback.onLoadChildren(callbacksMessenger,
                                 data.getString(DATA_MEDIA_ITEM_ID),
                                 data.getParcelableArrayList(DATA_MEDIA_ITEM_LIST),
-                                data.getBundle(DATA_OPTIONS),
-                                data.getBundle(DATA_NOTIFY_CHILDREN_CHANGED_OPTIONS));
+                                data.getBundle(DATA_OPTIONS));
                         break;
                     default:
                         Log.w(TAG, "Unhandled message: " + msg
@@ -2187,10 +2147,8 @@
             sendRequest(CLIENT_MSG_GET_MEDIA_ITEM, data, callbacksMessenger);
         }
 
-        void registerCallbackMessenger(Context context, Messenger callbackMessenger)
-                throws RemoteException {
+        void registerCallbackMessenger(Messenger callbackMessenger) throws RemoteException {
             Bundle data = new Bundle();
-            data.putString(DATA_PACKAGE_NAME, context.getPackageName());
             data.putBundle(DATA_ROOT_HINTS, mRootHints);
             sendRequest(CLIENT_MSG_REGISTER_CALLBACK_MESSENGER, data, callbackMessenger);
         }
diff --git a/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java b/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
index dd498be..1d78fc8 100644
--- a/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
+++ b/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
@@ -18,7 +18,6 @@
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-import static androidx.media.MediaSessionManager.RemoteUserInfo.LEGACY_CONTROLLER;
 
 import android.app.Activity;
 import android.app.PendingIntent;
@@ -32,10 +31,8 @@
 import android.media.MediaMetadataRetriever;
 import android.media.Rating;
 import android.media.RemoteControlClient;
-import android.media.session.MediaSession;
 import android.net.Uri;
 import android.os.BadParcelableException;
-import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -58,12 +55,9 @@
 import android.view.ViewConfiguration;
 
 import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.core.app.BundleCompat;
-import androidx.media.MediaSessionManager;
-import androidx.media.MediaSessionManager.RemoteUserInfo;
 import androidx.media.VolumeProviderCompat;
 import androidx.media.session.MediaButtonReceiver;
 
@@ -389,11 +383,6 @@
     // Maximum size of the bitmap in dp.
     private static final int MAX_BITMAP_SIZE_IN_DP = 320;
 
-    private static final String DATA_CALLING_PACKAGE = "data_calling_pkg";
-    private static final String DATA_CALLING_PID = "data_calling_pid";
-    private static final String DATA_CALLING_UID = "data_calling_uid";
-    private static final String DATA_EXTRAS = "data_extras";
-
     // Maximum size of the bitmap in px. It shouldn't be changed.
     static int sMaxBitmapSize;
 
@@ -460,11 +449,7 @@
             mbrIntent = PendingIntent.getBroadcast(context,
                     0/* requestCode, ignored */, mediaButtonIntent, 0/* flags */);
         }
-        if (android.os.Build.VERSION.SDK_INT >= 28) {
-            mImpl = new MediaSessionImplApi28(context, tag);
-            // Set default callback to respond to controllers' extra binder requests.
-            setCallback(new Callback() {});
-        } else if (android.os.Build.VERSION.SDK_INT >= 21) {
+        if (android.os.Build.VERSION.SDK_INT >= 21) {
             mImpl = new MediaSessionImplApi21(context, tag);
             // Set default callback to respond to controllers' extra binder requests.
             setCallback(new Callback() {});
@@ -817,18 +802,6 @@
     }
 
     /**
-     * Gets the controller information who sent the current request.
-     * <p>
-     * Note: This is only valid while in a request callback, such as {@link Callback#onPlay}.
-     *
-     * @throws IllegalStateException If this method is called outside of {@link Callback} methods.
-     * @see MediaSessionManager#isTrustedForMediaControl(RemoteUserInfo)
-     */
-    public final @NonNull RemoteUserInfo getCurrentControllerInfo() {
-        return mImpl.getCurrentControllerInfo();
-    }
-
-    /**
      * Returns the name of the package that sent the last media button, transport control, or
      * command from controllers and the system. This is only valid while in a request callback, such
      * as {@link Callback#onPlay}. This method is not available and returns null on pre-N devices.
@@ -1849,7 +1822,6 @@
         Object getRemoteControlClient();
 
         String getCallingPackage();
-        RemoteUserInfo getCurrentControllerInfo();
     }
 
     static class MediaSessionImplBase implements MediaSessionImpl {
@@ -1946,19 +1918,30 @@
             }
         }
 
-        void postToHandler(int what, int arg1, int arg2, Object obj, Bundle extras) {
+        void postToHandler(int what) {
+            postToHandler(what, null);
+        }
+
+        void postToHandler(int what, int arg1) {
+            postToHandler(what, null, arg1);
+        }
+
+        void postToHandler(int what, Object obj) {
+            postToHandler(what, obj, null);
+        }
+
+        void postToHandler(int what, Object obj, int arg1) {
             synchronized (mLock) {
                 if (mHandler != null) {
-                    Message msg = mHandler.obtainMessage(what, arg1, arg2, obj);
-                    Bundle data = new Bundle();
-                    data.putString(DATA_CALLING_PACKAGE, LEGACY_CONTROLLER);
-                    data.putInt(DATA_CALLING_PID, Binder.getCallingPid());
-                    data.putInt(DATA_CALLING_UID, Binder.getCallingUid());
-                    if (extras != null) {
-                        data.putBundle(DATA_EXTRAS, extras);
-                    }
-                    msg.setData(data);
-                    msg.sendToTarget();
+                    mHandler.post(what, obj, arg1);
+                }
+            }
+        }
+
+        void postToHandler(int what, Object obj, Bundle extras) {
+            synchronized (mLock) {
+                if (mHandler != null) {
+                    mHandler.post(what, obj, extras);
                 }
             }
         }
@@ -1976,7 +1959,6 @@
             if (mVolumeProvider != null) {
                 mVolumeProvider.setCallback(null);
             }
-            mLocalStream = stream;
             mVolumeType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL;
             ParcelableVolumeInfo info = new ParcelableVolumeInfo(mVolumeType, mLocalStream,
                     VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE,
@@ -2300,16 +2282,6 @@
             sendExtras(extras);
         }
 
-        @Override
-        public RemoteUserInfo getCurrentControllerInfo() {
-            synchronized (mLock) {
-                if (mHandler != null) {
-                    return mHandler.getRemoteUserInfo();
-                }
-            }
-            return null;
-        }
-
         // Registers/unregisters components as needed.
         boolean update() {
             boolean registeredRcc = false;
@@ -2820,26 +2792,6 @@
             public boolean isTransportControlEnabled() {
                 return (mFlags & FLAG_HANDLES_TRANSPORT_CONTROLS) != 0;
             }
-
-            void postToHandler(int what) {
-                MediaSessionImplBase.this.postToHandler(what, 0, 0, null, null);
-            }
-
-            void postToHandler(int what, int arg1) {
-                MediaSessionImplBase.this.postToHandler(what, arg1, 0, null, null);
-            }
-
-            void postToHandler(int what, Object obj) {
-                MediaSessionImplBase.this.postToHandler(what, 0, 0, obj, null);
-            }
-
-            void postToHandler(int what, Object obj, int arg1) {
-                MediaSessionImplBase.this.postToHandler(what, arg1, 0, obj, null);
-            }
-
-            void postToHandler(int what, Object obj, Bundle extras) {
-                MediaSessionImplBase.this.postToHandler(what, 0, 0, obj, extras);
-            }
         }
 
         private static final class Command {
@@ -2891,133 +2843,138 @@
             private static final int KEYCODE_MEDIA_PAUSE = 127;
             private static final int KEYCODE_MEDIA_PLAY = 126;
 
-            private RemoteUserInfo mRemoteUserInfo;
-
             public MessageHandler(Looper looper) {
                 super(looper);
             }
 
+            public void post(int what, Object obj, Bundle bundle) {
+                Message msg = obtainMessage(what, obj);
+                msg.setData(bundle);
+                msg.sendToTarget();
+            }
+
+            public void post(int what, Object obj) {
+                obtainMessage(what, obj).sendToTarget();
+            }
+
+            public void post(int what) {
+                post(what, null);
+            }
+
+            public void post(int what, Object obj, int arg1) {
+                obtainMessage(what, arg1, 0, obj).sendToTarget();
+            }
+
             @Override
             public void handleMessage(Message msg) {
                 MediaSessionCompat.Callback cb = mCallback;
                 if (cb == null) {
                     return;
                 }
-
-                Bundle data = msg.getData();
-                mRemoteUserInfo = new RemoteUserInfo(data.getString(DATA_CALLING_PACKAGE),
-                        data.getInt(DATA_CALLING_PID), data.getInt(DATA_CALLING_UID));
-                data = data.getBundle(DATA_EXTRAS);
-
-                try {
-                    switch (msg.what) {
-                        case MSG_COMMAND:
-                            Command cmd = (Command) msg.obj;
-                            cb.onCommand(cmd.command, cmd.extras, cmd.stub);
-                            break;
-                        case MSG_MEDIA_BUTTON:
-                            KeyEvent keyEvent = (KeyEvent) msg.obj;
-                            Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
-                            intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
-                            // Let the Callback handle events first before using the default
-                            // behavior
-                            if (!cb.onMediaButtonEvent(intent)) {
-                                onMediaButtonEvent(keyEvent, cb);
+                switch (msg.what) {
+                    case MSG_COMMAND:
+                        Command cmd = (Command) msg.obj;
+                        cb.onCommand(cmd.command, cmd.extras, cmd.stub);
+                        break;
+                    case MSG_MEDIA_BUTTON:
+                        KeyEvent keyEvent = (KeyEvent) msg.obj;
+                        Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+                        intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+                        // Let the Callback handle events first before using the default behavior
+                        if (!cb.onMediaButtonEvent(intent)) {
+                            onMediaButtonEvent(keyEvent, cb);
+                        }
+                        break;
+                    case MSG_PREPARE:
+                        cb.onPrepare();
+                        break;
+                    case MSG_PREPARE_MEDIA_ID:
+                        cb.onPrepareFromMediaId((String) msg.obj, msg.getData());
+                        break;
+                    case MSG_PREPARE_SEARCH:
+                        cb.onPrepareFromSearch((String) msg.obj, msg.getData());
+                        break;
+                    case MSG_PREPARE_URI:
+                        cb.onPrepareFromUri((Uri) msg.obj, msg.getData());
+                        break;
+                    case MSG_PLAY:
+                        cb.onPlay();
+                        break;
+                    case MSG_PLAY_MEDIA_ID:
+                        cb.onPlayFromMediaId((String) msg.obj, msg.getData());
+                        break;
+                    case MSG_PLAY_SEARCH:
+                        cb.onPlayFromSearch((String) msg.obj, msg.getData());
+                        break;
+                    case MSG_PLAY_URI:
+                        cb.onPlayFromUri((Uri) msg.obj, msg.getData());
+                        break;
+                    case MSG_SKIP_TO_ITEM:
+                        cb.onSkipToQueueItem((Long) msg.obj);
+                        break;
+                    case MSG_PAUSE:
+                        cb.onPause();
+                        break;
+                    case MSG_STOP:
+                        cb.onStop();
+                        break;
+                    case MSG_NEXT:
+                        cb.onSkipToNext();
+                        break;
+                    case MSG_PREVIOUS:
+                        cb.onSkipToPrevious();
+                        break;
+                    case MSG_FAST_FORWARD:
+                        cb.onFastForward();
+                        break;
+                    case MSG_REWIND:
+                        cb.onRewind();
+                        break;
+                    case MSG_SEEK_TO:
+                        cb.onSeekTo((Long) msg.obj);
+                        break;
+                    case MSG_RATE:
+                        cb.onSetRating((RatingCompat) msg.obj);
+                        break;
+                    case MSG_RATE_EXTRA:
+                        cb.onSetRating((RatingCompat) msg.obj, msg.getData());
+                        break;
+                    case MSG_CUSTOM_ACTION:
+                        cb.onCustomAction((String) msg.obj, msg.getData());
+                        break;
+                    case MSG_ADD_QUEUE_ITEM:
+                        cb.onAddQueueItem((MediaDescriptionCompat) msg.obj);
+                        break;
+                    case MSG_ADD_QUEUE_ITEM_AT:
+                        cb.onAddQueueItem((MediaDescriptionCompat) msg.obj, msg.arg1);
+                        break;
+                    case MSG_REMOVE_QUEUE_ITEM:
+                        cb.onRemoveQueueItem((MediaDescriptionCompat) msg.obj);
+                        break;
+                    case MSG_REMOVE_QUEUE_ITEM_AT:
+                        if (mQueue != null) {
+                            QueueItem item = (msg.arg1 >= 0 && msg.arg1 < mQueue.size())
+                                    ? mQueue.get(msg.arg1) : null;
+                            if (item != null) {
+                                cb.onRemoveQueueItem(item.getDescription());
                             }
-                            break;
-                        case MSG_PREPARE:
-                            cb.onPrepare();
-                            break;
-                        case MSG_PREPARE_MEDIA_ID:
-                            cb.onPrepareFromMediaId((String) msg.obj, data);
-                            break;
-                        case MSG_PREPARE_SEARCH:
-                            cb.onPrepareFromSearch((String) msg.obj, data);
-                            break;
-                        case MSG_PREPARE_URI:
-                            cb.onPrepareFromUri((Uri) msg.obj, data);
-                            break;
-                        case MSG_PLAY:
-                            cb.onPlay();
-                            break;
-                        case MSG_PLAY_MEDIA_ID:
-                            cb.onPlayFromMediaId((String) msg.obj, data);
-                            break;
-                        case MSG_PLAY_SEARCH:
-                            cb.onPlayFromSearch((String) msg.obj, data);
-                            break;
-                        case MSG_PLAY_URI:
-                            cb.onPlayFromUri((Uri) msg.obj, data);
-                            break;
-                        case MSG_SKIP_TO_ITEM:
-                            cb.onSkipToQueueItem((Long) msg.obj);
-                            break;
-                        case MSG_PAUSE:
-                            cb.onPause();
-                            break;
-                        case MSG_STOP:
-                            cb.onStop();
-                            break;
-                        case MSG_NEXT:
-                            cb.onSkipToNext();
-                            break;
-                        case MSG_PREVIOUS:
-                            cb.onSkipToPrevious();
-                            break;
-                        case MSG_FAST_FORWARD:
-                            cb.onFastForward();
-                            break;
-                        case MSG_REWIND:
-                            cb.onRewind();
-                            break;
-                        case MSG_SEEK_TO:
-                            cb.onSeekTo((Long) msg.obj);
-                            break;
-                        case MSG_RATE:
-                            cb.onSetRating((RatingCompat) msg.obj);
-                            break;
-                        case MSG_RATE_EXTRA:
-                            cb.onSetRating((RatingCompat) msg.obj, data);
-                            break;
-                        case MSG_CUSTOM_ACTION:
-                            cb.onCustomAction((String) msg.obj, data);
-                            break;
-                        case MSG_ADD_QUEUE_ITEM:
-                            cb.onAddQueueItem((MediaDescriptionCompat) msg.obj);
-                            break;
-                        case MSG_ADD_QUEUE_ITEM_AT:
-                            cb.onAddQueueItem((MediaDescriptionCompat) msg.obj, msg.arg1);
-                            break;
-                        case MSG_REMOVE_QUEUE_ITEM:
-                            cb.onRemoveQueueItem((MediaDescriptionCompat) msg.obj);
-                            break;
-                        case MSG_REMOVE_QUEUE_ITEM_AT:
-                            if (mQueue != null) {
-                                QueueItem item = (msg.arg1 >= 0 && msg.arg1 < mQueue.size())
-                                        ? mQueue.get(msg.arg1) : null;
-                                if (item != null) {
-                                    cb.onRemoveQueueItem(item.getDescription());
-                                }
-                            }
-                            break;
-                        case MSG_ADJUST_VOLUME:
-                            adjustVolume(msg.arg1, 0);
-                            break;
-                        case MSG_SET_VOLUME:
-                            setVolumeTo(msg.arg1, 0);
-                            break;
-                        case MSG_SET_CAPTIONING_ENABLED:
-                            cb.onSetCaptioningEnabled((boolean) msg.obj);
-                            break;
-                        case MSG_SET_REPEAT_MODE:
-                            cb.onSetRepeatMode(msg.arg1);
-                            break;
-                        case MSG_SET_SHUFFLE_MODE:
-                            cb.onSetShuffleMode(msg.arg1);
-                            break;
-                    }
-                } finally {
-                    mRemoteUserInfo = null;
+                        }
+                        break;
+                    case MSG_ADJUST_VOLUME:
+                        adjustVolume(msg.arg1, 0);
+                        break;
+                    case MSG_SET_VOLUME:
+                        setVolumeTo(msg.arg1, 0);
+                        break;
+                    case MSG_SET_CAPTIONING_ENABLED:
+                        cb.onSetCaptioningEnabled((boolean) msg.obj);
+                        break;
+                    case MSG_SET_REPEAT_MODE:
+                        cb.onSetRepeatMode(msg.arg1);
+                        break;
+                    case MSG_SET_SHUFFLE_MODE:
+                        cb.onSetShuffleMode(msg.arg1);
+                        break;
                 }
             }
 
@@ -3071,10 +3028,6 @@
                         break;
                 }
             }
-
-            RemoteUserInfo getRemoteUserInfo() {
-                return mRemoteUserInfo;
-            }
         }
     }
 
@@ -3097,8 +3050,7 @@
                         new RemoteControlClient.OnPlaybackPositionUpdateListener() {
                             @Override
                             public void onPlaybackPositionUpdate(long newPositionMs) {
-                                postToHandler(
-                                        MessageHandler.MSG_SEEK_TO, -1, -1, newPositionMs, null);
+                                postToHandler(MessageHandler.MSG_SEEK_TO, newPositionMs);
                             }
                         };
                 mRcc.setPlaybackPositionUpdateListener(listener);
@@ -3183,8 +3135,8 @@
                             public void onMetadataUpdate(int key, Object newValue) {
                                 if (key == MediaMetadataEditor.RATING_KEY_BY_USER
                                         && newValue instanceof Rating) {
-                                    postToHandler(MessageHandler.MSG_RATE, -1, -1,
-                                            RatingCompat.fromRating(newValue), null);
+                                    postToHandler(MessageHandler.MSG_RATE,
+                                            RatingCompat.fromRating(newValue));
                                 }
                             }
                         };
@@ -3458,11 +3410,6 @@
             }
         }
 
-        @Override
-        public RemoteUserInfo getCurrentControllerInfo() {
-            return null;
-        }
-
         class ExtraSession extends IMediaSession.Stub {
             @Override
             public void sendCommand(String command, Bundle args, ResultReceiverWrapper cb) {
@@ -3756,25 +3703,4 @@
             }
         }
     }
-
-    @RequiresApi(28)
-    static class MediaSessionImplApi28 extends MediaSessionImplApi21 {
-        private MediaSession mSession;
-
-        MediaSessionImplApi28(Context context, String tag) {
-            super(context, tag);
-        }
-
-        MediaSessionImplApi28(Object mediaSession) {
-            super(mediaSession);
-            mSession = (MediaSession) mediaSession;
-        }
-
-        @Override
-        public final @NonNull RemoteUserInfo getCurrentControllerInfo() {
-            android.media.session.MediaSessionManager.RemoteUserInfo info =
-                    mSession.getCurrentControllerInfo();
-            return new RemoteUserInfo(info.getPackageName(), info.getPid(), info.getUid());
-        }
-    }
 }
diff --git a/media/src/main/java/androidx/media/AudioAttributesCompat.java b/media/src/main/java/androidx/media/AudioAttributesCompat.java
index 69ef117..1fbb7be0 100644
--- a/media/src/main/java/androidx/media/AudioAttributesCompat.java
+++ b/media/src/main/java/androidx/media/AudioAttributesCompat.java
@@ -21,7 +21,6 @@
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.os.Build;
-import android.os.Bundle;
 import android.util.SparseIntArray;
 
 import androidx.annotation.IntDef;
@@ -229,16 +228,6 @@
     private static final int FLAG_ALL_PUBLIC =
             (FLAG_AUDIBILITY_ENFORCED | FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY);
 
-    /** Keys to convert to (or create from) Bundle. */
-    private static final String AUDIO_ATTRIBUTES_FRAMEWORKS =
-            "androidx.media.audio_attrs.FRAMEWORKS";
-    private static final String AUDIO_ATTRIBUTES_USAGE = "androidx.media.audio_attrs.USAGE";
-    private static final String AUDIO_ATTRIBUTES_CONTENT_TYPE =
-            "androidx.media.audio_attrs.CONTENT_TYPE";
-    private static final String AUDIO_ATTRIBUTES_FLAGS = "androidx.media.audio_attrs.FLAGS";
-    private static final String AUDIO_ATTRIBUTES_LEGACY_STREAM_TYPE =
-            "androidx.media.audio_attrs.LEGACY_STREAM_TYPE";
-
     int mUsage = USAGE_UNKNOWN;
     int mContentType = CONTENT_TYPE_UNKNOWN;
     int mFlags = 0x0;
@@ -388,56 +377,6 @@
     }
 
     /**
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    public @NonNull Bundle toBundle() {
-        Bundle bundle = new Bundle();
-        if (Build.VERSION.SDK_INT >= 21) {
-            bundle.putParcelable(AUDIO_ATTRIBUTES_FRAMEWORKS, mAudioAttributesWrapper.unwrap());
-        } else {
-            bundle.putInt(AUDIO_ATTRIBUTES_USAGE, mUsage);
-            bundle.putInt(AUDIO_ATTRIBUTES_CONTENT_TYPE, mContentType);
-            bundle.putInt(AUDIO_ATTRIBUTES_FLAGS, mFlags);
-            if (mLegacyStream != null) {
-                bundle.putInt(AUDIO_ATTRIBUTES_LEGACY_STREAM_TYPE, mLegacyStream);
-            }
-        }
-        return bundle;
-    }
-
-    /**
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    public static AudioAttributesCompat fromBundle(Bundle bundle) {
-        if (bundle == null) {
-            return null;
-        }
-
-        if (Build.VERSION.SDK_INT >= 21) {
-            AudioAttributes frameworkAttrs = (AudioAttributes)
-                    bundle.getParcelable(AUDIO_ATTRIBUTES_FRAMEWORKS);
-            return frameworkAttrs == null ? null : AudioAttributesCompat.wrap(frameworkAttrs);
-        } else {
-            int usage = bundle.getInt(AUDIO_ATTRIBUTES_USAGE, USAGE_UNKNOWN);
-            int contentType = bundle.getInt(AUDIO_ATTRIBUTES_CONTENT_TYPE, CONTENT_TYPE_UNKNOWN);
-            int flags = bundle.getInt(AUDIO_ATTRIBUTES_FLAGS, 0);
-
-            // Here, we do not use builder in order to 'copy' the exact state of the original one.
-            // Builder class guesses the usage based on other value (contentType/legacyStream), and
-            // overwrites it. So using builder cannot ensure the equality.
-            AudioAttributesCompat attr = new AudioAttributesCompat();
-            attr.mUsage = usage;
-            attr.mContentType = contentType;
-            attr.mFlags = flags;
-            attr.mLegacyStream = bundle.containsKey(AUDIO_ATTRIBUTES_LEGACY_STREAM_TYPE)
-                    ? bundle.getInt(AUDIO_ATTRIBUTES_LEGACY_STREAM_TYPE) : null;
-            return attr;
-        }
-    }
-
-    /**
      * Builder class for {@link AudioAttributesCompat} objects.
      *
      * <p>example:
diff --git a/media/src/main/java/androidx/media/Media2DataSource.java b/media/src/main/java/androidx/media/Media2DataSource.java
index 3855d56..4990259 100644
--- a/media/src/main/java/androidx/media/Media2DataSource.java
+++ b/media/src/main/java/androidx/media/Media2DataSource.java
@@ -17,10 +17,15 @@
 
 package androidx.media;
 
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import androidx.annotation.RestrictTo;
+
 import java.io.Closeable;
 import java.io.IOException;
 
 /**
+ * @hide
  * For supplying media data to the framework. Implement this if your app has
  * special requirements for the way media data is obtained.
  *
@@ -31,6 +36,7 @@
  * Media2DataSource from another thread while it's being used by the framework.</p>
  *
  */
+@RestrictTo(LIBRARY_GROUP)
 public abstract class Media2DataSource implements Closeable {
     /**
      * Called to request data from the given position.
diff --git a/media/src/main/java/androidx/media/MediaBrowser2.java b/media/src/main/java/androidx/media/MediaBrowser2.java
index beadf1f..6ef7fcf 100644
--- a/media/src/main/java/androidx/media/MediaBrowser2.java
+++ b/media/src/main/java/androidx/media/MediaBrowser2.java
@@ -17,18 +17,13 @@
 package androidx.media;
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-import static androidx.media.MediaConstants2.ARGUMENT_EXTRAS;
-import static androidx.media.MediaConstants2.ARGUMENT_PAGE;
-import static androidx.media.MediaConstants2.ARGUMENT_PAGE_SIZE;
 
 import android.content.Context;
-import android.os.BadParcelableException;
 import android.os.Bundle;
 import android.support.v4.media.MediaBrowserCompat;
 import android.support.v4.media.MediaBrowserCompat.ItemCallback;
 import android.support.v4.media.MediaBrowserCompat.MediaItem;
 import android.support.v4.media.MediaBrowserCompat.SubscriptionCallback;
-import android.util.Log;
 
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
@@ -43,12 +38,11 @@
 import java.util.concurrent.Executor;
 
 /**
+ * @hide
  * Browses media content offered by a {@link MediaLibraryService2}.
  */
+@RestrictTo(LIBRARY_GROUP)
 public class MediaBrowser2 extends MediaController2 {
-    static final String TAG = "MediaBrowser2";
-    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
     /**
      * @hide
      */
@@ -56,10 +50,11 @@
     public static final String EXTRA_ITEM_COUNT = "android.media.browse.extra.ITEM_COUNT";
 
     /**
+     * Key for Bundle version of {@link MediaSession2.ControllerInfo}.
      * @hide
      */
     @RestrictTo(LIBRARY_GROUP)
-    public static final String MEDIA_BROWSER2_SUBSCRIBE = "androidx.media.MEDIA_BROWSER2_SUBSCRIBE";
+    public static final String EXTRA_TARGET = "android.media.browse.extra.TARGET";
 
     private final Object mLock = new Object();
     @GuardedBy("mLock")
@@ -176,7 +171,7 @@
                 browser.disconnect();
             }
             mBrowserCompats.clear();
-            // Ensure that ControllerCallback#onDisconnected() is called by super.close().
+            // TODO: Ensure that ControllerCallback#onDisconnected() is called by super.close().
             super.close();
         }
     }
@@ -200,20 +195,13 @@
                 }
             });
         } else {
-            getCallbackExecutor().execute(new Runnable() {
-                @Override
-                public void run() {
-                    // Do this on the callback executor to set the looper of MediaBrowserCompat's
-                    // callback handler to this looper.
-                    MediaBrowserCompat newBrowser = new MediaBrowserCompat(getContext(),
-                            getSessionToken().getComponentName(),
-                            new GetLibraryRootCallback(extras), extras);
-                    synchronized (mLock) {
-                        mBrowserCompats.put(extras, newBrowser);
-                    }
-                    newBrowser.connect();
-                }
-            });
+            MediaBrowserCompat newBrowser = new MediaBrowserCompat(getContext(),
+                    getSessionToken().getComponentName(), new GetLibraryRootCallback(extras),
+                    extras);
+            newBrowser.connect();
+            synchronized (mLock) {
+                mBrowserCompats.put(extras, newBrowser);
+            }
         }
     }
 
@@ -230,9 +218,15 @@
         if (parentId == null) {
             throw new IllegalArgumentException("parentId shouldn't be null");
         }
-        MediaBrowserCompat browser = getBrowserCompat();
-        if (browser == null) {
-            return;
+        // TODO: Document this behavior
+        Bundle option;
+        if (extras != null && (extras.containsKey(MediaBrowserCompat.EXTRA_PAGE)
+                || extras.containsKey(MediaBrowserCompat.EXTRA_PAGE_SIZE))) {
+            option = new Bundle(extras);
+            option.remove(MediaBrowserCompat.EXTRA_PAGE);
+            option.remove(MediaBrowserCompat.EXTRA_PAGE_SIZE);
+        } else {
+            option = extras;
         }
         SubscribeCallback callback = new SubscribeCallback();
         synchronized (mLock) {
@@ -243,11 +237,11 @@
             }
             list.add(callback);
         }
-
-        Bundle options = new Bundle();
-        options.putBundle(ARGUMENT_EXTRAS, extras);
-        options.putBoolean(MEDIA_BROWSER2_SUBSCRIBE, true);
-        browser.subscribe(parentId, options, callback);
+        // TODO: Revisit using default browser is OK. Here's my concern.
+        //       Assume that MediaBrowser2 is connected with the MediaBrowserServiceCompat.
+        //       Since MediaBrowserServiceCompat can call MediaBrowserServiceCompat#
+        //       getBrowserRootHints(), the service may refuse calls from MediaBrowser2
+        getBrowserCompat().subscribe(parentId, option, callback);
     }
 
     /**
@@ -263,10 +257,6 @@
         if (parentId == null) {
             throw new IllegalArgumentException("parentId shouldn't be null");
         }
-        MediaBrowserCompat browser = getBrowserCompat();
-        if (browser == null) {
-            return;
-        }
         // Note: don't use MediaBrowserCompat#unsubscribe(String) here, to keep the subscription
         // callback for getChildren.
         synchronized (mLock) {
@@ -274,6 +264,7 @@
             if (list == null) {
                 return;
             }
+            MediaBrowserCompat browser = getBrowserCompat();
             for (int i = 0; i < list.size(); i++) {
                 browser.unsubscribe(parentId, list.get(i));
             }
@@ -297,15 +288,12 @@
         if (page < 1 || pageSize < 1) {
             throw new IllegalArgumentException("Neither page nor pageSize should be less than 1");
         }
-        MediaBrowserCompat browser = getBrowserCompat();
-        if (browser == null) {
-            return;
-        }
-
-        Bundle options = MediaUtils2.createBundle(extras);
+        Bundle options = new Bundle(extras);
         options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
         options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
-        browser.subscribe(parentId, options, new GetChildrenCallback(parentId, page, pageSize));
+        // TODO: Revisit using default browser is OK. See TODO in subscribe
+        getBrowserCompat().subscribe(parentId, options,
+                new GetChildrenCallback(parentId, page, pageSize));
     }
 
     /**
@@ -315,11 +303,8 @@
      * @param mediaId media id for specifying the item
      */
     public void getItem(@NonNull final String mediaId) {
-        MediaBrowserCompat browser = getBrowserCompat();
-        if (browser == null) {
-            return;
-        }
-        browser.getItem(mediaId, new ItemCallback() {
+        // TODO: Revisit using default browser is OK. See TODO in subscribe
+        getBrowserCompat().getItem(mediaId, new ItemCallback() {
             @Override
             public void onItemLoaded(final MediaItem item) {
                 getCallbackExecutor().execute(new Runnable() {
@@ -353,28 +338,7 @@
      * @param extras extra bundle
      */
     public void search(@NonNull String query, @Nullable Bundle extras) {
-        MediaBrowserCompat browser = getBrowserCompat();
-        if (browser == null) {
-            return;
-        }
-        browser.search(query, extras, new MediaBrowserCompat.SearchCallback() {
-            @Override
-            public void onSearchResult(final String query, final Bundle extras,
-                    final List<MediaItem> items) {
-                getCallbackExecutor().execute(new Runnable() {
-                    @Override
-                    public void run() {
-                        getCallback().onSearchResultChanged(
-                                MediaBrowser2.this, query, items.size(), extras);
-                    }
-                });
-            }
-
-            @Override
-            public void onError(final String query, final Bundle extras) {
-                // Currently no way to tell failures in MediaBrowser2#search().
-            }
-        });
+        // TODO: Implement
     }
 
     /**
@@ -387,40 +351,9 @@
      * @param pageSize page size. Should be greater or equal to {@code 1}
      * @param extras extra bundle
      */
-    public void getSearchResult(final @NonNull String query, final int page, final int pageSize,
-            final @Nullable Bundle extras) {
-        MediaBrowserCompat browser = getBrowserCompat();
-        if (browser == null) {
-            return;
-        }
-        Bundle options = MediaUtils2.createBundle(extras);
-        options.putInt(ARGUMENT_PAGE, page);
-        options.putInt(ARGUMENT_PAGE_SIZE, pageSize);
-        browser.search(query, options, new MediaBrowserCompat.SearchCallback() {
-            @Override
-            public void onSearchResult(final String query, final Bundle extrasSent,
-                    final List<MediaItem> items) {
-                getCallbackExecutor().execute(new Runnable() {
-                    @Override
-                    public void run() {
-                        List<MediaItem2> item2List = MediaUtils2.toMediaItem2List(items);
-                        getCallback().onGetSearchResultDone(
-                                MediaBrowser2.this, query, page, pageSize, item2List, extras);
-                    }
-                });
-            }
-
-            @Override
-            public void onError(final String query, final Bundle extrasSent) {
-                getCallbackExecutor().execute(new Runnable() {
-                    @Override
-                    public void run() {
-                        getCallback().onGetSearchResultDone(
-                                MediaBrowser2.this, query, page, pageSize, null, extras);
-                    }
-                });
-            }
-        });
+    public void getSearchResult(@NonNull String query, int page, int pageSize,
+            @Nullable Bundle extras) {
+        // TODO: Implement
     }
 
     @Override
@@ -434,20 +367,6 @@
         }
     }
 
-    private Bundle getExtrasWithoutPagination(Bundle extras) {
-        if (extras == null) {
-            return null;
-        }
-        extras.setClassLoader(getContext().getClassLoader());
-        try {
-            extras.remove(MediaBrowserCompat.EXTRA_PAGE);
-            extras.remove(MediaBrowserCompat.EXTRA_PAGE_SIZE);
-        } catch (BadParcelableException e) {
-            // Pass through...
-        }
-        return extras;
-    }
-
     private class GetLibraryRootCallback extends MediaBrowserCompat.ConnectionCallback {
         private final Bundle mExtras;
 
@@ -514,14 +433,11 @@
                 // Currently no way to tell failures in MediaBrowser2#subscribe().
                 return;
             }
-
-            final Bundle notifyChildrenChangedOptions =
-                    getBrowserCompat().getNotifyChildrenChangedOptions();
             getCallbackExecutor().execute(new Runnable() {
                 @Override
                 public void run() {
                     getCallback().onChildrenChanged(MediaBrowser2.this, parentId, itemCount,
-                            notifyChildrenChangedOptions);
+                            options);
                 }
             });
         }
@@ -556,7 +472,7 @@
 
         @Override
         public void onChildrenLoaded(final String parentId, List<MediaItem> children,
-                Bundle options) {
+                final Bundle options) {
             final List<MediaItem2> items;
             if (children == null) {
                 items = null;
@@ -566,17 +482,12 @@
                     items.add(MediaUtils2.createMediaItem2(children.get(i)));
                 }
             }
-            final Bundle extras = getExtrasWithoutPagination(options);
             getCallbackExecutor().execute(new Runnable() {
                 @Override
                 public void run() {
-                    MediaBrowserCompat browser = getBrowserCompat();
-                    if (browser == null) {
-                        return;
-                    }
                     getCallback().onGetChildrenDone(MediaBrowser2.this, parentId, mPage, mPageSize,
-                            items, extras);
-                    browser.unsubscribe(mParentId, GetChildrenCallback.this);
+                            items, options);
+                    getBrowserCompat().unsubscribe(mParentId, GetChildrenCallback.this);
                 }
             });
         }
diff --git a/media/src/main/java/androidx/media/MediaBrowserCompatUtils.java b/media/src/main/java/androidx/media/MediaBrowserCompatUtils.java
index b9491b6..c553256 100644
--- a/media/src/main/java/androidx/media/MediaBrowserCompatUtils.java
+++ b/media/src/main/java/androidx/media/MediaBrowserCompatUtils.java
@@ -70,8 +70,12 @@
             endIndex2 = startIndex2 + pageSize2 - 1;
         }
 
-        // For better readability, leaving the exclamation mark here.
-        return !(endIndex1 < startIndex2 || endIndex2 < startIndex1);
+        if (startIndex1 <= startIndex2 && startIndex2 <= endIndex1) {
+            return true;
+        } else if (startIndex1 <= endIndex2 && endIndex2 <= endIndex1) {
+            return true;
+        }
+        return false;
     }
 
     private MediaBrowserCompatUtils() {
diff --git a/media/src/main/java/androidx/media/MediaBrowserProtocol.java b/media/src/main/java/androidx/media/MediaBrowserProtocol.java
index eb5b449..5c85880 100644
--- a/media/src/main/java/androidx/media/MediaBrowserProtocol.java
+++ b/media/src/main/java/androidx/media/MediaBrowserProtocol.java
@@ -15,7 +15,6 @@
  */
 package androidx.media;
 
-import android.os.Bundle;
 import android.support.v4.media.MediaBrowserCompat;
 
 import androidx.annotation.RestrictTo;
@@ -30,13 +29,10 @@
 
     public static final String DATA_CALLBACK_TOKEN = "data_callback_token";
     public static final String DATA_CALLING_UID = "data_calling_uid";
-    public static final String DATA_CALLING_PID = "data_calling_pid";
     public static final String DATA_MEDIA_ITEM_ID = "data_media_item_id";
     public static final String DATA_MEDIA_ITEM_LIST = "data_media_item_list";
     public static final String DATA_MEDIA_SESSION_TOKEN = "data_media_session_token";
     public static final String DATA_OPTIONS = "data_options";
-    public static final String DATA_NOTIFY_CHILDREN_CHANGED_OPTIONS =
-            "data_notify_children_changed_options";
     public static final String DATA_PACKAGE_NAME = "data_package_name";
     public static final String DATA_RESULT_RECEIVER = "data_result_receiver";
     public static final String DATA_ROOT_HINTS = "data_root_hints";
@@ -98,9 +94,6 @@
      *     DATA_MEDIA_ITEM_LIST : An array list for the media item children
      *     DATA_OPTIONS : A bundle of service-specific arguments sent from the media browse to
      *                    the media browser service
-     *     DATA_NOTIFY_CHILDREN_CHANGED_OPTIONS : A bundle of service-specific arguments sent from
-     *                    the media browser service to the media browser by calling
-     *                    {@link MediaBrowserServiceCompat#notifyChildrenChanged(String, Bundle)}
      */
     public static final int SERVICE_MSG_ON_LOAD_CHILDREN = 3;
 
diff --git a/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java b/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java
index 5da2287..8f24837 100644
--- a/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java
+++ b/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java
@@ -27,14 +27,12 @@
 import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_SEND_CUSTOM_ACTION;
 import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
 import static androidx.media.MediaBrowserProtocol.DATA_CALLBACK_TOKEN;
-import static androidx.media.MediaBrowserProtocol.DATA_CALLING_PID;
 import static androidx.media.MediaBrowserProtocol.DATA_CALLING_UID;
 import static androidx.media.MediaBrowserProtocol.DATA_CUSTOM_ACTION;
 import static androidx.media.MediaBrowserProtocol.DATA_CUSTOM_ACTION_EXTRAS;
 import static androidx.media.MediaBrowserProtocol.DATA_MEDIA_ITEM_ID;
 import static androidx.media.MediaBrowserProtocol.DATA_MEDIA_ITEM_LIST;
 import static androidx.media.MediaBrowserProtocol.DATA_MEDIA_SESSION_TOKEN;
-import static androidx.media.MediaBrowserProtocol.DATA_NOTIFY_CHILDREN_CHANGED_OPTIONS;
 import static androidx.media.MediaBrowserProtocol.DATA_OPTIONS;
 import static androidx.media.MediaBrowserProtocol.DATA_PACKAGE_NAME;
 import static androidx.media.MediaBrowserProtocol.DATA_RESULT_RECEIVER;
@@ -63,7 +61,6 @@
 import android.os.Messenger;
 import android.os.Parcel;
 import android.os.RemoteException;
-import android.service.media.MediaBrowserService;
 import android.support.v4.media.MediaBrowserCompat;
 import android.support.v4.media.session.IMediaSession;
 import android.support.v4.media.session.MediaSessionCompat;
@@ -79,7 +76,6 @@
 import androidx.collection.ArrayMap;
 import androidx.core.app.BundleCompat;
 import androidx.core.util.Pair;
-import androidx.media.MediaSessionManager.RemoteUserInfo;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -171,10 +167,9 @@
     /** @hide */
     @RestrictTo(LIBRARY)
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, value = {RESULT_FLAG_OPTION_NOT_HANDLED,
-            RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED, RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED})
-    private @interface ResultFlags {
-    }
+    @IntDef(flag=true, value = { RESULT_FLAG_OPTION_NOT_HANDLED,
+            RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED, RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED })
+    private @interface ResultFlags { }
 
     final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap<>();
     ConnectionRecord mCurConnection;
@@ -187,8 +182,6 @@
         void setSessionToken(MediaSessionCompat.Token token);
         void notifyChildrenChanged(final String parentId, final Bundle options);
         Bundle getBrowserRootHints();
-        RemoteUserInfo getCurrentBrowserInfo();
-        List<RemoteUserInfo> getSubscribingBrowsers(String parentId);
     }
 
     class MediaBrowserServiceImplBase implements MediaBrowserServiceImpl {
@@ -213,7 +206,7 @@
                 @Override
                 public void run() {
                     Iterator<ConnectionRecord> iter = mConnections.values().iterator();
-                    while (iter.hasNext()) {
+                    while (iter.hasNext()){
                         ConnectionRecord connection = iter.next();
                         try {
                             connection.callbacks.onConnect(connection.root.getRootId(), token,
@@ -240,8 +233,7 @@
                             for (Pair<IBinder, Bundle> callback : callbackList) {
                                 if (MediaBrowserCompatUtils.hasDuplicatedItems(
                                         options, callback.second)) {
-                                    performLoadChildren(parentId, connection, callback.second,
-                                            options);
+                                    performLoadChildren(parentId, connection, callback.second);
                                 }
                             }
                         }
@@ -254,33 +246,10 @@
         public Bundle getBrowserRootHints() {
             if (mCurConnection == null) {
                 throw new IllegalStateException("This should be called inside of onLoadChildren,"
-                        + " onLoadItem, onSearch, or onCustomAction methods");
+                        + " onLoadItem or onSearch methods");
             }
             return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints);
         }
-
-        @Override
-        public RemoteUserInfo getCurrentBrowserInfo() {
-            if (mCurConnection == null) {
-                throw new IllegalStateException("This should be called inside of onLoadChildren,"
-                        + " onLoadItem, onSearch, or onCustomAction methods");
-            }
-            return mCurConnection.browserInfo;
-        }
-
-        @Override
-        public List<RemoteUserInfo> getSubscribingBrowsers(String parentId) {
-            List<RemoteUserInfo> result = new ArrayList<>();
-            for (IBinder binder : mConnections.keySet()) {
-                ConnectionRecord connection = mConnections.get(binder);
-                List<Pair<IBinder, Bundle>> callbackList =
-                        connection.subscriptions.get(parentId);
-                if (callbackList != null) {
-                    result.add(connection.browserInfo);
-                }
-            }
-            return result;
-        }
     }
 
     @RequiresApi(21)
@@ -329,6 +298,19 @@
         }
 
         @Override
+        public Bundle getBrowserRootHints() {
+            if (mMessenger == null) {
+                // TODO: Handle getBrowserRootHints when connected with framework MediaBrowser.
+                return null;
+            }
+            if (mCurConnection == null) {
+                throw new IllegalStateException("This should be called inside of onLoadChildren,"
+                        + " onLoadItem or onSearch methods");
+            }
+            return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints);
+        }
+
+        @Override
         public MediaBrowserServiceCompatApi21.BrowserRoot onGetRoot(
                 String clientPackageName, int clientUid, Bundle rootHints) {
             Bundle rootExtras = null;
@@ -346,13 +328,8 @@
                     mRootExtrasList.add(rootExtras);
                 }
             }
-            // We aren't sure whether this connection request would be accepted.
-            // Temporarily set mCurConnection just to make getCurrentBrowserInfo() working.
-            mCurConnection = new ConnectionRecord(clientPackageName, -1, clientUid, rootHints,
-                    null);
             BrowserRoot root = MediaBrowserServiceCompat.this.onGetRoot(
                     clientPackageName, clientUid, rootHints);
-            mCurConnection = null;
             if (root == null) {
                 return null;
             }
@@ -392,20 +369,6 @@
             MediaBrowserServiceCompat.this.onLoadChildren(parentId, result);
         }
 
-        @Override
-        public List<RemoteUserInfo> getSubscribingBrowsers(String parentId) {
-            List<RemoteUserInfo> result = new ArrayList<>();
-            for (IBinder binder : mConnections.keySet()) {
-                ConnectionRecord connection = mConnections.get(binder);
-                List<Pair<IBinder, Bundle>> callbackList =
-                        connection.subscriptions.get(parentId);
-                if (callbackList != null) {
-                    result.add(connection.browserInfo);
-                }
-            }
-            return result;
-        }
-
         void notifyChildrenChangedForFramework(final String parentId, final Bundle options) {
             MediaBrowserServiceCompatApi21.notifyChildrenChanged(mServiceObj, parentId);
         }
@@ -422,8 +385,7 @@
                             for (Pair<IBinder, Bundle> callback : callbackList) {
                                 if (MediaBrowserCompatUtils.hasDuplicatedItems(
                                         options, callback.second)) {
-                                    performLoadChildren(parentId, connection, callback.second,
-                                            options);
+                                    performLoadChildren(parentId, connection, callback.second);
                                 }
                             }
                         }
@@ -431,28 +393,6 @@
                 }
             });
         }
-
-        @Override
-        public Bundle getBrowserRootHints() {
-            if (mMessenger == null) {
-                // TODO: Handle getBrowserRootHints when connected with framework MediaBrowser.
-                return null;
-            }
-            if (mCurConnection == null) {
-                throw new IllegalStateException("This should be called inside of onGetRoot,"
-                        + " onLoadChildren, onLoadItem, onSearch, or onCustomAction methods");
-            }
-            return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints);
-        }
-
-        @Override
-        public RemoteUserInfo getCurrentBrowserInfo() {
-            if (mCurConnection == null) {
-                throw new IllegalStateException("This should be called inside of onGetRoot,"
-                        + " onLoadChildren, onLoadItem, onSearch, or onCustomAction methods");
-            }
-            return mCurConnection.browserInfo;
-        }
     }
 
     @RequiresApi(23)
@@ -529,7 +469,7 @@
 
         @Override
         public Bundle getBrowserRootHints() {
-            // mCurConnection is not null when EXTRA_MESSENGER_BINDER is used.
+            // If EXTRA_MESSENGER_BINDER is used, mCurConnection is not null.
             if (mCurConnection != null) {
                 return mCurConnection.rootHints == null ? null
                         : new Bundle(mCurConnection.rootHints);
@@ -548,21 +488,6 @@
         }
     }
 
-    @RequiresApi(28)
-    class MediaBrowserServiceImplApi28 extends MediaBrowserServiceImplApi26 {
-        @Override
-        public RemoteUserInfo getCurrentBrowserInfo() {
-            // mCurConnection is not null when EXTRA_MESSENGER_BINDER is used.
-            if (mCurConnection != null) {
-                return mCurConnection.browserInfo;
-            }
-            android.media.session.MediaSessionManager.RemoteUserInfo userInfoObj =
-                    ((MediaBrowserService) mServiceObj).getCurrentBrowserInfo();
-            return new RemoteUserInfo(
-                    userInfoObj.getPackageName(), userInfoObj.getPid(), userInfoObj.getUid());
-        }
-    }
-
     private final class ServiceHandler extends Handler {
         private final ServiceBinderImpl mServiceBinderImpl = new ServiceBinderImpl();
 
@@ -575,8 +500,7 @@
             switch (msg.what) {
                 case CLIENT_MSG_CONNECT:
                     mServiceBinderImpl.connect(data.getString(DATA_PACKAGE_NAME),
-                            data.getInt(DATA_CALLING_PID), data.getInt(DATA_CALLING_UID),
-                            data.getBundle(DATA_ROOT_HINTS),
+                            data.getInt(DATA_CALLING_UID), data.getBundle(DATA_ROOT_HINTS),
                             new ServiceCallbacksCompat(msg.replyTo));
                     break;
                 case CLIENT_MSG_DISCONNECT:
@@ -600,8 +524,7 @@
                     break;
                 case CLIENT_MSG_REGISTER_CALLBACK_MESSENGER:
                     mServiceBinderImpl.registerCallbacks(new ServiceCallbacksCompat(msg.replyTo),
-                            data.getString(DATA_PACKAGE_NAME), data.getInt(DATA_CALLING_PID),
-                            data.getInt(DATA_CALLING_UID), data.getBundle(DATA_ROOT_HINTS));
+                            data.getBundle(DATA_ROOT_HINTS));
                     break;
                 case CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER:
                     mServiceBinderImpl.unregisterCallbacks(new ServiceCallbacksCompat(msg.replyTo));
@@ -632,7 +555,6 @@
             Bundle data = msg.getData();
             data.setClassLoader(MediaBrowserCompat.class.getClassLoader());
             data.putInt(DATA_CALLING_UID, Binder.getCallingUid());
-            data.putInt(DATA_CALLING_PID, Binder.getCallingPid());
             return super.sendMessageAtTime(msg, uptimeMillis);
         }
 
@@ -649,23 +571,13 @@
      * All the info about a connection.
      */
     private class ConnectionRecord implements IBinder.DeathRecipient {
-        public final String pkg;
-        public final int pid;
-        public final int uid;
-        public final RemoteUserInfo browserInfo;
-        public final Bundle rootHints;
-        public final ServiceCallbacks callbacks;
-        public final HashMap<String, List<Pair<IBinder, Bundle>>> subscriptions = new HashMap<>();
-        public BrowserRoot root;
+        String pkg;
+        Bundle rootHints;
+        ServiceCallbacks callbacks;
+        BrowserRoot root;
+        HashMap<String, List<Pair<IBinder, Bundle>>> subscriptions = new HashMap<>();
 
-        ConnectionRecord(String pkg, int pid, int uid, Bundle rootHints,
-                ServiceCallbacks callback) {
-            this.pkg = pkg;
-            this.pid = pid;
-            this.uid = uid;
-            this.browserInfo = new RemoteUserInfo(pkg, pid, uid);
-            this.rootHints = rootHints;
-            this.callbacks = callback;
+        ConnectionRecord() {
         }
 
         @Override
@@ -828,7 +740,7 @@
         ServiceBinderImpl() {
         }
 
-        public void connect(final String pkg, final int pid, final int uid, final Bundle rootHints,
+        public void connect(final String pkg, final int uid, final Bundle rootHints,
                 final ServiceCallbacks callbacks) {
 
             if (!isValidPackage(pkg, uid)) {
@@ -844,11 +756,13 @@
                     // Clear out the old subscriptions. We are getting new ones.
                     mConnections.remove(b);
 
-                    final ConnectionRecord connection = new ConnectionRecord(pkg, pid, uid,
-                            rootHints, callbacks);
-                    mCurConnection = connection;
-                    connection.root = MediaBrowserServiceCompat.this.onGetRoot(pkg, uid, rootHints);
-                    mCurConnection = null;
+                    final ConnectionRecord connection = new ConnectionRecord();
+                    connection.pkg = pkg;
+                    connection.rootHints = rootHints;
+                    connection.callbacks = callbacks;
+
+                    connection.root =
+                            MediaBrowserServiceCompat.this.onGetRoot(pkg, uid, rootHints);
 
                     // If they didn't return something, don't allow this client.
                     if (connection.root == null) {
@@ -958,8 +872,7 @@
         }
 
         // Used when {@link MediaBrowserProtocol#EXTRA_MESSENGER_BINDER} is used.
-        public void registerCallbacks(final ServiceCallbacks callbacks, final String pkg,
-                final int pid, final int uid, final Bundle rootHints) {
+        public void registerCallbacks(final ServiceCallbacks callbacks, final Bundle rootHints) {
             mHandler.postOrRun(new Runnable() {
                 @Override
                 public void run() {
@@ -967,8 +880,9 @@
                     // Clear out the old subscriptions. We are getting new ones.
                     mConnections.remove(b);
 
-                    final ConnectionRecord connection = new ConnectionRecord(pkg, pid, uid,
-                            rootHints, callbacks);
+                    final ConnectionRecord connection = new ConnectionRecord();
+                    connection.callbacks = callbacks;
+                    connection.rootHints = rootHints;
                     mConnections.put(b, connection);
                     try {
                         b.linkToDeath(connection, 0);
@@ -1042,8 +956,8 @@
         void onConnect(String root, MediaSessionCompat.Token session, Bundle extras)
                 throws RemoteException;
         void onConnectFailed() throws RemoteException;
-        void onLoadChildren(String mediaId, List<MediaBrowserCompat.MediaItem> list, Bundle options,
-                Bundle notifyChildrenChangedOptions) throws RemoteException;
+        void onLoadChildren(String mediaId, List<MediaBrowserCompat.MediaItem> list, Bundle options)
+                throws RemoteException;
     }
 
     private static class ServiceCallbacksCompat implements ServiceCallbacks {
@@ -1079,11 +993,10 @@
 
         @Override
         public void onLoadChildren(String mediaId, List<MediaBrowserCompat.MediaItem> list,
-                Bundle options, Bundle notifyChildrenChangedOptions) throws RemoteException {
+                Bundle options) throws RemoteException {
             Bundle data = new Bundle();
             data.putString(DATA_MEDIA_ITEM_ID, mediaId);
             data.putBundle(DATA_OPTIONS, options);
-            data.putBundle(DATA_NOTIFY_CHILDREN_CHANGED_OPTIONS, notifyChildrenChangedOptions);
             if (list != null) {
                 data.putParcelableArrayList(DATA_MEDIA_ITEM_LIST,
                         list instanceof ArrayList ? (ArrayList) list : new ArrayList<>(list));
@@ -1118,9 +1031,7 @@
     @Override
     public void onCreate() {
         super.onCreate();
-        if (Build.VERSION.SDK_INT >= 28) {
-            mImpl = new MediaBrowserServiceImplApi28();
-        } else if (Build.VERSION.SDK_INT >= 26) {
+        if (Build.VERSION.SDK_INT >= 26) {
             mImpl = new MediaBrowserServiceImplApi26();
         } else if (Build.VERSION.SDK_INT >= 23) {
             mImpl = new MediaBrowserServiceImplApi23();
@@ -1342,17 +1253,6 @@
     }
 
     /**
-     * Gets the browser information who sent the current request.
-     *
-     * @throws IllegalStateException If this method is called outside of {@link #onGetRoot} or
-     *             {@link #onLoadChildren} or {@link #onLoadItem}.
-     * @see MediaSessionManager#isTrustedForMediaControl(RemoteUserInfo)
-     */
-    public final @NonNull RemoteUserInfo getCurrentBrowserInfo() {
-        return mImpl.getCurrentBrowserInfo();
-    }
-
-    /**
      * Notifies all connected media browsers that the children of
      * the specified parent id have changed in some way.
      * This will cause browsers to fetch subscribed content again.
@@ -1389,18 +1289,6 @@
     }
 
     /**
-     * Gets {@link RemoteUserInfo} of all browsers which are subscribing to the given parentId.
-     * @hide
-     */
-    @RestrictTo(LIBRARY)
-    public @NonNull List<RemoteUserInfo> getSubscribingBrowsers(@NonNull String parentId) {
-        if (parentId == null) {
-            throw new IllegalArgumentException("parentId cannot be null in getSubscribingBrowsers");
-        }
-        return mImpl.getSubscribingBrowsers(parentId);
-    }
-
-    /**
      * Return whether the given package is one of the ones that is owned by the uid.
      */
     boolean isValidPackage(String pkg, int uid) {
@@ -1437,7 +1325,7 @@
         callbackList.add(new Pair<>(token, options));
         connection.subscriptions.put(id, callbackList);
         // send the results
-        performLoadChildren(id, connection, options, null);
+        performLoadChildren(id, connection, options);
     }
 
     /**
@@ -1470,7 +1358,7 @@
      * Callers must make sure that this connection is still connected.
      */
     void performLoadChildren(final String parentId, final ConnectionRecord connection,
-            final Bundle subscribeOptions, final Bundle notifyChildrenChangedOptions) {
+            final Bundle options) {
         final Result<List<MediaBrowserCompat.MediaItem>> result
                 = new Result<List<MediaBrowserCompat.MediaItem>>(parentId) {
             @Override
@@ -1485,10 +1373,9 @@
 
                 List<MediaBrowserCompat.MediaItem> filteredList =
                         (getFlags() & RESULT_FLAG_OPTION_NOT_HANDLED) != 0
-                                ? applyOptions(list, subscribeOptions) : list;
+                                ? applyOptions(list, options) : list;
                 try {
-                    connection.callbacks.onLoadChildren(parentId, filteredList, subscribeOptions,
-                            notifyChildrenChangedOptions);
+                    connection.callbacks.onLoadChildren(parentId, filteredList, options);
                 } catch (RemoteException ex) {
                     // The other side is in the process of crashing.
                     Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId
@@ -1498,10 +1385,10 @@
         };
 
         mCurConnection = connection;
-        if (subscribeOptions == null) {
+        if (options == null) {
             onLoadChildren(parentId, result);
         } else {
-            onLoadChildren(parentId, result, subscribeOptions);
+            onLoadChildren(parentId, result, options);
         }
         mCurConnection = null;
 
diff --git a/media/src/main/java/androidx/media/MediaConstants2.java b/media/src/main/java/androidx/media/MediaConstants2.java
index 1fec6db..68a9a19 100644
--- a/media/src/main/java/androidx/media/MediaConstants2.java
+++ b/media/src/main/java/androidx/media/MediaConstants2.java
@@ -33,10 +33,8 @@
             "androidx.media.session.event.ON_PLAYBACK_INFO_CHANGED";
     static final String SESSION_EVENT_ON_PLAYBACK_SPEED_CHANGED =
             "androidx.media.session.event.ON_PLAYBACK_SPEED_CHANGED";
-    static final String SESSION_EVENT_ON_BUFFERING_STATE_CHANGED =
+    static final String SESSION_EVENT_ON_BUFFERING_STATE_CHAGNED =
             "androidx.media.session.event.ON_BUFFERING_STATE_CHANGED";
-    static final String SESSION_EVENT_ON_SEEK_COMPLETED =
-            "androidx.media.session.event.ON_SEEK_COMPLETED";
     static final String SESSION_EVENT_ON_REPEAT_MODE_CHANGED =
             "androidx.media.session.event.ON_REPEAT_MODE_CHANGED";
     static final String SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED =
@@ -47,10 +45,6 @@
             "androidx.media.session.event.ON_PLAYLIST_METADATA_CHANGED";
     static final String SESSION_EVENT_ON_ALLOWED_COMMANDS_CHANGED =
             "androidx.media.session.event.ON_ALLOWED_COMMANDS_CHANGED";
-    static final String SESSION_EVENT_ON_CHILDREN_CHANGED =
-            "androidx.media.session.event.ON_CHILDREN_CHANGED";
-    static final String SESSION_EVENT_ON_SEARCH_RESULT_CHANGED =
-            "androidx.media.session.event.ON_SEARCH_RESULT_CHANGED";
     static final String SESSION_EVENT_SEND_CUSTOM_COMMAND =
             "androidx.media.session.event.SEND_CUSTOM_COMMAND";
     static final String SESSION_EVENT_SET_CUSTOM_LAYOUT =
@@ -95,9 +89,6 @@
     static final String ARGUMENT_COMMAND_BUTTONS = "androidx.media.argument.COMMAND_BUTTONS";
     static final String ARGUMENT_ROUTE_BUNDLE = "androidx.media.argument.ROUTE_BUNDLE";
     static final String ARGUMENT_PLAYBACK_INFO = "androidx.media.argument.PLAYBACK_INFO";
-    static final String ARGUMENT_ITEM_COUNT = "androidx.media.argument.ITEM_COUNT";
-    static final String ARGUMENT_PAGE = "androidx.media.argument.PAGE";
-    static final String ARGUMENT_PAGE_SIZE = "androidx.media.argument.PAGE_SIZE";
 
     static final String ARGUMENT_ICONTROLLER_CALLBACK =
             "androidx.media.argument.ICONTROLLER_CALLBACK";
diff --git a/media/src/main/java/androidx/media/MediaController2.java b/media/src/main/java/androidx/media/MediaController2.java
index 5d81cc2..1da552d 100644
--- a/media/src/main/java/androidx/media/MediaController2.java
+++ b/media/src/main/java/androidx/media/MediaController2.java
@@ -16,7 +16,93 @@
 
 package androidx.media;
 
+import static android.support.v4.media.MediaMetadataCompat.METADATA_KEY_DURATION;
+
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+import static androidx.media.MediaConstants2.ARGUMENT_ALLOWED_COMMANDS;
+import static androidx.media.MediaConstants2.ARGUMENT_ARGUMENTS;
+import static androidx.media.MediaConstants2.ARGUMENT_BUFFERING_STATE;
+import static androidx.media.MediaConstants2.ARGUMENT_COMMAND_BUTTONS;
+import static androidx.media.MediaConstants2.ARGUMENT_COMMAND_CODE;
+import static androidx.media.MediaConstants2.ARGUMENT_CUSTOM_COMMAND;
+import static androidx.media.MediaConstants2.ARGUMENT_ERROR_CODE;
+import static androidx.media.MediaConstants2.ARGUMENT_EXTRAS;
+import static androidx.media.MediaConstants2.ARGUMENT_ICONTROLLER_CALLBACK;
+import static androidx.media.MediaConstants2.ARGUMENT_MEDIA_ID;
+import static androidx.media.MediaConstants2.ARGUMENT_MEDIA_ITEM;
+import static androidx.media.MediaConstants2.ARGUMENT_PACKAGE_NAME;
+import static androidx.media.MediaConstants2.ARGUMENT_PID;
+import static androidx.media.MediaConstants2.ARGUMENT_PLAYBACK_INFO;
+import static androidx.media.MediaConstants2.ARGUMENT_PLAYBACK_SPEED;
+import static androidx.media.MediaConstants2.ARGUMENT_PLAYBACK_STATE_COMPAT;
+import static androidx.media.MediaConstants2.ARGUMENT_PLAYER_STATE;
+import static androidx.media.MediaConstants2.ARGUMENT_PLAYLIST;
+import static androidx.media.MediaConstants2.ARGUMENT_PLAYLIST_INDEX;
+import static androidx.media.MediaConstants2.ARGUMENT_PLAYLIST_METADATA;
+import static androidx.media.MediaConstants2.ARGUMENT_QUERY;
+import static androidx.media.MediaConstants2.ARGUMENT_RATING;
+import static androidx.media.MediaConstants2.ARGUMENT_REPEAT_MODE;
+import static androidx.media.MediaConstants2.ARGUMENT_RESULT_RECEIVER;
+import static androidx.media.MediaConstants2.ARGUMENT_ROUTE_BUNDLE;
+import static androidx.media.MediaConstants2.ARGUMENT_SEEK_POSITION;
+import static androidx.media.MediaConstants2.ARGUMENT_SHUFFLE_MODE;
+import static androidx.media.MediaConstants2.ARGUMENT_UID;
+import static androidx.media.MediaConstants2.ARGUMENT_URI;
+import static androidx.media.MediaConstants2.ARGUMENT_VOLUME;
+import static androidx.media.MediaConstants2.ARGUMENT_VOLUME_DIRECTION;
+import static androidx.media.MediaConstants2.ARGUMENT_VOLUME_FLAGS;
+import static androidx.media.MediaConstants2.CONNECT_RESULT_CONNECTED;
+import static androidx.media.MediaConstants2.CONNECT_RESULT_DISCONNECTED;
+import static androidx.media.MediaConstants2.CONTROLLER_COMMAND_BY_COMMAND_CODE;
+import static androidx.media.MediaConstants2.CONTROLLER_COMMAND_BY_CUSTOM_COMMAND;
+import static androidx.media.MediaConstants2.CONTROLLER_COMMAND_CONNECT;
+import static androidx.media.MediaConstants2.CONTROLLER_COMMAND_DISCONNECT;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ALLOWED_COMMANDS_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_BUFFERING_STATE_CHAGNED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_CURRENT_MEDIA_ITEM_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ERROR;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYBACK_INFO_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYBACK_SPEED_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYER_STATE_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_REPEAT_MODE_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ROUTES_INFO_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_SEND_CUSTOM_COMMAND;
+import static androidx.media.MediaConstants2.SESSION_EVENT_SET_CUSTOM_LAYOUT;
+import static androidx.media.MediaPlayerBase.BUFFERING_STATE_UNKNOWN;
+import static androidx.media.MediaPlayerBase.UNKNOWN_TIME;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PREPARE;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_RESET;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_SEEK_TO;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_SET_SPEED;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_ADD_ITEM;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_REMOVE_ITEM;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_REPLACE_ITEM;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_LIST;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_LIST_METADATA;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_REPEAT_MODE;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_SHUFFLE_MODE;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_TO_NEXT_ITEM;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM;
+import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_TO_PREV_ITEM;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_FAST_FORWARD;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_SEARCH;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_URI;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_URI;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_REWIND;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SELECT_ROUTE;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SET_RATING;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SUBSCRIBE_ROUTES_INFO;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_UNSUBSCRIBE_ROUTES_INFO;
+import static androidx.media.SessionCommand2.COMMAND_CODE_VOLUME_ADJUST_VOLUME;
+import static androidx.media.SessionCommand2.COMMAND_CODE_VOLUME_SET_VOLUME;
 
 import android.annotation.TargetApi;
 import android.app.PendingIntent;
@@ -25,14 +111,25 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.SystemClock;
 import android.support.v4.media.MediaBrowserCompat;
+import android.support.v4.media.MediaMetadataCompat;
+import android.support.v4.media.session.MediaControllerCompat;
+import android.support.v4.media.session.MediaSessionCompat;
+import android.support.v4.media.session.PlaybackStateCompat;
+import android.util.Log;
 
+import androidx.annotation.GuardedBy;
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
-import androidx.annotation.VisibleForTesting;
 import androidx.media.MediaPlaylistAgent.RepeatMode;
 import androidx.media.MediaPlaylistAgent.ShuffleMode;
 import androidx.media.MediaSession2.CommandButton;
@@ -45,9 +142,8 @@
 import java.util.concurrent.Executor;
 
 /**
- * Allows an app to interact with an active {@link MediaSession2} or a
- * {@link MediaSessionService2} in any status. Media buttons and other commands can be sent to
- * the session.
+ * Allows an app to interact with an active {@link MediaSession2} in any status. Media buttons and
+ * other commands can be sent to the session.
  * <p>
  * When you're done, use {@link #close()} to clean up resources. This also helps session service
  * to be destroyed when there's no controller associated with it.
@@ -55,16 +151,9 @@
  * When controlling {@link MediaSession2}, the controller will be available immediately after
  * the creation.
  * <p>
- * When controlling {@link MediaSessionService2}, the {@link MediaController2} would be
- * available only if the session service allows this controller by
- * {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)} for the service.
- * Wait {@link ControllerCallback#onConnected(MediaController2, SessionCommandGroup2)} or
- * {@link ControllerCallback#onDisconnected(MediaController2)} for the result.
- * <p>
  * MediaController2 objects are thread-safe.
  * <p>
  * @see MediaSession2
- * @see MediaSessionService2
  */
 @TargetApi(Build.VERSION_CODES.KITKAT)
 public class MediaController2 implements AutoCloseable {
@@ -87,657 +176,6 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface VolumeFlags {}
 
-    private final SupportLibraryImpl mImpl;
-    // For testing.
-    Long mTimeDiff;
-
-    /**
-     * Create a {@link MediaController2} from the {@link SessionToken2}.
-     * This connects to the session and may wake up the service if it's not available.
-     *
-     * @param context Context
-     * @param token token to connect to
-     * @param executor executor to run callbacks on.
-     * @param callback controller callback to receive changes in
-     */
-    public MediaController2(@NonNull Context context, @NonNull SessionToken2 token,
-            @NonNull Executor executor, @NonNull ControllerCallback callback) {
-        mImpl = new MediaController2ImplBase(context, token, executor, callback);
-        mImpl.setInstance(this);
-    }
-
-    /**
-     * Release this object, and disconnect from the session. After this, callbacks wouldn't be
-     * received.
-     */
-    @Override
-    public void close() {
-        try {
-            mImpl.close();
-        } catch (Exception e) {
-            // Should not be here.
-        }
-    }
-
-    /**
-     * @return token
-     */
-    public @NonNull SessionToken2 getSessionToken() {
-        return mImpl.getSessionToken();
-    }
-
-    /**
-     * Returns whether this class is connected to active {@link MediaSession2} or not.
-     */
-    public boolean isConnected() {
-        return mImpl.isConnected();
-    }
-
-    /**
-     * Requests that the player starts or resumes playback.
-     */
-    public void play() {
-        mImpl.play();
-    }
-
-    /**
-     * Requests that the player pauses playback.
-     */
-    public void pause() {
-        mImpl.pause();
-    }
-
-    /**
-     * Requests that the player be reset to its uninitialized state.
-     */
-    public void reset() {
-        mImpl.reset();
-    }
-
-    /**
-     * Request that the player prepare its playback. In other words, other sessions can continue
-     * to play during the preparation of this session. This method can be used to speed up the
-     * start of the playback. Once the preparation is done, the session will change its playback
-     * state to {@link MediaPlayerInterface#PLAYER_STATE_PAUSED}. Afterwards, {@link #play} can be
-     * called to start playback.
-     */
-    public void prepare() {
-        mImpl.prepare();
-    }
-
-    /**
-     * Start fast forwarding. If playback is already fast forwarding this
-     * may increase the rate.
-     */
-    public void fastForward() {
-        mImpl.fastForward();
-    }
-
-    /**
-     * Start rewinding. If playback is already rewinding this may increase
-     * the rate.
-     */
-    public void rewind() {
-        mImpl.rewind();
-    }
-
-    /**
-     * Move to a new location in the media stream.
-     *
-     * @param pos Position to move to, in milliseconds.
-     */
-    public void seekTo(long pos) {
-        mImpl.seekTo(pos);
-    }
-
-    /**
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    public void skipForward() {
-        // To match with KEYCODE_MEDIA_SKIP_FORWARD
-        mImpl.skipForward();
-    }
-
-    /**
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    public void skipBackward() {
-        // To match with KEYCODE_MEDIA_SKIP_BACKWARD
-        mImpl.skipBackward();
-    }
-
-    /**
-     * Request that the player start playback for a specific media id.
-     *
-     * @param mediaId The id of the requested media.
-     * @param extras Optional extras that can include extra information about the media item
-     *               to be played.
-     */
-    public void playFromMediaId(@NonNull String mediaId, @Nullable Bundle extras) {
-        mImpl.playFromMediaId(mediaId, extras);
-    }
-
-    /**
-     * Request that the player start playback for a specific search query.
-     *
-     * @param query The search query. Should not be an empty string.
-     * @param extras Optional extras that can include extra information about the query.
-     */
-    public void playFromSearch(@NonNull String query, @Nullable Bundle extras) {
-        mImpl.playFromSearch(query, extras);
-    }
-
-    /**
-     * Request that the player start playback for a specific {@link Uri}.
-     *
-     * @param uri The URI of the requested media.
-     * @param extras Optional extras that can include extra information about the media item
-     *               to be played.
-     */
-    public void playFromUri(@NonNull Uri uri, @Nullable Bundle extras) {
-        mImpl.playFromUri(uri, extras);
-    }
-
-    /**
-     * Request that the player prepare playback for a specific media id. In other words, other
-     * sessions can continue to play during the preparation of this session. This method can be
-     * used to speed up the start of the playback. Once the preparation is done, the session
-     * will change its playback state to {@link MediaPlayerInterface#PLAYER_STATE_PAUSED}.
-     * Afterwards, {@link #play} can be called to start playback. If the preparation is not needed,
-     * {@link #playFromMediaId} can be directly called without this method.
-     *
-     * @param mediaId The id of the requested media.
-     * @param extras Optional extras that can include extra information about the media item
-     *               to be prepared.
-     */
-    public void prepareFromMediaId(@NonNull String mediaId, @Nullable Bundle extras) {
-        mImpl.prepareFromMediaId(mediaId, extras);
-    }
-
-    /**
-     * Request that the player prepare playback for a specific search query.
-     * In other words, other sessions can continue to play during the preparation of this session.
-     * This method can be used to speed up the start of the playback.
-     * Once the preparation is done, the session will change its playback state to
-     * {@link MediaPlayerInterface#PLAYER_STATE_PAUSED}. Afterwards,
-     * {@link #play} can be called to start playback. If the preparation is not needed,
-     * {@link #playFromSearch} can be directly called without this method.
-     *
-     * @param query The search query. Should not be an empty string.
-     * @param extras Optional extras that can include extra information about the query.
-     */
-    public void prepareFromSearch(@NonNull String query, @Nullable Bundle extras) {
-        mImpl.prepareFromSearch(query, extras);
-    }
-
-    /**
-     * Request that the player prepare playback for a specific {@link Uri}. In other words,
-     * other sessions can continue to play during the preparation of this session. This method
-     * can be used to speed up the start of the playback. Once the preparation is done, the
-     * session will change its playback state to {@link MediaPlayerInterface#PLAYER_STATE_PAUSED}.
-     * Afterwards, {@link #play} can be called to start playback. If the preparation is not needed,
-     * {@link #playFromUri} can be directly called without this method.
-     *
-     * @param uri The URI of the requested media.
-     * @param extras Optional extras that can include extra information about the media item
-     *               to be prepared.
-     */
-    public void prepareFromUri(@NonNull Uri uri, @Nullable Bundle extras) {
-        mImpl.prepareFromUri(uri, extras);
-    }
-
-    /**
-     * Set the volume of the output this session is playing on. The command will be ignored if it
-     * does not support {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}.
-     * <p>
-     * If the session is local playback, this changes the device's volume with the stream that
-     * session's player is using. Flags will be specified for the {@link AudioManager}.
-     * <p>
-     * If the session is remote player (i.e. session has set volume provider), its volume provider
-     * will receive this request instead.
-     *
-     * @see #getPlaybackInfo()
-     * @param value The value to set it to, between 0 and the reported max.
-     * @param flags flags from {@link AudioManager} to include with the volume request for local
-     *              playback
-     */
-    public void setVolumeTo(int value, @VolumeFlags int flags) {
-        mImpl.setVolumeTo(value, flags);
-    }
-
-    /**
-     * Adjust the volume of the output this session is playing on. The direction
-     * must be one of {@link AudioManager#ADJUST_LOWER},
-     * {@link AudioManager#ADJUST_RAISE}, or {@link AudioManager#ADJUST_SAME}.
-     * <p>
-     * The command will be ignored if the session does not support
-     * {@link VolumeProviderCompat#VOLUME_CONTROL_RELATIVE} or
-     * {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}.
-     * <p>
-     * If the session is local playback, this changes the device's volume with the stream that
-     * session's player is using. Flags will be specified for the {@link AudioManager}.
-     * <p>
-     * If the session is remote player (i.e. session has set volume provider), its volume provider
-     * will receive this request instead.
-     *
-     * @see #getPlaybackInfo()
-     * @param direction The direction to adjust the volume in.
-     * @param flags flags from {@link AudioManager} to include with the volume request for local
-     *              playback
-     */
-    public void adjustVolume(@VolumeDirection int direction, @VolumeFlags int flags) {
-        mImpl.adjustVolume(direction, flags);
-    }
-
-    /**
-     * Get an intent for launching UI associated with this session if one exists.
-     *
-     * @return A {@link PendingIntent} to launch UI or null.
-     */
-    public @Nullable PendingIntent getSessionActivity() {
-        return mImpl.getSessionActivity();
-    }
-
-    /**
-     * Get the lastly cached player state from
-     * {@link ControllerCallback#onPlayerStateChanged(MediaController2, int)}.
-     *
-     * @return player state
-     */
-    public int getPlayerState() {
-        return mImpl.getPlayerState();
-    }
-
-    /**
-     * Gets the duration of the current media item, or {@link MediaPlayerInterface#UNKNOWN_TIME} if
-     * unknown.
-     * @return the duration in ms, or {@link MediaPlayerInterface#UNKNOWN_TIME}.
-     */
-    public long getDuration() {
-        return mImpl.getDuration();
-    }
-
-    /**
-     * Gets the current playback position.
-     * <p>
-     * This returns the calculated value of the position, based on the difference between the
-     * update time and current time.
-     *
-     * @return position
-     */
-    public long getCurrentPosition() {
-        return mImpl.getCurrentPosition();
-    }
-
-    /**
-     * Get the lastly cached playback speed from
-     * {@link ControllerCallback#onPlaybackSpeedChanged(MediaController2, float)}.
-     *
-     * @return speed the lastly cached playback speed, or 0.0f if unknown.
-     */
-    public float getPlaybackSpeed() {
-        return mImpl.getPlaybackSpeed();
-    }
-
-    /**
-     * Set the playback speed.
-     */
-    public void setPlaybackSpeed(float speed) {
-        mImpl.setPlaybackSpeed(speed);
-    }
-
-    /**
-     * Gets the current buffering state of the player.
-     * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already
-     * buffered.
-     * @return the buffering state.
-     */
-    public @MediaPlayerInterface.BuffState int getBufferingState() {
-        return mImpl.getBufferingState();
-    }
-
-    /**
-     * Gets the lastly cached buffered position from the session when
-     * {@link ControllerCallback#onBufferingStateChanged(MediaController2, MediaItem2, int)} is
-     * called.
-     *
-     * @return buffering position in millis, or {@link MediaPlayerInterface#UNKNOWN_TIME} if
-     * unknown.
-     */
-    public long getBufferedPosition() {
-        return mImpl.getBufferedPosition();
-    }
-
-    /**
-     * Get the current playback info for this session.
-     *
-     * @return The current playback info or null.
-     */
-    public @Nullable PlaybackInfo getPlaybackInfo() {
-        return mImpl.getPlaybackInfo();
-    }
-
-    /**
-     * Rate the media. This will cause the rating to be set for the current user.
-     * The rating style must follow the user rating style from the session.
-     * You can get the rating style from the session through the
-     * {@link MediaMetadata2#getRating(String)} with the key
-     * {@link MediaMetadata2#METADATA_KEY_USER_RATING}.
-     * <p>
-     * If the user rating was {@code null}, the media item does not accept setting user rating.
-     *
-     * @param mediaId The id of the media
-     * @param rating The rating to set
-     */
-    public void setRating(@NonNull String mediaId, @NonNull Rating2 rating) {
-        mImpl.setRating(mediaId, rating);
-    }
-
-    /**
-     * Send custom command to the session
-     *
-     * @param command custom command
-     * @param args optional argument
-     * @param cb optional result receiver
-     */
-    public void sendCustomCommand(@NonNull SessionCommand2 command, @Nullable Bundle args,
-            @Nullable ResultReceiver cb) {
-        mImpl.sendCustomCommand(command, args, cb);
-    }
-
-    /**
-     * Returns the cached playlist from {@link ControllerCallback#onPlaylistChanged}.
-     * <p>
-     * This list may differ with the list that was specified with
-     * {@link #setPlaylist(List, MediaMetadata2)} depending on the {@link MediaPlaylistAgent}
-     * implementation. Use media items returned here for other playlist agent APIs such as
-     * {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)}.
-     *
-     * @return playlist. Can be {@code null} if the playlist hasn't set nor controller doesn't have
-     *      enough permission.
-     * @see SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST
-     */
-    public @Nullable List<MediaItem2> getPlaylist() {
-        return mImpl.getPlaylist();
-    }
-
-    /**
-     * Sets the playlist.
-     * <p>
-     * Even when the playlist is successfully set, use the playlist returned from
-     * {@link #getPlaylist()} for playlist APIs such as {@link #skipToPlaylistItem(MediaItem2)}.
-     * Otherwise the session in the remote process can't distinguish between media items.
-     *
-     * @param list playlist
-     * @param metadata metadata of the playlist
-     * @see #getPlaylist()
-     * @see ControllerCallback#onPlaylistChanged
-     */
-    public void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) {
-        mImpl.setPlaylist(list, metadata);
-    }
-
-    /**
-     * Updates the playlist metadata
-     *
-     * @param metadata metadata of the playlist
-     */
-    public void updatePlaylistMetadata(@Nullable MediaMetadata2 metadata) {
-        mImpl.updatePlaylistMetadata(metadata);
-    }
-
-    /**
-     * Gets the lastly cached playlist playlist metadata either from
-     * {@link ControllerCallback#onPlaylistMetadataChanged or
-     * {@link ControllerCallback#onPlaylistChanged}.
-     *
-     * @return metadata metadata of the playlist, or null if none is set
-     */
-    public @Nullable MediaMetadata2 getPlaylistMetadata() {
-        return mImpl.getPlaylistMetadata();
-    }
-
-    /**
-     * Adds the media item to the playlist at position index. Index equals or greater than
-     * the current playlist size (e.g. {@link Integer#MAX_VALUE}) will add the item at the end of
-     * the playlist.
-     * <p>
-     * This will not change the currently playing media item.
-     * If index is less than or equal to the current index of the playlist,
-     * the current index of the playlist will be incremented correspondingly.
-     *
-     * @param index the index you want to add
-     * @param item the media item you want to add
-     */
-    public void addPlaylistItem(int index, @NonNull MediaItem2 item) {
-        mImpl.addPlaylistItem(index, item);
-    }
-
-    /**
-     * Removes the media item at index in the playlist.
-     *<p>
-     * If the item is the currently playing item of the playlist, current playback
-     * will be stopped and playback moves to next source in the list.
-     *
-     * @param item the media item you want to add
-     */
-    public void removePlaylistItem(@NonNull MediaItem2 item) {
-        mImpl.removePlaylistItem(item);
-    }
-
-    /**
-     * Replace the media item at index in the playlist. This can be also used to update metadata of
-     * an item.
-     *
-     * @param index the index of the item to replace
-     * @param item the new item
-     */
-    public void replacePlaylistItem(int index, @NonNull MediaItem2 item) {
-        mImpl.replacePlaylistItem(index, item);
-    }
-
-    /**
-     * Get the lastly cached current item from
-     * {@link ControllerCallback#onCurrentMediaItemChanged(MediaController2, MediaItem2)}.
-     *
-     * @return the currently playing item, or null if unknown.
-     */
-    public MediaItem2 getCurrentMediaItem() {
-        return mImpl.getCurrentMediaItem();
-    }
-
-    /**
-     * Skips to the previous item in the playlist.
-     * <p>
-     * This calls {@link MediaPlaylistAgent#skipToPreviousItem()}.
-     */
-    public void skipToPreviousItem() {
-        mImpl.skipToPreviousItem();
-    }
-
-    /**
-     * Skips to the next item in the playlist.
-     * <p>
-     * This calls {@link MediaPlaylistAgent#skipToNextItem()}.
-     */
-    public void skipToNextItem() {
-        mImpl.skipToNextItem();
-    }
-
-    /**
-     * Skips to the item in the playlist.
-     * <p>
-     * This calls {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)}.
-     *
-     * @param item The item in the playlist you want to play
-     */
-    public void skipToPlaylistItem(@NonNull MediaItem2 item) {
-        mImpl.skipToPlaylistItem(item);
-    }
-
-    /**
-     * Gets the cached repeat mode from the {@link ControllerCallback#onRepeatModeChanged}.
-     *
-     * @return repeat mode
-     * @see MediaPlaylistAgent#REPEAT_MODE_NONE
-     * @see MediaPlaylistAgent#REPEAT_MODE_ONE
-     * @see MediaPlaylistAgent#REPEAT_MODE_ALL
-     * @see MediaPlaylistAgent#REPEAT_MODE_GROUP
-     */
-    public @RepeatMode int getRepeatMode() {
-        return mImpl.getRepeatMode();
-    }
-
-    /**
-     * Sets the repeat mode.
-     *
-     * @param repeatMode repeat mode
-     * @see MediaPlaylistAgent#REPEAT_MODE_NONE
-     * @see MediaPlaylistAgent#REPEAT_MODE_ONE
-     * @see MediaPlaylistAgent#REPEAT_MODE_ALL
-     * @see MediaPlaylistAgent#REPEAT_MODE_GROUP
-     */
-    public void setRepeatMode(@RepeatMode int repeatMode) {
-        mImpl.setRepeatMode(repeatMode);
-    }
-
-    /**
-     * Gets the cached shuffle mode from the {@link ControllerCallback#onShuffleModeChanged}.
-     *
-     * @return The shuffle mode
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP
-     */
-    public @ShuffleMode int getShuffleMode() {
-        return mImpl.getShuffleMode();
-    }
-
-    /**
-     * Sets the shuffle mode.
-     *
-     * @param shuffleMode The shuffle mode
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP
-     */
-    public void setShuffleMode(@ShuffleMode int shuffleMode) {
-        mImpl.setShuffleMode(shuffleMode);
-    }
-
-    /**
-     * Queries for information about the routes currently known.
-     */
-    public void subscribeRoutesInfo() {
-        mImpl.subscribeRoutesInfo();
-    }
-
-    /**
-     * Unsubscribes for changes to the routes.
-     * <p>
-     * The {@link ControllerCallback#onRoutesInfoChanged callback} will no longer be invoked for
-     * the routes once this method returns.
-     * </p>
-     */
-    public void unsubscribeRoutesInfo() {
-        mImpl.unsubscribeRoutesInfo();
-    }
-
-    /**
-     * Selects the specified route.
-     *
-     * @param route The route to select.
-     */
-    public void selectRoute(@NonNull Bundle route) {
-        mImpl.selectRoute(route);
-    }
-
-    @NonNull Context getContext() {
-        return mImpl.getContext();
-    }
-
-    @NonNull ControllerCallback getCallback() {
-        return mImpl.getCallback();
-    }
-
-    @NonNull Executor getCallbackExecutor() {
-        return mImpl.getCallbackExecutor();
-    }
-
-    @Nullable MediaBrowserCompat getBrowserCompat() {
-        return mImpl.getBrowserCompat();
-    }
-
-    /**
-     * Sets the time diff forcefully when calculating current position.
-     * @param timeDiff {@code null} for reset.
-     */
-    @VisibleForTesting
-    void setTimeDiff(Long timeDiff) {
-        mTimeDiff = timeDiff;
-    }
-
-    interface SupportLibraryImpl extends AutoCloseable {
-        void setInstance(MediaController2 controller);
-        SessionToken2 getSessionToken();
-        boolean isConnected();
-        void play();
-        void pause();
-        void reset();
-        void prepare();
-        void fastForward();
-        void rewind();
-        void seekTo(long pos);
-        void skipForward();
-        void skipBackward();
-        void playFromMediaId(@NonNull String mediaId, @Nullable Bundle extras);
-        void playFromSearch(@NonNull String query, @Nullable Bundle extras);
-        void playFromUri(@NonNull Uri uri, @Nullable Bundle extras);
-        void prepareFromMediaId(@NonNull String mediaId, @Nullable Bundle extras);
-        void prepareFromSearch(@NonNull String query, @Nullable Bundle extras);
-        void prepareFromUri(@NonNull Uri uri, @Nullable Bundle extras);
-        void setVolumeTo(int value, @VolumeFlags int flags);
-        void adjustVolume(@VolumeDirection int direction, @VolumeFlags int flags);
-        @Nullable PendingIntent getSessionActivity();
-        int getPlayerState();
-        long getDuration();
-        long getCurrentPosition();
-        float getPlaybackSpeed();
-        void setPlaybackSpeed(float speed);
-        @MediaPlayerInterface.BuffState int getBufferingState();
-        long getBufferedPosition();
-        @Nullable PlaybackInfo getPlaybackInfo();
-        void setRating(@NonNull String mediaId, @NonNull Rating2 rating);
-        void sendCustomCommand(@NonNull SessionCommand2 command, @Nullable Bundle args,
-                @Nullable ResultReceiver cb);
-        @Nullable List<MediaItem2> getPlaylist();
-        void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata);
-        void updatePlaylistMetadata(@Nullable MediaMetadata2 metadata);
-        @Nullable MediaMetadata2 getPlaylistMetadata();
-        void addPlaylistItem(int index, @NonNull MediaItem2 item);
-        void removePlaylistItem(@NonNull MediaItem2 item);
-        void replacePlaylistItem(int index, @NonNull MediaItem2 item);
-        MediaItem2 getCurrentMediaItem();
-        void skipToPreviousItem();
-        void skipToNextItem();
-        void skipToPlaylistItem(@NonNull MediaItem2 item);
-        @RepeatMode int getRepeatMode();
-        void setRepeatMode(@RepeatMode int repeatMode);
-        @ShuffleMode int getShuffleMode();
-        void setShuffleMode(@ShuffleMode int shuffleMode);
-        void subscribeRoutesInfo();
-        void unsubscribeRoutesInfo();
-        void selectRoute(@NonNull Bundle route);
-
-        // For MediaBrowser2
-        @NonNull Context getContext();
-        @NonNull ControllerCallback getCallback();
-        @NonNull Executor getCallbackExecutor();
-        @Nullable MediaBrowserCompat getBrowserCompat();
-    }
-
     /**
      * Interface for listening to change in activeness of the {@link MediaSession2}.  It's
      * active if and only if it has set a player.
@@ -835,7 +273,7 @@
          * @param state the new buffering state.
          */
         public void onBufferingStateChanged(@NonNull MediaController2 controller,
-                @NonNull MediaItem2 item, @MediaPlayerInterface.BuffState int state) { }
+                @NonNull MediaItem2 item, @MediaPlayerBase.BuffState int state) { }
 
         /**
          * Called to indicate that seeking is completed.
@@ -866,7 +304,7 @@
          * @see #onBufferingStateChanged(MediaController2, MediaItem2, int)
          */
         public void onCurrentMediaItemChanged(@NonNull MediaController2 controller,
-                @Nullable MediaItem2 item) { }
+                @NonNull MediaItem2 item) { }
 
         /**
          * Called when a playlist is changed.
@@ -1023,7 +461,8 @@
             bundle.putInt(KEY_MAX_VOLUME, mMaxVolume);
             bundle.putInt(KEY_CURRENT_VOLUME, mCurrentVolume);
             if (mAudioAttrsCompat != null) {
-                bundle.putBundle(KEY_AUDIO_ATTRIBUTES, mAudioAttrsCompat.toBundle());
+                bundle.putParcelable(KEY_AUDIO_ATTRIBUTES,
+                        MediaUtils2.toAudioAttributesBundle(mAudioAttrsCompat));
             }
             return bundle;
         }
@@ -1041,10 +480,1291 @@
             final int volumeControl = bundle.getInt(KEY_CONTROL_TYPE);
             final int maxVolume = bundle.getInt(KEY_MAX_VOLUME);
             final int currentVolume = bundle.getInt(KEY_CURRENT_VOLUME);
-            final AudioAttributesCompat attrs = AudioAttributesCompat.fromBundle(
+            final AudioAttributesCompat attrs = MediaUtils2.fromAudioAttributesBundle(
                     bundle.getBundle(KEY_AUDIO_ATTRIBUTES));
             return createPlaybackInfo(volumeType, attrs, volumeControl, maxVolume,
                     currentVolume);
         }
     }
+
+    private final class ControllerCompatCallback extends MediaControllerCompat.Callback {
+        @Override
+        public void onSessionReady() {
+            sendCommand(CONTROLLER_COMMAND_CONNECT, new ResultReceiver(mHandler) {
+                @Override
+                protected void onReceiveResult(int resultCode, Bundle resultData) {
+                    if (!mHandlerThread.isAlive()) {
+                        return;
+                    }
+                    switch (resultCode) {
+                        case CONNECT_RESULT_CONNECTED:
+                            onConnectedNotLocked(resultData);
+                            break;
+                        case CONNECT_RESULT_DISCONNECTED:
+                            mCallback.onDisconnected(MediaController2.this);
+                            close();
+                            break;
+                    }
+                }
+            });
+        }
+
+        @Override
+        public void onSessionDestroyed() {
+            close();
+        }
+
+        @Override
+        public void onPlaybackStateChanged(PlaybackStateCompat state) {
+            synchronized (mLock) {
+                mPlaybackStateCompat = state;
+            }
+        }
+
+        @Override
+        public void onMetadataChanged(MediaMetadataCompat metadata) {
+            synchronized (mLock) {
+                mMediaMetadataCompat = metadata;
+            }
+        }
+
+        @Override
+        public void onSessionEvent(String event, Bundle extras) {
+            switch (event) {
+                case SESSION_EVENT_ON_ALLOWED_COMMANDS_CHANGED: {
+                    SessionCommandGroup2 allowedCommands = SessionCommandGroup2.fromBundle(
+                            extras.getBundle(ARGUMENT_ALLOWED_COMMANDS));
+                    synchronized (mLock) {
+                        mAllowedCommands = allowedCommands;
+                    }
+                    mCallback.onAllowedCommandsChanged(MediaController2.this, allowedCommands);
+                    break;
+                }
+                case SESSION_EVENT_ON_PLAYER_STATE_CHANGED: {
+                    int playerState = extras.getInt(ARGUMENT_PLAYER_STATE);
+                    synchronized (mLock) {
+                        mPlayerState = playerState;
+                    }
+                    mCallback.onPlayerStateChanged(MediaController2.this, playerState);
+                    break;
+                }
+                case SESSION_EVENT_ON_CURRENT_MEDIA_ITEM_CHANGED: {
+                    MediaItem2 item = MediaItem2.fromBundle(extras.getBundle(ARGUMENT_MEDIA_ITEM));
+                    if (item == null) {
+                        return;
+                    }
+                    synchronized (mLock) {
+                        mCurrentMediaItem = item;
+                    }
+                    mCallback.onCurrentMediaItemChanged(MediaController2.this, item);
+                    break;
+                }
+                case SESSION_EVENT_ON_ERROR: {
+                    int errorCode = extras.getInt(ARGUMENT_ERROR_CODE);
+                    Bundle errorExtras = extras.getBundle(ARGUMENT_EXTRAS);
+                    mCallback.onError(MediaController2.this, errorCode, errorExtras);
+                    break;
+                }
+                case SESSION_EVENT_ON_ROUTES_INFO_CHANGED: {
+                    List<Bundle> routes = MediaUtils2.toBundleList(
+                            extras.getParcelableArray(ARGUMENT_ROUTE_BUNDLE));
+                    mCallback.onRoutesInfoChanged(MediaController2.this, routes);
+                    break;
+                }
+                case SESSION_EVENT_ON_PLAYLIST_CHANGED: {
+                    MediaMetadata2 playlistMetadata = MediaMetadata2.fromBundle(
+                            extras.getBundle(ARGUMENT_PLAYLIST_METADATA));
+                    List<MediaItem2> playlist = MediaUtils2.fromMediaItem2ParcelableArray(
+                            extras.getParcelableArray(ARGUMENT_PLAYLIST));
+                    synchronized (mLock) {
+                        mPlaylist = playlist;
+                        mPlaylistMetadata = playlistMetadata;
+                    }
+                    mCallback.onPlaylistChanged(MediaController2.this, playlist, playlistMetadata);
+                    break;
+                }
+                case SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED: {
+                    MediaMetadata2 playlistMetadata = MediaMetadata2.fromBundle(
+                            extras.getBundle(ARGUMENT_PLAYLIST_METADATA));
+                    synchronized (mLock) {
+                        mPlaylistMetadata = playlistMetadata;
+                    }
+                    mCallback.onPlaylistMetadataChanged(MediaController2.this, playlistMetadata);
+                    break;
+                }
+                case SESSION_EVENT_ON_REPEAT_MODE_CHANGED: {
+                    int repeatMode = extras.getInt(ARGUMENT_REPEAT_MODE);
+                    synchronized (mLock) {
+                        mRepeatMode = repeatMode;
+                    }
+                    mCallback.onRepeatModeChanged(MediaController2.this, repeatMode);
+                    break;
+                }
+                case SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED: {
+                    int shuffleMode = extras.getInt(ARGUMENT_SHUFFLE_MODE);
+                    synchronized (mLock) {
+                        mShuffleMode = shuffleMode;
+                    }
+                    mCallback.onShuffleModeChanged(MediaController2.this, shuffleMode);
+                    break;
+                }
+                case SESSION_EVENT_SEND_CUSTOM_COMMAND: {
+                    Bundle commandBundle = extras.getBundle(ARGUMENT_CUSTOM_COMMAND);
+                    if (commandBundle == null) {
+                        return;
+                    }
+                    SessionCommand2 command = SessionCommand2.fromBundle(commandBundle);
+                    Bundle args = extras.getBundle(ARGUMENT_ARGUMENTS);
+                    ResultReceiver receiver = extras.getParcelable(ARGUMENT_RESULT_RECEIVER);
+                    mCallback.onCustomCommand(MediaController2.this, command, args, receiver);
+                    break;
+                }
+                case SESSION_EVENT_SET_CUSTOM_LAYOUT: {
+                    List<CommandButton> layout = MediaUtils2.fromCommandButtonParcelableArray(
+                            extras.getParcelableArray(ARGUMENT_COMMAND_BUTTONS));
+                    if (layout == null) {
+                        return;
+                    }
+                    mCallback.onCustomLayoutChanged(MediaController2.this, layout);
+                    break;
+                }
+                case SESSION_EVENT_ON_PLAYBACK_INFO_CHANGED: {
+                    PlaybackInfo info = PlaybackInfo.fromBundle(
+                            extras.getBundle(ARGUMENT_PLAYBACK_INFO));
+                    if (info == null) {
+                        return;
+                    }
+                    synchronized (mLock) {
+                        mPlaybackInfo = info;
+                    }
+                    mCallback.onPlaybackInfoChanged(MediaController2.this, info);
+                    break;
+                }
+                case SESSION_EVENT_ON_PLAYBACK_SPEED_CHANGED: {
+                    PlaybackStateCompat state =
+                            extras.getParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT);
+                    if (state == null) {
+                        return;
+                    }
+                    synchronized (mLock) {
+                        mPlaybackStateCompat = state;
+                    }
+                    mCallback.onPlaybackSpeedChanged(
+                            MediaController2.this, state.getPlaybackSpeed());
+                    break;
+                }
+                case SESSION_EVENT_ON_BUFFERING_STATE_CHAGNED: {
+                    MediaItem2 item = MediaItem2.fromBundle(extras.getBundle(ARGUMENT_MEDIA_ITEM));
+                    int bufferingState = extras.getInt(ARGUMENT_BUFFERING_STATE);
+                    if (item == null) {
+                        return;
+                    }
+                    synchronized (mLock) {
+                        mBufferingState = bufferingState;
+                    }
+                    mCallback.onBufferingStateChanged(MediaController2.this, item, bufferingState);
+                    break;
+                }
+            }
+        }
+    }
+
+    private static final String TAG = "MediaController2";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    // Note: Using {@code null} doesn't helpful here because MediaBrowserServiceCompat always wraps
+    //       the rootHints so it becomes non-null.
+    static final Bundle sDefaultRootExtras = new Bundle();
+    static {
+        sDefaultRootExtras.putBoolean(MediaConstants2.ROOT_EXTRA_DEFAULT, true);
+    }
+
+    private final Context mContext;
+    private final Object mLock = new Object();
+
+    private final SessionToken2 mToken;
+    private final ControllerCallback mCallback;
+    private final Executor mCallbackExecutor;
+    private final IBinder.DeathRecipient mDeathRecipient;
+
+    private final HandlerThread mHandlerThread;
+    private final Handler mHandler;
+
+    @GuardedBy("mLock")
+    private MediaBrowserCompat mBrowserCompat;
+    @GuardedBy("mLock")
+    private boolean mIsReleased;
+    @GuardedBy("mLock")
+    private List<MediaItem2> mPlaylist;
+    @GuardedBy("mLock")
+    private MediaMetadata2 mPlaylistMetadata;
+    @GuardedBy("mLock")
+    private @RepeatMode int mRepeatMode;
+    @GuardedBy("mLock")
+    private @ShuffleMode int mShuffleMode;
+    @GuardedBy("mLock")
+    private int mPlayerState;
+    @GuardedBy("mLock")
+    private MediaItem2 mCurrentMediaItem;
+    @GuardedBy("mLock")
+    private int mBufferingState;
+    @GuardedBy("mLock")
+    private PlaybackInfo mPlaybackInfo;
+    @GuardedBy("mLock")
+    private SessionCommandGroup2 mAllowedCommands;
+
+    // Media 1.0 variables
+    @GuardedBy("mLock")
+    private MediaControllerCompat mControllerCompat;
+    @GuardedBy("mLock")
+    private ControllerCompatCallback mControllerCompatCallback;
+    @GuardedBy("mLock")
+    private PlaybackStateCompat mPlaybackStateCompat;
+    @GuardedBy("mLock")
+    private MediaMetadataCompat mMediaMetadataCompat;
+
+    // Assignment should be used with the lock hold, but should be used without a lock to prevent
+    // potential deadlock.
+    @GuardedBy("mLock")
+    private volatile boolean mConnected;
+
+    /**
+     * Create a {@link MediaController2} from the {@link SessionToken2}.
+     * This connects to the session and may wake up the service if it's not available.
+     *
+     * @param context Context
+     * @param token token to connect to
+     * @param executor executor to run callbacks on.
+     * @param callback controller callback to receive changes in
+     */
+    public MediaController2(@NonNull Context context, @NonNull SessionToken2 token,
+            @NonNull Executor executor, @NonNull ControllerCallback callback) {
+        super();
+        if (context == null) {
+            throw new IllegalArgumentException("context shouldn't be null");
+        }
+        if (token == null) {
+            throw new IllegalArgumentException("token shouldn't be null");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("callback shouldn't be null");
+        }
+        if (executor == null) {
+            throw new IllegalArgumentException("executor shouldn't be null");
+        }
+        mContext = context;
+        mHandlerThread = new HandlerThread("MediaController2_Thread");
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+        mToken = token;
+        mCallback = callback;
+        mCallbackExecutor = executor;
+        mDeathRecipient = new IBinder.DeathRecipient() {
+            @Override
+            public void binderDied() {
+                MediaController2.this.close();
+            }
+        };
+
+        initialize();
+    }
+
+    /**
+     * Release this object, and disconnect from the session. After this, callbacks wouldn't be
+     * received.
+     */
+    @Override
+    public void close() {
+        if (DEBUG) {
+            //Log.d(TAG, "release from " + mToken, new IllegalStateException());
+        }
+        synchronized (mLock) {
+            if (mIsReleased) {
+                // Prevent re-enterance from the ControllerCallback.onDisconnected()
+                return;
+            }
+            mHandler.removeCallbacksAndMessages(null);
+            mHandlerThread.quitSafely();
+
+            mIsReleased = true;
+
+            // Send command before the unregister callback to use mIControllerCallback in the
+            // callback.
+            sendCommand(CONTROLLER_COMMAND_DISCONNECT);
+            if (mControllerCompat != null) {
+                mControllerCompat.unregisterCallback(mControllerCompatCallback);
+            }
+            if (mBrowserCompat != null) {
+                mBrowserCompat.disconnect();
+                mBrowserCompat = null;
+            }
+            if (mControllerCompat != null) {
+                mControllerCompat.unregisterCallback(mControllerCompatCallback);
+                mControllerCompat = null;
+            }
+            mConnected = false;
+        }
+        mCallbackExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                mCallback.onDisconnected(MediaController2.this);
+            }
+        });
+    }
+
+    /**
+     * @return token
+     */
+    public @NonNull SessionToken2 getSessionToken() {
+        return mToken;
+    }
+
+    /**
+     * Returns whether this class is connected to active {@link MediaSession2} or not.
+     */
+    public boolean isConnected() {
+        synchronized (mLock) {
+            return mConnected;
+        }
+    }
+
+    /**
+     * Requests that the player starts or resumes playback.
+     */
+    public void play() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            sendCommand(COMMAND_CODE_PLAYBACK_PLAY);
+        }
+    }
+
+    /**
+     * Requests that the player pauses playback.
+     */
+    public void pause() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            sendCommand(COMMAND_CODE_PLAYBACK_PAUSE);
+        }
+    }
+
+    /**
+     * Requests that the player be reset to its uninitialized state.
+     */
+    public void reset() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            sendCommand(COMMAND_CODE_PLAYBACK_RESET);
+        }
+    }
+
+    /**
+     * Request that the player prepare its playback. In other words, other sessions can continue
+     * to play during the preparation of this session. This method can be used to speed up the
+     * start of the playback. Once the preparation is done, the session will change its playback
+     * state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards, {@link #play} can be called
+     * to start playback.
+     */
+    public void prepare() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            sendCommand(COMMAND_CODE_PLAYBACK_PREPARE);
+        }
+    }
+
+    /**
+     * Start fast forwarding. If playback is already fast forwarding this
+     * may increase the rate.
+     */
+    public void fastForward() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            sendCommand(COMMAND_CODE_SESSION_FAST_FORWARD);
+        }
+    }
+
+    /**
+     * Start rewinding. If playback is already rewinding this may increase
+     * the rate.
+     */
+    public void rewind() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            sendCommand(COMMAND_CODE_SESSION_REWIND);
+        }
+    }
+
+    /**
+     * Move to a new location in the media stream.
+     *
+     * @param pos Position to move to, in milliseconds.
+     */
+    public void seekTo(long pos) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putLong(ARGUMENT_SEEK_POSITION, pos);
+            sendCommand(COMMAND_CODE_PLAYBACK_SEEK_TO, args);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    public void skipForward() {
+        // To match with KEYCODE_MEDIA_SKIP_FORWARD
+    }
+
+    /**
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    public void skipBackward() {
+        // To match with KEYCODE_MEDIA_SKIP_BACKWARD
+    }
+
+    /**
+     * Request that the player start playback for a specific media id.
+     *
+     * @param mediaId The id of the requested media.
+     * @param extras Optional extras that can include extra information about the media item
+     *               to be played.
+     */
+    public void playFromMediaId(@NonNull String mediaId, @Nullable Bundle extras) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putString(ARGUMENT_MEDIA_ID, mediaId);
+            args.putBundle(ARGUMENT_EXTRAS, extras);
+            sendCommand(COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID, args);
+        }
+    }
+
+    /**
+     * Request that the player start playback for a specific search query.
+     *
+     * @param query The search query. Should not be an empty string.
+     * @param extras Optional extras that can include extra information about the query.
+     */
+    public void playFromSearch(@NonNull String query, @Nullable Bundle extras) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putString(ARGUMENT_QUERY, query);
+            args.putBundle(ARGUMENT_EXTRAS, extras);
+            sendCommand(COMMAND_CODE_SESSION_PLAY_FROM_SEARCH, args);
+        }
+    }
+
+    /**
+     * Request that the player start playback for a specific {@link Uri}.
+     *
+     * @param uri The URI of the requested media.
+     * @param extras Optional extras that can include extra information about the media item
+     *               to be played.
+     */
+    public void playFromUri(@NonNull Uri uri, @Nullable Bundle extras) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putParcelable(ARGUMENT_URI, uri);
+            args.putBundle(ARGUMENT_EXTRAS, extras);
+            sendCommand(COMMAND_CODE_SESSION_PLAY_FROM_URI, args);
+        }
+    }
+
+    /**
+     * Request that the player prepare playback for a specific media id. In other words, other
+     * sessions can continue to play during the preparation of this session. This method can be
+     * used to speed up the start of the playback. Once the preparation is done, the session
+     * will change its playback state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards,
+     * {@link #play} can be called to start playback. If the preparation is not needed,
+     * {@link #playFromMediaId} can be directly called without this method.
+     *
+     * @param mediaId The id of the requested media.
+     * @param extras Optional extras that can include extra information about the media item
+     *               to be prepared.
+     */
+    public void prepareFromMediaId(@NonNull String mediaId, @Nullable Bundle extras) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putString(ARGUMENT_MEDIA_ID, mediaId);
+            args.putBundle(ARGUMENT_EXTRAS, extras);
+            sendCommand(COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID, args);
+        }
+    }
+
+    /**
+     * Request that the player prepare playback for a specific search query.
+     * In other words, other sessions can continue to play during the preparation of this session.
+     * This method can be used to speed up the start of the playback.
+     * Once the preparation is done, the session will change its playback state to
+     * {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards,
+     * {@link #play} can be called to start playback. If the preparation is not needed,
+     * {@link #playFromSearch} can be directly called without this method.
+     *
+     * @param query The search query. Should not be an empty string.
+     * @param extras Optional extras that can include extra information about the query.
+     */
+    public void prepareFromSearch(@NonNull String query, @Nullable Bundle extras) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putString(ARGUMENT_QUERY, query);
+            args.putBundle(ARGUMENT_EXTRAS, extras);
+            sendCommand(COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH, args);
+        }
+    }
+
+    /**
+     * Request that the player prepare playback for a specific {@link Uri}. In other words,
+     * other sessions can continue to play during the preparation of this session. This method
+     * can be used to speed up the start of the playback. Once the preparation is done, the
+     * session will change its playback state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}.
+     * Afterwards, {@link #play} can be called to start playback. If the preparation is not needed,
+     * {@link #playFromUri} can be directly called without this method.
+     *
+     * @param uri The URI of the requested media.
+     * @param extras Optional extras that can include extra information about the media item
+     *               to be prepared.
+     */
+    public void prepareFromUri(@NonNull Uri uri, @Nullable Bundle extras) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putParcelable(ARGUMENT_URI, uri);
+            args.putBundle(ARGUMENT_EXTRAS, extras);
+            sendCommand(COMMAND_CODE_SESSION_PREPARE_FROM_URI, args);
+        }
+    }
+
+    /**
+     * Set the volume of the output this session is playing on. The command will be ignored if it
+     * does not support {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}.
+     * <p>
+     * If the session is local playback, this changes the device's volume with the stream that
+     * session's player is using. Flags will be specified for the {@link AudioManager}.
+     * <p>
+     * If the session is remote player (i.e. session has set volume provider), its volume provider
+     * will receive this request instead.
+     *
+     * @see #getPlaybackInfo()
+     * @param value The value to set it to, between 0 and the reported max.
+     * @param flags flags from {@link AudioManager} to include with the volume request for local
+     *              playback
+     */
+    public void setVolumeTo(int value, @VolumeFlags int flags) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putInt(ARGUMENT_VOLUME, value);
+            args.putInt(ARGUMENT_VOLUME_FLAGS, flags);
+            sendCommand(COMMAND_CODE_VOLUME_SET_VOLUME, args);
+        }
+    }
+
+    /**
+     * Adjust the volume of the output this session is playing on. The direction
+     * must be one of {@link AudioManager#ADJUST_LOWER},
+     * {@link AudioManager#ADJUST_RAISE}, or {@link AudioManager#ADJUST_SAME}.
+     * <p>
+     * The command will be ignored if the session does not support
+     * {@link VolumeProviderCompat#VOLUME_CONTROL_RELATIVE} or
+     * {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}.
+     * <p>
+     * If the session is local playback, this changes the device's volume with the stream that
+     * session's player is using. Flags will be specified for the {@link AudioManager}.
+     * <p>
+     * If the session is remote player (i.e. session has set volume provider), its volume provider
+     * will receive this request instead.
+     *
+     * @see #getPlaybackInfo()
+     * @param direction The direction to adjust the volume in.
+     * @param flags flags from {@link AudioManager} to include with the volume request for local
+     *              playback
+     */
+    public void adjustVolume(@VolumeDirection int direction, @VolumeFlags int flags) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putInt(ARGUMENT_VOLUME_DIRECTION, direction);
+            args.putInt(ARGUMENT_VOLUME_FLAGS, flags);
+            sendCommand(COMMAND_CODE_VOLUME_ADJUST_VOLUME, args);
+        }
+    }
+
+    /**
+     * Get an intent for launching UI associated with this session if one exists.
+     *
+     * @return A {@link PendingIntent} to launch UI or null.
+     */
+    public @Nullable PendingIntent getSessionActivity() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return null;
+            }
+            return mControllerCompat.getSessionActivity();
+        }
+    }
+
+    /**
+     * Get the lastly cached player state from
+     * {@link ControllerCallback#onPlayerStateChanged(MediaController2, int)}.
+     *
+     * @return player state
+     */
+    public int getPlayerState() {
+        synchronized (mLock) {
+            return mPlayerState;
+        }
+    }
+
+    /**
+     * Gets the duration of the current media item, or {@link MediaPlayerBase#UNKNOWN_TIME} if
+     * unknown.
+     * @return the duration in ms, or {@link MediaPlayerBase#UNKNOWN_TIME}.
+     */
+    public long getDuration() {
+        synchronized (mLock) {
+            if (mMediaMetadataCompat != null
+                    && mMediaMetadataCompat.containsKey(METADATA_KEY_DURATION)) {
+                return mMediaMetadataCompat.getLong(METADATA_KEY_DURATION);
+            }
+        }
+        return MediaPlayerBase.UNKNOWN_TIME;
+    }
+
+    /**
+     * Gets the current playback position.
+     * <p>
+     * This returns the calculated value of the position, based on the difference between the
+     * update time and current time.
+     *
+     * @return position
+     */
+    public long getCurrentPosition() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return UNKNOWN_TIME;
+            }
+            if (mPlaybackStateCompat != null) {
+                long timeDiff = SystemClock.elapsedRealtime()
+                        - mPlaybackStateCompat.getLastPositionUpdateTime();
+                long expectedPosition = mPlaybackStateCompat.getPosition()
+                        + (long) (mPlaybackStateCompat.getPlaybackSpeed() * timeDiff);
+                return Math.max(0, expectedPosition);
+            }
+            return UNKNOWN_TIME;
+        }
+    }
+
+    /**
+     * Get the lastly cached playback speed from
+     * {@link ControllerCallback#onPlaybackSpeedChanged(MediaController2, float)}.
+     *
+     * @return speed the lastly cached playback speed, or 0.0f if unknown.
+     */
+    public float getPlaybackSpeed() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return 0f;
+            }
+            return (mPlaybackStateCompat == null) ? 0f : mPlaybackStateCompat.getPlaybackSpeed();
+        }
+    }
+
+    /**
+     * Set the playback speed.
+     */
+    public void setPlaybackSpeed(float speed) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putFloat(ARGUMENT_PLAYBACK_SPEED, speed);
+            sendCommand(COMMAND_CODE_PLAYBACK_SET_SPEED, args);
+        }
+    }
+
+    /**
+     * Gets the current buffering state of the player.
+     * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already
+     * buffered.
+     * @return the buffering state.
+     */
+    public @MediaPlayerBase.BuffState int getBufferingState() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return BUFFERING_STATE_UNKNOWN;
+            }
+            return mBufferingState;
+        }
+    }
+
+    /**
+     * Gets the lastly cached buffered position from the session when
+     * {@link ControllerCallback#onBufferingStateChanged(MediaController2, MediaItem2, int)} is
+     * called.
+     *
+     * @return buffering position in millis, or {@link MediaPlayerBase#UNKNOWN_TIME} if unknown.
+     */
+    public long getBufferedPosition() {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return UNKNOWN_TIME;
+            }
+            return (mPlaybackStateCompat == null) ? UNKNOWN_TIME
+                    : mPlaybackStateCompat.getBufferedPosition();
+        }
+    }
+
+    /**
+     * Get the current playback info for this session.
+     *
+     * @return The current playback info or null.
+     */
+    public @Nullable PlaybackInfo getPlaybackInfo() {
+        synchronized (mLock) {
+            return mPlaybackInfo;
+        }
+    }
+
+    /**
+     * Rate the media. This will cause the rating to be set for the current user.
+     * The rating style must follow the user rating style from the session.
+     * You can get the rating style from the session through the
+     * {@link MediaMetadata2#getRating(String)} with the key
+     * {@link MediaMetadata2#METADATA_KEY_USER_RATING}.
+     * <p>
+     * If the user rating was {@code null}, the media item does not accept setting user rating.
+     *
+     * @param mediaId The id of the media
+     * @param rating The rating to set
+     */
+    public void setRating(@NonNull String mediaId, @NonNull Rating2 rating) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle args = new Bundle();
+            args.putString(ARGUMENT_MEDIA_ID, mediaId);
+            args.putBundle(ARGUMENT_RATING, rating.toBundle());
+            sendCommand(COMMAND_CODE_SESSION_SET_RATING, args);
+        }
+    }
+
+    /**
+     * Send custom command to the session
+     *
+     * @param command custom command
+     * @param args optional argument
+     * @param cb optional result receiver
+     */
+    public void sendCustomCommand(@NonNull SessionCommand2 command, @Nullable Bundle args,
+            @Nullable ResultReceiver cb) {
+        synchronized (mLock) {
+            if (!mConnected) {
+                Log.w(TAG, "Session isn't active", new IllegalStateException());
+                return;
+            }
+            Bundle bundle = new Bundle();
+            bundle.putBundle(ARGUMENT_CUSTOM_COMMAND, command.toBundle());
+            bundle.putBundle(ARGUMENT_ARGUMENTS, args);
+            sendCommand(CONTROLLER_COMMAND_BY_CUSTOM_COMMAND, bundle, cb);
+        }
+    }
+
+    /**
+     * Returns the cached playlist from {@link ControllerCallback#onPlaylistChanged}.
+     * <p>
+     * This list may differ with the list that was specified with
+     * {@link #setPlaylist(List, MediaMetadata2)} depending on the {@link MediaPlaylistAgent}
+     * implementation. Use media items returned here for other playlist agent APIs such as
+     * {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)}.
+     *
+     * @return playlist. Can be {@code null} if the playlist hasn't set nor controller doesn't have
+     *      enough permission.
+     * @see SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST
+     */
+    public @Nullable List<MediaItem2> getPlaylist() {
+        synchronized (mLock) {
+            return mPlaylist;
+        }
+    }
+
+    /**
+     * Sets the playlist.
+     * <p>
+     * Even when the playlist is successfully set, use the playlist returned from
+     * {@link #getPlaylist()} for playlist APIs such as {@link #skipToPlaylistItem(MediaItem2)}.
+     * Otherwise the session in the remote process can't distinguish between media items.
+     *
+     * @param list playlist
+     * @param metadata metadata of the playlist
+     * @see #getPlaylist()
+     * @see ControllerCallback#onPlaylistChanged
+     */
+    public void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) {
+        if (list == null) {
+            throw new IllegalArgumentException("list shouldn't be null");
+        }
+        Bundle args = new Bundle();
+        args.putParcelableArray(ARGUMENT_PLAYLIST, MediaUtils2.toMediaItem2ParcelableArray(list));
+        args.putBundle(ARGUMENT_PLAYLIST_METADATA, metadata == null ? null : metadata.toBundle());
+        sendCommand(COMMAND_CODE_PLAYLIST_SET_LIST, args);
+    }
+
+    /**
+     * Updates the playlist metadata
+     *
+     * @param metadata metadata of the playlist
+     */
+    public void updatePlaylistMetadata(@Nullable MediaMetadata2 metadata) {
+        Bundle args = new Bundle();
+        args.putBundle(ARGUMENT_PLAYLIST_METADATA, metadata == null ? null : metadata.toBundle());
+        sendCommand(COMMAND_CODE_PLAYLIST_SET_LIST_METADATA, args);
+    }
+
+    /**
+     * Gets the lastly cached playlist playlist metadata either from
+     * {@link ControllerCallback#onPlaylistMetadataChanged or
+     * {@link ControllerCallback#onPlaylistChanged}.
+     *
+     * @return metadata metadata of the playlist, or null if none is set
+     */
+    public @Nullable MediaMetadata2 getPlaylistMetadata() {
+        synchronized (mLock) {
+            return mPlaylistMetadata;
+        }
+    }
+
+    /**
+     * Adds the media item to the playlist at position index. Index equals or greater than
+     * the current playlist size (e.g. {@link Integer#MAX_VALUE}) will add the item at the end of
+     * the playlist.
+     * <p>
+     * This will not change the currently playing media item.
+     * If index is less than or equal to the current index of the playlist,
+     * the current index of the playlist will be incremented correspondingly.
+     *
+     * @param index the index you want to add
+     * @param item the media item you want to add
+     */
+    public void addPlaylistItem(int index, @NonNull MediaItem2 item) {
+        Bundle args = new Bundle();
+        args.putInt(ARGUMENT_PLAYLIST_INDEX, index);
+        args.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
+        sendCommand(COMMAND_CODE_PLAYLIST_ADD_ITEM, args);
+    }
+
+    /**
+     * Removes the media item at index in the playlist.
+     *<p>
+     * If the item is the currently playing item of the playlist, current playback
+     * will be stopped and playback moves to next source in the list.
+     *
+     * @param item the media item you want to add
+     */
+    public void removePlaylistItem(@NonNull MediaItem2 item) {
+        Bundle args = new Bundle();
+        args.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
+        sendCommand(COMMAND_CODE_PLAYLIST_REMOVE_ITEM, args);
+    }
+
+    /**
+     * Replace the media item at index in the playlist. This can be also used to update metadata of
+     * an item.
+     *
+     * @param index the index of the item to replace
+     * @param item the new item
+     */
+    public void replacePlaylistItem(int index, @NonNull MediaItem2 item) {
+        Bundle args = new Bundle();
+        args.putInt(ARGUMENT_PLAYLIST_INDEX, index);
+        args.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
+        sendCommand(COMMAND_CODE_PLAYLIST_REPLACE_ITEM, args);
+    }
+
+    /**
+     * Get the lastly cached current item from
+     * {@link ControllerCallback#onCurrentMediaItemChanged(MediaController2, MediaItem2)}.
+     *
+     * @return the currently playing item, or null if unknown.
+     */
+    public MediaItem2 getCurrentMediaItem() {
+        synchronized (mLock) {
+            return mCurrentMediaItem;
+        }
+    }
+
+    /**
+     * Skips to the previous item in the playlist.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToPreviousItem()}.
+     */
+    public void skipToPreviousItem() {
+        sendCommand(COMMAND_CODE_PLAYLIST_SKIP_TO_PREV_ITEM);
+    }
+
+    /**
+     * Skips to the next item in the playlist.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToNextItem()}.
+     */
+    public void skipToNextItem() {
+        sendCommand(COMMAND_CODE_PLAYLIST_SKIP_TO_NEXT_ITEM);
+    }
+
+    /**
+     * Skips to the item in the playlist.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)}.
+     *
+     * @param item The item in the playlist you want to play
+     */
+    public void skipToPlaylistItem(@NonNull MediaItem2 item) {
+        Bundle args = new Bundle();
+        args.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
+        sendCommand(COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM, args);
+    }
+
+    /**
+     * Gets the cached repeat mode from the {@link ControllerCallback#onRepeatModeChanged}.
+     *
+     * @return repeat mode
+     * @see MediaPlaylistAgent#REPEAT_MODE_NONE
+     * @see MediaPlaylistAgent#REPEAT_MODE_ONE
+     * @see MediaPlaylistAgent#REPEAT_MODE_ALL
+     * @see MediaPlaylistAgent#REPEAT_MODE_GROUP
+     */
+    public @RepeatMode int getRepeatMode() {
+        synchronized (mLock) {
+            return mRepeatMode;
+        }
+    }
+
+    /**
+     * Sets the repeat mode.
+     *
+     * @param repeatMode repeat mode
+     * @see MediaPlaylistAgent#REPEAT_MODE_NONE
+     * @see MediaPlaylistAgent#REPEAT_MODE_ONE
+     * @see MediaPlaylistAgent#REPEAT_MODE_ALL
+     * @see MediaPlaylistAgent#REPEAT_MODE_GROUP
+     */
+    public void setRepeatMode(@RepeatMode int repeatMode) {
+        Bundle args = new Bundle();
+        args.putInt(ARGUMENT_REPEAT_MODE, repeatMode);
+        sendCommand(COMMAND_CODE_PLAYLIST_SET_REPEAT_MODE, args);
+    }
+
+    /**
+     * Gets the cached shuffle mode from the {@link ControllerCallback#onShuffleModeChanged}.
+     *
+     * @return The shuffle mode
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP
+     */
+    public @ShuffleMode int getShuffleMode() {
+        synchronized (mLock) {
+            return mShuffleMode;
+        }
+    }
+
+    /**
+     * Sets the shuffle mode.
+     *
+     * @param shuffleMode The shuffle mode
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP
+     */
+    public void setShuffleMode(@ShuffleMode int shuffleMode) {
+        Bundle args = new Bundle();
+        args.putInt(ARGUMENT_SHUFFLE_MODE, shuffleMode);
+        sendCommand(COMMAND_CODE_PLAYLIST_SET_SHUFFLE_MODE, args);
+    }
+
+    /**
+     * Queries for information about the routes currently known.
+     */
+    public void subscribeRoutesInfo() {
+        sendCommand(COMMAND_CODE_SESSION_SUBSCRIBE_ROUTES_INFO);
+    }
+
+    /**
+     * Unsubscribes for changes to the routes.
+     * <p>
+     * The {@link ControllerCallback#onRoutesInfoChanged callback} will no longer be invoked for
+     * the routes once this method returns.
+     * </p>
+     */
+    public void unsubscribeRoutesInfo() {
+        sendCommand(COMMAND_CODE_SESSION_UNSUBSCRIBE_ROUTES_INFO);
+    }
+
+    /**
+     * Selects the specified route.
+     *
+     * @param route The route to select.
+     */
+    public void selectRoute(@NonNull Bundle route) {
+        if (route == null) {
+            throw new IllegalArgumentException("route shouldn't be null");
+        }
+        Bundle args = new Bundle();
+        args.putBundle(ARGUMENT_ROUTE_BUNDLE, route);
+        sendCommand(COMMAND_CODE_SESSION_SELECT_ROUTE, args);
+    }
+
+    // Should be used without a lock to prevent potential deadlock.
+    void onConnectedNotLocked(Bundle data) {
+        // is enough or should we pass it while connecting?
+        final SessionCommandGroup2 allowedCommands = SessionCommandGroup2.fromBundle(
+                data.getBundle(ARGUMENT_ALLOWED_COMMANDS));
+        final int playerState = data.getInt(ARGUMENT_PLAYER_STATE);
+        final int bufferingState = data.getInt(ARGUMENT_BUFFERING_STATE);
+        final PlaybackStateCompat playbackStateCompat = data.getParcelable(
+                ARGUMENT_PLAYBACK_STATE_COMPAT);
+        final int repeatMode = data.getInt(ARGUMENT_REPEAT_MODE);
+        final int shuffleMode = data.getInt(ARGUMENT_SHUFFLE_MODE);
+        final List<MediaItem2> playlist = MediaUtils2.fromMediaItem2ParcelableArray(
+                data.getParcelableArray(ARGUMENT_PLAYLIST));
+        final MediaItem2 currentMediaItem = MediaItem2.fromBundle(
+                data.getBundle(ARGUMENT_MEDIA_ITEM));
+        final PlaybackInfo playbackInfo =
+                PlaybackInfo.fromBundle(data.getBundle(ARGUMENT_PLAYBACK_INFO));
+        final MediaMetadata2 metadata = MediaMetadata2.fromBundle(
+                data.getBundle(ARGUMENT_PLAYLIST_METADATA));
+        if (DEBUG) {
+            Log.d(TAG, "onConnectedNotLocked sessionCompatToken=" + mToken.getSessionCompatToken()
+                    + ", allowedCommands=" + allowedCommands);
+        }
+        boolean close = false;
+        try {
+            synchronized (mLock) {
+                if (mIsReleased) {
+                    return;
+                }
+                if (mConnected) {
+                    Log.e(TAG, "Cannot be notified about the connection result many times."
+                            + " Probably a bug or malicious app.");
+                    close = true;
+                    return;
+                }
+                mAllowedCommands = allowedCommands;
+                mPlayerState = playerState;
+                mBufferingState = bufferingState;
+                mPlaybackStateCompat = playbackStateCompat;
+                mRepeatMode = repeatMode;
+                mShuffleMode = shuffleMode;
+                mPlaylist = playlist;
+                mCurrentMediaItem = currentMediaItem;
+                mPlaylistMetadata = metadata;
+                mConnected = true;
+                mPlaybackInfo = playbackInfo;
+            }
+            mCallbackExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
+                    // Note: We may trigger ControllerCallbacks with the initial values
+                    // But it's hard to define the order of the controller callbacks
+                    // Only notify about the
+                    mCallback.onConnected(MediaController2.this, allowedCommands);
+                }
+            });
+        } finally {
+            if (close) {
+                // Trick to call release() without holding the lock, to prevent potential deadlock
+                // with the developer's custom lock within the ControllerCallback.onDisconnected().
+                close();
+            }
+        }
+    }
+
+    private void initialize() {
+        if (mToken.getType() == SessionToken2.TYPE_SESSION) {
+            synchronized (mLock) {
+                mBrowserCompat = null;
+            }
+            connectToSession(mToken.getSessionCompatToken());
+        } else {
+            connectToService();
+        }
+    }
+
+    private void connectToSession(MediaSessionCompat.Token sessionCompatToken) {
+        MediaControllerCompat controllerCompat = null;
+        try {
+            controllerCompat = new MediaControllerCompat(mContext, sessionCompatToken);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+        synchronized (mLock) {
+            mControllerCompat = controllerCompat;
+            mControllerCompatCallback = new ControllerCompatCallback();
+            mControllerCompat.registerCallback(mControllerCompatCallback, mHandler);
+        }
+
+        if (controllerCompat.isSessionReady()) {
+            sendCommand(CONTROLLER_COMMAND_CONNECT, new ResultReceiver(mHandler) {
+                @Override
+                protected void onReceiveResult(int resultCode, Bundle resultData) {
+                    if (!mHandlerThread.isAlive()) {
+                        return;
+                    }
+                    switch (resultCode) {
+                        case CONNECT_RESULT_CONNECTED:
+                            onConnectedNotLocked(resultData);
+                            break;
+                        case CONNECT_RESULT_DISCONNECTED:
+                            mCallback.onDisconnected(MediaController2.this);
+                            close();
+                            break;
+                    }
+                }
+            });
+        }
+    }
+
+    private void connectToService() {
+        synchronized (mLock) {
+            mBrowserCompat = new MediaBrowserCompat(mContext, mToken.getComponentName(),
+                    new ConnectionCallback(), sDefaultRootExtras);
+            mBrowserCompat.connect();
+        }
+    }
+
+    private void sendCommand(int commandCode) {
+        sendCommand(commandCode, null);
+    }
+
+    private void sendCommand(int commandCode, Bundle args) {
+        if (args == null) {
+            args = new Bundle();
+        }
+        args.putInt(ARGUMENT_COMMAND_CODE, commandCode);
+        sendCommand(CONTROLLER_COMMAND_BY_COMMAND_CODE, args, null);
+    }
+
+    private void sendCommand(String command) {
+        sendCommand(command, null, null);
+    }
+
+    private void sendCommand(String command, ResultReceiver receiver) {
+        sendCommand(command, null, receiver);
+    }
+
+    private void sendCommand(String command, Bundle args, ResultReceiver receiver) {
+        if (args == null) {
+            args = new Bundle();
+        }
+        MediaControllerCompat controller;
+        ControllerCompatCallback callback;
+        synchronized (mLock) {
+            controller = mControllerCompat;
+            callback = mControllerCompatCallback;
+        }
+        args.putBinder(ARGUMENT_ICONTROLLER_CALLBACK, callback.getIControllerCallback().asBinder());
+        args.putString(ARGUMENT_PACKAGE_NAME, mContext.getPackageName());
+        args.putInt(ARGUMENT_UID, Process.myUid());
+        args.putInt(ARGUMENT_PID, Process.myPid());
+        controller.sendCommand(command, args, receiver);
+    }
+
+    @NonNull Context getContext() {
+        return mContext;
+    }
+
+    @NonNull ControllerCallback getCallback() {
+        return mCallback;
+    }
+
+    @NonNull Executor getCallbackExecutor() {
+        return mCallbackExecutor;
+    }
+
+    @Nullable MediaBrowserCompat getBrowserCompat() {
+        synchronized (mLock) {
+            return mBrowserCompat;
+        }
+    }
+
+    private class ConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
+        @Override
+        public void onConnected() {
+            MediaBrowserCompat browser = getBrowserCompat();
+            if (browser != null) {
+                connectToSession(browser.getSessionToken());
+            } else if (DEBUG) {
+                Log.d(TAG, "Controller is closed prematually", new IllegalStateException());
+            }
+        }
+
+        @Override
+        public void onConnectionSuspended() {
+            close();
+        }
+
+        @Override
+        public void onConnectionFailed() {
+            close();
+        }
+    }
 }
diff --git a/media/src/main/java/androidx/media/MediaController2ImplBase.java b/media/src/main/java/androidx/media/MediaController2ImplBase.java
deleted file mode 100644
index 1bd0009..0000000
--- a/media/src/main/java/androidx/media/MediaController2ImplBase.java
+++ /dev/null
@@ -1,1283 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media;
-
-import static android.support.v4.media.MediaMetadataCompat.METADATA_KEY_DURATION;
-
-import static androidx.media.MediaConstants2.ARGUMENT_ALLOWED_COMMANDS;
-import static androidx.media.MediaConstants2.ARGUMENT_ARGUMENTS;
-import static androidx.media.MediaConstants2.ARGUMENT_BUFFERING_STATE;
-import static androidx.media.MediaConstants2.ARGUMENT_COMMAND_BUTTONS;
-import static androidx.media.MediaConstants2.ARGUMENT_COMMAND_CODE;
-import static androidx.media.MediaConstants2.ARGUMENT_CUSTOM_COMMAND;
-import static androidx.media.MediaConstants2.ARGUMENT_ERROR_CODE;
-import static androidx.media.MediaConstants2.ARGUMENT_EXTRAS;
-import static androidx.media.MediaConstants2.ARGUMENT_ICONTROLLER_CALLBACK;
-import static androidx.media.MediaConstants2.ARGUMENT_ITEM_COUNT;
-import static androidx.media.MediaConstants2.ARGUMENT_MEDIA_ID;
-import static androidx.media.MediaConstants2.ARGUMENT_MEDIA_ITEM;
-import static androidx.media.MediaConstants2.ARGUMENT_PACKAGE_NAME;
-import static androidx.media.MediaConstants2.ARGUMENT_PID;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYBACK_INFO;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYBACK_SPEED;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYBACK_STATE_COMPAT;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYER_STATE;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYLIST;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYLIST_INDEX;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYLIST_METADATA;
-import static androidx.media.MediaConstants2.ARGUMENT_QUERY;
-import static androidx.media.MediaConstants2.ARGUMENT_RATING;
-import static androidx.media.MediaConstants2.ARGUMENT_REPEAT_MODE;
-import static androidx.media.MediaConstants2.ARGUMENT_RESULT_RECEIVER;
-import static androidx.media.MediaConstants2.ARGUMENT_ROUTE_BUNDLE;
-import static androidx.media.MediaConstants2.ARGUMENT_SEEK_POSITION;
-import static androidx.media.MediaConstants2.ARGUMENT_SHUFFLE_MODE;
-import static androidx.media.MediaConstants2.ARGUMENT_UID;
-import static androidx.media.MediaConstants2.ARGUMENT_URI;
-import static androidx.media.MediaConstants2.ARGUMENT_VOLUME;
-import static androidx.media.MediaConstants2.ARGUMENT_VOLUME_DIRECTION;
-import static androidx.media.MediaConstants2.ARGUMENT_VOLUME_FLAGS;
-import static androidx.media.MediaConstants2.CONNECT_RESULT_CONNECTED;
-import static androidx.media.MediaConstants2.CONNECT_RESULT_DISCONNECTED;
-import static androidx.media.MediaConstants2.CONTROLLER_COMMAND_BY_COMMAND_CODE;
-import static androidx.media.MediaConstants2.CONTROLLER_COMMAND_BY_CUSTOM_COMMAND;
-import static androidx.media.MediaConstants2.CONTROLLER_COMMAND_CONNECT;
-import static androidx.media.MediaConstants2.CONTROLLER_COMMAND_DISCONNECT;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ALLOWED_COMMANDS_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_BUFFERING_STATE_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_CHILDREN_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_CURRENT_MEDIA_ITEM_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ERROR;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYBACK_INFO_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYBACK_SPEED_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYER_STATE_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_REPEAT_MODE_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ROUTES_INFO_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SEARCH_RESULT_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SEEK_COMPLETED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_SEND_CUSTOM_COMMAND;
-import static androidx.media.MediaConstants2.SESSION_EVENT_SET_CUSTOM_LAYOUT;
-import static androidx.media.MediaPlayerInterface.BUFFERING_STATE_UNKNOWN;
-import static androidx.media.MediaPlayerInterface.UNKNOWN_TIME;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PREPARE;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_RESET;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_SEEK_TO;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_SET_SPEED;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_ADD_ITEM;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_REMOVE_ITEM;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_REPLACE_ITEM;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_LIST;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_LIST_METADATA;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_REPEAT_MODE;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_SHUFFLE_MODE;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_TO_NEXT_ITEM;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_TO_PREV_ITEM;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_FAST_FORWARD;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_SEARCH;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_URI;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_URI;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_REWIND;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SELECT_ROUTE;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SET_RATING;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SUBSCRIBE_ROUTES_INFO;
-import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_UNSUBSCRIBE_ROUTES_INFO;
-import static androidx.media.SessionCommand2.COMMAND_CODE_VOLUME_ADJUST_VOLUME;
-import static androidx.media.SessionCommand2.COMMAND_CODE_VOLUME_SET_VOLUME;
-
-import android.annotation.TargetApi;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.SystemClock;
-import android.support.v4.media.MediaBrowserCompat;
-import android.support.v4.media.MediaMetadataCompat;
-import android.support.v4.media.session.MediaControllerCompat;
-import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v4.media.session.PlaybackStateCompat;
-import android.util.Log;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.app.BundleCompat;
-import androidx.media.MediaController2.ControllerCallback;
-import androidx.media.MediaController2.PlaybackInfo;
-import androidx.media.MediaController2.VolumeDirection;
-import androidx.media.MediaController2.VolumeFlags;
-import androidx.media.MediaPlaylistAgent.RepeatMode;
-import androidx.media.MediaPlaylistAgent.ShuffleMode;
-import androidx.media.MediaSession2.CommandButton;
-
-import java.util.List;
-import java.util.concurrent.Executor;
-
-@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-class MediaController2ImplBase implements MediaController2.SupportLibraryImpl {
-
-    private static final String TAG = "MC2ImplBase";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    // Note: Using {@code null} doesn't helpful here because MediaBrowserServiceCompat always wraps
-    //       the rootHints so it becomes non-null.
-    static final Bundle sDefaultRootExtras = new Bundle();
-    static {
-        sDefaultRootExtras.putBoolean(MediaConstants2.ROOT_EXTRA_DEFAULT, true);
-    }
-
-    private final Context mContext;
-    private final Object mLock = new Object();
-
-    private final SessionToken2 mToken;
-    private final ControllerCallback mCallback;
-    private final Executor mCallbackExecutor;
-    private final IBinder.DeathRecipient mDeathRecipient;
-
-    private final HandlerThread mHandlerThread;
-    private final Handler mHandler;
-
-    private MediaController2 mInstance;
-
-    @GuardedBy("mLock")
-    private MediaBrowserCompat mBrowserCompat;
-    @GuardedBy("mLock")
-    private boolean mIsReleased;
-    @GuardedBy("mLock")
-    private List<MediaItem2> mPlaylist;
-    @GuardedBy("mLock")
-    private MediaMetadata2 mPlaylistMetadata;
-    @GuardedBy("mLock")
-    private @RepeatMode int mRepeatMode;
-    @GuardedBy("mLock")
-    private @ShuffleMode int mShuffleMode;
-    @GuardedBy("mLock")
-    private int mPlayerState;
-    @GuardedBy("mLock")
-    private MediaItem2 mCurrentMediaItem;
-    @GuardedBy("mLock")
-    private int mBufferingState;
-    @GuardedBy("mLock")
-    private PlaybackInfo mPlaybackInfo;
-    @GuardedBy("mLock")
-    private SessionCommandGroup2 mAllowedCommands;
-
-    // Media 1.0 variables
-    @GuardedBy("mLock")
-    private MediaControllerCompat mControllerCompat;
-    @GuardedBy("mLock")
-    private ControllerCompatCallback mControllerCompatCallback;
-    @GuardedBy("mLock")
-    private PlaybackStateCompat mPlaybackStateCompat;
-    @GuardedBy("mLock")
-    private MediaMetadataCompat mMediaMetadataCompat;
-
-    // Assignment should be used with the lock hold, but should be used without a lock to prevent
-    // potential deadlock.
-    @GuardedBy("mLock")
-    private volatile boolean mConnected;
-
-    MediaController2ImplBase(@NonNull Context context, @NonNull SessionToken2 token,
-            @NonNull Executor executor, @NonNull ControllerCallback callback) {
-        super();
-        if (context == null) {
-            throw new IllegalArgumentException("context shouldn't be null");
-        }
-        if (token == null) {
-            throw new IllegalArgumentException("token shouldn't be null");
-        }
-        if (callback == null) {
-            throw new IllegalArgumentException("callback shouldn't be null");
-        }
-        if (executor == null) {
-            throw new IllegalArgumentException("executor shouldn't be null");
-        }
-        mContext = context;
-        mHandlerThread = new HandlerThread("MediaController2_Thread");
-        mHandlerThread.start();
-        mHandler = new Handler(mHandlerThread.getLooper());
-        mToken = token;
-        mCallback = callback;
-        mCallbackExecutor = executor;
-        mDeathRecipient = new IBinder.DeathRecipient() {
-            @Override
-            public void binderDied() {
-                MediaController2ImplBase.this.close();
-            }
-        };
-
-        initialize();
-    }
-
-    @Override
-    public void setInstance(MediaController2 controller) {
-        mInstance = controller;
-    }
-
-    @Override
-    public void close() {
-        if (DEBUG) {
-            //Log.d(TAG, "release from " + mToken, new IllegalStateException());
-        }
-        synchronized (mLock) {
-            if (mIsReleased) {
-                // Prevent re-enterance from the ControllerCallback.onDisconnected()
-                return;
-            }
-            mHandler.removeCallbacksAndMessages(null);
-
-            if (Build.VERSION.SDK_INT >= 18) {
-                mHandlerThread.quitSafely();
-            } else {
-                mHandlerThread.quit();
-            }
-
-            mIsReleased = true;
-
-            // Send command before the unregister callback to use mIControllerCallback in the
-            // callback.
-            sendCommand(CONTROLLER_COMMAND_DISCONNECT);
-            if (mControllerCompat != null) {
-                mControllerCompat.unregisterCallback(mControllerCompatCallback);
-            }
-            if (mBrowserCompat != null) {
-                mBrowserCompat.disconnect();
-                mBrowserCompat = null;
-            }
-            if (mControllerCompat != null) {
-                mControllerCompat.unregisterCallback(mControllerCompatCallback);
-                mControllerCompat = null;
-            }
-            mConnected = false;
-        }
-        mCallbackExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                mCallback.onDisconnected(mInstance);
-            }
-        });
-    }
-
-    @Override
-    public @NonNull SessionToken2 getSessionToken() {
-        return mToken;
-    }
-
-    @Override
-    public boolean isConnected() {
-        synchronized (mLock) {
-            return mConnected;
-        }
-    }
-
-    @Override
-    public void play() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            sendCommand(COMMAND_CODE_PLAYBACK_PLAY);
-        }
-    }
-
-    @Override
-    public void pause() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            sendCommand(COMMAND_CODE_PLAYBACK_PAUSE);
-        }
-    }
-
-    @Override
-    public void reset() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            sendCommand(COMMAND_CODE_PLAYBACK_RESET);
-        }
-    }
-
-    @Override
-    public void prepare() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            sendCommand(COMMAND_CODE_PLAYBACK_PREPARE);
-        }
-    }
-
-    @Override
-    public void fastForward() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            sendCommand(COMMAND_CODE_SESSION_FAST_FORWARD);
-        }
-    }
-
-    @Override
-    public void rewind() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            sendCommand(COMMAND_CODE_SESSION_REWIND);
-        }
-    }
-
-    @Override
-    public void seekTo(long pos) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putLong(ARGUMENT_SEEK_POSITION, pos);
-            sendCommand(COMMAND_CODE_PLAYBACK_SEEK_TO, args);
-        }
-    }
-
-    @Override
-    public void skipForward() {
-        // To match with KEYCODE_MEDIA_SKIP_FORWARD
-    }
-
-    @Override
-    public void skipBackward() {
-        // To match with KEYCODE_MEDIA_SKIP_BACKWARD
-    }
-
-    @Override
-    public void playFromMediaId(@NonNull String mediaId, @Nullable Bundle extras) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putString(ARGUMENT_MEDIA_ID, mediaId);
-            args.putBundle(ARGUMENT_EXTRAS, extras);
-            sendCommand(COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID, args);
-        }
-    }
-
-    @Override
-    public void playFromSearch(@NonNull String query, @Nullable Bundle extras) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putString(ARGUMENT_QUERY, query);
-            args.putBundle(ARGUMENT_EXTRAS, extras);
-            sendCommand(COMMAND_CODE_SESSION_PLAY_FROM_SEARCH, args);
-        }
-    }
-
-    @Override
-    public void playFromUri(@NonNull Uri uri, @Nullable Bundle extras) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putParcelable(ARGUMENT_URI, uri);
-            args.putBundle(ARGUMENT_EXTRAS, extras);
-            sendCommand(COMMAND_CODE_SESSION_PLAY_FROM_URI, args);
-        }
-    }
-
-    @Override
-    public void prepareFromMediaId(@NonNull String mediaId, @Nullable Bundle extras) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putString(ARGUMENT_MEDIA_ID, mediaId);
-            args.putBundle(ARGUMENT_EXTRAS, extras);
-            sendCommand(COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID, args);
-        }
-    }
-
-    @Override
-    public void prepareFromSearch(@NonNull String query, @Nullable Bundle extras) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putString(ARGUMENT_QUERY, query);
-            args.putBundle(ARGUMENT_EXTRAS, extras);
-            sendCommand(COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH, args);
-        }
-    }
-
-    @Override
-    public void prepareFromUri(@NonNull Uri uri, @Nullable Bundle extras) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putParcelable(ARGUMENT_URI, uri);
-            args.putBundle(ARGUMENT_EXTRAS, extras);
-            sendCommand(COMMAND_CODE_SESSION_PREPARE_FROM_URI, args);
-        }
-    }
-
-    @Override
-    public void setVolumeTo(int value, @VolumeFlags int flags) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putInt(ARGUMENT_VOLUME, value);
-            args.putInt(ARGUMENT_VOLUME_FLAGS, flags);
-            sendCommand(COMMAND_CODE_VOLUME_SET_VOLUME, args);
-        }
-    }
-
-    @Override
-    public void adjustVolume(@VolumeDirection int direction, @VolumeFlags int flags) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putInt(ARGUMENT_VOLUME_DIRECTION, direction);
-            args.putInt(ARGUMENT_VOLUME_FLAGS, flags);
-            sendCommand(COMMAND_CODE_VOLUME_ADJUST_VOLUME, args);
-        }
-    }
-
-    @Override
-    public @Nullable PendingIntent getSessionActivity() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return null;
-            }
-            return mControllerCompat.getSessionActivity();
-        }
-    }
-
-    @Override
-    public int getPlayerState() {
-        synchronized (mLock) {
-            return mPlayerState;
-        }
-    }
-
-    @Override
-    public long getDuration() {
-        synchronized (mLock) {
-            if (mMediaMetadataCompat != null
-                    && mMediaMetadataCompat.containsKey(METADATA_KEY_DURATION)) {
-                return mMediaMetadataCompat.getLong(METADATA_KEY_DURATION);
-            }
-        }
-        return MediaPlayerInterface.UNKNOWN_TIME;
-    }
-
-    @Override
-    public long getCurrentPosition() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return UNKNOWN_TIME;
-            }
-            if (mPlaybackStateCompat != null) {
-                long timeDiff = (mInstance.mTimeDiff != null) ? mInstance.mTimeDiff
-                        : SystemClock.elapsedRealtime()
-                                - mPlaybackStateCompat.getLastPositionUpdateTime();
-                long expectedPosition = mPlaybackStateCompat.getPosition()
-                        + (long) (mPlaybackStateCompat.getPlaybackSpeed() * timeDiff);
-                return Math.max(0, expectedPosition);
-            }
-            return UNKNOWN_TIME;
-        }
-    }
-
-    @Override
-    public float getPlaybackSpeed() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return 0f;
-            }
-            return (mPlaybackStateCompat == null) ? 0f : mPlaybackStateCompat.getPlaybackSpeed();
-        }
-    }
-
-    @Override
-    public void setPlaybackSpeed(float speed) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putFloat(ARGUMENT_PLAYBACK_SPEED, speed);
-            sendCommand(COMMAND_CODE_PLAYBACK_SET_SPEED, args);
-        }
-    }
-
-    @Override
-    public @MediaPlayerInterface.BuffState int getBufferingState() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return BUFFERING_STATE_UNKNOWN;
-            }
-            return mBufferingState;
-        }
-    }
-
-    @Override
-    public long getBufferedPosition() {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return UNKNOWN_TIME;
-            }
-            return (mPlaybackStateCompat == null) ? UNKNOWN_TIME
-                    : mPlaybackStateCompat.getBufferedPosition();
-        }
-    }
-
-    @Override
-    public @Nullable PlaybackInfo getPlaybackInfo() {
-        synchronized (mLock) {
-            return mPlaybackInfo;
-        }
-    }
-
-    @Override
-    public void setRating(@NonNull String mediaId, @NonNull Rating2 rating) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle args = new Bundle();
-            args.putString(ARGUMENT_MEDIA_ID, mediaId);
-            args.putBundle(ARGUMENT_RATING, rating.toBundle());
-            sendCommand(COMMAND_CODE_SESSION_SET_RATING, args);
-        }
-    }
-
-    @Override
-    public void sendCustomCommand(@NonNull SessionCommand2 command, @Nullable Bundle args,
-            @Nullable ResultReceiver cb) {
-        synchronized (mLock) {
-            if (!mConnected) {
-                Log.w(TAG, "Session isn't active", new IllegalStateException());
-                return;
-            }
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_CUSTOM_COMMAND, command.toBundle());
-            bundle.putBundle(ARGUMENT_ARGUMENTS, args);
-            sendCommand(CONTROLLER_COMMAND_BY_CUSTOM_COMMAND, bundle, cb);
-        }
-    }
-
-    @Override
-    public @Nullable List<MediaItem2> getPlaylist() {
-        synchronized (mLock) {
-            return mPlaylist;
-        }
-    }
-
-    @Override
-    public void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) {
-        if (list == null) {
-            throw new IllegalArgumentException("list shouldn't be null");
-        }
-        Bundle args = new Bundle();
-        args.putParcelableArray(ARGUMENT_PLAYLIST, MediaUtils2.toMediaItem2ParcelableArray(list));
-        args.putBundle(ARGUMENT_PLAYLIST_METADATA, metadata == null ? null : metadata.toBundle());
-        sendCommand(COMMAND_CODE_PLAYLIST_SET_LIST, args);
-    }
-
-    @Override
-    public void updatePlaylistMetadata(@Nullable MediaMetadata2 metadata) {
-        Bundle args = new Bundle();
-        args.putBundle(ARGUMENT_PLAYLIST_METADATA, metadata == null ? null : metadata.toBundle());
-        sendCommand(COMMAND_CODE_PLAYLIST_SET_LIST_METADATA, args);
-    }
-
-    @Override
-    public @Nullable MediaMetadata2 getPlaylistMetadata() {
-        synchronized (mLock) {
-            return mPlaylistMetadata;
-        }
-    }
-
-    @Override
-    public void addPlaylistItem(int index, @NonNull MediaItem2 item) {
-        Bundle args = new Bundle();
-        args.putInt(ARGUMENT_PLAYLIST_INDEX, index);
-        args.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
-        sendCommand(COMMAND_CODE_PLAYLIST_ADD_ITEM, args);
-    }
-
-    @Override
-    public void removePlaylistItem(@NonNull MediaItem2 item) {
-        Bundle args = new Bundle();
-        args.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
-        sendCommand(COMMAND_CODE_PLAYLIST_REMOVE_ITEM, args);
-    }
-
-    @Override
-    public void replacePlaylistItem(int index, @NonNull MediaItem2 item) {
-        Bundle args = new Bundle();
-        args.putInt(ARGUMENT_PLAYLIST_INDEX, index);
-        args.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
-        sendCommand(COMMAND_CODE_PLAYLIST_REPLACE_ITEM, args);
-    }
-
-    @Override
-    public MediaItem2 getCurrentMediaItem() {
-        synchronized (mLock) {
-            return mCurrentMediaItem;
-        }
-    }
-
-    @Override
-    public void skipToPreviousItem() {
-        sendCommand(COMMAND_CODE_PLAYLIST_SKIP_TO_PREV_ITEM);
-    }
-
-    @Override
-    public void skipToNextItem() {
-        sendCommand(COMMAND_CODE_PLAYLIST_SKIP_TO_NEXT_ITEM);
-    }
-
-    @Override
-    public void skipToPlaylistItem(@NonNull MediaItem2 item) {
-        Bundle args = new Bundle();
-        args.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
-        sendCommand(COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM, args);
-    }
-
-    @Override
-    public @RepeatMode int getRepeatMode() {
-        synchronized (mLock) {
-            return mRepeatMode;
-        }
-    }
-
-    @Override
-    public void setRepeatMode(@RepeatMode int repeatMode) {
-        Bundle args = new Bundle();
-        args.putInt(ARGUMENT_REPEAT_MODE, repeatMode);
-        sendCommand(COMMAND_CODE_PLAYLIST_SET_REPEAT_MODE, args);
-    }
-
-    @Override
-    public @ShuffleMode int getShuffleMode() {
-        synchronized (mLock) {
-            return mShuffleMode;
-        }
-    }
-
-    @Override
-    public void setShuffleMode(@ShuffleMode int shuffleMode) {
-        Bundle args = new Bundle();
-        args.putInt(ARGUMENT_SHUFFLE_MODE, shuffleMode);
-        sendCommand(COMMAND_CODE_PLAYLIST_SET_SHUFFLE_MODE, args);
-    }
-
-    @Override
-    public void subscribeRoutesInfo() {
-        sendCommand(COMMAND_CODE_SESSION_SUBSCRIBE_ROUTES_INFO);
-    }
-
-    @Override
-    public void unsubscribeRoutesInfo() {
-        sendCommand(COMMAND_CODE_SESSION_UNSUBSCRIBE_ROUTES_INFO);
-    }
-
-    @Override
-    public void selectRoute(@NonNull Bundle route) {
-        if (route == null) {
-            throw new IllegalArgumentException("route shouldn't be null");
-        }
-        Bundle args = new Bundle();
-        args.putBundle(ARGUMENT_ROUTE_BUNDLE, route);
-        sendCommand(COMMAND_CODE_SESSION_SELECT_ROUTE, args);
-    }
-
-    @Override
-    public @NonNull Context getContext() {
-        return mContext;
-    }
-
-    @Override
-    public @NonNull ControllerCallback getCallback() {
-        return mCallback;
-    }
-
-    @Override
-    public @NonNull Executor getCallbackExecutor() {
-        return mCallbackExecutor;
-    }
-
-    @Override
-    public @Nullable MediaBrowserCompat getBrowserCompat() {
-        synchronized (mLock) {
-            return mBrowserCompat;
-        }
-    }
-
-    // Should be used without a lock to prevent potential deadlock.
-    void onConnectedNotLocked(Bundle data) {
-        data.setClassLoader(MediaSession2.class.getClassLoader());
-        // is enough or should we pass it while connecting?
-        final SessionCommandGroup2 allowedCommands = SessionCommandGroup2.fromBundle(
-                data.getBundle(ARGUMENT_ALLOWED_COMMANDS));
-        final int playerState = data.getInt(ARGUMENT_PLAYER_STATE);
-        final int bufferingState = data.getInt(ARGUMENT_BUFFERING_STATE);
-        final PlaybackStateCompat playbackStateCompat = data.getParcelable(
-                ARGUMENT_PLAYBACK_STATE_COMPAT);
-        final int repeatMode = data.getInt(ARGUMENT_REPEAT_MODE);
-        final int shuffleMode = data.getInt(ARGUMENT_SHUFFLE_MODE);
-        final List<MediaItem2> playlist = MediaUtils2.fromMediaItem2ParcelableArray(
-                data.getParcelableArray(ARGUMENT_PLAYLIST));
-        final MediaItem2 currentMediaItem = MediaItem2.fromBundle(
-                data.getBundle(ARGUMENT_MEDIA_ITEM));
-        final PlaybackInfo playbackInfo =
-                PlaybackInfo.fromBundle(data.getBundle(ARGUMENT_PLAYBACK_INFO));
-        final MediaMetadata2 metadata = MediaMetadata2.fromBundle(
-                data.getBundle(ARGUMENT_PLAYLIST_METADATA));
-        if (DEBUG) {
-            Log.d(TAG, "onConnectedNotLocked sessionCompatToken=" + mToken.getSessionCompatToken()
-                    + ", allowedCommands=" + allowedCommands);
-        }
-        boolean close = false;
-        try {
-            synchronized (mLock) {
-                if (mIsReleased) {
-                    return;
-                }
-                if (mConnected) {
-                    Log.e(TAG, "Cannot be notified about the connection result many times."
-                            + " Probably a bug or malicious app.");
-                    close = true;
-                    return;
-                }
-                mAllowedCommands = allowedCommands;
-                mPlayerState = playerState;
-                mBufferingState = bufferingState;
-                mPlaybackStateCompat = playbackStateCompat;
-                mRepeatMode = repeatMode;
-                mShuffleMode = shuffleMode;
-                mPlaylist = playlist;
-                mCurrentMediaItem = currentMediaItem;
-                mPlaylistMetadata = metadata;
-                mConnected = true;
-                mPlaybackInfo = playbackInfo;
-            }
-            mCallbackExecutor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    // Note: We may trigger ControllerCallbacks with the initial values
-                    // But it's hard to define the order of the controller callbacks
-                    // Only notify about the
-                    mCallback.onConnected(mInstance, allowedCommands);
-                }
-            });
-        } finally {
-            if (close) {
-                // Trick to call release() without holding the lock, to prevent potential deadlock
-                // with the developer's custom lock within the ControllerCallback.onDisconnected().
-                close();
-            }
-        }
-    }
-
-    private void initialize() {
-        if (mToken.getType() == SessionToken2.TYPE_SESSION) {
-            synchronized (mLock) {
-                mBrowserCompat = null;
-            }
-            connectToSession(mToken.getSessionCompatToken());
-        } else {
-            connectToService();
-        }
-    }
-
-    private void connectToSession(MediaSessionCompat.Token sessionCompatToken) {
-        MediaControllerCompat controllerCompat = null;
-        try {
-            controllerCompat = new MediaControllerCompat(mContext, sessionCompatToken);
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        }
-        synchronized (mLock) {
-            mControllerCompat = controllerCompat;
-            mControllerCompatCallback = new ControllerCompatCallback();
-            mControllerCompat.registerCallback(mControllerCompatCallback, mHandler);
-        }
-
-        if (controllerCompat.isSessionReady()) {
-            sendCommand(CONTROLLER_COMMAND_CONNECT, new ResultReceiver(mHandler) {
-                @Override
-                protected void onReceiveResult(int resultCode, Bundle resultData) {
-                    if (!mHandlerThread.isAlive()) {
-                        return;
-                    }
-                    switch (resultCode) {
-                        case CONNECT_RESULT_CONNECTED:
-                            onConnectedNotLocked(resultData);
-                            break;
-                        case CONNECT_RESULT_DISCONNECTED:
-                            mCallbackExecutor.execute(new Runnable() {
-                                @Override
-                                public void run() {
-                                    mCallback.onDisconnected(mInstance);
-                                }
-                            });
-                            close();
-                            break;
-                    }
-                }
-            });
-        }
-    }
-
-    private void connectToService() {
-        mCallbackExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                synchronized (mLock) {
-                    mBrowserCompat = new MediaBrowserCompat(mContext, mToken.getComponentName(),
-                            new ConnectionCallback(), sDefaultRootExtras);
-                    mBrowserCompat.connect();
-                }
-            }
-        });
-    }
-
-    private void sendCommand(int commandCode) {
-        sendCommand(commandCode, null);
-    }
-
-    private void sendCommand(int commandCode, Bundle args) {
-        if (args == null) {
-            args = new Bundle();
-        }
-        args.putInt(ARGUMENT_COMMAND_CODE, commandCode);
-        sendCommand(CONTROLLER_COMMAND_BY_COMMAND_CODE, args, null);
-    }
-
-    private void sendCommand(String command) {
-        sendCommand(command, null, null);
-    }
-
-    private void sendCommand(String command, ResultReceiver receiver) {
-        sendCommand(command, null, receiver);
-    }
-
-    private void sendCommand(String command, Bundle args, ResultReceiver receiver) {
-        if (args == null) {
-            args = new Bundle();
-        }
-        MediaControllerCompat controller;
-        ControllerCompatCallback callback;
-        synchronized (mLock) {
-            controller = mControllerCompat;
-            callback = mControllerCompatCallback;
-        }
-        BundleCompat.putBinder(args, ARGUMENT_ICONTROLLER_CALLBACK,
-                callback.getIControllerCallback().asBinder());
-        args.putString(ARGUMENT_PACKAGE_NAME, mContext.getPackageName());
-        args.putInt(ARGUMENT_UID, Process.myUid());
-        args.putInt(ARGUMENT_PID, Process.myPid());
-        controller.sendCommand(command, args, receiver);
-    }
-
-    private class ConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
-        @Override
-        public void onConnected() {
-            MediaBrowserCompat browser = getBrowserCompat();
-            if (browser != null) {
-                connectToSession(browser.getSessionToken());
-            } else if (DEBUG) {
-                Log.d(TAG, "Controller is closed prematually", new IllegalStateException());
-            }
-        }
-
-        @Override
-        public void onConnectionSuspended() {
-            close();
-        }
-
-        @Override
-        public void onConnectionFailed() {
-            close();
-        }
-    }
-
-    private final class ControllerCompatCallback extends MediaControllerCompat.Callback {
-        @Override
-        public void onSessionReady() {
-            sendCommand(CONTROLLER_COMMAND_CONNECT, new ResultReceiver(mHandler) {
-                @Override
-                protected void onReceiveResult(int resultCode, Bundle resultData) {
-                    if (!mHandlerThread.isAlive()) {
-                        return;
-                    }
-                    switch (resultCode) {
-                        case CONNECT_RESULT_CONNECTED:
-                            onConnectedNotLocked(resultData);
-                            break;
-                        case CONNECT_RESULT_DISCONNECTED:
-                            mCallbackExecutor.execute(new Runnable() {
-                                @Override
-                                public void run() {
-                                    mCallback.onDisconnected(mInstance);
-                                }
-                            });
-                            close();
-                            break;
-                    }
-                }
-            });
-        }
-
-        @Override
-        public void onSessionDestroyed() {
-            close();
-        }
-
-        @Override
-        public void onPlaybackStateChanged(PlaybackStateCompat state) {
-            synchronized (mLock) {
-                mPlaybackStateCompat = state;
-            }
-        }
-
-        @Override
-        public void onMetadataChanged(MediaMetadataCompat metadata) {
-            synchronized (mLock) {
-                mMediaMetadataCompat = metadata;
-            }
-        }
-
-        @Override
-        public void onSessionEvent(String event, Bundle extras) {
-            if (extras != null) {
-                extras.setClassLoader(MediaSession2.class.getClassLoader());
-            }
-            switch (event) {
-                case SESSION_EVENT_ON_ALLOWED_COMMANDS_CHANGED: {
-                    final SessionCommandGroup2 allowedCommands = SessionCommandGroup2.fromBundle(
-                            extras.getBundle(ARGUMENT_ALLOWED_COMMANDS));
-                    synchronized (mLock) {
-                        mAllowedCommands = allowedCommands;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onAllowedCommandsChanged(mInstance, allowedCommands);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_PLAYER_STATE_CHANGED: {
-                    final int playerState = extras.getInt(ARGUMENT_PLAYER_STATE);
-                    PlaybackStateCompat state =
-                            extras.getParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT);
-                    if (state == null) {
-                        return;
-                    }
-                    synchronized (mLock) {
-                        mPlayerState = playerState;
-                        mPlaybackStateCompat = state;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onPlayerStateChanged(mInstance, playerState);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_CURRENT_MEDIA_ITEM_CHANGED: {
-                    final MediaItem2 item = MediaItem2.fromBundle(
-                            extras.getBundle(ARGUMENT_MEDIA_ITEM));
-                    synchronized (mLock) {
-                        mCurrentMediaItem = item;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onCurrentMediaItemChanged(mInstance, item);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_ERROR: {
-                    final int errorCode = extras.getInt(ARGUMENT_ERROR_CODE);
-                    final Bundle errorExtras = extras.getBundle(ARGUMENT_EXTRAS);
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onError(mInstance, errorCode, errorExtras);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_ROUTES_INFO_CHANGED: {
-                    final List<Bundle> routes = MediaUtils2.toBundleList(
-                            extras.getParcelableArray(ARGUMENT_ROUTE_BUNDLE));
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onRoutesInfoChanged(mInstance, routes);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_PLAYLIST_CHANGED: {
-                    final MediaMetadata2 playlistMetadata = MediaMetadata2.fromBundle(
-                            extras.getBundle(ARGUMENT_PLAYLIST_METADATA));
-                    final List<MediaItem2> playlist = MediaUtils2.fromMediaItem2ParcelableArray(
-                            extras.getParcelableArray(ARGUMENT_PLAYLIST));
-                    synchronized (mLock) {
-                        mPlaylist = playlist;
-                        mPlaylistMetadata = playlistMetadata;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onPlaylistChanged(mInstance, playlist, playlistMetadata);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED: {
-                    final MediaMetadata2 playlistMetadata = MediaMetadata2.fromBundle(
-                            extras.getBundle(ARGUMENT_PLAYLIST_METADATA));
-                    synchronized (mLock) {
-                        mPlaylistMetadata = playlistMetadata;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onPlaylistMetadataChanged(mInstance, playlistMetadata);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_REPEAT_MODE_CHANGED: {
-                    final int repeatMode = extras.getInt(ARGUMENT_REPEAT_MODE);
-                    synchronized (mLock) {
-                        mRepeatMode = repeatMode;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onRepeatModeChanged(mInstance, repeatMode);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED: {
-                    final int shuffleMode = extras.getInt(ARGUMENT_SHUFFLE_MODE);
-                    synchronized (mLock) {
-                        mShuffleMode = shuffleMode;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onShuffleModeChanged(mInstance, shuffleMode);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_SEND_CUSTOM_COMMAND: {
-                    Bundle commandBundle = extras.getBundle(ARGUMENT_CUSTOM_COMMAND);
-                    if (commandBundle == null) {
-                        return;
-                    }
-                    final SessionCommand2 command = SessionCommand2.fromBundle(commandBundle);
-                    final Bundle args = extras.getBundle(ARGUMENT_ARGUMENTS);
-                    final ResultReceiver receiver = extras.getParcelable(ARGUMENT_RESULT_RECEIVER);
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onCustomCommand(mInstance, command, args, receiver);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_SET_CUSTOM_LAYOUT: {
-                    final List<CommandButton> layout = MediaUtils2.fromCommandButtonParcelableArray(
-                            extras.getParcelableArray(ARGUMENT_COMMAND_BUTTONS));
-                    if (layout == null) {
-                        return;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onCustomLayoutChanged(mInstance, layout);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_PLAYBACK_INFO_CHANGED: {
-                    final PlaybackInfo info = PlaybackInfo.fromBundle(
-                            extras.getBundle(ARGUMENT_PLAYBACK_INFO));
-                    if (info == null) {
-                        return;
-                    }
-                    synchronized (mLock) {
-                        mPlaybackInfo = info;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onPlaybackInfoChanged(mInstance, info);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_PLAYBACK_SPEED_CHANGED: {
-                    final PlaybackStateCompat state =
-                            extras.getParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT);
-                    if (state == null) {
-                        return;
-                    }
-                    synchronized (mLock) {
-                        mPlaybackStateCompat = state;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onPlaybackSpeedChanged(mInstance, state.getPlaybackSpeed());
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_BUFFERING_STATE_CHANGED: {
-                    final MediaItem2 item = MediaItem2.fromBundle(
-                            extras.getBundle(ARGUMENT_MEDIA_ITEM));
-                    final int bufferingState = extras.getInt(ARGUMENT_BUFFERING_STATE);
-                    PlaybackStateCompat state =
-                            extras.getParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT);
-                    if (item == null || state == null) {
-                        return;
-                    }
-                    synchronized (mLock) {
-                        mBufferingState = bufferingState;
-                        mPlaybackStateCompat = state;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onBufferingStateChanged(mInstance, item, bufferingState);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_SEEK_COMPLETED: {
-                    final long position = extras.getLong(ARGUMENT_SEEK_POSITION);
-                    PlaybackStateCompat state =
-                            extras.getParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT);
-                    if (state == null) {
-                        return;
-                    }
-                    synchronized (mLock) {
-                        mPlaybackStateCompat = state;
-                    }
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCallback.onSeekCompleted(mInstance, position);
-                        }
-                    });
-                    break;
-                }
-                case SESSION_EVENT_ON_CHILDREN_CHANGED: {
-                    String parentId = extras.getString(ARGUMENT_MEDIA_ID);
-                    if (parentId == null || !(mInstance instanceof MediaBrowser2)) {
-                        return;
-                    }
-                    int itemCount = extras.getInt(ARGUMENT_ITEM_COUNT, -1);
-                    Bundle childrenExtras = extras.getBundle(ARGUMENT_EXTRAS);
-                    ((MediaBrowser2.BrowserCallback) mCallback).onChildrenChanged(
-                            (MediaBrowser2) mInstance, parentId, itemCount, childrenExtras);
-                    break;
-                }
-                case SESSION_EVENT_ON_SEARCH_RESULT_CHANGED: {
-                    final String query = extras.getString(ARGUMENT_QUERY);
-                    if (query == null || !(mInstance instanceof MediaBrowser2)) {
-                        return;
-                    }
-                    final int itemCount = extras.getInt(ARGUMENT_ITEM_COUNT, -1);
-                    final Bundle searchExtras = extras.getBundle(ARGUMENT_EXTRAS);
-                    mCallbackExecutor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            ((MediaBrowser2.BrowserCallback) mCallback).onSearchResultChanged(
-                                    (MediaBrowser2) mInstance, query, itemCount, searchExtras);
-                        }
-                    });
-                    break;
-                }
-            }
-        }
-    }
-}
diff --git a/media/src/main/java/androidx/media/MediaLibraryService2.java b/media/src/main/java/androidx/media/MediaLibraryService2.java
index 9e3bfda..edd97c3 100644
--- a/media/src/main/java/androidx/media/MediaLibraryService2.java
+++ b/media/src/main/java/androidx/media/MediaLibraryService2.java
@@ -19,27 +19,28 @@
 import static android.support.v4.media.MediaBrowserCompat.EXTRA_PAGE;
 import static android.support.v4.media.MediaBrowserCompat.EXTRA_PAGE_SIZE;
 
-import static androidx.media.MediaConstants2.ARGUMENT_EXTRAS;
-import static androidx.media.MediaConstants2.ARGUMENT_PAGE;
-import static androidx.media.MediaConstants2.ARGUMENT_PAGE_SIZE;
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
 import android.app.PendingIntent;
 import android.content.Intent;
-import android.os.BadParcelableException;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.support.v4.media.MediaBrowserCompat.MediaItem;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
 import androidx.media.MediaLibraryService2.MediaLibrarySession.Builder;
 import androidx.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
 import androidx.media.MediaSession2.ControllerInfo;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 
 /**
+ * @hide
  * Base class for media library services.
  * <p>
  * Media library services enable applications to browse media content provided by an application
@@ -61,6 +62,7 @@
  *
  * @see MediaSessionService2
  */
+@RestrictTo(LIBRARY_GROUP)
 public abstract class MediaLibraryService2 extends MediaSessionService2 {
     /**
      * This is the interface name that a service implementing a session service should say that it
@@ -68,6 +70,8 @@
      */
     public static final String SERVICE_INTERFACE = "android.media.MediaLibraryService2";
 
+    // TODO: Revisit this value.
+
     /**
      * Session for the {@link MediaLibraryService2}. Build this object with
      * {@link Builder} and return in {@link #onCreateSession(String)}.
@@ -166,6 +170,7 @@
              * @param parentId parent id
              * @see SessionCommand2#COMMAND_CODE_LIBRARY_UNSUBSCRIBE
              */
+            // TODO: Make this to be called.
             public void onUnsubscribe(@NonNull MediaLibrarySession session,
                     @NonNull ControllerInfo controller, @NonNull String parentId) {
             }
@@ -212,8 +217,6 @@
          */
         // Override all methods just to show them with the type instead of generics in Javadoc.
         // This workarounds javadoc issue described in the MediaSession2.BuilderBase.
-        // Note: Don't override #setSessionCallback() because the callback can be set by the
-        // constructor.
         public static final class Builder extends MediaSession2.BuilderBase<MediaLibrarySession,
                 Builder, MediaLibrarySessionCallback> {
             private MediaLibrarySessionImplBase.Builder mImpl;
@@ -232,7 +235,7 @@
             }
 
             @Override
-            public @NonNull Builder setPlayer(@NonNull MediaPlayerInterface player) {
+            public @NonNull Builder setPlayer(@NonNull MediaPlayerBase player) {
                 return super.setPlayer(player);
             }
 
@@ -258,6 +261,12 @@
             }
 
             @Override
+            public @NonNull Builder setSessionCallback(@NonNull Executor executor,
+                    @NonNull MediaLibrarySessionCallback callback) {
+                return super.setSessionCallback(executor, callback);
+            }
+
+            @Override
             public @NonNull MediaLibrarySession build() {
                 return super.build();
             }
@@ -282,10 +291,9 @@
          */
         public void notifyChildrenChanged(@NonNull ControllerInfo controller,
                 @NonNull String parentId, int itemCount, @Nullable Bundle extras) {
-            List<MediaSessionManager.RemoteUserInfo> subscribingBrowsers =
-                    getServiceCompat().getSubscribingBrowsers(parentId);
-            getImpl().notifyChildrenChanged(controller, parentId, itemCount, extras,
-                    subscribingBrowsers);
+            Bundle options = new Bundle(extras);
+            options.putInt(MediaBrowser2.EXTRA_ITEM_COUNT, itemCount);
+            options.putBundle(MediaBrowser2.EXTRA_TARGET, controller.toBundle());
         }
 
         /**
@@ -300,11 +308,9 @@
         // This is for the backward compatibility.
         public void notifyChildrenChanged(@NonNull String parentId, int itemCount,
                 @Nullable Bundle extras) {
-            if (extras == null) {
-                getServiceCompat().notifyChildrenChanged(parentId);
-            } else {
-                getServiceCompat().notifyChildrenChanged(parentId, extras);
-            }
+            Bundle options = new Bundle(extras);
+            options.putInt(MediaBrowser2.EXTRA_ITEM_COUNT, itemCount);
+            getServiceCompat().notifyChildrenChanged(parentId, options);
         }
 
         /**
@@ -316,8 +322,8 @@
          * @param extras extra bundle
          */
         public void notifySearchResultChanged(@NonNull ControllerInfo controller,
-                @NonNull String query, int itemCount, @Nullable Bundle extras) {
-            getImpl().notifySearchResultChanged(controller, query, itemCount, extras);
+                @NonNull String query, int itemCount, @NonNull Bundle extras) {
+            // TODO: Implement
         }
 
         private MediaLibraryService2 getService() {
@@ -488,7 +494,10 @@
                 // controller.
                 return sDefaultBrowserRoot;
             }
-            final ControllerInfo controller = getController();
+            final CountDownLatch latch = new CountDownLatch(1);
+            // TODO: Revisit this when we support caller information.
+            final ControllerInfo info = new ControllerInfo(MediaLibraryService2.this, clientUid, -1,
+                    clientPackageName, null);
             MediaLibrarySession session = getLibrarySession();
             // Call onGetLibraryRoot() directly instead of execute on the executor. Here's the
             // reason.
@@ -502,7 +511,7 @@
             // Because of the reason, just call onGetLibraryRoot directly here. onGetLibraryRoot()
             // has documentation that it may be called on the main thread.
             LibraryRoot libraryRoot = session.getCallback().onGetLibraryRoot(
-                    session, controller, extras);
+                    session, info, extras);
             if (libraryRoot == null) {
                 return null;
             }
@@ -517,47 +526,36 @@
         @Override
         public void onLoadChildren(final String parentId, final Result<List<MediaItem>> result,
                 final Bundle options) {
-            result.detach();
             final ControllerInfo controller = getController();
             getLibrarySession().getCallbackExecutor().execute(new Runnable() {
                 @Override
                 public void run() {
-                    if (options != null) {
-                        options.setClassLoader(MediaLibraryService2.this.getClassLoader());
-                        try {
-                            int page = options.getInt(EXTRA_PAGE);
-                            int pageSize = options.getInt(EXTRA_PAGE_SIZE);
-                            if (page > 0 && pageSize > 0) {
-                                // Requesting the list of children through pagination.
-                                List<MediaItem2> children = getLibrarySession().getCallback()
-                                        .onGetChildren(getLibrarySession(), controller, parentId,
-                                                page, pageSize, options);
-                                result.sendResult(MediaUtils2.fromMediaItem2List(children));
-                                return;
-                            } else if (options.containsKey(
-                                    MediaBrowser2.MEDIA_BROWSER2_SUBSCRIBE)) {
-                                // This onLoadChildren() was triggered by MediaBrowser2.subscribe().
-                                options.remove(MediaBrowser2.MEDIA_BROWSER2_SUBSCRIBE);
-                                getLibrarySession().getCallback().onSubscribe(getLibrarySession(),
-                                        controller, parentId, options.getBundle(ARGUMENT_EXTRAS));
-                                return;
+                    int page = options.getInt(EXTRA_PAGE, -1);
+                    int pageSize = options.getInt(EXTRA_PAGE_SIZE, -1);
+                    if (page >= 0 && pageSize >= 0) {
+                        // Requesting the list of children through the pagenation.
+                        List<MediaItem2> children = getLibrarySession().getCallback().onGetChildren(
+                                getLibrarySession(), controller, parentId, page, pageSize, options);
+                        if (children == null) {
+                            result.sendError(null);
+                        } else {
+                            List<MediaItem> list = new ArrayList<>();
+                            for (int i = 0; i < children.size(); i++) {
+                                list.add(MediaUtils2.createMediaItem(children.get(i)));
                             }
-                        } catch (BadParcelableException e) {
-                            // pass-through.
+                            result.sendResult(list);
                         }
+                    } else {
+                        // Only wants to register callbacks
+                        getLibrarySession().getCallback().onSubscribe(getLibrarySession(),
+                                controller, parentId, options);
                     }
-                    List<MediaItem2> children = getLibrarySession().getCallback()
-                            .onGetChildren(getLibrarySession(), controller, parentId,
-                                    1 /* page */, Integer.MAX_VALUE /* pageSize*/,
-                                    null /* extras */);
-                    result.sendResult(MediaUtils2.fromMediaItem2List(children));
                 }
             });
         }
 
         @Override
         public void onLoadItem(final String itemId, final Result<MediaItem> result) {
-            result.detach();
             final ControllerInfo controller = getController();
             getLibrarySession().getCallbackExecutor().execute(new Runnable() {
                 @Override
@@ -565,7 +563,7 @@
                     MediaItem2 item = getLibrarySession().getCallback().onGetItem(
                             getLibrarySession(), controller, itemId);
                     if (item == null) {
-                        result.sendResult(null);
+                        result.sendError(null);
                     } else {
                         result.sendResult(MediaUtils2.createMediaItem(item));
                     }
@@ -574,65 +572,17 @@
         }
 
         @Override
-        public void onSearch(final String query, final Bundle extras,
-                final Result<List<MediaItem>> result) {
-            result.detach();
-            final ControllerInfo controller = getController();
-            extras.setClassLoader(MediaLibraryService2.this.getClassLoader());
-            try {
-                final int page = extras.getInt(ARGUMENT_PAGE);
-                final int pageSize = extras.getInt(ARGUMENT_PAGE_SIZE);
-                if (!(page > 0 && pageSize > 0)) {
-                    getLibrarySession().getCallbackExecutor().execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            getLibrarySession().getCallback().onSearch(
-                                    getLibrarySession(), controller, query, extras);
-                        }
-                    });
-                } else {
-                    getLibrarySession().getCallbackExecutor().execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            List<MediaItem2> searchResult = getLibrarySession().getCallback()
-                                    .onGetSearchResult(getLibrarySession(), controller, query,
-                                            page, pageSize, extras);
-                            if (searchResult == null) {
-                                result.sendResult(null);
-                                return;
-                            }
-                            result.sendResult(MediaUtils2.fromMediaItem2List(searchResult));
-                        }
-                    });
-                }
-            } catch (BadParcelableException e) {
-                // Do nothing.
-            }
+        public void onSearch(String query, Bundle extras, Result<List<MediaItem>> result) {
+            // TODO: Implement
         }
 
         @Override
         public void onCustomAction(String action, Bundle extras, Result<Bundle> result) {
-            // No-op. Library session will handle the custom action.
+            // TODO: Implement
         }
 
         private ControllerInfo getController() {
-            MediaLibrarySession session = getLibrarySession();
-            List<ControllerInfo> controllers = session.getConnectedControllers();
-
-            MediaSessionManager.RemoteUserInfo info = getCurrentBrowserInfo();
-            if (info == null) {
-                return null;
-            }
-
-            for (int i = 0; i < controllers.size(); i++) {
-                // Note: This cannot pick the right controller between two controllers in same
-                // process.
-                ControllerInfo controller = controllers.get(i);
-                if (controller.getPackageName().equals(info.getPackageName())
-                        && controller.getUid() == info.getUid()) {
-                    return controller;
-                }
-            }
+            // TODO: Implement, by using getBrowserRootHints() / getCurrentBrowserInfo() / ...
             return null;
         }
     }
diff --git a/media/src/main/java/androidx/media/MediaLibrarySessionImplBase.java b/media/src/main/java/androidx/media/MediaLibrarySessionImplBase.java
index dfaa98c..c21edd3 100644
--- a/media/src/main/java/androidx/media/MediaLibrarySessionImplBase.java
+++ b/media/src/main/java/androidx/media/MediaLibrarySessionImplBase.java
@@ -31,7 +31,7 @@
 class MediaLibrarySessionImplBase extends MediaSession2ImplBase {
     MediaLibrarySessionImplBase(Context context,
             MediaSessionCompat sessionCompat, String id,
-            MediaPlayerInterface player, MediaPlaylistAgent playlistAgent,
+            MediaPlayerBase player, MediaPlaylistAgent playlistAgent,
             VolumeProviderCompat volumeProvider, PendingIntent sessionActivity,
             Executor callbackExecutor,
             MediaSession2.SessionCallback callback) {
@@ -39,11 +39,6 @@
                 callbackExecutor, callback);
     }
 
-    @Override
-    MediaSession2 createInstance() {
-        return new MediaLibrarySession(this);
-    }
-
     static final class Builder extends MediaSession2ImplBase.BuilderBase<
             MediaLibrarySession, MediaLibrarySession.MediaLibrarySessionCallback> {
         Builder(Context context) {
diff --git a/media/src/main/java/androidx/media/MediaPlayer2.java b/media/src/main/java/androidx/media/MediaPlayer2.java
index 4edb946..1864d72 100644
--- a/media/src/main/java/androidx/media/MediaPlayer2.java
+++ b/media/src/main/java/androidx/media/MediaPlayer2.java
@@ -28,7 +28,6 @@
 import android.media.MediaTimestamp;
 import android.media.PlaybackParams;
 import android.media.ResourceBusyException;
-import android.media.SubtitleData;
 import android.media.SyncParams;
 import android.media.TimedMetaData;
 import android.media.UnsupportedSchemeException;
@@ -48,16 +47,27 @@
 import java.util.UUID;
 import java.util.concurrent.Executor;
 
+
 /**
- * MediaPlayer2 class can be used to control playback of audio/video files and streams.
+ * @hide
+ * MediaPlayer2 class can be used to control playback
+ * of audio/video files and streams. An example on how to use the methods in
+ * this class can be found in {@link android.widget.VideoView}.
  *
  * <p>Topics covered here are:
  * <ol>
  * <li><a href="#StateDiagram">State Diagram</a>
+ * <li><a href="#Valid_and_Invalid_States">Valid and Invalid States</a>
  * <li><a href="#Permissions">Permissions</a>
  * <li><a href="#Callbacks">Register informational and error callbacks</a>
  * </ol>
  *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about how to use MediaPlayer2, read the
+ * <a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a> developer guide.</p>
+ * </div>
+ *
  * <a name="StateDiagram"></a>
  * <h3>State Diagram</h3>
  *
@@ -77,18 +87,18 @@
  * <p>From this state diagram, one can see that a MediaPlayer2 object has the
  *    following states:</p>
  * <ul>
- *     <li>When a MediaPlayer2 object is just created using {@link #create()} or
- *         after {@link #reset()} is called, it is in the <strong>Idle</strong> state; and Once
- *         {@link #close()} is called, it can no longer be used and there is no way to bring it
- *         back to any other state.
+ *     <li>When a MediaPlayer2 object is just created using <code>create</code> or
+ *         after {@link #reset()} is called, it is in the <em>Idle</em> state; and after
+ *         {@link #close()} is called, it is in the <em>End</em> state. Between these
+ *         two states is the life cycle of the MediaPlayer2 object.
  *         <ul>
- *         <li>Calling {@link #setDataSource(DataSourceDesc)} and {@link #prepare()} transfers a
- *         MediaPlayer2 object in the <strong>Idle</strong> state to the <strong>Paused</strong>
- *         state. It is good programming practice to register a event callback for
- *         {@link MediaPlayer2EventCallback#onCallCompleted} and
- *         look out for {@link #CALL_STATUS_BAD_VALUE} and {@link #CALL_STATUS_ERROR_IO} that may be
- *         caused from {@link #setDataSource}.
- *         </li>
+ *         <li> It is a programming error to invoke methods such
+ *         as {@link #getCurrentPosition()},
+ *         {@link #getDuration()}, {@link #getVideoHeight()},
+ *         {@link #getVideoWidth()}, {@link #setAudioAttributes(AudioAttributes)},
+ *         {@link #setPlayerVolume(float)}, {@link #pause()}, {@link #play()},
+ *         {@link #seekTo(long, int)} or
+ *         {@link #prepare()} in the <em>Idle</em> state.
  *         <li>It is also recommended that once
  *         a MediaPlayer2 object is no longer being used, call {@link #close()} immediately
  *         so that resources used by the internal player engine associated with the
@@ -96,7 +106,13 @@
  *         singleton resources such as hardware acceleration components and
  *         failure to call {@link #close()} may cause subsequent instances of
  *         MediaPlayer2 objects to fallback to software implementations or fail
- *         altogether. </li>
+ *         altogether. Once the MediaPlayer2
+ *         object is in the <em>End</em> state, it can no longer be used and
+ *         there is no way to bring it back to any other state. </li>
+ *         <li>Furthermore,
+ *         the MediaPlayer2 objects created using <code>new</code> is in the
+ *         <em>Idle</em> state.
+ *         </li>
  *         </ul>
  *         </li>
  *     <li>In general, some playback control operation may fail due to various
@@ -105,55 +121,71 @@
  *         Thus, error reporting and recovery is an important concern under
  *         these circumstances. Sometimes, due to programming errors, invoking a playback
  *         control operation in an invalid state may also occur. Under all these
- *         error conditions, the player goes to <strong>Error</strong> state and invokes a user
- *         supplied {@link MediaPlayer2EventCallback#onError}} method if an event callback has been
- *         registered beforehand via {@link #setMediaPlayer2EventCallback}.
+ *         error conditions, the internal player engine invokes a user supplied
+ *         MediaPlayer2EventCallback.onError() method if an MediaPlayer2EventCallback has been
+ *         registered beforehand via
+ *         {@link #setMediaPlayer2EventCallback(Executor, MediaPlayer2EventCallback)}.
  *         <ul>
  *         <li>It is important to note that once an error occurs, the
- *         MediaPlayer2 object enters the <strong>Error</strong> state (except as noted
- *         above), even if a callback has not been registered by the application.</li>
- *         <li>In order to reuse a MediaPlayer2 object that is in the <strong>
- *         Error</strong> state and recover from the error,
- *         {@link #reset()} can be called to restore the object to its <strong>Idle</strong>
+ *         MediaPlayer2 object enters the <em>Error</em> state (except as noted
+ *         above), even if an error listener has not been registered by the application.</li>
+ *         <li>In order to reuse a MediaPlayer2 object that is in the <em>
+ *         Error</em> state and recover from the error,
+ *         {@link #reset()} can be called to restore the object to its <em>Idle</em>
  *         state.</li>
  *         <li>It is good programming practice to have your application
- *         register a {@link MediaPlayer2EventCallback} to look out for error callbacks from
+ *         register a OnErrorListener to look out for error notifications from
  *         the internal player engine.</li>
- *         <li> {@link MediaPlayer2EventCallback#onCallCompleted} is called with
- *         {@link #CALL_STATUS_INVALID_OPERATION} on programming errors such as calling
- *         {@link #prepare()} and {@link #setDataSource(DataSourceDesc)} methods in an invalid
- *         state. </li>
+ *         <li>IllegalStateException is
+ *         thrown to prevent programming errors such as calling
+ *         {@link #prepare()}, {@link #setDataSource(DataSourceDesc)}
+ *         methods in an invalid state. </li>
  *         </ul>
  *         </li>
- *     <li>A MediaPlayer2 object must first enter the <strong>Paused</strong> state
+ *     <li>Calling
+ *         {@link #setDataSource(DataSourceDesc)} transfers a
+ *         MediaPlayer2 object in the <em>Idle</em> state to the
+ *         <em>Initialized</em> state.
+ *         <ul>
+ *         <li>An IllegalStateException is thrown if
+ *         setDataSource() is called in any other state.</li>
+ *         <li>It is good programming
+ *         practice to always look out for <code>IllegalArgumentException</code>
+ *         and <code>IOException</code> that may be thrown from
+ *         <code>setDataSource</code>.</li>
+ *         </ul>
+ *         </li>
+ *     <li>A MediaPlayer2 object must first enter the <em>Prepared</em> state
  *         before playback can be started.
  *         <ul>
- *         <li>The <strong>Paused</strong> state can be reached by calling {@link #prepare()}. Note
- *         that {@link #prepare()} is asynchronous. When the preparation completes,
+ *         <li>There are an asynchronous way that the <em>Prepared</em> state can be reached:
+ *         a call to {@link #prepare()} (asynchronous) which
+ *         first transfers the object to the <em>Preparing</em> state after the
+ *         call returns (which occurs almost right way) while the internal
+ *         player engine continues working on the rest of preparation work
+ *         until the preparation work completes. When the preparation completes,
  *         the internal player engine then calls a user supplied callback method,
- *         {@link MediaPlayer2EventCallback#onInfo} interface with {@link #MEDIA_INFO_PREPARED},
- *         if a MediaPlayer2EventCallback is registered beforehand via
+ *         onInfo() of the MediaPlayer2EventCallback interface with {@link #MEDIA_INFO_PREPARED},
+ *         if an MediaPlayer2EventCallback is registered beforehand via
  *         {@link #setMediaPlayer2EventCallback(Executor, MediaPlayer2EventCallback)}.</li>
- *         <li>The player also goes to <strong>Paused</strong> state when {@link #pause()} is called
- *         to pause the ongoing playback. Note that {@link #pause()} is asynchronous. Once
- *         {@link #pause()} is processed successfully by the internal media engine,
- *         <strong>Paused</strong> state will be notified with
- *         {@link MediaPlayerInterface.PlayerEventCallback#onPlayerStateChanged} callback.
- *         In addition to the callback, {@link #getMediaPlayer2State()} can also be used to test
- *         whether the MediaPlayer2 object is in the <strong>Paused</strong> state.
- *         </li>
- *         <li>While in the <em>Paused</em> state, properties such as audio/sound volume, looping
- *         can be adjusted by invoking the corresponding set methods.</li>
+ *         <li>It is important to note that
+ *         the <em>Preparing</em> state is a transient state, and the behavior
+ *         of calling any method with side effect while a MediaPlayer2 object is
+ *         in the <em>Preparing</em> state is undefined.</li>
+ *         <li>An IllegalStateException is
+ *         thrown if {@link #prepare()} is called in
+ *         any other state.</li>
+ *         <li>While in the <em>Prepared</em> state, properties
+ *         such as audio/sound volume, screenOnWhilePlaying, looping can be
+ *         adjusted by invoking the corresponding set methods.</li>
  *         </ul>
  *         </li>
- *     <li>To start the playback, {@link #play()} must be called. Once {@link #play()} is processed
- *         successfully by the internal media engine, <strong>Playing</strong> state will be
- *         notified with {@link MediaPlayerInterface.PlayerEventCallback#onPlayerStateChanged}
- *         callback.
- *         In addition to the callback, {@link #getMediaPlayer2State()} can be called to test
- *         whether the MediaPlayer2 object is in the <strong>Started</strong> state.
+ *     <li>To start the playback, {@link #play()} must be called. After
+ *         {@link #play()} returns successfully, the MediaPlayer2 object is in the
+ *         <em>Started</em> state. {@link #getPlayerState()} can be called to test
+ *         whether the MediaPlayer2 object is in the <em>Started</em> state.
  *         <ul>
- *         <li>While in the <strong>Playing</strong> state, the internal player engine calls
+ *         <li>While in the <em>Started</em> state, the internal player engine calls
  *         a user supplied callback method MediaPlayer2EventCallback.onInfo() with
  *         {@link #MEDIA_INFO_BUFFERING_UPDATE} if an MediaPlayer2EventCallback has been
  *         registered beforehand via
@@ -161,21 +193,42 @@
  *         This callback allows applications to keep track of the buffering status
  *         while streaming audio/video.</li>
  *         <li>Calling {@link #play()} has not effect
- *         on a MediaPlayer2 object that is already in the <strong>Playing</strong> state.</li>
+ *         on a MediaPlayer2 object that is already in the <em>Started</em> state.</li>
  *         </ul>
  *         </li>
- *     <li>The playback position can be adjusted with a call to {@link #seekTo}.
+ *     <li>Playback can be paused and stopped, and the current playback position
+ *         can be adjusted. Playback can be paused via {@link #pause()}. When the call to
+ *         {@link #pause()} returns, the MediaPlayer2 object enters the
+ *         <em>Paused</em> state. Note that the transition from the <em>Started</em>
+ *         state to the <em>Paused</em> state and vice versa happens
+ *         asynchronously in the player engine. It may take some time before
+ *         the state is updated in calls to {@link #getPlayerState()}, and it can be
+ *         a number of seconds in the case of streamed content.
  *         <ul>
- *         <li>Although the asynchronous {@link #seekTo} call returns right away,
- *         the actual seek operation may take a while to
+ *         <li>Calling {@link #play()} to resume playback for a paused
+ *         MediaPlayer2 object, and the resumed playback
+ *         position is the same as where it was paused. When the call to
+ *         {@link #play()} returns, the paused MediaPlayer2 object goes back to
+ *         the <em>Started</em> state.</li>
+ *         <li>Calling {@link #pause()} has no effect on
+ *         a MediaPlayer2 object that is already in the <em>Paused</em> state.</li>
+ *         </ul>
+ *         </li>
+ *     <li>The playback position can be adjusted with a call to
+ *         {@link #seekTo(long, int)}.
+ *         <ul>
+ *         <li>Although the asynchronuous {@link #seekTo(long, int)}
+ *         call returns right away, the actual seek operation may take a while to
  *         finish, especially for audio/video being streamed. When the actual
  *         seek operation completes, the internal player engine calls a user
  *         supplied MediaPlayer2EventCallback.onCallCompleted() with
  *         {@link #CALL_COMPLETED_SEEK_TO}
  *         if an MediaPlayer2EventCallback has been registered beforehand via
  *         {@link #setMediaPlayer2EventCallback(Executor, MediaPlayer2EventCallback)}.</li>
- *         <li>Please note that {@link #seekTo(long, int)} can also be called in
- *         <strong>Paused</strong> state. When {@link #seekTo(long, int)} is called in those states,
+ *         <li>Please
+ *         note that {@link #seekTo(long, int)} can also be called in the other states,
+ *         such as <em>Prepared</em>, <em>Paused</em> and <em>PlaybackCompleted
+ *         </em> state. When {@link #seekTo(long, int)} is called in those states,
  *         one video frame will be displayed if the stream has video and the requested
  *         position is valid.
  *         </li>
@@ -188,20 +241,206 @@
  *     <li>When the playback reaches the end of stream, the playback completes.
  *         <ul>
  *         <li>If current source is set to loop by {@link #loopCurrent(boolean)},
- *         the MediaPlayer2 object shall remain in the <strong>Playing</strong> state.</li>
+ *         the MediaPlayer2 object shall remain in the <em>Started</em> state.</li>
  *         <li>If the looping mode was set to <var>false
  *         </var>, the player engine calls a user supplied callback method,
- *         {@link MediaPlayer2EventCallback#onInfo} with {@link #MEDIA_INFO_PLAYBACK_COMPLETE},
- *         if an MediaPlayer2EventCallback is registered beforehand via
+ *         MediaPlayer2EventCallback.onCompletion(), if an MediaPlayer2EventCallback is
+ *         registered beforehand via
  *         {@link #setMediaPlayer2EventCallback(Executor, MediaPlayer2EventCallback)}.
- *         The invoke of the callback signals that the object is now in the <strong>Paused</strong>
- *         state.</li>
- *         <li>While in the <strong>Paused</strong> state, calling {@link #play()} can restart the
- *         playback from the beginning of the audio/video source.</li>
+ *         The invoke of the callback signals that the object is now in the <em>
+ *         PlaybackCompleted</em> state.</li>
+ *         <li>While in the <em>PlaybackCompleted</em>
+ *         state, calling {@link #play()} can restart the playback from the
+ *         beginning of the audio/video source.</li>
  * </ul>
  *
+ *
+ * <a name="Valid_and_Invalid_States"></a>
+ * <h3>Valid and invalid states</h3>
+ *
+ * <table border="0" cellspacing="0" cellpadding="0">
+ * <tr><td>Method Name </p></td>
+ *     <td>Valid Sates </p></td>
+ *     <td>Invalid States </p></td>
+ *     <td>Comments </p></td></tr>
+ * <tr><td>attachAuxEffect </p></td>
+ *     <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} </p></td>
+ *     <td>{Idle, Error} </p></td>
+ *     <td>This method must be called after setDataSource.
+ *     Calling it does not change the object state. </p></td></tr>
+ * <tr><td>getAudioSessionId </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>getCurrentPosition </p></td>
+ *     <td>{Idle, Initialized, Prepared, Started, Paused, Stopped,
+ *         PlaybackCompleted} </p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change the
+ *         state. Calling this method in an invalid state transfers the object
+ *         to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>getDuration </p></td>
+ *     <td>{Prepared, Started, Paused, Stopped, PlaybackCompleted} </p></td>
+ *     <td>{Idle, Initialized, Error} </p></td>
+ *     <td>Successful invoke of this method in a valid state does not change the
+ *         state. Calling this method in an invalid state transfers the object
+ *         to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>getVideoHeight </p></td>
+ *     <td>{Idle, Initialized, Prepared, Started, Paused, Stopped,
+ *         PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change the
+ *         state. Calling this method in an invalid state transfers the object
+ *         to the <em>Error</em> state.  </p></td></tr>
+ * <tr><td>getVideoWidth </p></td>
+ *     <td>{Idle, Initialized, Prepared, Started, Paused, Stopped,
+ *         PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change
+ *         the state. Calling this method in an invalid state transfers the
+ *         object to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>getPlayerState </p></td>
+ *     <td>{Idle, Initialized, Prepared, Started, Paused, Stopped,
+ *          PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change
+ *         the state. Calling this method in an invalid state transfers the
+ *         object to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>pause </p></td>
+ *     <td>{Started, Paused, PlaybackCompleted}</p></td>
+ *     <td>{Idle, Initialized, Prepared, Stopped, Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the
+ *         object to the <em>Paused</em> state. Calling this method in an
+ *         invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
+ * <tr><td>prepare </p></td>
+ *     <td>{Initialized, Stopped} </p></td>
+ *     <td>{Idle, Prepared, Started, Paused, PlaybackCompleted, Error} </p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the
+ *         object to the <em>Preparing</em> state. Calling this method in an
+ *         invalid state throws an IllegalStateException.</p></td></tr>
+ * <tr><td>release </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>After {@link #close()}, the object is no longer available. </p></td></tr>
+ * <tr><td>reset </p></td>
+ *     <td>{Idle, Initialized, Prepared, Started, Paused, Stopped,
+ *         PlaybackCompleted, Error}</p></td>
+ *     <td>{}</p></td>
+ *     <td>After {@link #reset()}, the object is like being just created.</p></td></tr>
+ * <tr><td>seekTo </p></td>
+ *     <td>{Prepared, Started, Paused, PlaybackCompleted} </p></td>
+ *     <td>{Idle, Initialized, Stopped, Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change
+ *         the state. Calling this method in an invalid state transfers the
+ *         object to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>setAudioAttributes </p></td>
+ *     <td>{Idle, Initialized, Stopped, Prepared, Started, Paused,
+ *          PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method does not change the state. In order for the
+ *         target audio attributes type to become effective, this method must be called before
+ *         prepare().</p></td></tr>
+ * <tr><td>setAudioSessionId </p></td>
+ *     <td>{Idle} </p></td>
+ *     <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted,
+ *          Error} </p></td>
+ *     <td>This method must be called in idle state as the audio session ID must be known before
+ *         calling setDataSource. Calling it does not change the object
+ *         state. </p></td></tr>
+ * <tr><td>setAudioStreamType (deprecated)</p></td>
+ *     <td>{Idle, Initialized, Stopped, Prepared, Started, Paused,
+ *          PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method does not change the state. In order for the
+ *         target audio stream type to become effective, this method must be called before
+ *         prepare().</p></td></tr>
+ * <tr><td>setAuxEffectSendLevel </p></td>
+ *     <td>any</p></td>
+ *     <td>{} </p></td>
+ *     <td>Calling this method does not change the object state. </p></td></tr>
+ * <tr><td>setDataSource </p></td>
+ *     <td>{Idle} </p></td>
+ *     <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted,
+ *          Error} </p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the
+ *         object to the <em>Initialized</em> state. Calling this method in an
+ *         invalid state throws an IllegalStateException.</p></td></tr>
+ * <tr><td>setDisplay </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setSurface </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>loopCurrent </p></td>
+ *     <td>{Idle, Initialized, Stopped, Prepared, Started, Paused,
+ *         PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change
+ *         the state. Calling this method in an
+ *         invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
+ * <tr><td>isLooping </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setDrmEventCallback </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setMediaPlayer2EventCallback </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setPlaybackParams</p></td>
+ *     <td>{Initialized, Prepared, Started, Paused, PlaybackCompleted, Error}</p></td>
+ *     <td>{Idle, Stopped} </p></td>
+ *     <td>This method will change state in some cases, depending on when it's called.
+ *         </p></td></tr>
+ * <tr><td>setPlayerVolume </p></td>
+ *     <td>{Idle, Initialized, Stopped, Prepared, Started, Paused,
+ *          PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method does not change the state.
+ * <tr><td>play </p></td>
+ *     <td>{Prepared, Started, Paused, PlaybackCompleted}</p></td>
+ *     <td>{Idle, Initialized, Stopped, Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the
+ *         object to the <em>Started</em> state. Calling this method in an
+ *         invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
+ * <tr><td>stop </p></td>
+ *     <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td>
+ *     <td>{Idle, Initialized, Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the
+ *         object to the <em>Stopped</em> state. Calling this method in an
+ *         invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
+ * <tr><td>getTrackInfo </p></td>
+ *     <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td>
+ *     <td>{Idle, Initialized, Error}</p></td>
+ *     <td>Successful invoke of this method does not change the state.</p></td></tr>
+ * <tr><td>selectTrack </p></td>
+ *     <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td>
+ *     <td>{Idle, Initialized, Error}</p></td>
+ *     <td>Successful invoke of this method does not change the state.</p></td></tr>
+ * <tr><td>deselectTrack </p></td>
+ *     <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td>
+ *     <td>{Idle, Initialized, Error}</p></td>
+ *     <td>Successful invoke of this method does not change the state.</p></td></tr>
+ *
+ * </table>
+ *
  * <a name="Permissions"></a>
  * <h3>Permissions</h3>
+ * <p>One may need to declare a corresponding WAKE_LOCK permission {@link
+ * android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
+ * element.
+ *
  * <p>This class requires the {@link android.Manifest.permission#INTERNET} permission
  * when used with network-based content.
  *
@@ -221,7 +460,8 @@
  *
  */
 @TargetApi(Build.VERSION_CODES.P)
-public abstract class MediaPlayer2 {
+@RestrictTo(LIBRARY_GROUP)
+public abstract class MediaPlayer2 extends MediaPlayerBase {
     /**
      * Create a MediaPlayer2 object.
      *
@@ -238,12 +478,6 @@
     public MediaPlayer2() { }
 
     /**
-     * Returns a {@link MediaPlayerInterface} implementation which runs based on
-     * this MediaPlayer2 instance.
-     */
-    public abstract MediaPlayerInterface getMediaPlayerInterface();
-
-    /**
      * Releases the resources held by this {@code MediaPlayer2} object.
      *
      * It is considered good practice to call this method when you're
@@ -261,8 +495,13 @@
      * of the same codec are supported, some performance degradation
      * may be expected when unnecessary multiple instances are used
      * at the same time.
+     *
+     * {@code close()} may be safely called after a prior {@code close()}.
+     * This class implements the Java {@code AutoCloseable} interface and
+     * may be used with try-with-resources.
      */
     // This is a synchronous call.
+    @Override
     public abstract void close();
 
     /**
@@ -274,6 +513,7 @@
      *
      */
     // This is an asynchronous call.
+    @Override
     public abstract void play();
 
     /**
@@ -284,18 +524,21 @@
      *
      */
     // This is an asynchronous call.
+    @Override
     public abstract void prepare();
 
     /**
      * Pauses playback. Call play() to resume.
      */
     // This is an asynchronous call.
+    @Override
     public abstract void pause();
 
     /**
      * Tries to play next data source if applicable.
      */
     // This is an asynchronous call.
+    @Override
     public abstract void skipToNext();
 
     /**
@@ -305,6 +548,7 @@
      * @param msec the offset in milliseconds from the start to seek to
      */
     // This is an asynchronous call.
+    @Override
     public void seekTo(long msec) {
         seekTo(msec, SEEK_PREVIOUS_SYNC /* mode */);
     }
@@ -314,6 +558,7 @@
      *
      * @return the current position in milliseconds
      */
+    @Override
     public abstract long getCurrentPosition();
 
     /**
@@ -322,6 +567,7 @@
      * @return the duration in milliseconds, if no duration is available
      *         (for example, if streaming live content), -1 is returned.
      */
+    @Override
     public abstract long getDuration();
 
     /**
@@ -333,14 +579,25 @@
      *
      * @return the current buffered media source position in milliseconds
      */
+    @Override
     public abstract long getBufferedPosition();
 
     /**
-     * Gets the current MediaPlayer2 state.
+     * Gets the current player state.
      *
-     * @return the current MediaPlayer2 state.
+     * @return the current player state.
      */
-    public abstract @MediaPlayer2State int getMediaPlayer2State();
+    @Override
+    public abstract @PlayerState int getPlayerState();
+
+    /**
+     * Gets the current buffering state of the player.
+     * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already
+     * buffered.
+     * @return the buffering state, one of the following:
+     */
+    @Override
+    public abstract @BuffState int getBufferingState();
 
     /**
      * Sets the audio attributes for this MediaPlayer2.
@@ -350,12 +607,14 @@
      * @param attributes a non-null set of audio attributes
      */
     // This is an asynchronous call.
+    @Override
     public abstract void setAudioAttributes(@NonNull AudioAttributesCompat attributes);
 
     /**
      * Gets the audio attributes for this MediaPlayer2.
      * @return attributes a set of audio attributes
      */
+    @Override
     public abstract @Nullable AudioAttributesCompat getAudioAttributes();
 
     /**
@@ -364,6 +623,7 @@
      * @param dsd the descriptor of data source you want to play
      */
     // This is an asynchronous call.
+    @Override
     public abstract void setDataSource(@NonNull DataSourceDesc dsd);
 
     /**
@@ -373,6 +633,7 @@
      * @param dsd the descriptor of data source you want to play after current one
      */
     // This is an asynchronous call.
+    @Override
     public abstract void setNextDataSource(@NonNull DataSourceDesc dsd);
 
     /**
@@ -381,6 +642,7 @@
      * @param dsds the list of data sources you want to play after current one
      */
     // This is an asynchronous call.
+    @Override
     public abstract void setNextDataSources(@NonNull List<DataSourceDesc> dsds);
 
     /**
@@ -388,6 +650,7 @@
      *
      * @return the current DataSourceDesc
      */
+    @Override
     public abstract @NonNull DataSourceDesc getCurrentDataSource();
 
     /**
@@ -395,6 +658,7 @@
      * @param loop true if the current data source is meant to loop.
      */
     // This is an asynchronous call.
+    @Override
     public abstract void loopCurrent(boolean loop);
 
     /**
@@ -407,6 +671,7 @@
      * @param speed the desired playback speed
      */
     // This is an asynchronous call.
+    @Override
     public abstract void setPlaybackSpeed(float speed);
 
     /**
@@ -414,6 +679,7 @@
      * Note that it may differ from the speed set in {@link #setPlaybackSpeed(float)}.
      * @return the actual playback speed
      */
+    @Override
     public float getPlaybackSpeed() {
         return 1.0f;
     }
@@ -424,6 +690,7 @@
      * {@link #setPlaybackSpeed(float)}.
      * @return true if reverse playback is supported.
      */
+    @Override
     public boolean isReversePlaybackSupported() {
         return false;
     }
@@ -438,6 +705,7 @@
      * @param volume a value between 0.0f and {@link #getMaxPlayerVolume()}.
      */
     // This is an asynchronous call.
+    @Override
     public abstract void setPlayerVolume(float volume);
 
     /**
@@ -445,16 +713,36 @@
      * Note that it does not take into account the associated stream volume.
      * @return the player volume.
      */
+    @Override
     public abstract float getPlayerVolume();
 
     /**
      * @return the maximum volume that can be used in {@link #setPlayerVolume(float)}.
      */
+    @Override
     public float getMaxPlayerVolume() {
         return 1.0f;
     }
 
     /**
+     * Adds a callback to be notified of events for this player.
+     * @param e the {@link Executor} to be used for the events.
+     * @param cb the callback to receive the events.
+     */
+    // This is a synchronous call.
+    @Override
+    public abstract void registerPlayerEventCallback(@NonNull Executor e,
+                                                     @NonNull PlayerEventCallback cb);
+
+    /**
+     * Removes a previously registered callback for player events
+     * @param cb the callback to remove
+     */
+    // This is a synchronous call.
+    @Override
+    public abstract void unregisterPlayerEventCallback(@NonNull PlayerEventCallback cb);
+
+    /**
      * Insert a task in the command queue to help the client to identify whether a batch
      * of commands has been finished. When this command is processed, a notification
      * {@code MediaPlayer2EventCallback.onCommandLabelReached} will be fired with the
@@ -544,7 +832,10 @@
      *
      *  Additional vendor-specific fields may also be present in
      *  the return value.
+     *  @hide
+     *  TODO: This method is not ready for public. Currently returns metrics data in MediaPlayer1.
      */
+    @RestrictTo(LIBRARY_GROUP)
     public abstract PersistableBundle getMetrics();
 
     /**
@@ -639,8 +930,7 @@
     /**
      * Moves the media to specified time position by considering the given mode.
      * <p>
-     * When seekTo is finished, the user will be notified via
-     * {@link MediaPlayer2EventCallback#onInfo} with {@link #CALL_COMPLETED_SEEK_TO}.
+     * When seekTo is finished, the user will be notified via OnSeekComplete supplied by the user.
      * There is at most one active seekTo processed at any time. If there is a to-be-completed
      * seekTo, new seekTo requests will be queued in such a way that only the last request
      * is kept. When current seekTo is completed, the queued request will be processed if
@@ -658,7 +948,7 @@
     public abstract void seekTo(long msec, @SeekMode int mode);
 
     /**
-     * Gets current playback position as a {@link MediaTimestamp}.
+     * Get current playback position as a {@link MediaTimestamp}.
      * <p>
      * The MediaTimestamp represents how the media time correlates to the system time in
      * a linear fashion using an anchor and a clock rate. During regular playback, the media
@@ -684,6 +974,7 @@
      * data source and calling prepare().
      */
     // This is a synchronous call.
+    @Override
     public abstract void reset();
 
     /**
@@ -818,9 +1109,8 @@
     /**
      * Selects a track.
      * <p>
-     * If a MediaPlayer2 is in invalid state, {@link #CALL_STATUS_INVALID_OPERATION} will be
-     * reported with {@link MediaPlayer2EventCallback#onCallCompleted}.
-     * If a MediaPlayer2 is in <em>Playing</em> state, the selected track is presented immediately.
+     * If a MediaPlayer2 is in invalid state, it throws an IllegalStateException exception.
+     * If a MediaPlayer2 is in <em>Started</em> state, the selected track is presented immediately.
      * If a MediaPlayer2 is not in Started state, it just marks the track to be played.
      * </p>
      * <p>
@@ -834,10 +1124,13 @@
      * </p>
      * <p>
      * Currently, only timed text tracks or audio tracks can be selected via this method.
+     * In addition, the support for selecting an audio track at runtime is pretty limited
+     * in that an audio track can only be selected in the <em>Prepared</em> state.
      * </p>
      * @param index the index of the track to be selected. The valid range of the index
      * is 0..total number of track - 1. The total number of tracks as well as the type of
      * each individual track can be found by calling {@link #getTrackInfo()} method.
+     * @throws IllegalStateException if called in an invalid state.
      *
      * @see MediaPlayer2#getTrackInfo
      */
@@ -845,7 +1138,7 @@
     public abstract void selectTrack(int index);
 
     /**
-     * Deselects a track.
+     * Deselect a track.
      * <p>
      * Currently, the track must be a timed text track and no audio or video tracks can be
      * deselected. If the timed text track identified by index has not been
@@ -854,6 +1147,7 @@
      * @param index the index of the track to be deselected. The valid range of the index
      * is 0..total number of tracks - 1. The total number of tracks as well as the type of
      * each individual track can be found by calling {@link #getTrackInfo()} method.
+     * @throws IllegalStateException if called in an invalid state.
      *
      * @see MediaPlayer2#getTrackInfo
      */
@@ -935,26 +1229,13 @@
                 @CallStatus int status) { }
 
         /**
-         * Called when a discontinuity in the normal progression of the media time is detected.
-         * The "normal progression" of media time is defined as the expected increase of the
-         * playback position when playing media, relative to the playback speed (for instance every
-         * second, media time increases by two seconds when playing at 2x).<br>
-         * Discontinuities are encountered in the following cases:
-         * <ul>
-         * <li>when the player is starved for data and cannot play anymore</li>
-         * <li>when the player encounters a playback error</li>
-         * <li>when the a seek operation starts, and when it's completed</li>
-         * <li>when the playback speed changes</li>
-         * <li>when the playback state changes</li>
-         * <li>when the player is reset</li>
-         * </ul>
+         * Called to indicate media clock has changed.
          *
          * @param mp the MediaPlayer2 the media time pertains to.
          * @param dsd the DataSourceDesc of this data source
-         * @param timestamp the timestamp that correlates media time, system time and clock rate,
-         *     or {@link MediaTimestamp#TIMESTAMP_UNKNOWN} in an error case.
+         * @param timestamp the new media clock.
          */
-        public void onMediaTimeDiscontinuity(
+        public void onMediaTimeChanged(
                 MediaPlayer2 mp, DataSourceDesc dsd, MediaTimestamp timestamp) { }
 
         /**
@@ -966,14 +1247,12 @@
          */
         public void onCommandLabelReached(MediaPlayer2 mp, @NonNull Object label) { }
 
-        /**
+        /* TODO : uncomment below once API is available in supportlib.
          * Called when when a player subtitle track has new subtitle data available.
          * @param mp the player that reports the new subtitle data
-         * @param dsd the DataSourceDesc of this data source
          * @param data the subtitle data
          */
-        public void onSubtitleData(
-                MediaPlayer2 mp, DataSourceDesc dsd, @NonNull SubtitleData data) { }
+        // public void onSubtitleData(MediaPlayer2 mp, @NonNull SubtitleData data) { }
     }
 
     /**
@@ -992,46 +1271,6 @@
     // This is a synchronous call.
     public abstract void clearMediaPlayer2EventCallback();
 
-    /**
-     * MediaPlayer2 has not been prepared or just has been reset.
-     * In this state, MediaPlayer2 doesn't fetch data.
-     */
-    public static final int MEDIAPLAYER2_STATE_IDLE = 1001;
-
-    /**
-     * MediaPlayer2 has been just prepared.
-     * In this state, MediaPlayer2 just fetches data from media source,
-     * but doesn't actively render data.
-     */
-    public static final int MEDIAPLAYER2_STATE_PREPARED = 1002;
-
-    /**
-     * MediaPlayer2 is paused.
-     * In this state, MediaPlayer2 doesn't actively render data.
-     */
-    public static final int MEDIAPLAYER2_STATE_PAUSED = 1003;
-
-    /**
-     * MediaPlayer2 is actively playing back data.
-     */
-    public static final int MEDIAPLAYER2_STATE_PLAYING = 1004;
-
-    /**
-     * MediaPlayer2 has hit some fatal error and cannot continue playback.
-     */
-    public static final int MEDIAPLAYER2_STATE_ERROR = 1005;
-
-    /** @hide */
-    @IntDef(flag = false, value = {
-            MEDIAPLAYER2_STATE_IDLE,
-            MEDIAPLAYER2_STATE_PREPARED,
-            MEDIAPLAYER2_STATE_PAUSED,
-            MEDIAPLAYER2_STATE_PLAYING,
-            MEDIAPLAYER2_STATE_ERROR })
-    @Retention(RetentionPolicy.SOURCE)
-    @RestrictTo(LIBRARY_GROUP)
-    public @interface MediaPlayer2State {}
-
     /* Do not change these values without updating their counterparts
      * in include/media/mediaplayer2.h!
      */
@@ -1092,9 +1331,7 @@
     /** The player switched to this datas source because it is the
      * next-to-be-played in the playlist.
      * @see MediaPlayer2.MediaPlayer2EventCallback#onInfo
-     * @hide
      */
-    @RestrictTo(LIBRARY_GROUP)
     public static final int MEDIA_INFO_STARTED_AS_NEXT = 2;
 
     /** The player just pushed the very first video frame for rendering.
@@ -1275,6 +1512,16 @@
      */
     public static final int CALL_COMPLETED_PREPARE = 6;
 
+    /** The player just completed a call {@link #releaseDrm}.
+     * @see MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
+     */
+    public static final int CALL_COMPLETED_RELEASE_DRM = 12;
+
+    /** The player just completed a call {@link #restoreDrmKeys}.
+     * @see MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
+     */
+    public static final int CALL_COMPLETED_RESTORE_DRM_KEYS = 13;
+
     /** The player just completed a call {@link #seekTo}.
      * @see MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
      */
@@ -1362,6 +1609,8 @@
             CALL_COMPLETED_PAUSE,
             CALL_COMPLETED_PLAY,
             CALL_COMPLETED_PREPARE,
+            CALL_COMPLETED_RELEASE_DRM,
+            CALL_COMPLETED_RESTORE_DRM_KEYS,
             CALL_COMPLETED_SEEK_TO,
             CALL_COMPLETED_SELECT_TRACK,
             CALL_COMPLETED_SET_AUDIO_ATTRIBUTES,
@@ -1412,6 +1661,12 @@
      */
     public static final int CALL_STATUS_ERROR_IO = 4;
 
+    /** Status code represents that DRM operation is called before preparing a DRM scheme through
+     *  {@link #prepareDrm}.
+     * @see MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
+     */
+    public static final int CALL_STATUS_NO_DRM_SCHEME = 5;
+
     /**
      * @hide
      */
@@ -1421,7 +1676,8 @@
             CALL_STATUS_INVALID_OPERATION,
             CALL_STATUS_BAD_VALUE,
             CALL_STATUS_PERMISSION_DENIED,
-            CALL_STATUS_ERROR_IO})
+            CALL_STATUS_ERROR_IO,
+            CALL_STATUS_NO_DRM_SCHEME})
     @Retention(RetentionPolicy.SOURCE)
     @RestrictTo(LIBRARY_GROUP)
     public @interface CallStatus {}
@@ -1752,100 +2008,4 @@
             super(detailMessage);
         }
     }
-
-    /**
-     * Definitions for the metrics that are reported via the {@link #getMetrics} call.
-     */
-    public static final class MetricsConstants {
-        private MetricsConstants() {}
-
-        /**
-         * Key to extract the MIME type of the video track
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
-
-        /**
-         * Key to extract the codec being used to decode the video track
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-
-        /**
-         * Key to extract the width (in pixels) of the video track
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String WIDTH = "android.media.mediaplayer.width";
-
-        /**
-         * Key to extract the height (in pixels) of the video track
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String HEIGHT = "android.media.mediaplayer.height";
-
-        /**
-         * Key to extract the count of video frames played
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String FRAMES = "android.media.mediaplayer.frames";
-
-        /**
-         * Key to extract the count of video frames dropped
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-
-        /**
-         * Key to extract the MIME type of the audio track
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
-
-        /**
-         * Key to extract the codec being used to decode the audio track
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-
-        /**
-         * Key to extract the duration (in milliseconds) of the
-         * media being played
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is a long.
-         */
-        public static final String DURATION = "android.media.mediaplayer.durationMs";
-
-        /**
-         * Key to extract the playing time (in milliseconds) of the
-         * media being played
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is a long.
-         */
-        public static final String PLAYING = "android.media.mediaplayer.playingMs";
-
-        /**
-         * Key to extract the count of errors encountered while
-         * playing the media
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String ERRORS = "android.media.mediaplayer.err";
-
-        /**
-         * Key to extract an (optional) error code detected while
-         * playing the media
-         * from the {@link MediaPlayer2#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String ERROR_CODE = "android.media.mediaplayer.errcode";
-
-    }
 }
diff --git a/media/src/main/java/androidx/media/MediaPlayer2Impl.java b/media/src/main/java/androidx/media/MediaPlayer2Impl.java
index 3504876..3b3e119 100644
--- a/media/src/main/java/androidx/media/MediaPlayer2Impl.java
+++ b/media/src/main/java/androidx/media/MediaPlayer2Impl.java
@@ -28,7 +28,6 @@
 import android.media.MediaTimestamp;
 import android.media.PlaybackParams;
 import android.media.ResourceBusyException;
-import android.media.SubtitleData;
 import android.media.SyncParams;
 import android.media.TimedMetaData;
 import android.media.UnsupportedSchemeException;
@@ -37,7 +36,9 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.PersistableBundle;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Pair;
 import android.view.Surface;
@@ -46,11 +47,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
-import androidx.collection.ArrayMap;
 import androidx.core.util.Preconditions;
-import androidx.media.MediaPlayerInterface.BuffState;
-import androidx.media.MediaPlayerInterface.PlayerEventCallback;
-import androidx.media.MediaPlayerInterface.PlayerState;
 
 import java.io.IOException;
 import java.nio.ByteOrder;
@@ -73,15 +70,13 @@
 
     private static final String TAG = "MediaPlayer2Impl";
 
-    private static final int SOURCE_STATE_ERROR = -1;
-    private static final int SOURCE_STATE_INIT = 0;
-    private static final int SOURCE_STATE_PREPARING = 1;
-    private static final int SOURCE_STATE_PREPARED = 2;
+    private static final int NEXT_SOURCE_STATE_ERROR = -1;
+    private static final int NEXT_SOURCE_STATE_INIT = 0;
+    private static final int NEXT_SOURCE_STATE_PREPARING = 1;
+    private static final int NEXT_SOURCE_STATE_PREPARED = 2;
 
     private static ArrayMap<Integer, Integer> sInfoEventMap;
     private static ArrayMap<Integer, Integer> sErrorEventMap;
-    private static ArrayMap<Integer, Integer> sPrepareDrmStatusMap;
-    private static ArrayMap<Integer, Integer> sStateMap;
 
     static {
         sInfoEventMap = new ArrayMap<>();
@@ -111,29 +106,24 @@
         sErrorEventMap.put(MediaPlayer.MEDIA_ERROR_MALFORMED, MEDIA_ERROR_MALFORMED);
         sErrorEventMap.put(MediaPlayer.MEDIA_ERROR_UNSUPPORTED, MEDIA_ERROR_UNSUPPORTED);
         sErrorEventMap.put(MediaPlayer.MEDIA_ERROR_TIMED_OUT, MEDIA_ERROR_TIMED_OUT);
-
-        sPrepareDrmStatusMap = new ArrayMap<>();
-        sPrepareDrmStatusMap.put(
-                MediaPlayer.PREPARE_DRM_STATUS_SUCCESS, PREPARE_DRM_STATUS_SUCCESS);
-        sPrepareDrmStatusMap.put(
-                MediaPlayer.PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR,
-                PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR);
-        sPrepareDrmStatusMap.put(
-                MediaPlayer.PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR,
-                PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR);
-        sPrepareDrmStatusMap.put(
-                MediaPlayer.PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR,
-                PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR);
-
-        sStateMap = new ArrayMap<>();
-        sStateMap.put(MEDIAPLAYER2_STATE_IDLE, MediaPlayerInterface.PLAYER_STATE_IDLE);
-        sStateMap.put(MEDIAPLAYER2_STATE_PREPARED, MediaPlayerInterface.PLAYER_STATE_PAUSED);
-        sStateMap.put(MEDIAPLAYER2_STATE_PAUSED, MediaPlayerInterface.PLAYER_STATE_PAUSED);
-        sStateMap.put(MEDIAPLAYER2_STATE_PLAYING, MediaPlayerInterface.PLAYER_STATE_PLAYING);
-        sStateMap.put(MEDIAPLAYER2_STATE_ERROR, MediaPlayerInterface.PLAYER_STATE_ERROR);
     }
 
-    private MediaPlayerSourceQueue mPlayer;
+    private MediaPlayer mPlayer;  // MediaPlayer is thread-safe.
+
+    private final Object mSrcLock = new Object();
+    //--- guarded by |mSrcLock| start
+    private long mSrcIdGenerator = 0;
+    private DataSourceDesc mCurrentDSD;
+    private long mCurrentSrcId = mSrcIdGenerator++;
+    private List<DataSourceDesc> mNextDSDs;
+    private long mNextSrcId = mSrcIdGenerator++;
+    private int mNextSourceState = NEXT_SOURCE_STATE_INIT;
+    private boolean mNextSourcePlayPending = false;
+    //--- guarded by |mSrcLock| end
+
+    private AtomicInteger mBufferedPercentageCurrent = new AtomicInteger(0);
+    private AtomicInteger mBufferedPercentageNext = new AtomicInteger(0);
+    private volatile float mVolume = 1.0f;
 
     private HandlerThread mHandlerThread;
     private final Handler mTaskHandler;
@@ -145,6 +135,8 @@
 
     private final Object mLock = new Object();
     //--- guarded by |mLock| start
+    @PlayerState private int mPlayerState;
+    @BuffState private int mBufferingState;
     private AudioAttributesCompat mAudioAttributes;
     private ArrayList<Pair<Executor, MediaPlayer2EventCallback>> mMp2EventCallbackRecords =
             new ArrayList<>();
@@ -152,21 +144,8 @@
             new ArrayMap<>();
     private ArrayList<Pair<Executor, DrmEventCallback>> mDrmEventCallbackRecords =
             new ArrayList<>();
-    private MediaPlayerInterfaceImpl mMediaPlayerInterfaceImpl;
     //--- guarded by |mLock| end
 
-    private void handleDataSourceError(final DataSourceError err) {
-        if (err == null) {
-            return;
-        }
-        notifyMediaPlayer2Event(new Mp2EventNotifier() {
-            @Override
-            public void notify(MediaPlayer2EventCallback callback) {
-                callback.onError(MediaPlayer2Impl.this, err.mDSD, err.mWhat, err.mExtra);
-            }
-        });
-    }
-
     /**
      * Default constructor.
      * <p>When done with the MediaPlayer2Impl, you should call  {@link #close()},
@@ -178,24 +157,10 @@
         mHandlerThread.start();
         Looper looper = mHandlerThread.getLooper();
         mTaskHandler = new Handler(looper);
-
-        // TODO: To make sure MediaPlayer1 listeners work, the caller thread should have a looper.
-        // Fix the framework or document this behavior.
-        mPlayer = new MediaPlayerSourceQueue();
-    }
-
-    /**
-     * Returns a {@link MediaPlayerInterface} implementation which runs based on
-     * this MediaPlayer2 instance.
-     */
-    @Override
-    public MediaPlayerInterface getMediaPlayerInterface() {
-        synchronized (mLock) {
-            if (mMediaPlayerInterfaceImpl == null) {
-                mMediaPlayerInterfaceImpl = new MediaPlayerInterfaceImpl();
-            }
-            return mMediaPlayerInterfaceImpl;
-        }
+        mPlayer = new MediaPlayer();
+        mPlayerState = PLAYER_STATE_IDLE;
+        mBufferingState = BUFFERING_STATE_UNKNOWN;
+        setUpListeners();
     }
 
     /**
@@ -239,7 +204,8 @@
         addTask(new Task(CALL_COMPLETED_PLAY, false) {
             @Override
             void process() {
-                mPlayer.play();
+                mPlayer.start();
+                setPlayerState(PLAYER_STATE_PLAYING);
             }
         });
     }
@@ -260,6 +226,7 @@
             @Override
             void process() throws IOException {
                 mPlayer.prepareAsync();
+                setBufferingState(BUFFERING_STATE_BUFFERING_AND_STARVED);
             }
         });
     }
@@ -275,6 +242,7 @@
             @Override
             void process() {
                 mPlayer.pause();
+                setPlayerState(PLAYER_STATE_PAUSED);
             }
         });
     }
@@ -289,7 +257,7 @@
         addTask(new Task(CALL_COMPLETED_SKIP_TO_NEXT, false) {
             @Override
             void process() {
-                mPlayer.skipToNext();
+                // TODO: switch to next data source and play
             }
         });
     }
@@ -327,21 +295,14 @@
     @Override
     public long getBufferedPosition() {
         // Use cached buffered percent for now.
-        return mPlayer.getBufferedPosition();
+        return getDuration() * mBufferedPercentageCurrent.get() / 100;
     }
 
-    /**
-     * Gets the current MediaPlayer2 state.
-     *
-     * @return the current MediaPlayer2 state.
-     */
     @Override
-    public @MediaPlayer2State int getMediaPlayer2State() {
-        return mPlayer.getMediaPlayer2State();
-    }
-
-    private @MediaPlayerInterface.PlayerState int getPlayerState() {
-        return mPlayer.getPlayerState();
+    public @PlayerState int getPlayerState() {
+        synchronized (mLock) {
+            return mPlayerState;
+        }
     }
 
     /**
@@ -349,8 +310,11 @@
      * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already
      * buffered.
      */
-    private @MediaPlayerInterface.BuffState int getBufferingState() {
-        return  mPlayer.getBufferingState();
+    @Override
+    public @BuffState int getBufferingState() {
+        synchronized (mLock) {
+            return mBufferingState;
+        }
     }
 
     /**
@@ -397,10 +361,13 @@
             void process() {
                 Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
                 // TODO: setDataSource could update exist data source
-                try {
-                    mPlayer.setFirst(dsd);
-                } catch (IOException e) {
-                    Log.e(TAG, "process: setDataSource", e);
+                synchronized (mSrcLock) {
+                    mCurrentDSD = dsd;
+                    mCurrentSrcId = mSrcIdGenerator++;
+                    try {
+                        handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId);
+                    } catch (IOException e) {
+                    }
                 }
             }
         });
@@ -420,7 +387,21 @@
             @Override
             void process() {
                 Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
-                handleDataSourceError(mPlayer.setNext(dsd));
+                synchronized (mSrcLock) {
+                    mNextDSDs = new ArrayList<DataSourceDesc>(1);
+                    mNextDSDs.add(dsd);
+                    mNextSrcId = mSrcIdGenerator++;
+                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                    mNextSourcePlayPending = false;
+                }
+                /* FIXME : define and handle state.
+                int state = getMediaPlayer2State();
+                if (state != MEDIAPLAYER2_STATE_IDLE) {
+                    synchronized (mSrcLock) {
+                        prepareNextDataSource_l();
+                    }
+                }
+                */
             }
         });
     }
@@ -446,14 +427,30 @@
                                 "DataSourceDesc in the source list cannot be null.");
                     }
                 }
-                handleDataSourceError(mPlayer.setNextMultiple(dsds));
+
+                synchronized (mSrcLock) {
+                    mNextDSDs = new ArrayList(dsds);
+                    mNextSrcId = mSrcIdGenerator++;
+                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                    mNextSourcePlayPending = false;
+                }
+                /* FIXME : define and handle state.
+                int state = getMediaPlayer2State();
+                if (state != MEDIAPLAYER2_STATE_IDLE) {
+                    synchronized (mSrcLock) {
+                        prepareNextDataSource_l();
+                    }
+                }
+                */
             }
         });
     }
 
     @Override
     public @NonNull DataSourceDesc getCurrentDataSource() {
-        return mPlayer.getFirst().getDSD();
+        synchronized (mSrcLock) {
+            return mCurrentDSD;
+        }
     }
 
     /**
@@ -524,7 +521,8 @@
         addTask(new Task(CALL_COMPLETED_SET_PLAYER_VOLUME, false) {
             @Override
             void process() {
-                mPlayer.setVolume(volume);
+                mVolume = volume;
+                mPlayer.setVolume(volume, volume);
             }
         });
     }
@@ -536,7 +534,7 @@
      */
     @Override
     public float getPlayerVolume() {
-        return mPlayer.getVolume();
+        return mVolume;
     }
 
     /**
@@ -552,7 +550,8 @@
      * @param e the {@link Executor} to be used for the events.
      * @param cb the callback to receive the events.
      */
-    private void registerPlayerEventCallback(@NonNull Executor e,
+    @Override
+    public void registerPlayerEventCallback(@NonNull Executor e,
             @NonNull PlayerEventCallback cb) {
         if (cb == null) {
             throw new IllegalArgumentException("Illegal null PlayerEventCallback");
@@ -570,7 +569,8 @@
      * Removes a previously registered callback for player events
      * @param cb the callback to remove
      */
-    private void unregisterPlayerEventCallback(@NonNull PlayerEventCallback cb) {
+    @Override
+    public void unregisterPlayerEventCallback(@NonNull PlayerEventCallback cb) {
         if (cb == null) {
             throw new IllegalArgumentException("Illegal null PlayerEventCallback");
         }
@@ -628,9 +628,7 @@
      */
     @Override
     public void clearPendingCommands() {
-        synchronized (mTaskLock) {
-            mPendingTasks.clear();
-        }
+        // TODO: implement this.
     }
 
     private void addTask(Task task) {
@@ -652,15 +650,14 @@
         }
     }
 
-    private static void handleDataSource(MediaPlayerSource src)
+    private void handleDataSource(boolean isCurrent, @NonNull final DataSourceDesc dsd, long srcId)
             throws IOException {
-        final DataSourceDesc dsd = src.getDSD();
         Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
 
-        MediaPlayer player = src.mPlayer;
+        // TODO: handle the case isCurrent is false.
         switch (dsd.getType()) {
             case DataSourceDesc.TYPE_CALLBACK:
-                player.setDataSource(new MediaDataSource() {
+                mPlayer.setDataSource(new MediaDataSource() {
                     Media2DataSource mDataSource = dsd.getMedia2DataSource();
                     @Override
                     public int readAt(long position, byte[] buffer, int offset, int size)
@@ -681,14 +678,14 @@
                 break;
 
             case DataSourceDesc.TYPE_FD:
-                player.setDataSource(
+                mPlayer.setDataSource(
                         dsd.getFileDescriptor(),
                         dsd.getFileDescriptorOffset(),
                         dsd.getFileDescriptorLength());
                 break;
 
             case DataSourceDesc.TYPE_URI:
-                player.setDataSource(
+                mPlayer.setDataSource(
                         dsd.getUriContext(),
                         dsd.getUri(),
                         dsd.getUriHeaders(),
@@ -874,12 +871,9 @@
     @Override
     public void reset() {
         mPlayer.reset();
-        synchronized (mLock) {
-            mAudioAttributes = null;
-            mMp2EventCallbackRecords.clear();
-            mPlayerEventCallbackMap.clear();
-            mDrmEventCallbackRecords.clear();
-        }
+        setPlayerState(PLAYER_STATE_IDLE);
+        setBufferingState(BUFFERING_STATE_UNKNOWN);
+        /* FIXME: reset other internal variables. */
     }
 
     /**
@@ -1003,11 +997,45 @@
             return null;
         }
 
+        TrackInfoImpl(Parcel in) {
+            mTrackType = in.readInt();
+            // TODO: parcel in the full MediaFormat; currently we are using createSubtitleFormat
+            // even for audio/video tracks, meaning we only set the mime and language.
+            String mime = in.readString();
+            String language = in.readString();
+            mFormat = MediaFormat.createSubtitleFormat(mime, language);
+
+            if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
+                mFormat.setInteger(MediaFormat.KEY_IS_AUTOSELECT, in.readInt());
+                mFormat.setInteger(MediaFormat.KEY_IS_DEFAULT, in.readInt());
+                mFormat.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.readInt());
+            }
+        }
+
         TrackInfoImpl(int type, MediaFormat format) {
             mTrackType = type;
             mFormat = format;
         }
 
+        /**
+         * Flatten this object in to a Parcel.
+         *
+         * @param dest The Parcel in which the object should be written.
+         * @param flags Additional flags about how the object should be written.
+         * May be 0 or {@link android.os.Parcelable#PARCELABLE_WRITE_RETURN_VALUE}.
+         */
+        /* package private */ void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(mTrackType);
+            dest.writeString(getLanguage());
+
+            if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
+                dest.writeString(mFormat.getString(MediaFormat.KEY_MIME));
+                dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_AUTOSELECT));
+                dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_DEFAULT));
+                dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE));
+            }
+        }
+
         @Override
         public String toString() {
             StringBuilder out = new StringBuilder(128);
@@ -1034,6 +1062,23 @@
             out.append("}");
             return out.toString();
         }
+
+        /**
+         * Used to read a TrackInfoImpl from a Parcel.
+         */
+        /* package private */ static final Parcelable.Creator<TrackInfoImpl> CREATOR =
+                new Parcelable.Creator<TrackInfoImpl>() {
+                    @Override
+                    public TrackInfoImpl createFromParcel(Parcel in) {
+                        return new TrackInfoImpl(in);
+                    }
+
+                    @Override
+                    public TrackInfoImpl[] newArray(int size) {
+                        return new TrackInfoImpl[size];
+                    }
+                };
+
     };
 
     /**
@@ -1185,9 +1230,8 @@
         mPlayer.setOnDrmConfigHelper(new MediaPlayer.OnDrmConfigHelper() {
             @Override
             public void onDrmConfig(MediaPlayer mp) {
-                MediaPlayerSource src = mPlayer.getSourceForPlayer(mp);
-                DataSourceDesc dsd = src == null ? null : src.getDSD();
-                listener.onDrmConfig(MediaPlayer2Impl.this, dsd);
+                /** FIXME: pass the right DSD. */
+                listener.onDrmConfig(MediaPlayer2Impl.this, null);
             }
         });
     }
@@ -1296,11 +1340,16 @@
      */
     @Override
     public void releaseDrm() throws NoDrmSchemeException {
-        try {
-            mPlayer.releaseDrm();
-        } catch (MediaPlayer.NoDrmSchemeException e) {
-            throw new NoDrmSchemeException(e.getMessage());
-        }
+        addTask(new Task(CALL_COMPLETED_RELEASE_DRM, false) {
+            @Override
+            void process() throws NoDrmSchemeException {
+                try {
+                    mPlayer.releaseDrm();
+                } catch (MediaPlayer.NoDrmSchemeException e) {
+                    throw new NoDrmSchemeException(e.getMessage());
+                }
+            }
+        });
     }
 
 
@@ -1394,11 +1443,16 @@
     @Override
     public void restoreDrmKeys(@NonNull final byte[] keySetId)
             throws NoDrmSchemeException {
-        try {
-            mPlayer.restoreKeys(keySetId);
-        } catch (MediaPlayer.NoDrmSchemeException e) {
-            throw new NoDrmSchemeException(e.getMessage());
-        }
+        addTask(new Task(CALL_COMPLETED_RESTORE_DRM_KEYS, false) {
+            @Override
+            void process() throws NoDrmSchemeException {
+                try {
+                    mPlayer.restoreKeys(keySetId);
+                } catch (MediaPlayer.NoDrmSchemeException e) {
+                    throw new NoDrmSchemeException(e.getMessage());
+                }
+            }
+        });
     }
 
 
@@ -1450,16 +1504,46 @@
     private void setPlaybackParamsInternal(final PlaybackParams params) {
         PlaybackParams current = mPlayer.getPlaybackParams();
         mPlayer.setPlaybackParams(params);
-        if (current.getSpeed() != params.getSpeed()) {
+        if (Math.abs(current.getSpeed() - params.getSpeed()) > 0.0001f) {
             notifyPlayerEvent(new PlayerEventNotifier() {
                 @Override
                 public void notify(PlayerEventCallback cb) {
-                    cb.onPlaybackSpeedChanged(mMediaPlayerInterfaceImpl, params.getSpeed());
+                    cb.onPlaybackSpeedChanged(MediaPlayer2Impl.this, params.getSpeed());
                 }
             });
         }
     }
 
+    private void setPlayerState(@PlayerState final int state) {
+        synchronized (mLock) {
+            if (mPlayerState == state) {
+                return;
+            }
+            mPlayerState = state;
+        }
+        notifyPlayerEvent(new PlayerEventNotifier() {
+            @Override
+            public void notify(PlayerEventCallback cb) {
+                cb.onPlayerStateChanged(MediaPlayer2Impl.this, state);
+            }
+        });
+    }
+
+    private void setBufferingState(@BuffState final int state) {
+        synchronized (mLock) {
+            if (mBufferingState == state) {
+                return;
+            }
+            mBufferingState = state;
+        }
+        notifyPlayerEvent(new PlayerEventNotifier() {
+            @Override
+            public void notify(PlayerEventCallback cb) {
+                cb.onBufferingStateChanged(MediaPlayer2Impl.this, mCurrentDSD, state);
+            }
+        });
+    }
+
     private void notifyMediaPlayer2Event(final Mp2EventNotifier notifier) {
         List<Pair<Executor, MediaPlayer2EventCallback>> records;
         synchronized (mLock) {
@@ -1493,21 +1577,6 @@
         }
     }
 
-    private void notifyDrmEvent(final DrmEventNotifier notifier) {
-        List<Pair<Executor, DrmEventCallback>> records;
-        synchronized (mLock) {
-            records = new ArrayList<>(mDrmEventCallbackRecords);
-        }
-        for (final Pair<Executor, DrmEventCallback> record : records) {
-            record.first.execute(new Runnable() {
-                @Override
-                public void run() {
-                    notifier.notify(record.second);
-                }
-            });
-        }
-    }
-
     private interface Mp2EventNotifier {
         void notify(MediaPlayer2EventCallback callback);
     }
@@ -1516,34 +1585,28 @@
         void notify(PlayerEventCallback callback);
     }
 
-    private interface DrmEventNotifier {
-        void notify(DrmEventCallback callback);
-    }
-
-    private void setUpListeners(final MediaPlayerSource src) {
-        MediaPlayer p = src.mPlayer;
-        p.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+    private void setUpListeners() {
+        mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
             @Override
             public void onPrepared(MediaPlayer mp) {
-                handleDataSourceError(mPlayer.onPrepared(mp));
+                setPlayerState(PLAYER_STATE_PAUSED);
+                setBufferingState(BUFFERING_STATE_BUFFERING_AND_PLAYABLE);
                 notifyMediaPlayer2Event(new Mp2EventNotifier() {
                     @Override
                     public void notify(MediaPlayer2EventCallback callback) {
-                        MediaPlayer2Impl mp2 = MediaPlayer2Impl.this;
-                        DataSourceDesc dsd = src.getDSD();
-                        callback.onInfo(mp2, dsd, MEDIA_INFO_PREPARED, 0);
+                        callback.onInfo(MediaPlayer2Impl.this, mCurrentDSD, MEDIA_INFO_PREPARED, 0);
                     }
                 });
                 notifyPlayerEvent(new PlayerEventNotifier() {
                     @Override
                     public void notify(PlayerEventCallback cb) {
-                        cb.onMediaPrepared(mMediaPlayerInterfaceImpl, src.getDSD());
+                        cb.onMediaPrepared(MediaPlayer2Impl.this, mCurrentDSD);
                     }
                 });
                 synchronized (mTaskLock) {
                     if (mCurrentTask != null
                             && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE
-                            && mCurrentTask.mDSD == src.getDSD()
+                            && mCurrentTask.mDSD == mCurrentDSD
                             && mCurrentTask.mNeedToWaitForEventToComplete) {
                         mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
                         mCurrentTask = null;
@@ -1552,18 +1615,18 @@
                 }
             }
         });
-        p.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
+        mPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
             @Override
             public void onVideoSizeChanged(MediaPlayer mp, final int width, final int height) {
                 notifyMediaPlayer2Event(new Mp2EventNotifier() {
                     @Override
                     public void notify(MediaPlayer2EventCallback cb) {
-                        cb.onVideoSizeChanged(MediaPlayer2Impl.this, src.getDSD(), width, height);
+                        cb.onVideoSizeChanged(MediaPlayer2Impl.this, mCurrentDSD, width, height);
                     }
                 });
             }
         });
-        p.setOnInfoListener(new MediaPlayer.OnInfoListener() {
+        mPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
             @Override
             public boolean onInfo(MediaPlayer mp, int what, int extra) {
                 switch (what) {
@@ -1571,52 +1634,50 @@
                         notifyMediaPlayer2Event(new Mp2EventNotifier() {
                             @Override
                             public void notify(MediaPlayer2EventCallback cb) {
-                                cb.onInfo(MediaPlayer2Impl.this, src.getDSD(),
+                                cb.onInfo(MediaPlayer2Impl.this, mCurrentDSD,
                                         MEDIA_INFO_VIDEO_RENDERING_START, 0);
                             }
                         });
                         break;
                     case MediaPlayer.MEDIA_INFO_BUFFERING_START:
-                        mPlayer.setBufferingState(
-                                mp, MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_STARVED);
+                        setBufferingState(BUFFERING_STATE_BUFFERING_AND_STARVED);
                         break;
                     case MediaPlayer.MEDIA_INFO_BUFFERING_END:
-                        mPlayer.setBufferingState(
-                                mp, MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_PLAYABLE);
+                        setBufferingState(BUFFERING_STATE_BUFFERING_AND_PLAYABLE);
                         break;
                 }
                 return false;
             }
         });
-        p.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+        mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
             @Override
             public void onCompletion(MediaPlayer mp) {
-                handleDataSourceError(mPlayer.onCompletion(mp));
+                setPlayerState(PLAYER_STATE_PAUSED);
                 notifyMediaPlayer2Event(new Mp2EventNotifier() {
                     @Override
                     public void notify(MediaPlayer2EventCallback cb) {
-                        MediaPlayer2Impl mp2 = MediaPlayer2Impl.this;
-                        DataSourceDesc dsd = src.getDSD();
-                        cb.onInfo(mp2, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0);
+                        cb.onInfo(MediaPlayer2Impl.this, mCurrentDSD, MEDIA_INFO_PLAYBACK_COMPLETE,
+                                0);
                     }
                 });
             }
         });
-        p.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+        mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
             @Override
             public boolean onError(MediaPlayer mp, final int what, final int extra) {
-                mPlayer.onError(mp);
+                setPlayerState(PLAYER_STATE_ERROR);
+                setBufferingState(BUFFERING_STATE_UNKNOWN);
                 notifyMediaPlayer2Event(new Mp2EventNotifier() {
                     @Override
                     public void notify(MediaPlayer2EventCallback cb) {
                         int w = sErrorEventMap.getOrDefault(what, MEDIA_ERROR_UNKNOWN);
-                        cb.onError(MediaPlayer2Impl.this, src.getDSD(), w, extra);
+                        cb.onError(MediaPlayer2Impl.this, mCurrentDSD, w, extra);
                     }
                 });
                 return true;
             }
         });
-        p.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
+        mPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
             @Override
             public void onSeekComplete(MediaPlayer mp) {
                 synchronized (mTaskLock) {
@@ -1634,12 +1695,12 @@
                     public void notify(PlayerEventCallback cb) {
                         // TODO: The actual seeked position might be different from the
                         // requested position. Clarify which one is expected here.
-                        cb.onSeekCompleted(mMediaPlayerInterfaceImpl, seekPos);
+                        cb.onSeekCompleted(MediaPlayer2Impl.this, seekPos);
                     }
                 });
             }
         });
-        p.setOnTimedMetaDataAvailableListener(
+        mPlayer.setOnTimedMetaDataAvailableListener(
                 new MediaPlayer.OnTimedMetaDataAvailableListener() {
                     @Override
                     public void onTimedMetaDataAvailable(MediaPlayer mp, final TimedMetaData data) {
@@ -1647,91 +1708,40 @@
                             @Override
                             public void notify(MediaPlayer2EventCallback cb) {
                                 cb.onTimedMetaDataAvailable(
-                                        MediaPlayer2Impl.this, src.getDSD(), data);
+                                        MediaPlayer2Impl.this, mCurrentDSD, data);
                             }
                         });
                     }
                 });
-        p.setOnInfoListener(new MediaPlayer.OnInfoListener() {
+        mPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
             @Override
             public boolean onInfo(MediaPlayer mp, final int what, final int extra) {
                 notifyMediaPlayer2Event(new Mp2EventNotifier() {
                     @Override
                     public void notify(MediaPlayer2EventCallback cb) {
                         int w = sInfoEventMap.getOrDefault(what, MEDIA_INFO_UNKNOWN);
-                        cb.onInfo(MediaPlayer2Impl.this, src.getDSD(), w, extra);
+                        cb.onInfo(MediaPlayer2Impl.this, mCurrentDSD, w, extra);
                     }
                 });
                 return true;
             }
         });
-        p.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
+        mPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
             @Override
             public void onBufferingUpdate(MediaPlayer mp, final int percent) {
                 if (percent >= 100) {
-                    mPlayer.setBufferingState(
-                            mp, MediaPlayerInterface.BUFFERING_STATE_BUFFERING_COMPLETE);
+                    setBufferingState(BUFFERING_STATE_BUFFERING_COMPLETE);
                 }
-                src.mBufferedPercentage.set(percent);
+                mBufferedPercentageCurrent.set(percent);
                 notifyMediaPlayer2Event(new Mp2EventNotifier() {
                     @Override
                     public void notify(MediaPlayer2EventCallback cb) {
-                        cb.onInfo(MediaPlayer2Impl.this, src.getDSD(),
+                        cb.onInfo(MediaPlayer2Impl.this, mCurrentDSD,
                                 MEDIA_INFO_BUFFERING_UPDATE, percent);
                     }
                 });
             }
         });
-        p.setOnMediaTimeDiscontinuityListener(
-                new MediaPlayer.OnMediaTimeDiscontinuityListener() {
-                    @Override
-                    public void onMediaTimeDiscontinuity(
-                            MediaPlayer mp, final MediaTimestamp timestamp) {
-                        notifyMediaPlayer2Event(new Mp2EventNotifier() {
-                            @Override
-                            public void notify(MediaPlayer2EventCallback cb) {
-                                cb.onMediaTimeDiscontinuity(
-                                        MediaPlayer2Impl.this, src.getDSD(), timestamp);
-                            }
-                        });
-                    }
-                });
-        p.setOnSubtitleDataListener(new MediaPlayer.OnSubtitleDataListener() {
-            @Override
-            public  void onSubtitleData(MediaPlayer mp, final SubtitleData data) {
-                notifyMediaPlayer2Event(new Mp2EventNotifier() {
-                    @Override
-                    public void notify(MediaPlayer2EventCallback cb) {
-                        cb.onSubtitleData(MediaPlayer2Impl.this, src.getDSD(), data);
-                    }
-                });
-            }
-        });
-        p.setOnDrmInfoListener(new MediaPlayer.OnDrmInfoListener() {
-            @Override
-            public void onDrmInfo(MediaPlayer mp, final MediaPlayer.DrmInfo drmInfo) {
-                notifyDrmEvent(new DrmEventNotifier() {
-                    @Override
-                    public void notify(DrmEventCallback cb) {
-                        cb.onDrmInfo(MediaPlayer2Impl.this, src.getDSD(),
-                                new DrmInfoImpl(drmInfo.getPssh(), drmInfo.getSupportedSchemes()));
-                    }
-                });
-            }
-        });
-        p.setOnDrmPreparedListener(new MediaPlayer.OnDrmPreparedListener() {
-            @Override
-            public void onDrmPrepared(MediaPlayer mp, final int status) {
-                notifyDrmEvent(new DrmEventNotifier() {
-                    @Override
-                    public void notify(DrmEventCallback cb) {
-                        int s = sPrepareDrmStatusMap.getOrDefault(
-                                status, PREPARE_DRM_STATUS_PREPARATION_ERROR);
-                        cb.onDrmPrepared(MediaPlayer2Impl.this, src.getDSD(), s);
-                    }
-                });
-            }
-        });
     }
 
     /**
@@ -1934,10 +1944,14 @@
                 status = CALL_STATUS_PERMISSION_DENIED;
             } catch (IOException e) {
                 status = CALL_STATUS_ERROR_IO;
+            } catch (NoDrmSchemeException e) {
+                status = CALL_STATUS_NO_DRM_SCHEME;
             } catch (Exception e) {
                 status = CALL_STATUS_ERROR_UNKNOWN;
             }
-            mDSD = getCurrentDataSource();
+            synchronized (mSrcLock) {
+                mDSD = mCurrentDSD;
+            }
 
             if (!mNeedToWaitForEventToComplete || status != CALL_STATUS_NO_ERROR) {
 
@@ -1965,590 +1979,4 @@
             });
         }
     };
-
-    private static class DataSourceError {
-        final DataSourceDesc mDSD;
-        final int mWhat;
-
-        final int mExtra;
-        DataSourceError(DataSourceDesc dsd, int what, int extra) {
-            mDSD = dsd;
-            mWhat = what;
-            mExtra = extra;
-        }
-
-    }
-
-    private class MediaPlayerSource {
-
-        volatile DataSourceDesc mDSD;
-        final MediaPlayer mPlayer = new MediaPlayer();
-        final AtomicInteger mBufferedPercentage = new AtomicInteger(0);
-        int mSourceState = SOURCE_STATE_INIT;
-        @MediaPlayer2State int mMp2State = MEDIAPLAYER2_STATE_IDLE;
-        @BuffState int mBufferingState = MediaPlayerInterface.BUFFERING_STATE_UNKNOWN;
-        @PlayerState int mPlayerState = MediaPlayerInterface.PLAYER_STATE_IDLE;
-        boolean mPlayPending;
-
-        MediaPlayerSource(final DataSourceDesc dsd) {
-            mDSD = dsd;
-            setUpListeners(this);
-        }
-
-        DataSourceDesc getDSD() {
-            return mDSD;
-        }
-
-    }
-
-    private class MediaPlayerSourceQueue {
-
-        List<MediaPlayerSource> mQueue = new ArrayList<>();
-        float mVolume = 1.0f;
-        Surface mSurface;
-
-        MediaPlayerSourceQueue() {
-            mQueue.add(new MediaPlayerSource(null));
-        }
-
-        synchronized MediaPlayer getCurrentPlayer() {
-            return mQueue.get(0).mPlayer;
-        }
-
-        synchronized MediaPlayerSource getFirst() {
-            return mQueue.get(0);
-        }
-
-        synchronized void setFirst(DataSourceDesc dsd) throws IOException {
-            if (mQueue.isEmpty()) {
-                mQueue.add(0, new MediaPlayerSource(dsd));
-            } else {
-                mQueue.get(0).mDSD = dsd;
-                setUpListeners(mQueue.get(0));
-            }
-            handleDataSource(mQueue.get(0));
-        }
-
-        synchronized DataSourceError setNext(DataSourceDesc dsd) {
-            MediaPlayerSource src = new MediaPlayerSource(dsd);
-            if (mQueue.isEmpty()) {
-                mQueue.add(src);
-                return prepareAt(0);
-            } else {
-                mQueue.add(1, src);
-                return prepareAt(1);
-            }
-        }
-
-        synchronized DataSourceError setNextMultiple(List<DataSourceDesc> descs) {
-            List<MediaPlayerSource> sources = new ArrayList<>();
-            for (DataSourceDesc dsd: descs) {
-                sources.add(new MediaPlayerSource(dsd));
-            }
-            if (mQueue.isEmpty()) {
-                mQueue.addAll(sources);
-                return prepareAt(0);
-            } else {
-                mQueue.addAll(1, sources);
-                return prepareAt(1);
-            }
-        }
-
-        synchronized void play() {
-            MediaPlayerSource src = mQueue.get(0);
-            if (src.mSourceState == SOURCE_STATE_PREPARED) {
-                src.mPlayer.start();
-                setMp2State(src.mPlayer, MEDIAPLAYER2_STATE_PLAYING);
-            }
-        }
-
-        synchronized void prepare() {
-            getCurrentPlayer().prepareAsync();
-        }
-
-        synchronized void release() {
-            getCurrentPlayer().release();
-        }
-
-        synchronized void prepareAsync() {
-            MediaPlayer mp = getCurrentPlayer();
-            mp.prepareAsync();
-            setBufferingState(mp, MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_STARVED);
-        }
-
-        synchronized void pause() {
-            MediaPlayer mp = getCurrentPlayer();
-            mp.pause();
-            setMp2State(mp, MEDIAPLAYER2_STATE_PAUSED);
-        }
-
-        synchronized long getCurrentPosition() {
-            return getCurrentPlayer().getCurrentPosition();
-        }
-
-        synchronized long getDuration() {
-            return getCurrentPlayer().getDuration();
-        }
-
-        synchronized long getBufferedPosition() {
-            MediaPlayerSource src = mQueue.get(0);
-            return (long) src.mPlayer.getDuration() * src.mBufferedPercentage.get() / 100;
-        }
-
-        synchronized void setAudioAttributes(AudioAttributes attributes) {
-            getCurrentPlayer().setAudioAttributes(attributes);
-        }
-
-        synchronized DataSourceError onPrepared(MediaPlayer mp) {
-            for (int i = 0; i < mQueue.size(); i++) {
-                MediaPlayerSource src = mQueue.get(i);
-                if (mp == src.mPlayer) {
-                    if (i == 0) {
-                        if (src.mPlayPending) {
-                            src.mPlayPending = false;
-                            src.mPlayer.start();
-                            setMp2State(src.mPlayer, MEDIAPLAYER2_STATE_PLAYING);
-                        } else {
-                            setMp2State(src.mPlayer, MEDIAPLAYER2_STATE_PREPARED);
-                        }
-                    }
-                    src.mSourceState = SOURCE_STATE_PREPARED;
-                    setBufferingState(src.mPlayer,
-                            MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_PLAYABLE);
-                    return prepareAt(i + 1);
-                }
-            }
-            return null;
-        }
-
-        synchronized DataSourceError onCompletion(MediaPlayer mp) {
-            if (!mQueue.isEmpty() && mp == getCurrentPlayer()) {
-                if (mQueue.size() == 1) {
-                    setMp2State(mp, MEDIAPLAYER2_STATE_PAUSED);
-                    return null;
-                }
-                moveToNext();
-            }
-            return playCurrent();
-        }
-
-        synchronized void moveToNext() {
-            final MediaPlayerSource src1 = mQueue.remove(0);
-            src1.mPlayer.release();
-            if (mQueue.isEmpty()) {
-                throw new IllegalStateException("player/source queue emptied");
-            }
-            final MediaPlayerSource src2 = mQueue.get(0);
-            if (src1.mPlayerState != src2.mPlayerState) {
-                notifyPlayerEvent(new PlayerEventNotifier() {
-                    @Override
-                    public void notify(PlayerEventCallback cb) {
-                        cb.onPlayerStateChanged(mMediaPlayerInterfaceImpl, src2.mPlayerState);
-                    }
-                });
-            }
-            notifyPlayerEvent(new PlayerEventNotifier() {
-                @Override
-                public void notify(PlayerEventCallback cb) {
-                    cb.onCurrentDataSourceChanged(mMediaPlayerInterfaceImpl, src2.mDSD);
-                }
-            });
-        }
-
-        synchronized DataSourceError playCurrent() {
-            DataSourceError err = null;
-            final MediaPlayerSource src = mQueue.get(0);
-            src.mPlayer.setSurface(mSurface);
-            src.mPlayer.setVolume(mVolume, mVolume);
-            if (src.mSourceState == SOURCE_STATE_PREPARED) {
-                // start next source only when it's in prepared state.
-                src.mPlayer.start();
-                notifyMediaPlayer2Event(new Mp2EventNotifier() {
-                    @Override
-                    public void notify(MediaPlayer2EventCallback callback) {
-                        callback.onInfo(MediaPlayer2Impl.this, src.getDSD(),
-                                MEDIA_INFO_STARTED_AS_NEXT, 0);
-                    }
-                });
-
-            } else {
-                if (src.mSourceState == SOURCE_STATE_INIT) {
-                    err = prepareAt(0);
-                }
-                src.mPlayPending = true;
-            }
-            return err;
-        }
-
-        synchronized void onError(MediaPlayer mp) {
-            setMp2State(mp, MEDIAPLAYER2_STATE_ERROR);
-            setBufferingState(mp, MediaPlayerInterface.BUFFERING_STATE_UNKNOWN);
-        }
-
-        synchronized DataSourceError prepareAt(int n) {
-            if (n >= mQueue.size()
-                    || mQueue.get(n).mSourceState != SOURCE_STATE_INIT
-                    || getPlayerState() == MediaPlayerInterface.PLAYER_STATE_IDLE) {
-                // There is no next source or it's in preparing or prepared state.
-                return null;
-            }
-
-            MediaPlayerSource src = mQueue.get(n);
-            try {
-                src.mSourceState = SOURCE_STATE_PREPARING;
-                handleDataSource(src);
-                src.mPlayer.prepareAsync();
-                return null;
-            } catch (Exception e) {
-                DataSourceDesc dsd = src.getDSD();
-                setMp2State(src.mPlayer, MEDIAPLAYER2_STATE_ERROR);
-                return new DataSourceError(dsd, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED);
-            }
-
-        }
-
-        synchronized void skipToNext() {
-            if (mQueue.size() <= 1) {
-                throw new IllegalStateException("No next source available");
-            }
-            final MediaPlayerSource src = mQueue.get(0);
-            moveToNext();
-            if (src.mPlayerState == MediaPlayerInterface.PLAYER_STATE_PLAYING) {
-                playCurrent();
-            }
-        }
-
-        synchronized void setLooping(boolean loop) {
-            getCurrentPlayer().setLooping(loop);
-        }
-
-        synchronized void setPlaybackParams(PlaybackParams playbackParams) {
-            getCurrentPlayer().setPlaybackParams(playbackParams);
-        }
-
-        synchronized float getVolume() {
-            return mVolume;
-        }
-
-        synchronized void setVolume(float volume) {
-            mVolume = volume;
-            getCurrentPlayer().setVolume(volume, volume);
-        }
-
-        synchronized void setSurface(Surface surface) {
-            mSurface = surface;
-            getCurrentPlayer().setSurface(surface);
-        }
-
-        synchronized int getVideoWidth() {
-            return getCurrentPlayer().getVideoWidth();
-        }
-
-        synchronized int getVideoHeight() {
-            return getCurrentPlayer().getVideoHeight();
-        }
-
-        synchronized PersistableBundle getMetrics() {
-            return getCurrentPlayer().getMetrics();
-        }
-
-        synchronized PlaybackParams getPlaybackParams() {
-            return getCurrentPlayer().getPlaybackParams();
-        }
-
-        synchronized void setSyncParams(SyncParams params) {
-            getCurrentPlayer().setSyncParams(params);
-        }
-
-        synchronized SyncParams getSyncParams() {
-            return getCurrentPlayer().getSyncParams();
-        }
-
-        synchronized void seekTo(long msec, int mode) {
-            getCurrentPlayer().seekTo(msec, mode);
-        }
-
-        synchronized void reset() {
-            MediaPlayerSource src = mQueue.get(0);
-            src.mPlayer.reset();
-            src.mBufferedPercentage.set(0);
-            mVolume = 1.0f;
-            setMp2State(src.mPlayer, MEDIAPLAYER2_STATE_IDLE);
-            setBufferingState(src.mPlayer, MediaPlayerInterface.BUFFERING_STATE_UNKNOWN);
-        }
-
-        synchronized MediaTimestamp getTimestamp() {
-            return getCurrentPlayer().getTimestamp();
-        }
-
-        synchronized void setAudioSessionId(int sessionId) {
-            getCurrentPlayer().setAudioSessionId(sessionId);
-        }
-
-        synchronized int getAudioSessionId() {
-            return getCurrentPlayer().getAudioSessionId();
-        }
-
-        synchronized void attachAuxEffect(int effectId) {
-            getCurrentPlayer().attachAuxEffect(effectId);
-        }
-
-        synchronized void setAuxEffectSendLevel(float level) {
-            getCurrentPlayer().setAuxEffectSendLevel(level);
-        }
-
-        synchronized MediaPlayer.TrackInfo[] getTrackInfo() {
-            return getCurrentPlayer().getTrackInfo();
-        }
-
-        synchronized int getSelectedTrack(int trackType) {
-            return getCurrentPlayer().getSelectedTrack(trackType);
-        }
-
-        synchronized void selectTrack(int index) {
-            getCurrentPlayer().selectTrack(index);
-        }
-
-        synchronized void deselectTrack(int index) {
-            getCurrentPlayer().deselectTrack(index);
-        }
-
-        synchronized MediaPlayer.DrmInfo getDrmInfo() {
-            return getCurrentPlayer().getDrmInfo();
-        }
-
-        synchronized void prepareDrm(UUID uuid)
-                throws ResourceBusyException, MediaPlayer.ProvisioningServerErrorException,
-                MediaPlayer.ProvisioningNetworkErrorException, UnsupportedSchemeException {
-            getCurrentPlayer().prepareDrm(uuid);
-        }
-
-        synchronized void releaseDrm() throws MediaPlayer.NoDrmSchemeException {
-            getCurrentPlayer().releaseDrm();
-        }
-
-        synchronized byte[] provideKeyResponse(byte[] keySetId, byte[] response)
-                throws DeniedByServerException, MediaPlayer.NoDrmSchemeException {
-            return getCurrentPlayer().provideKeyResponse(keySetId, response);
-        }
-
-        synchronized void restoreKeys(byte[] keySetId) throws MediaPlayer.NoDrmSchemeException {
-            getCurrentPlayer().restoreKeys(keySetId);
-        }
-
-        synchronized String getDrmPropertyString(String propertyName)
-                throws MediaPlayer.NoDrmSchemeException {
-            return getCurrentPlayer().getDrmPropertyString(propertyName);
-        }
-
-        synchronized void setDrmPropertyString(String propertyName, String value)
-                throws MediaPlayer.NoDrmSchemeException {
-            getCurrentPlayer().setDrmPropertyString(propertyName, value);
-        }
-
-        synchronized void setOnDrmConfigHelper(MediaPlayer.OnDrmConfigHelper onDrmConfigHelper) {
-            getCurrentPlayer().setOnDrmConfigHelper(onDrmConfigHelper);
-        }
-
-        synchronized MediaDrm.KeyRequest getKeyRequest(byte[] keySetId, byte[] initData,
-                String mimeType,
-                int keyType, Map<String, String> optionalParameters)
-                throws MediaPlayer.NoDrmSchemeException {
-            return getCurrentPlayer().getKeyRequest(keySetId, initData, mimeType, keyType,
-                    optionalParameters);
-        }
-
-        synchronized void setMp2State(MediaPlayer mp, @MediaPlayer2State int mp2State) {
-            for (final MediaPlayerSource src: mQueue) {
-                if (src.mPlayer != mp) {
-                    continue;
-                }
-                if (src.mMp2State == mp2State) {
-                    return;
-                }
-                src.mMp2State = mp2State;
-
-                final int playerState = sStateMap.get(mp2State);
-                if (src.mPlayerState == playerState) {
-                    return;
-                }
-                src.mPlayerState = playerState;
-                notifyPlayerEvent(new PlayerEventNotifier() {
-                    @Override
-                    public void notify(PlayerEventCallback cb) {
-                        cb.onPlayerStateChanged(mMediaPlayerInterfaceImpl, playerState);
-                    }
-                });
-                return;
-            }
-        }
-
-        synchronized void setBufferingState(MediaPlayer mp, @BuffState final int state) {
-            for (final MediaPlayerSource src: mQueue) {
-                if (src.mPlayer != mp) {
-                    continue;
-                }
-                if (src.mBufferingState == state) {
-                    return;
-                }
-                src.mBufferingState = state;
-                notifyPlayerEvent(new PlayerEventNotifier() {
-                    @Override
-                    public void notify(PlayerEventCallback cb) {
-                        DataSourceDesc dsd = src.getDSD();
-                        cb.onBufferingStateChanged(mMediaPlayerInterfaceImpl, dsd, state);
-                    }
-                });
-                return;
-            }
-        }
-
-        synchronized @MediaPlayer2State int getMediaPlayer2State() {
-            return mQueue.get(0).mMp2State;
-        }
-
-        synchronized @BuffState int getBufferingState() {
-            return mQueue.get(0).mBufferingState;
-        }
-
-        synchronized @PlayerState int getPlayerState() {
-            return mQueue.get(0).mPlayerState;
-        }
-
-        synchronized MediaPlayerSource getSourceForPlayer(MediaPlayer mp) {
-            for (MediaPlayerSource src: mQueue) {
-                if (src.mPlayer == mp) {
-                    return src;
-                }
-            }
-            return null;
-        }
-    }
-
-    private class MediaPlayerInterfaceImpl extends MediaPlayerInterface {
-        @Override
-        public void play() {
-            MediaPlayer2Impl.this.play();
-        }
-
-        @Override
-        public void prepare() {
-            MediaPlayer2Impl.this.prepare();
-        }
-
-        @Override
-        public void pause() {
-            MediaPlayer2Impl.this.pause();
-        }
-
-        @Override
-        public void reset() {
-            MediaPlayer2Impl.this.reset();
-        }
-
-        @Override
-        public void skipToNext() {
-            MediaPlayer2Impl.this.skipToNext();
-        }
-
-        @Override
-        public void seekTo(long pos) {
-            MediaPlayer2Impl.this.seekTo(pos);
-        }
-
-        @Override
-        public long getCurrentPosition() {
-            return MediaPlayer2Impl.this.getCurrentPosition();
-        }
-
-        @Override
-        public long getDuration() {
-            return MediaPlayer2Impl.this.getDuration();
-        }
-
-        @Override
-        public long getBufferedPosition() {
-            return MediaPlayer2Impl.this.getBufferedPosition();
-        }
-
-        @Override
-        public int getPlayerState() {
-            return MediaPlayer2Impl.this.getPlayerState();
-        }
-
-        @Override
-        public int getBufferingState() {
-            return MediaPlayer2Impl.this.getBufferingState();
-        }
-
-        @Override
-        public void setAudioAttributes(AudioAttributesCompat attributes) {
-            MediaPlayer2Impl.this.setAudioAttributes(attributes);
-        }
-
-        @Override
-        public AudioAttributesCompat getAudioAttributes() {
-            return MediaPlayer2Impl.this.getAudioAttributes();
-        }
-
-        @Override
-        public void setDataSource(DataSourceDesc dsd) {
-            MediaPlayer2Impl.this.setDataSource(dsd);
-        }
-
-        @Override
-        public void setNextDataSource(DataSourceDesc dsd) {
-            MediaPlayer2Impl.this.setNextDataSource(dsd);
-        }
-
-        @Override
-        public void setNextDataSources(List<DataSourceDesc> dsds) {
-            MediaPlayer2Impl.this.setNextDataSources(dsds);
-        }
-
-        @Override
-        public DataSourceDesc getCurrentDataSource() {
-            return MediaPlayer2Impl.this.getCurrentDataSource();
-        }
-
-        @Override
-        public void loopCurrent(boolean loop) {
-            MediaPlayer2Impl.this.loopCurrent(loop);
-        }
-
-        @Override
-        public void setPlaybackSpeed(float speed) {
-            MediaPlayer2Impl.this.setPlaybackSpeed(speed);
-        }
-
-        @Override
-        public float getPlaybackSpeed() {
-            return MediaPlayer2Impl.this.getPlaybackSpeed();
-        }
-
-        @Override
-        public void setPlayerVolume(float volume) {
-            MediaPlayer2Impl.this.setPlayerVolume(volume);
-        }
-
-        @Override
-        public float getPlayerVolume() {
-            return MediaPlayer2Impl.this.getPlayerVolume();
-        }
-
-        @Override
-        public void registerPlayerEventCallback(Executor e, final PlayerEventCallback cb) {
-            MediaPlayer2Impl.this.registerPlayerEventCallback(e, cb);
-        }
-
-        @Override
-        public void unregisterPlayerEventCallback(PlayerEventCallback cb) {
-            MediaPlayer2Impl.this.unregisterPlayerEventCallback(cb);
-        }
-
-        @Override
-        public void close() throws Exception {
-            MediaPlayer2Impl.this.close();
-        }
-    }
 }
diff --git a/media/src/main/java/androidx/media/MediaPlayerInterface.java b/media/src/main/java/androidx/media/MediaPlayerBase.java
similarity index 90%
rename from media/src/main/java/androidx/media/MediaPlayerInterface.java
rename to media/src/main/java/androidx/media/MediaPlayerBase.java
index 9d51609..de0e128 100644
--- a/media/src/main/java/androidx/media/MediaPlayerInterface.java
+++ b/media/src/main/java/androidx/media/MediaPlayerBase.java
@@ -32,10 +32,10 @@
 import java.util.concurrent.Executor;
 
 /**
- * Base interface for all media players that want media session.
+ * Base class for all media players that want media session.
  */
 @TargetApi(Build.VERSION_CODES.KITKAT)
-public abstract class MediaPlayerInterface implements AutoCloseable {
+public abstract class MediaPlayerBase implements AutoCloseable {
     /**
      * @hide
      */
@@ -111,9 +111,9 @@
 
     /**
      * Prepares the player for playback.
-     * See {@link PlayerEventCallback#onMediaPrepared(MediaPlayerInterface, DataSourceDesc)} for
-     * being notified when the preparation phase completed. During this time, the player may
-     * allocate resources required to play, such as audio and video decoders.
+     * See {@link PlayerEventCallback#onMediaPrepared(MediaPlayerBase, DataSourceDesc)} for being
+     * notified when the preparation phase completed. During this time, the player may allocate
+     * resources required to play, such as audio and video decoders.
      */
     public abstract void prepare();
 
@@ -123,7 +123,7 @@
     public abstract void pause();
 
     /**
-     * Resets the MediaPlayerInterface to its uninitialized state.
+     * Resets the MediaPlayerBase to its uninitialized state.
      */
     public abstract void reset();
 
@@ -166,7 +166,7 @@
 
     /**
      * Returns the current player state.
-     * See also {@link PlayerEventCallback#onPlayerStateChanged(MediaPlayerInterface, int)} for
+     * See also {@link PlayerEventCallback#onPlayerStateChanged(MediaPlayerBase, int)} for
      * notification of changes.
      * @return the current player state
      */
@@ -294,8 +294,8 @@
 
     /**
      * A callback class to receive notifications for events on the media player.
-     * See {@link MediaPlayerInterface#registerPlayerEventCallback(Executor, PlayerEventCallback)}
-     * to register this callback.
+     * See {@link MediaPlayerBase#registerPlayerEventCallback(Executor, PlayerEventCallback)} to
+     * register this callback.
      */
     public abstract static class PlayerEventCallback {
         /**
@@ -304,7 +304,7 @@
          * @param mpb the player whose data source changed.
          * @param dsd the new current data source. null, if no more data sources available.
          */
-        public void onCurrentDataSourceChanged(@NonNull MediaPlayerInterface mpb,
+        public void onCurrentDataSourceChanged(@NonNull MediaPlayerBase mpb,
                 @Nullable DataSourceDesc dsd) { }
 
         /**
@@ -313,17 +313,16 @@
          * @param mpb the player that is prepared.
          * @param dsd the data source that the player is prepared to play.
          */
-        public void onMediaPrepared(@NonNull MediaPlayerInterface mpb,
+        public void onMediaPrepared(@NonNull MediaPlayerBase mpb,
                 @NonNull DataSourceDesc dsd) { }
 
         /**
          * Called to indicate that the state of the player has changed.
-         * See {@link MediaPlayerInterface#getPlayerState()} for polling the player state.
+         * See {@link MediaPlayerBase#getPlayerState()} for polling the player state.
          * @param mpb the player whose state has changed.
          * @param state the new state of the player.
          */
-        public void onPlayerStateChanged(@NonNull MediaPlayerInterface mpb,
-                @PlayerState int state) { }
+        public void onPlayerStateChanged(@NonNull MediaPlayerBase mpb, @PlayerState int state) { }
 
         /**
          * Called to report buffering events for a data source.
@@ -331,7 +330,7 @@
          * @param dsd the data source for which buffering is happening.
          * @param state the new buffering state.
          */
-        public void onBufferingStateChanged(@NonNull MediaPlayerInterface mpb,
+        public void onBufferingStateChanged(@NonNull MediaPlayerBase mpb,
                 @NonNull DataSourceDesc dsd, @BuffState int state) { }
 
         /**
@@ -339,7 +338,7 @@
          * @param mpb the player that has changed the playback speed.
          * @param speed the new playback speed.
          */
-        public void onPlaybackSpeedChanged(@NonNull MediaPlayerInterface mpb, float speed) { }
+        public void onPlaybackSpeedChanged(@NonNull MediaPlayerBase mpb, float speed) { }
 
         /**
          * Called to indicate that {@link #seekTo(long)} is completed.
@@ -348,6 +347,6 @@
          * @param position the previous seeking request.
          * @see #seekTo(long)
          */
-        public void onSeekCompleted(@NonNull MediaPlayerInterface mpb, long position) { }
+        public void onSeekCompleted(@NonNull MediaPlayerBase mpb, long position) { }
     }
 }
diff --git a/media/src/main/java/androidx/media/MediaPlaylistAgent.java b/media/src/main/java/androidx/media/MediaPlaylistAgent.java
index 4e1eee4..07838e8 100644
--- a/media/src/main/java/androidx/media/MediaPlaylistAgent.java
+++ b/media/src/main/java/androidx/media/MediaPlaylistAgent.java
@@ -377,12 +377,12 @@
 
     /**
      * Called by {@link MediaSession2} when it wants to translate {@link DataSourceDesc} from the
-     * {@link MediaPlayerInterface.PlayerEventCallback} to the {@link MediaItem2}. Override this
-     * method if you want to create {@link DataSourceDesc}s dynamically, instead of specifying them
-     * with {@link #setPlaylist(List, MediaMetadata2)}.
+     * {@link MediaPlayerBase.PlayerEventCallback} to the {@link MediaItem2}. Override this method
+     * if you want to create {@link DataSourceDesc}s dynamically, instead of specifying them with
+     * {@link #setPlaylist(List, MediaMetadata2)}.
      * <p>
      * Session would throw an exception if this returns {@code null} for the dsd from the
-     * {@link MediaPlayerInterface.PlayerEventCallback}.
+     * {@link MediaPlayerBase.PlayerEventCallback}.
      * <p>
      * Default implementation calls the {@link #getPlaylist()} and searches the {@link MediaItem2}
      * with the {@param dsd}.
diff --git a/media/src/main/java/androidx/media/MediaSession2.java b/media/src/main/java/androidx/media/MediaSession2.java
index ce95078..909e979 100644
--- a/media/src/main/java/androidx/media/MediaSession2.java
+++ b/media/src/main/java/androidx/media/MediaSession2.java
@@ -27,9 +27,8 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.ResultReceiver;
-import android.support.v4.media.session.MediaSessionCompat;
+import android.support.v4.media.session.IMediaControllerCallback;
 import android.support.v4.media.session.PlaybackStateCompat;
 
 import androidx.annotation.IntDef;
@@ -37,8 +36,8 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.media.MediaController2.PlaybackInfo;
-import androidx.media.MediaPlayerInterface.BuffState;
-import androidx.media.MediaPlayerInterface.PlayerState;
+import androidx.media.MediaPlayerBase.BuffState;
+import androidx.media.MediaPlayerBase.PlayerState;
 import androidx.media.MediaPlaylistAgent.PlaylistEventCallback;
 import androidx.media.MediaPlaylistAgent.RepeatMode;
 import androidx.media.MediaPlaylistAgent.ShuffleMode;
@@ -61,10 +60,6 @@
  * handle media keys. In general an app only needs one session for all playback, though multiple
  * sessions can be created to provide finer grain controls of media.
  * <p>
- * If you want to support background playback, {@link MediaSessionService2} is preferred
- * instead. With it, your playback can be revived even after playback is finished. See
- * {@link MediaSessionService2} for details.
- * <p>
  * A session can be obtained by {@link Builder}. The owner of the session may pass its session token
  * to other processes to allow them to create a {@link MediaController2} to interact with the
  * session.
@@ -77,8 +72,6 @@
  * and notify any controllers.
  * <p>
  * {@link MediaSession2} objects should be used on the thread on the looper.
- *
- * @see MediaSessionService2
  */
 @TargetApi(Build.VERSION_CODES.KITKAT)
 public class MediaSession2 extends MediaInterface2.SessionPlayer implements AutoCloseable {
@@ -161,594 +154,6 @@
      */
     public static final int ERROR_CODE_SETUP_REQUIRED = 12;
 
-    static final String TAG = "MediaSession2";
-
-    private final SupportLibraryImpl mImpl;
-
-    MediaSession2(SupportLibraryImpl impl) {
-        mImpl = impl;
-    }
-
-    SupportLibraryImpl getImpl() {
-        return mImpl;
-    }
-
-    /**
-     * Sets the underlying {@link MediaPlayerInterface} and {@link MediaPlaylistAgent} for this
-     * session to dispatch incoming event to.
-     * <p>
-     * When a {@link MediaPlaylistAgent} is specified here, the playlist agent should manage
-     * {@link MediaPlayerInterface} for calling
-     * {@link MediaPlayerInterface#setNextDataSources(List)}.
-     * <p>
-     * If the {@link MediaPlaylistAgent} isn't set, session will recreate the default playlist
-     * agent.
-     *
-     * @param player a {@link MediaPlayerInterface} that handles actual media playback in your app
-     * @param playlistAgent a {@link MediaPlaylistAgent} that manages playlist of the {@code player}
-     * @param volumeProvider a {@link VolumeProviderCompat}. If {@code null}, system will adjust the
-     *                       appropriate stream volume for this session's player.
-     */
-    public void updatePlayer(@NonNull MediaPlayerInterface player,
-            @Nullable MediaPlaylistAgent playlistAgent,
-            @Nullable VolumeProviderCompat volumeProvider) {
-        mImpl.updatePlayer(player, playlistAgent, volumeProvider);
-    }
-
-    @Override
-    public void close() {
-        try {
-            mImpl.close();
-        } catch (Exception e) {
-            // Should not be here.
-        }
-    }
-
-    /**
-     * @return player
-     */
-    public @NonNull MediaPlayerInterface getPlayer() {
-        return mImpl.getPlayer();
-    }
-
-    /**
-     * @return playlist agent
-     */
-    public @NonNull MediaPlaylistAgent getPlaylistAgent() {
-        return mImpl.getPlaylistAgent();
-    }
-
-    /**
-     * @return volume provider
-     */
-    public @Nullable VolumeProviderCompat getVolumeProvider() {
-        return mImpl.getVolumeProvider();
-    }
-
-    /**
-     * Returns the {@link SessionToken2} for creating {@link MediaController2}.
-     */
-    public @NonNull SessionToken2 getToken() {
-        return mImpl.getToken();
-    }
-
-    @NonNull Context getContext() {
-        return mImpl.getContext();
-    }
-
-    @NonNull Executor getCallbackExecutor() {
-        return mImpl.getCallbackExecutor();
-    }
-
-    @NonNull SessionCallback getCallback() {
-        return mImpl.getCallback();
-    }
-
-    /**
-     * Returns the list of connected controller.
-     *
-     * @return list of {@link ControllerInfo}
-     */
-    public @NonNull List<ControllerInfo> getConnectedControllers() {
-        return mImpl.getConnectedControllers();
-    }
-
-    /**
-     * Set the {@link AudioFocusRequest} to obtain the audio focus
-     *
-     * @param afr the full request parameters
-     */
-    public void setAudioFocusRequest(@Nullable AudioFocusRequest afr) {
-        mImpl.setAudioFocusRequest(afr);
-    }
-
-    /**
-     * Sets ordered list of {@link CommandButton} for controllers to build UI with it.
-     * <p>
-     * It's up to controller's decision how to represent the layout in its own UI.
-     * Here's the same way
-     * (layout[i] means a CommandButton at index i in the given list)
-     * For 5 icons row
-     *      layout[3] layout[1] layout[0] layout[2] layout[4]
-     * For 3 icons row
-     *      layout[1] layout[0] layout[2]
-     * For 5 icons row with overflow icon (can show +5 extra buttons with overflow button)
-     *      expanded row:   layout[5] layout[6] layout[7] layout[8] layout[9]
-     *      main row:       layout[3] layout[1] layout[0] layout[2] layout[4]
-     * <p>
-     * This API can be called in the
-     * {@link SessionCallback#onConnect(MediaSession2, ControllerInfo)}.
-     *
-     * @param controller controller to specify layout.
-     * @param layout ordered list of layout.
-     */
-    public void setCustomLayout(@NonNull ControllerInfo controller,
-            @NonNull List<CommandButton> layout) {
-        mImpl.setCustomLayout(controller, layout);
-    }
-
-    /**
-     * Set the new allowed command group for the controller
-     *
-     * @param controller controller to change allowed commands
-     * @param commands new allowed commands
-     */
-    public void setAllowedCommands(@NonNull ControllerInfo controller,
-            @NonNull SessionCommandGroup2 commands) {
-        mImpl.setAllowedCommands(controller, commands);
-    }
-
-    /**
-     * Send custom command to all connected controllers.
-     *
-     * @param command a command
-     * @param args optional argument
-     */
-    public void sendCustomCommand(@NonNull SessionCommand2 command, @Nullable Bundle args) {
-        mImpl.sendCustomCommand(command, args);
-    }
-
-    /**
-     * Send custom command to a specific controller.
-     *
-     * @param command a command
-     * @param args optional argument
-     * @param receiver result receiver for the session
-     */
-    public void sendCustomCommand(@NonNull ControllerInfo controller,
-            @NonNull SessionCommand2 command, @Nullable Bundle args,
-            @Nullable ResultReceiver receiver) {
-        mImpl.sendCustomCommand(controller, command, args, receiver);
-    }
-
-    /**
-     * Play playback.
-     * <p>
-     * This calls {@link MediaPlayerInterface#play()}.
-     */
-    @Override
-    public void play() {
-        mImpl.play();
-    }
-
-    /**
-     * Pause playback.
-     * <p>
-     * This calls {@link MediaPlayerInterface#pause()}.
-     */
-    @Override
-    public void pause() {
-        mImpl.pause();
-    }
-
-    /**
-     * Stop playback, and reset the player to the initial state.
-     * <p>
-     * This calls {@link MediaPlayerInterface#reset()}.
-     */
-    @Override
-    public void reset() {
-        mImpl.reset();
-    }
-
-    /**
-     * Request that the player prepare its playback. In other words, other sessions can continue
-     * to play during the preparation of this session. This method can be used to speed up the
-     * start of the playback. Once the preparation is done, the session will change its playback
-     * state to {@link MediaPlayerInterface#PLAYER_STATE_PAUSED}. Afterwards, {@link #play} can be
-     * called to start playback.
-     * <p>
-     * This calls {@link MediaPlayerInterface#reset()}.
-     */
-    @Override
-    public void prepare() {
-        mImpl.prepare();
-    }
-
-    /**
-     * Move to a new location in the media stream.
-     *
-     * @param pos Position to move to, in milliseconds.
-     */
-    @Override
-    public void seekTo(long pos) {
-        mImpl.seekTo(pos);
-    }
-
-    /**
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void skipForward() {
-        mImpl.skipForward();
-    }
-
-    /**
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    @Override
-    public void skipBackward() {
-        mImpl.skipBackward();
-    }
-
-    /**
-     * Notify errors to the connected controllers
-     *
-     * @param errorCode error code
-     * @param extras extras
-     */
-    @Override
-    public void notifyError(@ErrorCode int errorCode, @Nullable Bundle extras) {
-        mImpl.notifyError(errorCode, extras);
-    }
-
-    /**
-     * Notify routes information to a connected controller
-     *
-     * @param controller controller information
-     * @param routes The routes information. Each bundle should be from
-     *              MediaRouteDescritor.asBundle().
-     */
-    public void notifyRoutesInfoChanged(@NonNull ControllerInfo controller,
-            @Nullable List<Bundle> routes) {
-        mImpl.notifyRoutesInfoChanged(controller, routes);
-    }
-
-    /**
-     * Gets the current player state.
-     *
-     * @return the current player state
-     */
-    @Override
-    public @PlayerState int getPlayerState() {
-        return mImpl.getPlayerState();
-    }
-
-    /**
-     * Gets the current position.
-     *
-     * @return the current playback position in ms, or {@link MediaPlayerInterface#UNKNOWN_TIME} if
-     *         unknown.
-     */
-    @Override
-    public long getCurrentPosition() {
-        return mImpl.getCurrentPosition();
-    }
-
-    /**
-     * Gets the duration of the currently playing media item.
-     *
-     * @return the duration of the current item from {@link MediaPlayerInterface#getDuration()}.
-     */
-    @Override
-    public long getDuration() {
-        return mImpl.getDuration();
-    }
-
-    /**
-     * Gets the buffered position, or {@link MediaPlayerInterface#UNKNOWN_TIME} if unknown.
-     *
-     * @return the buffered position in ms, or {@link MediaPlayerInterface#UNKNOWN_TIME}.
-     */
-    @Override
-    public long getBufferedPosition() {
-        return mImpl.getBufferedPosition();
-    }
-
-    /**
-     * Gets the current buffering state of the player.
-     * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already
-     * buffered.
-     *
-     * @return the buffering state.
-     */
-    @Override
-    public @BuffState int getBufferingState() {
-        return mImpl.getBufferingState();
-    }
-
-    /**
-     * Get the playback speed.
-     *
-     * @return speed
-     */
-    @Override
-    public float getPlaybackSpeed() {
-        return mImpl.getPlaybackSpeed();
-    }
-
-    /**
-     * Set the playback speed.
-     */
-    @Override
-    public void setPlaybackSpeed(float speed) {
-        mImpl.setPlaybackSpeed(speed);
-    }
-
-    /**
-     * Sets the data source missing helper. Helper will be used to provide default implementation of
-     * {@link MediaPlaylistAgent} when it isn't set by developer.
-     * <p>
-     * Default implementation of the {@link MediaPlaylistAgent} will call helper when a
-     * {@link MediaItem2} in the playlist doesn't have a {@link DataSourceDesc}. This may happen
-     * when
-     * <ul>
-     *      <li>{@link MediaItem2} specified by {@link #setPlaylist(List, MediaMetadata2)} doesn't
-     *          have {@link DataSourceDesc}</li>
-     *      <li>{@link MediaController2#addPlaylistItem(int, MediaItem2)} is called and accepted
-     *          by {@link SessionCallback#onCommandRequest(
-     *          MediaSession2, ControllerInfo, SessionCommand2)}.
-     *          In that case, an item would be added automatically without the data source.</li>
-     * </ul>
-     * <p>
-     * If it's not set, playback wouldn't happen for the item without data source descriptor.
-     * <p>
-     * The helper will be run on the executor that was specified by
-     * {@link Builder#setSessionCallback(Executor, SessionCallback)}.
-     *
-     * @param helper a data source missing helper.
-     * @throws IllegalStateException when the helper is set when the playlist agent is set
-     * @see #setPlaylist(List, MediaMetadata2)
-     * @see SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)
-     * @see SessionCommand2#COMMAND_CODE_PLAYLIST_ADD_ITEM
-     * @see SessionCommand2#COMMAND_CODE_PLAYLIST_REPLACE_ITEM
-     */
-    @Override
-    public void setOnDataSourceMissingHelper(@NonNull OnDataSourceMissingHelper helper) {
-        mImpl.setOnDataSourceMissingHelper(helper);
-    }
-
-    /**
-     * Clears the data source missing helper.
-     *
-     * @see #setOnDataSourceMissingHelper(OnDataSourceMissingHelper)
-     */
-    @Override
-    public void clearOnDataSourceMissingHelper() {
-        mImpl.clearOnDataSourceMissingHelper();
-    }
-
-    /**
-     * Returns the playlist from the {@link MediaPlaylistAgent}.
-     * <p>
-     * This list may differ with the list that was specified with
-     * {@link #setPlaylist(List, MediaMetadata2)} depending on the {@link MediaPlaylistAgent}
-     * implementation. Use media items returned here for other playlist agent APIs such as
-     * {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)}.
-     *
-     * @return playlist
-     * @see MediaPlaylistAgent#getPlaylist()
-     * @see SessionCallback#onPlaylistChanged(
-     *          MediaSession2, MediaPlaylistAgent, List, MediaMetadata2)
-     */
-    @Override
-    public List<MediaItem2> getPlaylist() {
-        return mImpl.getPlaylist();
-    }
-
-    /**
-     * Sets a list of {@link MediaItem2} to the {@link MediaPlaylistAgent}. Ensure uniqueness of
-     * each {@link MediaItem2} in the playlist so the session can uniquely identity individual
-     * items.
-     * <p>
-     * This may be an asynchronous call, and {@link MediaPlaylistAgent} may keep the copy of the
-     * list. Wait for {@link SessionCallback#onPlaylistChanged(MediaSession2, MediaPlaylistAgent,
-     * List, MediaMetadata2)} to know the operation finishes.
-     * <p>
-     * You may specify a {@link MediaItem2} without {@link DataSourceDesc}. In that case,
-     * {@link MediaPlaylistAgent} has responsibility to dynamically query {link DataSourceDesc}
-     * when such media item is ready for preparation or play. Default implementation needs
-     * {@link OnDataSourceMissingHelper} for such case.
-     * <p>
-     * It's recommended to fill {@link MediaMetadata2} in each {@link MediaItem2} especially for the
-     * duration information with the key {@link MediaMetadata2#METADATA_KEY_DURATION}. Without the
-     * duration information in the metadata, session will do extra work to get the duration and send
-     * it to the controller.
-     *
-     * @param list A list of {@link MediaItem2} objects to set as a play list.
-     * @throws IllegalArgumentException if given list is {@code null}, or has duplicated media
-     * items.
-     * @see MediaPlaylistAgent#setPlaylist(List, MediaMetadata2)
-     * @see SessionCallback#onPlaylistChanged(
-     *          MediaSession2, MediaPlaylistAgent, List, MediaMetadata2)
-     * @see #setOnDataSourceMissingHelper
-     */
-    @Override
-    public void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) {
-        mImpl.setPlaylist(list, metadata);
-    }
-
-    /**
-     * Skips to the item in the playlist.
-     * <p>
-     * This calls {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)} and the behavior depends
-     * on the playlist agent implementation, especially with the shuffle/repeat mode.
-     *
-     * @param item The item in the playlist you want to play
-     * @see #getShuffleMode()
-     * @see #getRepeatMode()
-     */
-    @Override
-    public void skipToPlaylistItem(@NonNull MediaItem2 item) {
-        mImpl.skipToPlaylistItem(item);
-    }
-
-    /**
-     * Skips to the previous item.
-     * <p>
-     * This calls {@link MediaPlaylistAgent#skipToPreviousItem()} and the behavior depends on the
-     * playlist agent implementation, especially with the shuffle/repeat mode.
-     *
-     * @see #getShuffleMode()
-     * @see #getRepeatMode()
-     **/
-    @Override
-    public void skipToPreviousItem() {
-        mImpl.skipToPreviousItem();
-    }
-
-    /**
-     * Skips to the next item.
-     * <p>
-     * This calls {@link MediaPlaylistAgent#skipToNextItem()} and the behavior depends on the
-     * playlist agent implementation, especially with the shuffle/repeat mode.
-     *
-     * @see #getShuffleMode()
-     * @see #getRepeatMode()
-     */
-    @Override
-    public void skipToNextItem() {
-        mImpl.skipToNextItem();
-    }
-
-    /**
-     * Gets the playlist metadata from the {@link MediaPlaylistAgent}.
-     *
-     * @return the playlist metadata
-     */
-    @Override
-    public MediaMetadata2 getPlaylistMetadata() {
-        return mImpl.getPlaylistMetadata();
-    }
-
-    /**
-     * Adds the media item to the playlist at position index. Index equals or greater than
-     * the current playlist size (e.g. {@link Integer#MAX_VALUE}) will add the item at the end of
-     * the playlist.
-     * <p>
-     * This will not change the currently playing media item.
-     * If index is less than or equal to the current index of the play list,
-     * the current index of the play list will be incremented correspondingly.
-     *
-     * @param index the index you want to add
-     * @param item the media item you want to add
-     */
-    @Override
-    public void addPlaylistItem(int index, @NonNull MediaItem2 item) {
-        mImpl.addPlaylistItem(index, item);
-    }
-
-    /**
-     * Removes the media item in the playlist.
-     * <p>
-     * If the item is the currently playing item of the playlist, current playback
-     * will be stopped and playback moves to next source in the list.
-     *
-     * @param item the media item you want to add
-     */
-    @Override
-    public void removePlaylistItem(@NonNull MediaItem2 item) {
-        mImpl.removePlaylistItem(item);
-    }
-
-    /**
-     * Replaces the media item at index in the playlist. This can be also used to update metadata of
-     * an item.
-     *
-     * @param index the index of the item to replace
-     * @param item the new item
-     */
-    @Override
-    public void replacePlaylistItem(int index, @NonNull MediaItem2 item) {
-        mImpl.replacePlaylistItem(index, item);
-    }
-
-    /**
-     * Return currently playing media item.
-     *
-     * @return currently playing media item
-     */
-    @Override
-    public MediaItem2 getCurrentMediaItem() {
-        return mImpl.getCurrentMediaItem();
-    }
-
-    /**
-     * Updates the playlist metadata to the {@link MediaPlaylistAgent}.
-     *
-     * @param metadata metadata of the playlist
-     */
-    @Override
-    public void updatePlaylistMetadata(@Nullable MediaMetadata2 metadata) {
-        mImpl.updatePlaylistMetadata(metadata);
-    }
-
-    /**
-     * Gets the repeat mode from the {@link MediaPlaylistAgent}.
-     *
-     * @return repeat mode
-     * @see MediaPlaylistAgent#REPEAT_MODE_NONE
-     * @see MediaPlaylistAgent#REPEAT_MODE_ONE
-     * @see MediaPlaylistAgent#REPEAT_MODE_ALL
-     * @see MediaPlaylistAgent#REPEAT_MODE_GROUP
-     */
-    @Override
-    public @RepeatMode int getRepeatMode() {
-        return mImpl.getRepeatMode();
-    }
-
-    /**
-     * Sets the repeat mode to the {@link MediaPlaylistAgent}.
-     *
-     * @param repeatMode repeat mode
-     * @see MediaPlaylistAgent#REPEAT_MODE_NONE
-     * @see MediaPlaylistAgent#REPEAT_MODE_ONE
-     * @see MediaPlaylistAgent#REPEAT_MODE_ALL
-     * @see MediaPlaylistAgent#REPEAT_MODE_GROUP
-     */
-    @Override
-    public void setRepeatMode(@RepeatMode int repeatMode) {
-        mImpl.setRepeatMode(repeatMode);
-    }
-
-    /**
-     * Gets the shuffle mode from the {@link MediaPlaylistAgent}.
-     *
-     * @return The shuffle mode
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP
-     */
-    @Override
-    public @ShuffleMode int getShuffleMode() {
-        return mImpl.getShuffleMode();
-    }
-
-    /**
-     * Sets the shuffle mode to the {@link MediaPlaylistAgent}.
-     *
-     * @param shuffleMode The shuffle mode
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL
-     * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP
-     */
-    @Override
-    public void setShuffleMode(@ShuffleMode int shuffleMode) {
-        mImpl.setShuffleMode(shuffleMode);
-    }
-
     /**
      * Interface definition of a callback to be invoked when a {@link MediaItem2} in the playlist
      * didn't have a {@link DataSourceDesc} but it's needed now for preparing or playing it.
@@ -812,7 +217,7 @@
          * Called when a controller sent a command which will be sent directly to one of the
          * following:
          * <ul>
-         *  <li> {@link MediaPlayerInterface} </li>
+         *  <li> {@link MediaPlayerBase} </li>
          *  <li> {@link MediaPlaylistAgent} </li>
          *  <li> {@link android.media.AudioManager} or {@link VolumeProviderCompat} </li>
          * </ul>
@@ -931,7 +336,7 @@
          * <p>
          * During the preparation, a session should not hold audio focus in order to allow other
          * sessions play seamlessly. The state of playback should be updated to
-         * {@link MediaPlayerInterface#PLAYER_STATE_PAUSED} after the preparation is done.
+         * {@link MediaPlayerBase#PLAYER_STATE_PAUSED} after the preparation is done.
          * <p>
          * The playback of the prepared content should start in the later calls of
          * {@link MediaSession2#play()}.
@@ -956,9 +361,8 @@
          * An empty query indicates that the app may prepare any music. The implementation should
          * attempt to make a smart choice about what to play.
          * <p>
-         * The state of playback should be updated to
-         * {@link MediaPlayerInterface#PLAYER_STATE_PAUSED} after the preparation is done.
-         * The playback of the prepared content should start in the
+         * The state of playback should be updated to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}
+         * after the preparation is done. The playback of the prepared content should start in the
          * later calls of {@link MediaSession2#play()}.
          * <p>
          * Override {@link #onPlayFromSearch} to handle requests for starting playback without
@@ -980,7 +384,7 @@
          * <p>
          * During the preparation, a session should not hold audio focus in order to allow
          * other sessions play seamlessly. The state of playback should be updated to
-         * {@link MediaPlayerInterface#PLAYER_STATE_PAUSED} after the preparation is done.
+         * {@link MediaPlayerBase#PLAYER_STATE_PAUSED} after the preparation is done.
          * <p>
          * The playback of the prepared content should start in the later calls of
          * {@link MediaSession2#play()}.
@@ -1057,7 +461,7 @@
          * @param item new item
          */
         public void onCurrentMediaItemChanged(@NonNull MediaSession2 session,
-                @NonNull MediaPlayerInterface player, @Nullable MediaItem2 item) { }
+                @NonNull MediaPlayerBase player, @NonNull MediaItem2 item) { }
 
         /**
          * Called when the player is <i>prepared</i>, i.e. it is ready to play the content
@@ -1066,18 +470,18 @@
          * @param player the player for this event
          * @param item the media item for which buffering is happening
          */
-        public void onMediaPrepared(@NonNull MediaSession2 session,
-                @NonNull MediaPlayerInterface player, @NonNull MediaItem2 item) { }
+        public void onMediaPrepared(@NonNull MediaSession2 session, @NonNull MediaPlayerBase player,
+                @NonNull MediaItem2 item) { }
 
         /**
          * Called to indicate that the state of the player has changed.
-         * See {@link MediaPlayerInterface#getPlayerState()} for polling the player state.
+         * See {@link MediaPlayerBase#getPlayerState()} for polling the player state.
          * @param session the session for this event
          * @param player the player for this event
          * @param state the new state of the player.
          */
         public void onPlayerStateChanged(@NonNull MediaSession2 session,
-                @NonNull MediaPlayerInterface player, @PlayerState int state) { }
+                @NonNull MediaPlayerBase player, @PlayerState int state) { }
 
         /**
          * Called to report buffering events for a data source.
@@ -1088,8 +492,7 @@
          * @param state the new buffering state.
          */
         public void onBufferingStateChanged(@NonNull MediaSession2 session,
-                @NonNull MediaPlayerInterface player, @NonNull MediaItem2 item,
-                @BuffState int state) { }
+                @NonNull MediaPlayerBase player, @NonNull MediaItem2 item, @BuffState int state) { }
 
         /**
          * Called to indicate that the playback speed has changed.
@@ -1098,18 +501,18 @@
          * @param speed the new playback speed.
          */
         public void onPlaybackSpeedChanged(@NonNull MediaSession2 session,
-                @NonNull MediaPlayerInterface player, float speed) { }
+                @NonNull MediaPlayerBase player, float speed) { }
 
         /**
          * Called to indicate that {@link #seekTo(long)} is completed.
          *
          * @param session the session for this event.
-         * @param player the player that has completed seeking.
+         * @param mpb the player that has completed seeking.
          * @param position the previous seeking request.
          * @see #seekTo(long)
          */
-        public void onSeekCompleted(@NonNull MediaSession2 session,
-                @NonNull MediaPlayerInterface player, long position) { }
+        public void onSeekCompleted(@NonNull MediaSession2 session, @NonNull MediaPlayerBase mpb,
+                long position) { }
 
         /**
          * Called when a playlist is changed from the {@link MediaPlaylistAgent}.
@@ -1168,6 +571,153 @@
     }
 
     /**
+     * Base builder class for MediaSession2 and its subclass. Any change in this class should be
+     * also applied to the subclasses {@link MediaSession2.Builder} and
+     * {@link MediaLibraryService2.MediaLibrarySession.Builder}.
+     * <p>
+     * APIs here should be package private, but should have documentations for developers.
+     * Otherwise, javadoc will generate documentation with the generic types such as follows.
+     * <pre>U extends BuilderBase<T, U, C> setSessionCallback(Executor executor, C callback)</pre>
+     * <p>
+     * This class is hidden to prevent from generating test stub, which fails with
+     * 'unexpected bound' because it tries to auto generate stub class as follows.
+     * <pre>abstract static class BuilderBase<
+     *      T extends android.media.MediaSession2,
+     *      U extends android.media.MediaSession2.BuilderBase<
+     *              T, U, C extends android.media.MediaSession2.SessionCallback>, C></pre>
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    abstract static class BuilderBase
+            <T extends MediaSession2, U extends BuilderBase<T, U, C>, C extends SessionCallback> {
+        final Context mContext;
+        MediaSession2ImplBase.BuilderBase<T, C> mBaseImpl;
+        MediaPlayerBase mPlayer;
+        String mId;
+        Executor mCallbackExecutor;
+        C mCallback;
+        MediaPlaylistAgent mPlaylistAgent;
+        VolumeProviderCompat mVolumeProvider;
+        PendingIntent mSessionActivity;
+
+        BuilderBase(Context context) {
+            if (context == null) {
+                throw new IllegalArgumentException("context shouldn't be null");
+            }
+            mContext = context;
+            // Ensure non-null
+            mId = "";
+        }
+
+        /**
+         * Sets the underlying {@link MediaPlayerBase} for this session to dispatch incoming event
+         * to.
+         *
+         * @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
+         */
+        @NonNull U setPlayer(@NonNull MediaPlayerBase player) {
+            if (player == null) {
+                throw new IllegalArgumentException("player shouldn't be null");
+            }
+            mBaseImpl.setPlayer(player);
+            return (U) this;
+        }
+
+        /**
+         * Sets the {@link MediaPlaylistAgent} for this session to manages playlist of the
+         * underlying {@link MediaPlayerBase}. The playlist agent should manage
+         * {@link MediaPlayerBase} for calling {@link MediaPlayerBase#setNextDataSources(List)}.
+         * <p>
+         * If the {@link MediaPlaylistAgent} isn't set, session will create the default playlist
+         * agent.
+         *
+         * @param playlistAgent a {@link MediaPlaylistAgent} that manages playlist of the
+         *                      {@code player}
+         */
+        U setPlaylistAgent(@NonNull MediaPlaylistAgent playlistAgent) {
+            if (playlistAgent == null) {
+                throw new IllegalArgumentException("playlistAgent shouldn't be null");
+            }
+            mBaseImpl.setPlaylistAgent(playlistAgent);
+            return (U) this;
+        }
+
+        /**
+         * Sets the {@link VolumeProviderCompat} for this session to handle volume events. If not
+         * set, system will adjust the appropriate stream volume for this session's player.
+         *
+         * @param volumeProvider The provider that will receive volume button events.
+         */
+        @NonNull U setVolumeProvider(@Nullable VolumeProviderCompat volumeProvider) {
+            mBaseImpl.setVolumeProvider(volumeProvider);
+            return (U) this;
+        }
+
+        /**
+         * Set an intent for launching UI for this Session. This can be used as a
+         * quick link to an ongoing media screen. The intent should be for an
+         * activity that may be started using {@link Context#startActivity(Intent)}.
+         *
+         * @param pi The intent to launch to show UI for this session.
+         */
+        @NonNull U setSessionActivity(@Nullable PendingIntent pi) {
+            mBaseImpl.setSessionActivity(pi);
+            return (U) this;
+        }
+
+        /**
+         * Set ID of the session. If it's not set, an empty string with used to create a session.
+         * <p>
+         * Use this if and only if your app supports multiple playback at the same time and also
+         * wants to provide external apps to have finer controls of them.
+         *
+         * @param id id of the session. Must be unique per package.
+         * @throws IllegalArgumentException if id is {@code null}
+         * @return
+         */
+        @NonNull U setId(@NonNull String id) {
+            if (id == null) {
+                throw new IllegalArgumentException("id shouldn't be null");
+            }
+            mBaseImpl.setId(id);
+            return (U) this;
+        }
+
+        /**
+         * Set callback for the session.
+         *
+         * @param executor callback executor
+         * @param callback session callback.
+         * @return
+         */
+        @NonNull U setSessionCallback(@NonNull Executor executor, @NonNull C callback) {
+            if (executor == null) {
+                throw new IllegalArgumentException("executor shouldn't be null");
+            }
+            if (callback == null) {
+                throw new IllegalArgumentException("callback shouldn't be null");
+            }
+            mBaseImpl.setSessionCallback(executor, callback);
+            return (U) this;
+        }
+
+        /**
+         * Build {@link MediaSession2}.
+         *
+         * @return a new session
+         * @throws IllegalStateException if the session with the same id is already exists for the
+         *      package.
+         */
+        @NonNull T build() {
+            return mBaseImpl.build();
+        }
+
+        void setImpl(MediaSession2ImplBase.BuilderBase<T, C> impl) {
+            mBaseImpl = impl;
+        }
+    }
+
+    /**
      * Builder for {@link MediaSession2}.
      * <p>
      * Any incoming event from the {@link MediaController2} will be handled on the thread
@@ -1183,7 +733,7 @@
         }
 
         @Override
-        public @NonNull Builder setPlayer(@NonNull MediaPlayerInterface player) {
+        public @NonNull Builder setPlayer(@NonNull MediaPlayerBase player) {
             return super.setPlayer(player);
         }
 
@@ -1225,18 +775,20 @@
     public static final class ControllerInfo {
         private final int mUid;
         private final String mPackageName;
+        // Note: IMediaControllerCallback should be used only for MediaSession2ImplBase
+        private final IMediaControllerCallback mIControllerCallback;
         private final boolean mIsTrusted;
-        private final ControllerCb mControllerCb;
 
         /**
          * @hide
          */
         @RestrictTo(LIBRARY_GROUP)
-        ControllerInfo(@NonNull String packageName, int pid, int uid, @NonNull ControllerCb cb) {
+        public ControllerInfo(@NonNull Context context, int uid, int pid,
+                @NonNull String packageName, @NonNull IMediaControllerCallback callback) {
             mUid = uid;
             mPackageName = packageName;
+            mIControllerCallback = callback;
             mIsTrusted = false;
-            mControllerCb = cb;
         }
 
         /**
@@ -1266,9 +818,13 @@
             return mIsTrusted;
         }
 
+        IBinder getId() {
+            return mIControllerCallback.asBinder();
+        }
+
         @Override
         public int hashCode() {
-            return mControllerCb.hashCode();
+            return mIControllerCallback.hashCode();
         }
 
         @Override
@@ -1277,7 +833,7 @@
                 return false;
             }
             ControllerInfo other = (ControllerInfo) obj;
-            return mControllerCb.equals(other.mControllerCb);
+            return mIControllerCallback.asBinder().equals(other.mIControllerCallback.asBinder());
         }
 
         @Override
@@ -1285,12 +841,26 @@
             return "ControllerInfo {pkg=" + mPackageName + ", uid=" + mUid + "})";
         }
 
-        @NonNull IBinder getId() {
-            return mControllerCb.getId();
+        /**
+         * @hide
+         * @return Bundle
+         */
+        @RestrictTo(LIBRARY_GROUP)
+        public @NonNull Bundle toBundle() {
+            return new Bundle();
         }
 
-        @NonNull ControllerCb getControllerCb() {
-            return mControllerCb;
+        /**
+         * @hide
+         * @return Bundle
+         */
+        @RestrictTo(LIBRARY_GROUP)
+        public static @NonNull ControllerInfo fromBundle(@NonNull Context context, Bundle bundle) {
+            return new ControllerInfo(context, -1, -1, "TODO", null);
+        }
+
+        IMediaControllerCallback getControllerBinder() {
+            return mIControllerCallback;
         }
     }
 
@@ -1490,60 +1060,12 @@
         }
     }
 
-    abstract static class ControllerCb {
-        @Override
-        public int hashCode() {
-            return getId().hashCode();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof ControllerCb)) {
-                return false;
-            }
-            ControllerCb other = (ControllerCb) obj;
-            return getId().equals(other.getId());
-        }
-
-        abstract @NonNull IBinder getId();
-
-        // Mostly matched with the methods in MediaController2.ControllerCallback
-        abstract void onCustomLayoutChanged(@NonNull List<CommandButton> layout)
-                throws RemoteException;
-        abstract void onPlaybackInfoChanged(@NonNull PlaybackInfo info) throws RemoteException;
-        abstract void onAllowedCommandsChanged(@NonNull SessionCommandGroup2 commands)
-                throws RemoteException;
-        abstract void onCustomCommand(@NonNull SessionCommand2 command, @Nullable Bundle args,
-                @Nullable ResultReceiver receiver) throws RemoteException;
-        abstract void onPlayerStateChanged(int playerState) throws RemoteException;
-        abstract void onPlaybackSpeedChanged(float speed) throws RemoteException;
-        abstract void onBufferingStateChanged(@NonNull MediaItem2 item,
-                @MediaPlayerInterface.BuffState int state) throws RemoteException;
-        abstract void onSeekCompleted(long position) throws RemoteException;
-        abstract void onError(@ErrorCode int errorCode, @Nullable Bundle extras)
-                throws RemoteException;
-        abstract void onCurrentMediaItemChanged(@Nullable MediaItem2 item) throws RemoteException;
-        abstract void onPlaylistChanged(@NonNull List<MediaItem2> playlist,
-                @Nullable MediaMetadata2 metadata) throws RemoteException;
-        abstract void onPlaylistMetadataChanged(@Nullable MediaMetadata2 metadata)
-                throws RemoteException;
-        abstract void onShuffleModeChanged(@MediaPlaylistAgent.ShuffleMode int shuffleMode)
-                throws RemoteException;
-        abstract void onRepeatModeChanged(@MediaPlaylistAgent.RepeatMode int repeatMode)
-                throws RemoteException;
-        abstract void onRoutesInfoChanged(@Nullable List<Bundle> routes) throws RemoteException;
-        abstract void onChildrenChanged(@NonNull  String parentId, int itemCount,
-                @Nullable Bundle extras) throws RemoteException;
-        abstract void onSearchResultChanged(@NonNull String query, int itemCount,
-                @Nullable Bundle extras) throws RemoteException;
-    }
-
     abstract static class SupportLibraryImpl extends MediaInterface2.SessionPlayer
             implements AutoCloseable {
-        abstract void updatePlayer(@NonNull MediaPlayerInterface player,
+        abstract void updatePlayer(@NonNull MediaPlayerBase player,
                 @Nullable MediaPlaylistAgent playlistAgent,
                 @Nullable VolumeProviderCompat volumeProvider);
-        abstract @NonNull MediaPlayerInterface getPlayer();
+        abstract @NonNull MediaPlayerBase getPlayer();
         abstract @NonNull MediaPlaylistAgent getPlaylistAgent();
         abstract @Nullable VolumeProviderCompat getVolumeProvider();
         abstract @NonNull SessionToken2 getToken();
@@ -1561,17 +1083,9 @@
         abstract void notifyRoutesInfoChanged(@NonNull ControllerInfo controller,
                 @Nullable List<Bundle> routes);
 
-        // LibrarySession methods
-        abstract void notifyChildrenChanged(@NonNull ControllerInfo controller,
-                @NonNull String parentId, int itemCount, @Nullable Bundle extras,
-                @NonNull List<MediaSessionManager.RemoteUserInfo> subscribingBrowsers);
-        abstract void notifySearchResultChanged(@NonNull ControllerInfo controller,
-                @NonNull String query, int itemCount, @Nullable Bundle extras);
-
         // Internally used methods
-        abstract MediaSession2 createInstance();
+        abstract void setInstance(MediaSession2 session);
         abstract MediaSession2 getInstance();
-        abstract MediaSessionCompat getSessionCompat();
         abstract Context getContext();
         abstract Executor getCallbackExecutor();
         abstract SessionCallback getCallback();
@@ -1580,152 +1094,577 @@
         abstract PlaybackInfo getPlaybackInfo();
     }
 
+    static final String TAG = "MediaSession2";
+
+    private final SupportLibraryImpl mImpl;
+
+    MediaSession2(SupportLibraryImpl impl) {
+        mImpl = impl;
+        mImpl.setInstance(this);
+    }
+
     /**
-     * Base builder class for MediaSession2 and its subclass. Any change in this class should be
-     * also applied to the subclasses {@link MediaSession2.Builder} and
-     * {@link MediaLibraryService2.MediaLibrarySession.Builder}.
+     * Sets the underlying {@link MediaPlayerBase} and {@link MediaPlaylistAgent} for this session
+     * to dispatch incoming event to.
      * <p>
-     * APIs here should be package private, but should have documentations for developers.
-     * Otherwise, javadoc will generate documentation with the generic types such as follows.
-     * <pre>U extends BuilderBase<T, U, C> setSessionCallback(Executor executor, C callback)</pre>
+     * When a {@link MediaPlaylistAgent} is specified here, the playlist agent should manage
+     * {@link MediaPlayerBase} for calling {@link MediaPlayerBase#setNextDataSources(List)}.
      * <p>
-     * This class is hidden to prevent from generating test stub, which fails with
-     * 'unexpected bound' because it tries to auto generate stub class as follows.
-     * <pre>abstract static class BuilderBase<
-     *      T extends android.media.MediaSession2,
-     *      U extends android.media.MediaSession2.BuilderBase<
-     *              T, U, C extends android.media.MediaSession2.SessionCallback>, C></pre>
+     * If the {@link MediaPlaylistAgent} isn't set, session will recreate the default playlist
+     * agent.
+     *
+     * @param player a {@link MediaPlayerBase} that handles actual media playback in your app
+     * @param playlistAgent a {@link MediaPlaylistAgent} that manages playlist of the {@code player}
+     * @param volumeProvider a {@link VolumeProviderCompat}. If {@code null}, system will adjust the
+     *                       appropriate stream volume for this session's player.
+     */
+    public void updatePlayer(@NonNull MediaPlayerBase player,
+            @Nullable MediaPlaylistAgent playlistAgent,
+            @Nullable VolumeProviderCompat volumeProvider) {
+        mImpl.updatePlayer(player, playlistAgent, volumeProvider);
+    }
+
+    @Override
+    public void close() {
+        try {
+            mImpl.close();
+        } catch (Exception e) {
+            // Should not be here.
+        }
+    }
+
+    /**
+     * @return player
+     */
+    public @NonNull MediaPlayerBase getPlayer() {
+        return mImpl.getPlayer();
+    }
+
+    /**
+     * @return playlist agent
+     */
+    public @NonNull MediaPlaylistAgent getPlaylistAgent() {
+        return mImpl.getPlaylistAgent();
+    }
+
+    /**
+     * @return volume provider
+     */
+    public @Nullable VolumeProviderCompat getVolumeProvider() {
+        return mImpl.getVolumeProvider();
+    }
+
+    /**
+     * Returns the {@link SessionToken2} for creating {@link MediaController2}.
+     */
+    public @NonNull SessionToken2 getToken() {
+        return mImpl.getToken();
+    }
+
+    @NonNull Context getContext() {
+        return mImpl.getContext();
+    }
+
+    @NonNull Executor getCallbackExecutor() {
+        return mImpl.getCallbackExecutor();
+    }
+
+    @NonNull SessionCallback getCallback() {
+        return mImpl.getCallback();
+    }
+
+    /**
+     * Returns the list of connected controller.
+     *
+     * @return list of {@link ControllerInfo}
+     */
+    public @NonNull List<ControllerInfo> getConnectedControllers() {
+        return mImpl.getConnectedControllers();
+    }
+
+    /**
+     * Set the {@link AudioFocusRequest} to obtain the audio focus
+     *
+     * @param afr the full request parameters
+     */
+    public void setAudioFocusRequest(@Nullable AudioFocusRequest afr) {
+        mImpl.setAudioFocusRequest(afr);
+    }
+
+    /**
+     * Sets ordered list of {@link CommandButton} for controllers to build UI with it.
+     * <p>
+     * It's up to controller's decision how to represent the layout in its own UI.
+     * Here's the same way
+     * (layout[i] means a CommandButton at index i in the given list)
+     * For 5 icons row
+     *      layout[3] layout[1] layout[0] layout[2] layout[4]
+     * For 3 icons row
+     *      layout[1] layout[0] layout[2]
+     * For 5 icons row with overflow icon (can show +5 extra buttons with overflow button)
+     *      expanded row:   layout[5] layout[6] layout[7] layout[8] layout[9]
+     *      main row:       layout[3] layout[1] layout[0] layout[2] layout[4]
+     * <p>
+     * This API can be called in the
+     * {@link SessionCallback#onConnect(MediaSession2, ControllerInfo)}.
+     *
+     * @param controller controller to specify layout.
+     * @param layout ordered list of layout.
+     */
+    public void setCustomLayout(@NonNull ControllerInfo controller,
+            @NonNull List<CommandButton> layout) {
+        mImpl.setCustomLayout(controller, layout);
+    }
+
+    /**
+     * Set the new allowed command group for the controller
+     *
+     * @param controller controller to change allowed commands
+     * @param commands new allowed commands
+     */
+    public void setAllowedCommands(@NonNull ControllerInfo controller,
+            @NonNull SessionCommandGroup2 commands) {
+        mImpl.setAllowedCommands(controller, commands);
+    }
+
+    /**
+     * Send custom command to all connected controllers.
+     *
+     * @param command a command
+     * @param args optional argument
+     */
+    public void sendCustomCommand(@NonNull SessionCommand2 command, @Nullable Bundle args) {
+        mImpl.sendCustomCommand(command, args);
+    }
+
+    /**
+     * Send custom command to a specific controller.
+     *
+     * @param command a command
+     * @param args optional argument
+     * @param receiver result receiver for the session
+     */
+    public void sendCustomCommand(@NonNull ControllerInfo controller,
+            @NonNull SessionCommand2 command, @Nullable Bundle args,
+            @Nullable ResultReceiver receiver) {
+        mImpl.sendCustomCommand(controller, command, args, receiver);
+    }
+
+    /**
+     * Play playback.
+     * <p>
+     * This calls {@link MediaPlayerBase#play()}.
+     */
+    @Override
+    public void play() {
+        mImpl.play();
+    }
+
+    /**
+     * Pause playback.
+     * <p>
+     * This calls {@link MediaPlayerBase#pause()}.
+     */
+    @Override
+    public void pause() {
+        mImpl.pause();
+    }
+
+    /**
+     * Stop playback, and reset the player to the initial state.
+     * <p>
+     * This calls {@link MediaPlayerBase#reset()}.
+     */
+    @Override
+    public void reset() {
+        mImpl.reset();
+    }
+
+    /**
+     * Request that the player prepare its playback. In other words, other sessions can continue
+     * to play during the preparation of this session. This method can be used to speed up the
+     * start of the playback. Once the preparation is done, the session will change its playback
+     * state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards, {@link #play} can be called
+     * to start playback.
+     * <p>
+     * This calls {@link MediaPlayerBase#reset()}.
+     */
+    @Override
+    public void prepare() {
+        mImpl.prepare();
+    }
+
+    /**
+     * Move to a new location in the media stream.
+     *
+     * @param pos Position to move to, in milliseconds.
+     */
+    @Override
+    public void seekTo(long pos) {
+        mImpl.seekTo(pos);
+    }
+
+    /**
      * @hide
      */
     @RestrictTo(LIBRARY_GROUP)
-    abstract static class BuilderBase
-            <T extends MediaSession2, U extends BuilderBase<T, U, C>, C extends SessionCallback> {
-        final Context mContext;
-        MediaSession2ImplBase.BuilderBase<T, C> mBaseImpl;
-        MediaPlayerInterface mPlayer;
-        String mId;
-        Executor mCallbackExecutor;
-        C mCallback;
-        MediaPlaylistAgent mPlaylistAgent;
-        VolumeProviderCompat mVolumeProvider;
-        PendingIntent mSessionActivity;
+    @Override
+    public void skipForward() {
+        mImpl.skipForward();
+    }
 
-        BuilderBase(Context context) {
-            if (context == null) {
-                throw new IllegalArgumentException("context shouldn't be null");
-            }
-            mContext = context;
-            // Ensure non-null
-            mId = "";
-        }
+    /**
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    @Override
+    public void skipBackward() {
+        mImpl.skipBackward();
+    }
 
-        /**
-         * Sets the underlying {@link MediaPlayerInterface} for this session to dispatch incoming
-         * event to.
-         *
-         * @param player a {@link MediaPlayerInterface} that handles actual media playback in your
-         *               app.
-         */
-        @NonNull U setPlayer(@NonNull MediaPlayerInterface player) {
-            if (player == null) {
-                throw new IllegalArgumentException("player shouldn't be null");
-            }
-            mBaseImpl.setPlayer(player);
-            return (U) this;
-        }
+    /**
+     * Notify errors to the connected controllers
+     *
+     * @param errorCode error code
+     * @param extras extras
+     */
+    @Override
+    public void notifyError(@ErrorCode int errorCode, @Nullable Bundle extras) {
+        mImpl.notifyError(errorCode, extras);
+    }
 
-        /**
-         * Sets the {@link MediaPlaylistAgent} for this session to manages playlist of the
-         * underlying {@link MediaPlayerInterface}. The playlist agent should manage
-         * {@link MediaPlayerInterface} for calling
-         * {@link MediaPlayerInterface#setNextDataSources(List)}.
-         * <p>
-         * If the {@link MediaPlaylistAgent} isn't set, session will create the default playlist
-         * agent.
-         *
-         * @param playlistAgent a {@link MediaPlaylistAgent} that manages playlist of the
-         *                      {@code player}
-         */
-        U setPlaylistAgent(@NonNull MediaPlaylistAgent playlistAgent) {
-            if (playlistAgent == null) {
-                throw new IllegalArgumentException("playlistAgent shouldn't be null");
-            }
-            mBaseImpl.setPlaylistAgent(playlistAgent);
-            return (U) this;
-        }
+    /**
+     * Notify routes information to a connected controller
+     *
+     * @param controller controller information
+     * @param routes The routes information. Each bundle should be from
+     *              MediaRouteDescritor.asBundle().
+     */
+    public void notifyRoutesInfoChanged(@NonNull ControllerInfo controller,
+            @Nullable List<Bundle> routes) {
+        mImpl.notifyRoutesInfoChanged(controller, routes);
+    }
 
-        /**
-         * Sets the {@link VolumeProviderCompat} for this session to handle volume events. If not
-         * set, system will adjust the appropriate stream volume for this session's player.
-         *
-         * @param volumeProvider The provider that will receive volume button events.
-         */
-        @NonNull U setVolumeProvider(@Nullable VolumeProviderCompat volumeProvider) {
-            mBaseImpl.setVolumeProvider(volumeProvider);
-            return (U) this;
-        }
+    /**
+     * Gets the current player state.
+     *
+     * @return the current player state
+     */
+    @Override
+    public @PlayerState int getPlayerState() {
+        return mImpl.getPlayerState();
+    }
 
-        /**
-         * Set an intent for launching UI for this Session. This can be used as a
-         * quick link to an ongoing media screen. The intent should be for an
-         * activity that may be started using {@link Context#startActivity(Intent)}.
-         *
-         * @param pi The intent to launch to show UI for this session.
-         */
-        @NonNull U setSessionActivity(@Nullable PendingIntent pi) {
-            mBaseImpl.setSessionActivity(pi);
-            return (U) this;
-        }
+    /**
+     * Gets the current position.
+     *
+     * @return the current playback position in ms, or {@link MediaPlayerBase#UNKNOWN_TIME} if
+     *         unknown.
+     */
+    @Override
+    public long getCurrentPosition() {
+        return mImpl.getCurrentPosition();
+    }
 
-        /**
-         * Set ID of the session. If it's not set, an empty string with used to create a session.
-         * <p>
-         * Use this if and only if your app supports multiple playback at the same time and also
-         * wants to provide external apps to have finer controls of them.
-         *
-         * @param id id of the session. Must be unique per package.
-         * @throws IllegalArgumentException if id is {@code null}
-         * @return
-         */
-        @NonNull U setId(@NonNull String id) {
-            if (id == null) {
-                throw new IllegalArgumentException("id shouldn't be null");
-            }
-            mBaseImpl.setId(id);
-            return (U) this;
-        }
+    @Override
+    public long getDuration() {
+        return mImpl.getDuration();
+    }
 
-        /**
-         * Set callback for the session.
-         *
-         * @param executor callback executor
-         * @param callback session callback.
-         * @return
-         */
-        @NonNull U setSessionCallback(@NonNull Executor executor, @NonNull C callback) {
-            if (executor == null) {
-                throw new IllegalArgumentException("executor shouldn't be null");
-            }
-            if (callback == null) {
-                throw new IllegalArgumentException("callback shouldn't be null");
-            }
-            mBaseImpl.setSessionCallback(executor, callback);
-            return (U) this;
-        }
+    /**
+     * Gets the buffered position, or {@link MediaPlayerBase#UNKNOWN_TIME} if unknown.
+     *
+     * @return the buffered position in ms, or {@link MediaPlayerBase#UNKNOWN_TIME}.
+     */
+    @Override
+    public long getBufferedPosition() {
+        return mImpl.getBufferedPosition();
+    }
 
-        /**
-         * Build {@link MediaSession2}.
-         *
-         * @return a new session
-         * @throws IllegalStateException if the session with the same id is already exists for the
-         *      package.
-         */
-        @NonNull T build() {
-            return mBaseImpl.build();
-        }
+    /**
+     * Gets the current buffering state of the player.
+     * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already
+     * buffered.
+     *
+     * @return the buffering state.
+     */
+    @Override
+    public @BuffState int getBufferingState() {
+        return mImpl.getBufferingState();
+    }
 
-        void setImpl(MediaSession2ImplBase.BuilderBase<T, C> impl) {
-            mBaseImpl = impl;
-        }
+    /**
+     * Get the playback speed.
+     *
+     * @return speed
+     */
+    @Override
+    public float getPlaybackSpeed() {
+        return mImpl.getPlaybackSpeed();
+    }
+
+    /**
+     * Set the playback speed.
+     */
+    @Override
+    public void setPlaybackSpeed(float speed) {
+        mImpl.setPlaybackSpeed(speed);
+    }
+
+    /**
+     * Sets the data source missing helper. Helper will be used to provide default implementation of
+     * {@link MediaPlaylistAgent} when it isn't set by developer.
+     * <p>
+     * Default implementation of the {@link MediaPlaylistAgent} will call helper when a
+     * {@link MediaItem2} in the playlist doesn't have a {@link DataSourceDesc}. This may happen
+     * when
+     * <ul>
+     *      <li>{@link MediaItem2} specified by {@link #setPlaylist(List, MediaMetadata2)} doesn't
+     *          have {@link DataSourceDesc}</li>
+     *      <li>{@link MediaController2#addPlaylistItem(int, MediaItem2)} is called and accepted
+     *          by {@link SessionCallback#onCommandRequest(
+     *          MediaSession2, ControllerInfo, SessionCommand2)}.
+     *          In that case, an item would be added automatically without the data source.</li>
+     * </ul>
+     * <p>
+     * If it's not set, playback wouldn't happen for the item without data source descriptor.
+     * <p>
+     * The helper will be run on the executor that was specified by
+     * {@link Builder#setSessionCallback(Executor, SessionCallback)}.
+     *
+     * @param helper a data source missing helper.
+     * @throws IllegalStateException when the helper is set when the playlist agent is set
+     * @see #setPlaylist(List, MediaMetadata2)
+     * @see SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)
+     * @see SessionCommand2#COMMAND_CODE_PLAYLIST_ADD_ITEM
+     * @see SessionCommand2#COMMAND_CODE_PLAYLIST_REPLACE_ITEM
+     */
+    @Override
+    public void setOnDataSourceMissingHelper(@NonNull OnDataSourceMissingHelper helper) {
+        mImpl.setOnDataSourceMissingHelper(helper);
+    }
+
+    /**
+     * Clears the data source missing helper.
+     *
+     * @see #setOnDataSourceMissingHelper(OnDataSourceMissingHelper)
+     */
+    @Override
+    public void clearOnDataSourceMissingHelper() {
+        mImpl.clearOnDataSourceMissingHelper();
+    }
+
+    /**
+     * Returns the playlist from the {@link MediaPlaylistAgent}.
+     * <p>
+     * This list may differ with the list that was specified with
+     * {@link #setPlaylist(List, MediaMetadata2)} depending on the {@link MediaPlaylistAgent}
+     * implementation. Use media items returned here for other playlist agent APIs such as
+     * {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)}.
+     *
+     * @return playlist
+     * @see MediaPlaylistAgent#getPlaylist()
+     * @see SessionCallback#onPlaylistChanged(
+     *          MediaSession2, MediaPlaylistAgent, List, MediaMetadata2)
+     */
+    @Override
+    public List<MediaItem2> getPlaylist() {
+        return mImpl.getPlaylist();
+    }
+
+    /**
+     * Sets a list of {@link MediaItem2} to the {@link MediaPlaylistAgent}. Ensure uniqueness of
+     * each {@link MediaItem2} in the playlist so the session can uniquely identity individual
+     * items.
+     * <p>
+     * This may be an asynchronous call, and {@link MediaPlaylistAgent} may keep the copy of the
+     * list. Wait for {@link SessionCallback#onPlaylistChanged(MediaSession2, MediaPlaylistAgent,
+     * List, MediaMetadata2)} to know the operation finishes.
+     * <p>
+     * You may specify a {@link MediaItem2} without {@link DataSourceDesc}. In that case,
+     * {@link MediaPlaylistAgent} has responsibility to dynamically query {link DataSourceDesc}
+     * when such media item is ready for preparation or play. Default implementation needs
+     * {@link OnDataSourceMissingHelper} for such case.
+     *
+     * @param list A list of {@link MediaItem2} objects to set as a play list.
+     * @throws IllegalArgumentException if given list is {@code null}, or has duplicated media
+     * items.
+     * @see MediaPlaylistAgent#setPlaylist(List, MediaMetadata2)
+     * @see SessionCallback#onPlaylistChanged(
+     *          MediaSession2, MediaPlaylistAgent, List, MediaMetadata2)
+     * @see #setOnDataSourceMissingHelper
+     */
+    @Override
+    public void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) {
+        mImpl.setPlaylist(list, metadata);
+    }
+
+    /**
+     * Skips to the item in the playlist.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)} and the behavior depends
+     * on the playlist agent implementation, especially with the shuffle/repeat mode.
+     *
+     * @param item The item in the playlist you want to play
+     * @see #getShuffleMode()
+     * @see #getRepeatMode()
+     */
+    @Override
+    public void skipToPlaylistItem(@NonNull MediaItem2 item) {
+        mImpl.skipToPlaylistItem(item);
+    }
+
+    /**
+     * Skips to the previous item.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToPreviousItem()} and the behavior depends on the
+     * playlist agent implementation, especially with the shuffle/repeat mode.
+     *
+     * @see #getShuffleMode()
+     * @see #getRepeatMode()
+     **/
+    @Override
+    public void skipToPreviousItem() {
+        mImpl.skipToPreviousItem();
+    }
+
+    /**
+     * Skips to the next item.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToNextItem()} and the behavior depends on the
+     * playlist agent implementation, especially with the shuffle/repeat mode.
+     *
+     * @see #getShuffleMode()
+     * @see #getRepeatMode()
+     */
+    @Override
+    public void skipToNextItem() {
+        mImpl.skipToNextItem();
+    }
+
+    /**
+     * Gets the playlist metadata from the {@link MediaPlaylistAgent}.
+     *
+     * @return the playlist metadata
+     */
+    @Override
+    public MediaMetadata2 getPlaylistMetadata() {
+        return mImpl.getPlaylistMetadata();
+    }
+
+    /**
+     * Adds the media item to the playlist at position index. Index equals or greater than
+     * the current playlist size (e.g. {@link Integer#MAX_VALUE}) will add the item at the end of
+     * the playlist.
+     * <p>
+     * This will not change the currently playing media item.
+     * If index is less than or equal to the current index of the play list,
+     * the current index of the play list will be incremented correspondingly.
+     *
+     * @param index the index you want to add
+     * @param item the media item you want to add
+     */
+    @Override
+    public void addPlaylistItem(int index, @NonNull MediaItem2 item) {
+        mImpl.addPlaylistItem(index, item);
+    }
+
+    /**
+     * Removes the media item in the playlist.
+     * <p>
+     * If the item is the currently playing item of the playlist, current playback
+     * will be stopped and playback moves to next source in the list.
+     *
+     * @param item the media item you want to add
+     */
+    @Override
+    public void removePlaylistItem(@NonNull MediaItem2 item) {
+        mImpl.removePlaylistItem(item);
+    }
+
+    /**
+     * Replaces the media item at index in the playlist. This can be also used to update metadata of
+     * an item.
+     *
+     * @param index the index of the item to replace
+     * @param item the new item
+     */
+    @Override
+    public void replacePlaylistItem(int index, @NonNull MediaItem2 item) {
+        mImpl.replacePlaylistItem(index, item);
+    }
+
+    /**
+     * Return currently playing media item.
+     *
+     * @return currently playing media item
+     */
+    @Override
+    public MediaItem2 getCurrentMediaItem() {
+        return mImpl.getCurrentMediaItem();
+    }
+
+    /**
+     * Updates the playlist metadata to the {@link MediaPlaylistAgent}.
+     *
+     * @param metadata metadata of the playlist
+     */
+    @Override
+    public void updatePlaylistMetadata(@Nullable MediaMetadata2 metadata) {
+        mImpl.updatePlaylistMetadata(metadata);
+    }
+
+    /**
+     * Gets the repeat mode from the {@link MediaPlaylistAgent}.
+     *
+     * @return repeat mode
+     * @see MediaPlaylistAgent#REPEAT_MODE_NONE
+     * @see MediaPlaylistAgent#REPEAT_MODE_ONE
+     * @see MediaPlaylistAgent#REPEAT_MODE_ALL
+     * @see MediaPlaylistAgent#REPEAT_MODE_GROUP
+     */
+    @Override
+    public @RepeatMode int getRepeatMode() {
+        return mImpl.getRepeatMode();
+    }
+
+    /**
+     * Sets the repeat mode to the {@link MediaPlaylistAgent}.
+     *
+     * @param repeatMode repeat mode
+     * @see MediaPlaylistAgent#REPEAT_MODE_NONE
+     * @see MediaPlaylistAgent#REPEAT_MODE_ONE
+     * @see MediaPlaylistAgent#REPEAT_MODE_ALL
+     * @see MediaPlaylistAgent#REPEAT_MODE_GROUP
+     */
+    @Override
+    public void setRepeatMode(@RepeatMode int repeatMode) {
+        mImpl.setRepeatMode(repeatMode);
+    }
+
+    /**
+     * Gets the shuffle mode from the {@link MediaPlaylistAgent}.
+     *
+     * @return The shuffle mode
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP
+     */
+    @Override
+    public @ShuffleMode int getShuffleMode() {
+        return mImpl.getShuffleMode();
+    }
+
+    /**
+     * Sets the shuffle mode to the {@link MediaPlaylistAgent}.
+     *
+     * @param shuffleMode The shuffle mode
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL
+     * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP
+     */
+    @Override
+    public void setShuffleMode(@ShuffleMode int shuffleMode) {
+        mImpl.setShuffleMode(shuffleMode);
     }
 }
diff --git a/media/src/main/java/androidx/media/MediaSession2ImplBase.java b/media/src/main/java/androidx/media/MediaSession2ImplBase.java
index 1e768a0..e474b45 100644
--- a/media/src/main/java/androidx/media/MediaSession2ImplBase.java
+++ b/media/src/main/java/androidx/media/MediaSession2ImplBase.java
@@ -16,8 +16,7 @@
 
 package androidx.media;
 
-import static androidx.media.MediaPlayerInterface.BUFFERING_STATE_UNKNOWN;
-import static androidx.media.MediaSession2.ControllerCb;
+import static androidx.media.MediaPlayerBase.BUFFERING_STATE_UNKNOWN;
 import static androidx.media.MediaSession2.ControllerInfo;
 import static androidx.media.MediaSession2.ErrorCode;
 import static androidx.media.MediaSession2.OnDataSourceMissingHelper;
@@ -36,11 +35,9 @@
 import android.media.AudioManager;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
-import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.support.v4.media.session.MediaSessionCompat;
 import android.support.v4.media.session.PlaybackStateCompat;
@@ -50,9 +47,8 @@
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.core.util.ObjectsCompat;
 import androidx.media.MediaController2.PlaybackInfo;
-import androidx.media.MediaPlayerInterface.PlayerEventCallback;
+import androidx.media.MediaPlayerBase.PlayerEventCallback;
 import androidx.media.MediaPlaylistAgent.PlaylistEventCallback;
 
 import java.lang.ref.WeakReference;
@@ -72,19 +68,19 @@
     private final HandlerThread mHandlerThread;
     private final Handler mHandler;
     private final MediaSessionCompat mSessionCompat;
-    private final MediaSession2Stub mSession2Stub;
-    private final MediaSessionLegacyStub mSessionLegacyStub;
+    private final MediaSession2StubImplBase mSession2Stub;
     private final String mId;
     private final Executor mCallbackExecutor;
     private final SessionCallback mCallback;
     private final SessionToken2 mSessionToken;
     private final AudioManager mAudioManager;
-    private final MediaPlayerInterface.PlayerEventCallback mPlayerEventCallback;
+    private final MediaPlayerBase.PlayerEventCallback mPlayerEventCallback;
     private final MediaPlaylistAgent.PlaylistEventCallback mPlaylistEventCallback;
-    private final MediaSession2 mInstance;
+
+    private WeakReference<MediaSession2> mInstance;
 
     @GuardedBy("mLock")
-    private MediaPlayerInterface mPlayer;
+    private MediaPlayerBase mPlayer;
     @GuardedBy("mLock")
     private MediaPlaylistAgent mPlaylistAgent;
     @GuardedBy("mLock")
@@ -94,21 +90,21 @@
     @GuardedBy("mLock")
     private OnDataSourceMissingHelper mDsmHelper;
     @GuardedBy("mLock")
+    private PlaybackStateCompat mPlaybackStateCompat;
+    @GuardedBy("mLock")
     private PlaybackInfo mPlaybackInfo;
 
     MediaSession2ImplBase(Context context, MediaSessionCompat sessionCompat, String id,
-            MediaPlayerInterface player, MediaPlaylistAgent playlistAgent,
+            MediaPlayerBase player, MediaPlaylistAgent playlistAgent,
             VolumeProviderCompat volumeProvider, PendingIntent sessionActivity,
             Executor callbackExecutor, SessionCallback callback) {
         mContext = context;
-        mInstance = createInstance();
         mHandlerThread = new HandlerThread("MediaController2_Thread");
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
 
         mSessionCompat = sessionCompat;
-        mSession2Stub = new MediaSession2Stub(this);
-        mSessionLegacyStub = new MediaSessionLegacyStub(this);
+        mSession2Stub = new MediaSession2StubImplBase(this);
         mSessionCompat.setCallback(mSession2Stub, mHandler);
         mSessionCompat.setSessionActivity(sessionActivity);
 
@@ -117,6 +113,7 @@
         mCallbackExecutor = callbackExecutor;
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
 
+        // TODO: Set callback values properly
         mPlayerEventCallback = new MyPlayerEventCallback(this);
         mPlaylistEventCallback = new MyPlaylistEventCallback(this);
 
@@ -140,22 +137,16 @@
     }
 
     @Override
-    public void updatePlayer(@NonNull MediaPlayerInterface player,
+    public void updatePlayer(@NonNull MediaPlayerBase player,
             @Nullable MediaPlaylistAgent playlistAgent,
             @Nullable VolumeProviderCompat volumeProvider) {
         if (player == null) {
             throw new IllegalArgumentException("player shouldn't be null");
         }
-        final boolean hasPlayerChanged;
-        final boolean hasAgentChanged;
-        final boolean hasPlaybackInfoChanged;
-        final MediaPlayerInterface oldPlayer;
+        final MediaPlayerBase oldPlayer;
         final MediaPlaylistAgent oldAgent;
         final PlaybackInfo info = createPlaybackInfo(volumeProvider, player.getAudioAttributes());
         synchronized (mLock) {
-            hasPlayerChanged = (mPlayer != player);
-            hasAgentChanged = (mPlaylistAgent != playlistAgent);
-            hasPlaybackInfoChanged = (mPlaybackInfo != info);
             oldPlayer = mPlayer;
             oldAgent = mPlaylistAgent;
             mPlayer = player;
@@ -170,10 +161,6 @@
             mVolumeProvider = volumeProvider;
             mPlaybackInfo = info;
         }
-        if (volumeProvider == null) {
-            int stream = getLegacyStreamType(player.getAudioAttributes());
-            mSessionCompat.setPlaybackToLocal(stream);
-        }
         if (player != oldPlayer) {
             player.registerPlayerEventCallback(mCallbackExecutor, mPlayerEventCallback);
             if (oldPlayer != null) {
@@ -184,40 +171,35 @@
         if (playlistAgent != oldAgent) {
             playlistAgent.registerPlaylistEventCallback(mCallbackExecutor, mPlaylistEventCallback);
             if (oldAgent != null) {
-                // Warning: Poorly implement agent may ignore this
+                // Warning: Poorly implement player may ignore this
                 oldAgent.unregisterPlaylistEventCallback(mPlaylistEventCallback);
             }
         }
 
         if (oldPlayer != null) {
-            // If it's not the first updatePlayer(), tell changes in the player, agent, and playback
-            // info.
-            if (hasAgentChanged) {
-                // Update agent first. Otherwise current position may be changed off the current
-                // media item's duration, and controller may consider it as a bug.
-                notifyAgentUpdatedNotLocked(oldAgent);
-            }
-            if (hasPlayerChanged) {
-                notifyPlayerUpdatedNotLocked(oldPlayer);
-            }
-            if (hasPlaybackInfoChanged) {
-                // Currently hasPlaybackInfo is always true, but check this in case that we're
-                // adding PlaybackInfo#equals().
-                notifyToAllControllers(new NotifyRunnable() {
-                    @Override
-                    public void run(ControllerCb callback) throws RemoteException {
-                        callback.onPlaybackInfoChanged(info);
-                    }
-                });
-            }
+            mSession2Stub.notifyPlaybackInfoChanged(info);
+            notifyPlayerUpdatedNotLocked(oldPlayer);
         }
+        // TODO(jaewan): Repeat the same thing for the playlist agent.
     }
 
     private PlaybackInfo createPlaybackInfo(VolumeProviderCompat volumeProvider,
             AudioAttributesCompat attrs) {
         PlaybackInfo info;
         if (volumeProvider == null) {
-            int stream = getLegacyStreamType(attrs);
+            int stream;
+            if (attrs == null) {
+                stream = AudioManager.STREAM_MUSIC;
+            } else {
+                stream = attrs.getVolumeControlStream();
+                if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) {
+                    // It may happen if the AudioAttributes doesn't have usage.
+                    // Change it to the STREAM_MUSIC because it's not supported by audio manager
+                    // for querying volume level.
+                    stream = AudioManager.STREAM_MUSIC;
+                }
+            }
+
             int controlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
             if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
                 controlType = VolumeProviderCompat.VOLUME_CONTROL_FIXED;
@@ -239,23 +221,6 @@
         return info;
     }
 
-    private int getLegacyStreamType(@Nullable AudioAttributesCompat attrs) {
-        int stream;
-        if (attrs == null) {
-            stream = AudioManager.STREAM_MUSIC;
-        } else {
-            stream = attrs.getLegacyStreamType();
-            if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) {
-                // Usually, AudioAttributesCompat#getLegacyStreamType() does not return
-                // USE_DEFAULT_STREAM_TYPE unless the developer sets it with
-                // AudioAttributesCompat.Builder#setLegacyStreamType().
-                // But for safety, let's convert USE_DEFAULT_STREAM_TYPE to STREAM_MUSIC here.
-                stream = AudioManager.STREAM_MUSIC;
-            }
-        }
-        return stream;
-    }
-
     @Override
     public void close() {
         synchronized (mLock) {
@@ -267,17 +232,13 @@
             mSessionCompat.release();
             mHandler.removeCallbacksAndMessages(null);
             if (mHandlerThread.isAlive()) {
-                if (Build.VERSION.SDK_INT >= 18) {
-                    mHandlerThread.quitSafely();
-                } else {
-                    mHandlerThread.quit();
-                }
+                mHandlerThread.quitSafely();
             }
         }
     }
 
     @Override
-    public @NonNull MediaPlayerInterface getPlayer() {
+    public @NonNull MediaPlayerBase getPlayer() {
         synchronized (mLock) {
             return mPlayer;
         }
@@ -303,34 +264,31 @@
     }
 
     @Override
-    public @NonNull List<ControllerInfo> getConnectedControllers() {
+    public @NonNull List<MediaSession2.ControllerInfo> getConnectedControllers() {
         return mSession2Stub.getConnectedControllers();
     }
 
     @Override
     public void setAudioFocusRequest(@Nullable AudioFocusRequest afr) {
+        // TODO(jaewan): implement this (b/72529899)
+        // mProvider.setAudioFocusRequest_impl(focusGain);
     }
 
     @Override
     public void setCustomLayout(@NonNull ControllerInfo controller,
-            @NonNull final List<MediaSession2.CommandButton> layout) {
+            @NonNull List<MediaSession2.CommandButton> layout) {
         if (controller == null) {
             throw new IllegalArgumentException("controller shouldn't be null");
         }
         if (layout == null) {
             throw new IllegalArgumentException("layout shouldn't be null");
         }
-        notifyToController(controller, new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onCustomLayoutChanged(layout);
-            }
-        });
+        mSession2Stub.notifyCustomLayout(controller, layout);
     }
 
     @Override
     public void setAllowedCommands(@NonNull ControllerInfo controller,
-            @NonNull final SessionCommandGroup2 commands) {
+            @NonNull SessionCommandGroup2 commands) {
         if (controller == null) {
             throw new IllegalArgumentException("controller shouldn't be null");
         }
@@ -338,49 +296,32 @@
             throw new IllegalArgumentException("commands shouldn't be null");
         }
         mSession2Stub.setAllowedCommands(controller, commands);
-        notifyToController(controller, new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onAllowedCommandsChanged(commands);
-            }
-        });
     }
 
     @Override
-    public void sendCustomCommand(@NonNull final SessionCommand2 command,
-            @Nullable final Bundle args) {
+    public void sendCustomCommand(@NonNull SessionCommand2 command, @Nullable Bundle args) {
         if (command == null) {
             throw new IllegalArgumentException("command shouldn't be null");
         }
-        notifyToAllControllers(new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onCustomCommand(command, args, null);
-            }
-        });
+        mSession2Stub.sendCustomCommand(command, args);
     }
 
     @Override
     public void sendCustomCommand(@NonNull ControllerInfo controller,
-            @NonNull final SessionCommand2 command, @Nullable final Bundle args,
-            @Nullable final ResultReceiver receiver) {
+            @NonNull SessionCommand2 command, @Nullable Bundle args,
+            @Nullable ResultReceiver receiver) {
         if (controller == null) {
             throw new IllegalArgumentException("controller shouldn't be null");
         }
         if (command == null) {
             throw new IllegalArgumentException("command shouldn't be null");
         }
-        notifyToController(controller, new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onCustomCommand(command, args, receiver);
-            }
-        });
+        mSession2Stub.sendCustomCommand(controller, command, args, receiver);
     }
 
     @Override
     public void play() {
-        MediaPlayerInterface player;
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -393,7 +334,7 @@
 
     @Override
     public void pause() {
-        MediaPlayerInterface player;
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -406,7 +347,7 @@
 
     @Override
     public void reset() {
-        MediaPlayerInterface player;
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -419,7 +360,7 @@
 
     @Override
     public void prepare() {
-        MediaPlayerInterface player;
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -432,7 +373,7 @@
 
     @Override
     public void seekTo(long pos) {
-        MediaPlayerInterface player;
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -454,29 +395,19 @@
     }
 
     @Override
-    public void notifyError(@ErrorCode final int errorCode, @Nullable final Bundle extras) {
-        notifyToAllControllers(new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onError(errorCode, extras);
-            }
-        });
+    public void notifyError(@ErrorCode int errorCode, @Nullable Bundle extras) {
+        mSession2Stub.notifyError(errorCode, extras);
     }
 
     @Override
     public void notifyRoutesInfoChanged(@NonNull ControllerInfo controller,
-            @Nullable final List<Bundle> routes) {
-        notifyToController(controller, new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onRoutesInfoChanged(routes);
-            }
-        });
+            @Nullable List<Bundle> routes) {
+        mSession2Stub.notifyRoutesInfoChanged(controller, routes);
     }
 
     @Override
-    public @MediaPlayerInterface.PlayerState int getPlayerState() {
-        MediaPlayerInterface player;
+    public @MediaPlayerBase.PlayerState int getPlayerState() {
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -485,12 +416,12 @@
         } else if (DEBUG) {
             Log.d(TAG, "API calls after the close()", new IllegalStateException());
         }
-        return MediaPlayerInterface.PLAYER_STATE_ERROR;
+        return MediaPlayerBase.PLAYER_STATE_ERROR;
     }
 
     @Override
     public long getCurrentPosition() {
-        MediaPlayerInterface player;
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -499,28 +430,18 @@
         } else if (DEBUG) {
             Log.d(TAG, "API calls after the close()", new IllegalStateException());
         }
-        return MediaPlayerInterface.UNKNOWN_TIME;
+        return MediaPlayerBase.UNKNOWN_TIME;
     }
 
     @Override
     public long getDuration() {
-        MediaPlayerInterface player;
-        synchronized (mLock) {
-            player = mPlayer;
-        }
-        if (player != null) {
-            // Note: This should be the same as
-            // getCurrentMediaItem().getMetadata().getLong(METADATA_KEY_DURATION)
-            return player.getDuration();
-        } else if (DEBUG) {
-            Log.d(TAG, "API calls after the close()", new IllegalStateException());
-        }
-        return MediaPlayerInterface.UNKNOWN_TIME;
+        // TODO: implement
+        return 0;
     }
 
     @Override
     public long getBufferedPosition() {
-        MediaPlayerInterface player;
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -529,12 +450,12 @@
         } else if (DEBUG) {
             Log.d(TAG, "API calls after the close()", new IllegalStateException());
         }
-        return MediaPlayerInterface.UNKNOWN_TIME;
+        return MediaPlayerBase.UNKNOWN_TIME;
     }
 
     @Override
-    public @MediaPlayerInterface.BuffState int getBufferingState() {
-        MediaPlayerInterface player;
+    public @MediaPlayerBase.BuffState int getBufferingState() {
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -548,7 +469,7 @@
 
     @Override
     public float getPlaybackSpeed() {
-        MediaPlayerInterface player;
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -562,7 +483,7 @@
 
     @Override
     public void setPlaybackSpeed(float speed) {
-        MediaPlayerInterface player;
+        MediaPlayerBase player;
         synchronized (mLock) {
             player = mPlayer;
         }
@@ -819,63 +740,18 @@
     }
 
     ///////////////////////////////////////////////////
-    // LibrarySession Methods
-    ///////////////////////////////////////////////////
-
-    @Override
-    void notifyChildrenChanged(ControllerInfo controller, final String parentId,
-            final int itemCount, final Bundle extras,
-            List<MediaSessionManager.RemoteUserInfo> subscribingBrowsers) {
-        if (controller == null) {
-            throw new IllegalArgumentException("controller shouldn't be null");
-        }
-        if (TextUtils.isEmpty(parentId)) {
-            throw new IllegalArgumentException("query shouldn't be empty");
-        }
-
-        // Notify controller only if it has subscribed the parentId.
-        for (MediaSessionManager.RemoteUserInfo info : subscribingBrowsers) {
-            if (info.getPackageName().equals(controller.getPackageName())
-                    && info.getUid() == controller.getUid()) {
-                notifyToController(controller, new NotifyRunnable() {
-                    @Override
-                    public void run(ControllerCb callback) throws RemoteException {
-                        callback.onChildrenChanged(parentId, itemCount, extras);
-                    }
-                });
-                return;
-            }
-        }
-    }
-
-    @Override
-    void notifySearchResultChanged(ControllerInfo controller, final String query,
-            final int itemCount, final Bundle extras) {
-        if (controller == null) {
-            throw new IllegalArgumentException("controller shouldn't be null");
-        }
-        if (TextUtils.isEmpty(query)) {
-            throw new IllegalArgumentException("query shouldn't be empty");
-        }
-        notifyToController(controller, new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onSearchResultChanged(query, itemCount, extras);
-            }
-        });
-    }
-
-    ///////////////////////////////////////////////////
     // package private and private methods
     ///////////////////////////////////////////////////
+
     @Override
-    MediaSession2 createInstance() {
-        return new MediaSession2(this);
+    void setInstance(MediaSession2 session) {
+        mInstance = new WeakReference<>(session);
+
     }
 
     @Override
-    @NonNull MediaSession2 getInstance() {
-        return mInstance;
+    MediaSession2 getInstance() {
+        return mInstance.get();
     }
 
     @Override
@@ -894,11 +770,6 @@
     }
 
     @Override
-    MediaSessionCompat getSessionCompat() {
-        return mSessionCompat;
-    }
-
-    @Override
     boolean isClosed() {
         return !mHandlerThread.isAlive();
     }
@@ -908,6 +779,12 @@
         synchronized (mLock) {
             int state = MediaUtils2.createPlaybackStateCompatState(getPlayerState(),
                     getBufferingState());
+            // TODO: Consider following missing stuff
+            //       - setCustomAction(): Fill custom layout
+            //       - setErrorMessage(): Fill error message when notifyError() is called.
+            //       - setActiveQueueItemId(): Fill here with the current media item...
+            //       - setExtra(): No idea at this moment.
+            // TODO: generate actions from the allowed commands.
             long allActions = PlaybackStateCompat.ACTION_STOP | PlaybackStateCompat.ACTION_PAUSE
                     | PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_REWIND
                     | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
@@ -939,6 +816,11 @@
             return mPlaybackInfo;
         }
     }
+
+    MediaSession2StubImplBase getSession2Stub() {
+        return mSession2Stub;
+    }
+
     private static String getServiceName(Context context, String serviceAction, String id) {
         PackageManager manager = context.getPackageManager();
         Intent serviceIntent = new Intent(serviceAction);
@@ -964,203 +846,105 @@
         return serviceName;
     }
 
-    private void notifyAgentUpdatedNotLocked(MediaPlaylistAgent oldAgent) {
-        // Tells the playlist change first, to current item can change be notified with an item
-        // within the playlist.
-        List<MediaItem2> oldPlaylist = oldAgent.getPlaylist();
-        final List<MediaItem2> newPlaylist = getPlaylist();
-        if (!ObjectsCompat.equals(oldPlaylist, newPlaylist)) {
-            notifyToAllControllers(new NotifyRunnable() {
-                @Override
-                public void run(ControllerCb callback) throws RemoteException {
-                    callback.onPlaylistChanged(
-                            newPlaylist, getPlaylistMetadata());
-                }
-            });
-        } else {
-            MediaMetadata2 oldMetadata = oldAgent.getPlaylistMetadata();
-            final MediaMetadata2 newMetadata = getPlaylistMetadata();
-            if (!ObjectsCompat.equals(oldMetadata, newMetadata)) {
-                notifyToAllControllers(new NotifyRunnable() {
-                    @Override
-                    public void run(ControllerCb callback) throws RemoteException {
-                        callback.onPlaylistMetadataChanged(newMetadata);
-                    }
-                });
-            }
+    private void notifyPlayerUpdatedNotLocked(MediaPlayerBase oldPlayer) {
+        MediaPlayerBase player;
+        synchronized (mLock) {
+            player = mPlayer;
         }
-        MediaItem2 oldCurrentItem = oldAgent.getCurrentMediaItem();
-        final MediaItem2 newCurrentItem = getCurrentMediaItem();
-        if (!ObjectsCompat.equals(oldCurrentItem, newCurrentItem)) {
-            notifyToAllControllers(new NotifyRunnable() {
-                @Override
-                public void run(ControllerCb callback) throws RemoteException {
-                    callback.onCurrentMediaItemChanged(newCurrentItem);
-                }
-            });
+        // TODO(jaewan): (Can be post-P) Find better way for player.getPlayerState() //
+        //               In theory, Session.getXXX() may not be the same as Player.getXXX()
+        //               and we should notify information of the session.getXXX() instead of
+        //               player.getXXX()
+        // Notify to controllers as well.
+        final int state = player.getPlayerState();
+        if (state != oldPlayer.getPlayerState()) {
+            // TODO: implement
+            mSession2Stub.notifyPlayerStateChanged(state);
         }
-        final int repeatMode = getRepeatMode();
-        if (oldAgent.getRepeatMode() != repeatMode) {
-            notifyToAllControllers(new NotifyRunnable() {
-                @Override
-                public void run(ControllerCb callback) throws RemoteException {
-                    callback.onRepeatModeChanged(repeatMode);
-                }
-            });
-        }
-        final int shuffleMode = getShuffleMode();
-        if (oldAgent.getShuffleMode() != shuffleMode) {
-            notifyToAllControllers(new NotifyRunnable() {
-                @Override
-                public void run(ControllerCb callback) throws RemoteException {
-                    callback.onShuffleModeChanged(shuffleMode);
-                }
-            });
-        }
-    }
 
-    private void notifyPlayerUpdatedNotLocked(MediaPlayerInterface oldPlayer) {
-        // Always forcefully send the player state and buffered state to send the current position
-        // and buffered position.
-        final int playerState = getPlayerState();
-        notifyToAllControllers(new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onPlayerStateChanged(playerState);
-            }
-        });
-        final MediaItem2 item = getCurrentMediaItem();
-        if (item != null) {
-            final int bufferingState = getBufferingState();
-            notifyToAllControllers(new NotifyRunnable() {
-                @Override
-                public void run(ControllerCb callback) throws RemoteException {
-                    callback.onBufferingStateChanged(item, bufferingState);
-                }
-            });
+        final long currentTimeMs = System.currentTimeMillis();
+        final long position = player.getCurrentPosition();
+        if (position != oldPlayer.getCurrentPosition()) {
+            // TODO: implement
+            //mSession2Stub.notifyPositionChangedNotLocked(currentTimeMs, position);
         }
-        final float speed = getPlaybackSpeed();
+
+        final float speed = player.getPlaybackSpeed();
         if (speed != oldPlayer.getPlaybackSpeed()) {
-            notifyToAllControllers(new NotifyRunnable() {
-                @Override
-                public void run(ControllerCb callback) throws RemoteException {
-                    callback.onPlaybackSpeedChanged(speed);
-                }
-            });
+            // TODO: implement
+            //mSession2Stub.notifyPlaybackSpeedChangedNotLocked(speed);
         }
-        // Note: AudioInfo is updated outside of this API.
+
+        final long bufferedPosition = player.getBufferedPosition();
+        if (bufferedPosition != oldPlayer.getBufferedPosition()) {
+            // TODO: implement
+            //mSession2Stub.notifyBufferedPositionChangedNotLocked(bufferedPosition);
+        }
     }
 
     private void notifyPlaylistChangedOnExecutor(MediaPlaylistAgent playlistAgent,
-            final List<MediaItem2> list, final MediaMetadata2 metadata) {
+            List<MediaItem2> list, MediaMetadata2 metadata) {
         synchronized (mLock) {
             if (playlistAgent != mPlaylistAgent) {
                 // Ignore calls from the old agent.
                 return;
             }
         }
-        mCallback.onPlaylistChanged(mInstance, playlistAgent, list, metadata);
-        notifyToAllControllers(new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onPlaylistChanged(list, metadata);
-            }
-        });
+        MediaSession2 session2 = mInstance.get();
+        if (session2 != null) {
+            mCallback.onPlaylistChanged(session2, playlistAgent, list, metadata);
+            mSession2Stub.notifyPlaylistChanged(list, metadata);
+        }
     }
 
     private void notifyPlaylistMetadataChangedOnExecutor(MediaPlaylistAgent playlistAgent,
-            final MediaMetadata2 metadata) {
+            MediaMetadata2 metadata) {
         synchronized (mLock) {
             if (playlistAgent != mPlaylistAgent) {
                 // Ignore calls from the old agent.
                 return;
             }
         }
-        mCallback.onPlaylistMetadataChanged(mInstance, playlistAgent, metadata);
-        notifyToAllControllers(new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onPlaylistMetadataChanged(metadata);
-            }
-        });
+        MediaSession2 session2 = mInstance.get();
+        if (session2 != null) {
+            mCallback.onPlaylistMetadataChanged(session2, playlistAgent, metadata);
+            mSession2Stub.notifyPlaylistMetadataChanged(metadata);
+        }
     }
 
     private void notifyRepeatModeChangedOnExecutor(MediaPlaylistAgent playlistAgent,
-            final int repeatMode) {
+            int repeatMode) {
         synchronized (mLock) {
             if (playlistAgent != mPlaylistAgent) {
                 // Ignore calls from the old agent.
                 return;
             }
         }
-        mCallback.onRepeatModeChanged(mInstance, playlistAgent, repeatMode);
-        notifyToAllControllers(new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onRepeatModeChanged(repeatMode);
-            }
-        });
+        MediaSession2 session2 = mInstance.get();
+        if (session2 != null) {
+            mCallback.onRepeatModeChanged(session2, playlistAgent, repeatMode);
+            mSession2Stub.notifyRepeatModeChanged(repeatMode);
+        }
     }
 
     private void notifyShuffleModeChangedOnExecutor(MediaPlaylistAgent playlistAgent,
-            final int shuffleMode) {
+            int shuffleMode) {
         synchronized (mLock) {
             if (playlistAgent != mPlaylistAgent) {
                 // Ignore calls from the old agent.
                 return;
             }
         }
-        mCallback.onShuffleModeChanged(mInstance, playlistAgent, shuffleMode);
-        notifyToAllControllers(new NotifyRunnable() {
-            @Override
-            public void run(ControllerCb callback) throws RemoteException {
-                callback.onShuffleModeChanged(shuffleMode);
-            }
-        });
-    }
-
-    private void notifyToController(@NonNull final ControllerInfo controller,
-            @NonNull NotifyRunnable runnable) {
-        if (controller == null) {
-            return;
-        }
-        try {
-            runnable.run(controller.getControllerCb());
-        } catch (DeadObjectException e) {
-            if (DEBUG) {
-                Log.d(TAG, controller.toString() + " is gone", e);
-            }
-            mSession2Stub.removeControllerInfo(controller);
-            mCallbackExecutor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    mCallback.onDisconnected(MediaSession2ImplBase.this.getInstance(), controller);
-                }
-            });
-        } catch (RemoteException e) {
-            // Currently it's TransactionTooLargeException or DeadSystemException.
-            // We'd better to leave log for those cases because
-            //   - TransactionTooLargeException means that we may need to fix our code.
-            //     (e.g. add pagination or special way to deliver Bitmap)
-            //   - DeadSystemException means that errors around it can be ignored.
-            Log.w(TAG, "Exception in " + controller.toString(), e);
-        }
-    }
-
-    private void notifyToAllControllers(@NonNull NotifyRunnable runnable) {
-        List<ControllerInfo> controllers = getConnectedControllers();
-        for (int i = 0; i < controllers.size(); i++) {
-            notifyToController(controllers.get(i), runnable);
+        MediaSession2 session2 = mInstance.get();
+        if (session2 != null) {
+            mCallback.onShuffleModeChanged(session2, playlistAgent, shuffleMode);
+            mSession2Stub.notifyShuffleModeChanged(shuffleMode);
         }
     }
 
     ///////////////////////////////////////////////////
     // Inner classes
     ///////////////////////////////////////////////////
-    @FunctionalInterface
-    private interface NotifyRunnable {
-        void run(ControllerCb callback) throws RemoteException;
-    }
 
     private static class MyPlayerEventCallback extends PlayerEventCallback {
         private final WeakReference<MediaSession2ImplBase> mSession;
@@ -1170,41 +954,31 @@
         }
 
         @Override
-        public void onCurrentDataSourceChanged(final MediaPlayerInterface player,
+        public void onCurrentDataSourceChanged(final MediaPlayerBase mpb,
                 final DataSourceDesc dsd) {
             final MediaSession2ImplBase session = getSession();
-            if (session == null) {
+            // TODO: handle properly when dsd == null
+            if (session == null || dsd == null) {
                 return;
             }
             session.getCallbackExecutor().execute(new Runnable() {
                 @Override
                 public void run() {
-                    final MediaItem2 item;
-                    if (dsd == null) {
-                        // This is OK because onCurrentDataSourceChanged() can be called with the
-                        // null dsd, so onCurrentMediaItemChanged() can be as well.
-                        item = null;
-                    } else {
-                        item = MyPlayerEventCallback.this.getMediaItem(session, dsd);
-                        if (item == null) {
-                            Log.w(TAG, "Cannot obtain media item from the dsd=" + dsd);
-                            return;
-                        }
+                    MediaItem2 item = MyPlayerEventCallback.this.getMediaItem(session, dsd);
+                    if (item == null) {
+                        return;
                     }
-                    session.getCallback().onCurrentMediaItemChanged(session.getInstance(), player,
+                    session.getCallback().onCurrentMediaItemChanged(session.getInstance(), mpb,
                             item);
-                    session.notifyToAllControllers(new NotifyRunnable() {
-                        @Override
-                        public void run(ControllerCb callback) throws RemoteException {
-                            callback.onCurrentMediaItemChanged(item);
-                        }
-                    });
+                    if (item.equals(session.getCurrentMediaItem())) {
+                        session.getSession2Stub().notifyCurrentMediaItemChanged(item);
+                    }
                 }
             });
         }
 
         @Override
-        public void onMediaPrepared(final MediaPlayerInterface mpb, final DataSourceDesc dsd) {
+        public void onMediaPrepared(final MediaPlayerBase mpb, final DataSourceDesc dsd) {
             final MediaSession2ImplBase session = getSession();
             if (session == null || dsd == null) {
                 return;
@@ -1216,58 +990,14 @@
                     if (item == null) {
                         return;
                     }
-                    if (item.equals(session.getCurrentMediaItem())) {
-                        long duration = session.getDuration();
-                        if (duration < 0) {
-                            return;
-                        }
-                        MediaMetadata2 metadata = item.getMetadata();
-                        if (metadata != null) {
-                            if (!metadata.containsKey(MediaMetadata2.METADATA_KEY_DURATION)) {
-                                metadata = new MediaMetadata2.Builder(metadata).putLong(
-                                        MediaMetadata2.METADATA_KEY_DURATION, duration).build();
-                            } else {
-                                long durationFromMetadata =
-                                        metadata.getLong(MediaMetadata2.METADATA_KEY_DURATION);
-                                if (duration != durationFromMetadata) {
-                                    // Warns developers about the mismatch. Don't log media item
-                                    // here to keep metadata secure.
-                                    Log.w(TAG, "duration mismatch for an item."
-                                            + " duration from player=" + duration
-                                            + " duration from metadata=" + durationFromMetadata
-                                            + ". May be a timing issue?");
-                                }
-                                // Trust duration in the metadata set by developer.
-                                // In theory, duration may differ if the current item has been
-                                // changed before the getDuration(). So it's better not touch
-                                // duration set by developer.
-                                metadata = null;
-                            }
-                        } else {
-                            metadata = new MediaMetadata2.Builder()
-                                    .putLong(MediaMetadata2.METADATA_KEY_DURATION, duration)
-                                    .putString(MediaMetadata2.METADATA_KEY_MEDIA_ID,
-                                            item.getMediaId())
-                                    .build();
-                        }
-                        if (metadata != null) {
-                            item.setMetadata(metadata);
-                            session.notifyToAllControllers(new NotifyRunnable() {
-                                @Override
-                                public void run(ControllerCb callback) throws RemoteException {
-                                    callback.onPlaylistChanged(
-                                            session.getPlaylist(), session.getPlaylistMetadata());
-                                }
-                            });
-                        }
-                    }
                     session.getCallback().onMediaPrepared(session.getInstance(), mpb, item);
+                    // TODO (jaewan): Notify controllers through appropriate callback. (b/74505936)
                 }
             });
         }
 
         @Override
-        public void onPlayerStateChanged(final MediaPlayerInterface player, final int state) {
+        public void onPlayerStateChanged(final MediaPlayerBase mpb, final int state) {
             final MediaSession2ImplBase session = getSession();
             if (session == null) {
                 return;
@@ -1275,21 +1005,15 @@
             session.getCallbackExecutor().execute(new Runnable() {
                 @Override
                 public void run() {
-                    session.getCallback().onPlayerStateChanged(
-                            session.getInstance(), player, state);
-                    session.notifyToAllControllers(new NotifyRunnable() {
-                        @Override
-                        public void run(ControllerCb callback) throws RemoteException {
-                            callback.onPlayerStateChanged(state);
-                        }
-                    });
+                    session.getCallback().onPlayerStateChanged(session.getInstance(), mpb, state);
+                    session.getSession2Stub().notifyPlayerStateChanged(state);
                 }
             });
         }
 
         @Override
-        public void onBufferingStateChanged(final MediaPlayerInterface mpb,
-                final DataSourceDesc dsd, final int state) {
+        public void onBufferingStateChanged(final MediaPlayerBase mpb, final DataSourceDesc dsd,
+                final int state) {
             final MediaSession2ImplBase session = getSession();
             if (session == null || dsd == null) {
                 return;
@@ -1297,24 +1021,19 @@
             session.getCallbackExecutor().execute(new Runnable() {
                 @Override
                 public void run() {
-                    final MediaItem2 item = MyPlayerEventCallback.this.getMediaItem(session, dsd);
+                    MediaItem2 item = MyPlayerEventCallback.this.getMediaItem(session, dsd);
                     if (item == null) {
                         return;
                     }
                     session.getCallback().onBufferingStateChanged(
                             session.getInstance(), mpb, item, state);
-                    session.notifyToAllControllers(new NotifyRunnable() {
-                        @Override
-                        public void run(ControllerCb callback) throws RemoteException {
-                            callback.onBufferingStateChanged(item, state);
-                        }
-                    });
+                    session.getSession2Stub().notifyBufferingStateChanged(item, state);
                 }
             });
         }
 
         @Override
-        public void onPlaybackSpeedChanged(final MediaPlayerInterface mpb, final float speed) {
+        public void onPlaybackSpeedChanged(final MediaPlayerBase mpb, final float speed) {
             final MediaSession2ImplBase session = getSession();
             if (session == null) {
                 return;
@@ -1323,32 +1042,7 @@
                 @Override
                 public void run() {
                     session.getCallback().onPlaybackSpeedChanged(session.getInstance(), mpb, speed);
-                    session.notifyToAllControllers(new NotifyRunnable() {
-                        @Override
-                        public void run(ControllerCb callback) throws RemoteException {
-                            callback.onPlaybackSpeedChanged(speed);
-                        }
-                    });
-                }
-            });
-        }
-
-        @Override
-        public void onSeekCompleted(final MediaPlayerInterface mpb, final long position) {
-            final MediaSession2ImplBase session = getSession();
-            if (session == null) {
-                return;
-            }
-            session.getCallbackExecutor().execute(new Runnable() {
-                @Override
-                public void run() {
-                    session.getCallback().onSeekCompleted(session.getInstance(), mpb, position);
-                    session.notifyToAllControllers(new NotifyRunnable() {
-                        @Override
-                        public void run(ControllerCb callback) throws RemoteException {
-                            callback.onSeekCompleted(position);
-                        }
-                    });
+                    session.getSession2Stub().notifyPlaybackSpeedChanged(speed);
                 }
             });
         }
@@ -1429,7 +1123,7 @@
     abstract static class BuilderBase
             <T extends MediaSession2, C extends SessionCallback> {
         final Context mContext;
-        MediaPlayerInterface mPlayer;
+        MediaPlayerBase mPlayer;
         String mId;
         Executor mCallbackExecutor;
         C mCallback;
@@ -1446,7 +1140,7 @@
             mId = TAG;
         }
 
-        void setPlayer(@NonNull MediaPlayerInterface player) {
+        void setPlayer(@NonNull MediaPlayerBase player) {
             if (player == null) {
                 throw new IllegalArgumentException("player shouldn't be null");
             }
diff --git a/media/src/main/java/androidx/media/MediaSession2Stub.java b/media/src/main/java/androidx/media/MediaSession2StubImplBase.java
similarity index 68%
rename from media/src/main/java/androidx/media/MediaSession2Stub.java
rename to media/src/main/java/androidx/media/MediaSession2StubImplBase.java
index 87b17cf..48e641e 100644
--- a/media/src/main/java/androidx/media/MediaSession2Stub.java
+++ b/media/src/main/java/androidx/media/MediaSession2StubImplBase.java
@@ -25,7 +25,6 @@
 import static androidx.media.MediaConstants2.ARGUMENT_ERROR_CODE;
 import static androidx.media.MediaConstants2.ARGUMENT_EXTRAS;
 import static androidx.media.MediaConstants2.ARGUMENT_ICONTROLLER_CALLBACK;
-import static androidx.media.MediaConstants2.ARGUMENT_ITEM_COUNT;
 import static androidx.media.MediaConstants2.ARGUMENT_MEDIA_ID;
 import static androidx.media.MediaConstants2.ARGUMENT_MEDIA_ITEM;
 import static androidx.media.MediaConstants2.ARGUMENT_PACKAGE_NAME;
@@ -56,8 +55,7 @@
 import static androidx.media.MediaConstants2.CONTROLLER_COMMAND_CONNECT;
 import static androidx.media.MediaConstants2.CONTROLLER_COMMAND_DISCONNECT;
 import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ALLOWED_COMMANDS_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_BUFFERING_STATE_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_CHILDREN_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_BUFFERING_STATE_CHAGNED;
 import static androidx.media.MediaConstants2.SESSION_EVENT_ON_CURRENT_MEDIA_ITEM_CHANGED;
 import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ERROR;
 import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYBACK_INFO_CHANGED;
@@ -67,12 +65,9 @@
 import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED;
 import static androidx.media.MediaConstants2.SESSION_EVENT_ON_REPEAT_MODE_CHANGED;
 import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ROUTES_INFO_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SEARCH_RESULT_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SEEK_COMPLETED;
 import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED;
 import static androidx.media.MediaConstants2.SESSION_EVENT_SEND_CUSTOM_COMMAND;
 import static androidx.media.MediaConstants2.SESSION_EVENT_SET_CUSTOM_LAYOUT;
-import static androidx.media.SessionCommand2.COMMAND_CODE_CUSTOM;
 import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE;
 import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY;
 import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PREPARE;
@@ -111,22 +106,21 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.DeadObjectException;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.support.v4.media.session.IMediaControllerCallback;
 import android.support.v4.media.session.MediaSessionCompat;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.SparseArray;
 
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.collection.ArrayMap;
-import androidx.core.app.BundleCompat;
 import androidx.media.MediaController2.PlaybackInfo;
 import androidx.media.MediaSession2.CommandButton;
-import androidx.media.MediaSession2.ControllerCb;
 import androidx.media.MediaSession2.ControllerInfo;
 
 import java.util.ArrayList;
@@ -135,7 +129,7 @@
 import java.util.Set;
 
 @TargetApi(Build.VERSION_CODES.KITKAT)
-class MediaSession2Stub extends MediaSessionCompat.Callback {
+class MediaSession2StubImplBase extends MediaSessionCompat.Callback {
 
     private static final String TAG = "MS2StubImplBase";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -167,16 +161,78 @@
     private final ArrayMap<ControllerInfo, SessionCommandGroup2> mAllowedCommandGroupMap =
             new ArrayMap<>();
 
-    MediaSession2Stub(MediaSession2.SupportLibraryImpl session) {
+    MediaSession2StubImplBase(MediaSession2.SupportLibraryImpl session) {
         mSession = session;
         mContext = mSession.getContext();
     }
 
     @Override
+    public void onPrepare() {
+        mSession.getCallbackExecutor().execute(new Runnable() {
+            @Override
+            public void run() {
+                if (mSession.isClosed()) {
+                    return;
+                }
+                mSession.prepare();
+            }
+        });
+    }
+
+    @Override
+    public void onPlay() {
+        mSession.getCallbackExecutor().execute(new Runnable() {
+            @Override
+            public void run() {
+                if (mSession.isClosed()) {
+                    return;
+                }
+                mSession.play();
+            }
+        });
+    }
+
+    @Override
+    public void onPause() {
+        mSession.getCallbackExecutor().execute(new Runnable() {
+            @Override
+            public void run() {
+                if (mSession.isClosed()) {
+                    return;
+                }
+                mSession.pause();
+            }
+        });
+    }
+
+    @Override
+    public void onStop() {
+        mSession.getCallbackExecutor().execute(new Runnable() {
+            @Override
+            public void run() {
+                if (mSession.isClosed()) {
+                    return;
+                }
+                mSession.reset();
+            }
+        });
+    }
+
+    @Override
+    public void onSeekTo(final long pos) {
+        mSession.getCallbackExecutor().execute(new Runnable() {
+            @Override
+            public void run() {
+                if (mSession.isClosed()) {
+                    return;
+                }
+                mSession.seekTo(pos);
+            }
+        });
+    }
+
+    @Override
     public void onCommand(String command, final Bundle extras, final ResultReceiver cb) {
-        if (extras != null) {
-            extras.setClassLoader(MediaSession2.class.getClassLoader());
-        }
         switch (command) {
             case CONTROLLER_COMMAND_CONNECT:
                 connect(extras, cb);
@@ -186,8 +242,8 @@
                 break;
             case CONTROLLER_COMMAND_BY_COMMAND_CODE: {
                 final int commandCode = extras.getInt(ARGUMENT_COMMAND_CODE);
-                IMediaControllerCallback caller = IMediaControllerCallback.Stub.asInterface(
-                        BundleCompat.getBinder(extras, ARGUMENT_ICONTROLLER_CALLBACK));
+                IMediaControllerCallback caller =
+                        (IMediaControllerCallback) extras.getBinder(ARGUMENT_ICONTROLLER_CALLBACK);
                 if (caller == null) {
                     return;
                 }
@@ -276,10 +332,7 @@
                                 int flags = extras.getInt(ARGUMENT_VOLUME_FLAGS);
                                 VolumeProviderCompat vp = mSession.getVolumeProvider();
                                 if (vp == null) {
-                                    MediaSessionCompat sessionCompat = mSession.getSessionCompat();
-                                    if (sessionCompat != null) {
-                                        sessionCompat.getController().setVolumeTo(value, flags);
-                                    }
+                                    // TODO: Revisit
                                 } else {
                                     vp.onSetVolumeTo(value);
                                 }
@@ -290,11 +343,7 @@
                                 int flags = extras.getInt(ARGUMENT_VOLUME_FLAGS);
                                 VolumeProviderCompat vp = mSession.getVolumeProvider();
                                 if (vp == null) {
-                                    MediaSessionCompat sessionCompat = mSession.getSessionCompat();
-                                    if (sessionCompat != null) {
-                                        sessionCompat.getController().adjustVolume(
-                                                direction, flags);
-                                    }
+                                    // TODO: Revisit
                                 } else {
                                     vp.onAdjustVolume(direction);
                                 }
@@ -389,8 +438,8 @@
             case CONTROLLER_COMMAND_BY_CUSTOM_COMMAND: {
                 final SessionCommand2 customCommand =
                         SessionCommand2.fromBundle(extras.getBundle(ARGUMENT_CUSTOM_COMMAND));
-                IMediaControllerCallback caller = IMediaControllerCallback.Stub.asInterface(
-                        BundleCompat.getBinder(extras, ARGUMENT_ICONTROLLER_CALLBACK));
+                IMediaControllerCallback caller =
+                        (IMediaControllerCallback) extras.getBinder(ARGUMENT_ICONTROLLER_CALLBACK);
                 if (caller == null || customCommand == null) {
                     return;
                 }
@@ -418,10 +467,261 @@
         return controllers;
     }
 
+    void notifyCustomLayout(ControllerInfo controller, final List<CommandButton> layout) {
+        notifyInternal(controller, new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putParcelableArray(ARGUMENT_COMMAND_BUTTONS,
+                        MediaUtils2.toCommandButtonParcelableArray(layout));
+                controller.getControllerBinder().onEvent(SESSION_EVENT_SET_CUSTOM_LAYOUT, bundle);
+            }
+        });
+    }
+
     void setAllowedCommands(ControllerInfo controller, final SessionCommandGroup2 commands) {
         synchronized (mLock) {
             mAllowedCommandGroupMap.put(controller, commands);
         }
+        notifyInternal(controller, new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putBundle(ARGUMENT_ALLOWED_COMMANDS, commands.toBundle());
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_ALLOWED_COMMANDS_CHANGED, bundle);
+            }
+        });
+    }
+
+    public void sendCustomCommand(ControllerInfo controller, final SessionCommand2 command,
+            final Bundle args, final ResultReceiver receiver) {
+        if (receiver != null && controller == null) {
+            throw new IllegalArgumentException("Controller shouldn't be null if result receiver is"
+                    + " specified");
+        }
+        if (command == null) {
+            throw new IllegalArgumentException("command shouldn't be null");
+        }
+        notifyInternal(controller, new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                // TODO: Send this event through MediaSessionCompat.XXX()
+                Bundle bundle = new Bundle();
+                bundle.putBundle(ARGUMENT_CUSTOM_COMMAND, command.toBundle());
+                bundle.putBundle(ARGUMENT_ARGUMENTS, args);
+                bundle.putParcelable(ARGUMENT_RESULT_RECEIVER, receiver);
+                controller.getControllerBinder().onEvent(SESSION_EVENT_SEND_CUSTOM_COMMAND, bundle);
+            }
+        });
+    }
+
+    public void sendCustomCommand(final SessionCommand2 command, final Bundle args) {
+        if (command == null) {
+            throw new IllegalArgumentException("command shouldn't be null");
+        }
+        final Bundle bundle = new Bundle();
+        bundle.putBundle(ARGUMENT_CUSTOM_COMMAND, command.toBundle());
+        bundle.putBundle(ARGUMENT_ARGUMENTS, args);
+        notifyAll(new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                controller.getControllerBinder().onEvent(SESSION_EVENT_SEND_CUSTOM_COMMAND, bundle);
+            }
+        });
+    }
+
+    void notifyCurrentMediaItemChanged(final MediaItem2 item) {
+        notifyAll(COMMAND_CODE_PLAYLIST_GET_CURRENT_MEDIA_ITEM, new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_CURRENT_MEDIA_ITEM_CHANGED, bundle);
+            }
+        });
+    }
+
+    void notifyPlaybackInfoChanged(final PlaybackInfo info) {
+        notifyAll(new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putBundle(ARGUMENT_PLAYBACK_INFO, info.toBundle());
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_PLAYBACK_INFO_CHANGED, bundle);
+            }
+        });
+    }
+
+    void notifyPlayerStateChanged(final int state) {
+        notifyAll(new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putInt(ARGUMENT_PLAYER_STATE, state);
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_PLAYER_STATE_CHANGED, bundle);
+            }
+        });
+    }
+
+    void notifyPlaybackSpeedChanged(final float speed) {
+        notifyAll(new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putParcelable(
+                        ARGUMENT_PLAYBACK_STATE_COMPAT, mSession.getPlaybackStateCompat());
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_PLAYBACK_SPEED_CHANGED, bundle);
+            }
+        });
+    }
+
+    void notifyBufferingStateChanged(final MediaItem2 item, final int bufferingState) {
+        notifyAll(new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
+                bundle.putInt(ARGUMENT_BUFFERING_STATE, bufferingState);
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_BUFFERING_STATE_CHAGNED, bundle);
+            }
+        });
+    }
+
+    void notifyError(final int errorCode, final Bundle extras) {
+        notifyAll(new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putInt(ARGUMENT_ERROR_CODE, errorCode);
+                bundle.putBundle(ARGUMENT_EXTRAS, extras);
+                controller.getControllerBinder().onEvent(SESSION_EVENT_ON_ERROR, bundle);
+            }
+        });
+    }
+
+    void notifyRoutesInfoChanged(@NonNull final ControllerInfo controller,
+            @Nullable final List<Bundle> routes) {
+        notifyInternal(controller, new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = null;
+                if (routes != null) {
+                    bundle = new Bundle();
+                    bundle.putParcelableArray(ARGUMENT_ROUTE_BUNDLE, routes.toArray(new Bundle[0]));
+                }
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_ROUTES_INFO_CHANGED, bundle);
+            }
+        });
+    }
+
+    void notifyPlaylistChanged(final List<MediaItem2> playlist,
+            final MediaMetadata2 metadata) {
+        notifyAll(COMMAND_CODE_PLAYLIST_GET_LIST, new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putParcelableArray(ARGUMENT_PLAYLIST,
+                        MediaUtils2.toMediaItem2ParcelableArray(playlist));
+                bundle.putBundle(ARGUMENT_PLAYLIST_METADATA,
+                        metadata == null ? null : metadata.toBundle());
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_PLAYLIST_CHANGED, bundle);
+            }
+        });
+    }
+
+    void notifyPlaylistMetadataChanged(final MediaMetadata2 metadata) {
+        notifyAll(SessionCommand2.COMMAND_CODE_PLAYLIST_GET_LIST_METADATA, new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putBundle(ARGUMENT_PLAYLIST_METADATA,
+                        metadata == null ? null : metadata.toBundle());
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED, bundle);
+            }
+        });
+    }
+
+    void notifyRepeatModeChanged(final int repeatMode) {
+        notifyAll(new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putInt(ARGUMENT_REPEAT_MODE, repeatMode);
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_REPEAT_MODE_CHANGED, bundle);
+            }
+        });
+    }
+
+    void notifyShuffleModeChanged(final int shuffleMode) {
+        notifyAll(new Session2Runnable() {
+            @Override
+            public void run(ControllerInfo controller) throws RemoteException {
+                Bundle bundle = new Bundle();
+                bundle.putInt(ARGUMENT_SHUFFLE_MODE, shuffleMode);
+                controller.getControllerBinder().onEvent(
+                        SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED, bundle);
+            }
+        });
+    }
+
+    private List<ControllerInfo> getControllers() {
+        ArrayList<ControllerInfo> controllers = new ArrayList<>();
+        synchronized (mLock) {
+            for (int i = 0; i < mControllers.size(); i++) {
+                controllers.add(mControllers.valueAt(i));
+            }
+        }
+        return controllers;
+    }
+
+    private void notifyAll(@NonNull Session2Runnable runnable) {
+        List<ControllerInfo> controllers = getControllers();
+        for (int i = 0; i < controllers.size(); i++) {
+            notifyInternal(controllers.get(i), runnable);
+        }
+    }
+
+    private void notifyAll(int commandCode, @NonNull Session2Runnable runnable) {
+        List<ControllerInfo> controllers = getControllers();
+        for (int i = 0; i < controllers.size(); i++) {
+            ControllerInfo controller = controllers.get(i);
+            if (isAllowedCommand(controller, commandCode)) {
+                notifyInternal(controller, runnable);
+            }
+        }
+    }
+
+    // TODO: Add a way to check permission from here.
+    private void notifyInternal(@NonNull ControllerInfo controller,
+            @NonNull Session2Runnable runnable) {
+        if (controller == null || controller.getControllerBinder() == null) {
+            return;
+        }
+        try {
+            runnable.run(controller);
+        } catch (DeadObjectException e) {
+            if (DEBUG) {
+                Log.d(TAG, controller.toString() + " is gone", e);
+            }
+            onControllerClosed(controller.getControllerBinder());
+        } catch (RemoteException e) {
+            // Currently it's TransactionTooLargeException or DeadSystemException.
+            // We'd better to leave log for those cases because
+            //   - TransactionTooLargeException means that we may need to fix our code.
+            //     (e.g. add pagination or special way to deliver Bitmap)
+            //   - DeadSystemException means that errors around it can be ignored.
+            Log.w(TAG, "Exception in " + controller.toString(), e);
+        }
     }
 
     private boolean isAllowedCommand(ControllerInfo controller, SessionCommand2 command) {
@@ -442,17 +742,12 @@
 
     private void onCommand2(@NonNull IBinder caller, final int commandCode,
             @NonNull final Session2Runnable runnable) {
-        onCommand2Internal(caller, null, commandCode, runnable);
+        // TODO: Prevent instantiation of SessionCommand2
+        onCommand2(caller, new SessionCommand2(commandCode), runnable);
     }
 
     private void onCommand2(@NonNull IBinder caller, @NonNull final SessionCommand2 sessionCommand,
             @NonNull final Session2Runnable runnable) {
-        onCommand2Internal(caller, sessionCommand, COMMAND_CODE_CUSTOM, runnable);
-    }
-
-    private void onCommand2Internal(@NonNull IBinder caller,
-            @Nullable final SessionCommand2 sessionCommand, final int commandCode,
-            @NonNull final Session2Runnable runnable) {
         final ControllerInfo controller;
         synchronized (mLock) {
             controller = mControllers.get(caller);
@@ -463,25 +758,18 @@
         mSession.getCallbackExecutor().execute(new Runnable() {
             @Override
             public void run() {
-                SessionCommand2 command;
-                if (sessionCommand != null) {
-                    if (!isAllowedCommand(controller, sessionCommand)) {
-                        return;
-                    }
-                    command = sCommandsForOnCommandRequest.get(sessionCommand.getCommandCode());
-                } else {
-                    if (!isAllowedCommand(controller, commandCode)) {
-                        return;
-                    }
-                    command = sCommandsForOnCommandRequest.get(commandCode);
+                if (!isAllowedCommand(controller, sessionCommand)) {
+                    return;
                 }
+                int commandCode = sessionCommand.getCommandCode();
+                SessionCommand2 command = sCommandsForOnCommandRequest.get(commandCode);
                 if (command != null) {
                     boolean accepted = mSession.getCallback().onCommandRequest(
                             mSession.getInstance(), controller, command);
                     if (!accepted) {
                         // Don't run rejected command.
                         if (DEBUG) {
-                            Log.d(TAG, "Command (" + command + ") from "
+                            Log.d(TAG, "Command (code=" + commandCode + ") from "
                                     + controller + " was rejected by " + mSession);
                         }
                         return;
@@ -501,22 +789,35 @@
         });
     }
 
-    void removeControllerInfo(ControllerInfo controller) {
+    private void onControllerClosed(IMediaControllerCallback iController) {
+        ControllerInfo controller;
         synchronized (mLock) {
-            controller = mControllers.remove(controller.getId());
+            controller = mControllers.remove(iController.asBinder());
             if (DEBUG) {
                 Log.d(TAG, "releasing " + controller);
             }
         }
+        if (controller == null) {
+            return;
+        }
+        final ControllerInfo removedController = controller;
+        mSession.getCallbackExecutor().execute(new Runnable() {
+            @Override
+            public void run() {
+                mSession.getCallback().onDisconnected(mSession.getInstance(), removedController);
+            }
+        });
     }
 
     private ControllerInfo createControllerInfo(Bundle extras) {
         IMediaControllerCallback callback = IMediaControllerCallback.Stub.asInterface(
-                BundleCompat.getBinder(extras, ARGUMENT_ICONTROLLER_CALLBACK));
+                extras.getBinder(ARGUMENT_ICONTROLLER_CALLBACK));
         String packageName = extras.getString(ARGUMENT_PACKAGE_NAME);
         int uid = extras.getInt(ARGUMENT_UID);
         int pid = extras.getInt(ARGUMENT_PID);
-        return new ControllerInfo(packageName, pid, uid, new Controller2Cb(callback));
+        // TODO: sanity check for packageName, uid, and pid.
+
+        return new ControllerInfo(mContext, uid, pid, packageName, callback);
     }
 
     private void connect(Bundle extras, final ResultReceiver cb) {
@@ -625,173 +926,4 @@
     private interface Session2Runnable {
         void run(ControllerInfo controller) throws RemoteException;
     }
-
-    final class Controller2Cb extends ControllerCb {
-        private final IMediaControllerCallback mIControllerCallback;
-
-        Controller2Cb(@NonNull IMediaControllerCallback callback) {
-            mIControllerCallback = callback;
-        }
-
-        @Override
-        @NonNull IBinder getId() {
-            return mIControllerCallback.asBinder();
-        }
-
-        @Override
-        void onCustomLayoutChanged(List<CommandButton> layout) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putParcelableArray(ARGUMENT_COMMAND_BUTTONS,
-                    MediaUtils2.toCommandButtonParcelableArray(layout));
-            mIControllerCallback.onEvent(SESSION_EVENT_SET_CUSTOM_LAYOUT, bundle);
-        }
-
-        @Override
-        void onPlaybackInfoChanged(PlaybackInfo info) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_PLAYBACK_INFO, info.toBundle());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_PLAYBACK_INFO_CHANGED, bundle);
-
-        }
-
-        @Override
-        void onAllowedCommandsChanged(SessionCommandGroup2 commands) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_ALLOWED_COMMANDS, commands.toBundle());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_ALLOWED_COMMANDS_CHANGED, bundle);
-        }
-
-        @Override
-        void onCustomCommand(SessionCommand2 command, Bundle args, ResultReceiver receiver)
-                throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_CUSTOM_COMMAND, command.toBundle());
-            bundle.putBundle(ARGUMENT_ARGUMENTS, args);
-            bundle.putParcelable(ARGUMENT_RESULT_RECEIVER, receiver);
-            mIControllerCallback.onEvent(SESSION_EVENT_SEND_CUSTOM_COMMAND, bundle);
-        }
-
-        @Override
-        void onPlayerStateChanged(int playerState)
-                throws RemoteException {
-            // Note: current position should be also sent to the controller here for controller
-            // to calculate the position more correctly.
-            Bundle bundle = new Bundle();
-            bundle.putInt(ARGUMENT_PLAYER_STATE, playerState);
-            bundle.putParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT, mSession.getPlaybackStateCompat());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_PLAYER_STATE_CHANGED, bundle);
-        }
-
-        @Override
-        void onPlaybackSpeedChanged(float speed) throws RemoteException {
-            // Note: current position should be also sent to the controller here for controller
-            // to calculate the position more correctly.
-            Bundle bundle = new Bundle();
-            bundle.putParcelable(
-                    ARGUMENT_PLAYBACK_STATE_COMPAT, mSession.getPlaybackStateCompat());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_PLAYBACK_SPEED_CHANGED, bundle);
-        }
-
-        @Override
-        void onBufferingStateChanged(MediaItem2 item, int state) throws RemoteException {
-            // Note: buffered position should be also sent to the controller here. It's to
-            // follow the behavior of MediaPlayerInterface.PlayerEventCallback.
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
-            bundle.putInt(ARGUMENT_BUFFERING_STATE, state);
-            bundle.putParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT,
-                    mSession.getPlaybackStateCompat());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_BUFFERING_STATE_CHANGED, bundle);
-
-        }
-
-        @Override
-        void onSeekCompleted(long position) throws RemoteException {
-            // Note: current position should be also sent to the controller here because the
-            // position here may refer to the parameter of the previous seek() API calls.
-            Bundle bundle = new Bundle();
-            bundle.putLong(ARGUMENT_SEEK_POSITION, position);
-            bundle.putParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT,
-                    mSession.getPlaybackStateCompat());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_SEEK_COMPLETED, bundle);
-        }
-
-        @Override
-        void onError(int errorCode, Bundle extras) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putInt(ARGUMENT_ERROR_CODE, errorCode);
-            bundle.putBundle(ARGUMENT_EXTRAS, extras);
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_ERROR, bundle);
-        }
-
-        @Override
-        void onCurrentMediaItemChanged(MediaItem2 item) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_MEDIA_ITEM, (item == null) ? null : item.toBundle());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_CURRENT_MEDIA_ITEM_CHANGED, bundle);
-        }
-
-        @Override
-        void onPlaylistChanged(List<MediaItem2> playlist, MediaMetadata2 metadata)
-                throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putParcelableArray(ARGUMENT_PLAYLIST,
-                    MediaUtils2.toMediaItem2ParcelableArray(playlist));
-            bundle.putBundle(ARGUMENT_PLAYLIST_METADATA,
-                    metadata == null ? null : metadata.toBundle());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_PLAYLIST_CHANGED, bundle);
-        }
-
-        @Override
-        void onPlaylistMetadataChanged(MediaMetadata2 metadata) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_PLAYLIST_METADATA,
-                    metadata == null ? null : metadata.toBundle());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED, bundle);
-        }
-
-        @Override
-        void onShuffleModeChanged(int shuffleMode) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putInt(ARGUMENT_SHUFFLE_MODE, shuffleMode);
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED, bundle);
-        }
-
-        @Override
-        void onRepeatModeChanged(int repeatMode) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putInt(ARGUMENT_REPEAT_MODE, repeatMode);
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_REPEAT_MODE_CHANGED, bundle);
-        }
-
-        @Override
-        void onRoutesInfoChanged(List<Bundle> routes) throws RemoteException {
-            Bundle bundle = null;
-            if (routes != null) {
-                bundle = new Bundle();
-                bundle.putParcelableArray(ARGUMENT_ROUTE_BUNDLE, routes.toArray(new Bundle[0]));
-            }
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_ROUTES_INFO_CHANGED, bundle);
-        }
-
-        @Override
-        void onChildrenChanged(String parentId, int itemCount, Bundle extras)
-                throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putString(ARGUMENT_MEDIA_ID, parentId);
-            bundle.putInt(ARGUMENT_ITEM_COUNT, itemCount);
-            bundle.putBundle(ARGUMENT_EXTRAS, extras);
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_CHILDREN_CHANGED, bundle);
-        }
-
-        @Override
-        void onSearchResultChanged(String query, int itemCount, Bundle extras)
-                throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putString(ARGUMENT_QUERY, query);
-            bundle.putInt(ARGUMENT_ITEM_COUNT, itemCount);
-            bundle.putBundle(ARGUMENT_EXTRAS, extras);
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_SEARCH_RESULT_CHANGED, bundle);
-        }
-    }
 }
diff --git a/media/src/main/java/androidx/media/MediaSessionLegacyStub.java b/media/src/main/java/androidx/media/MediaSessionLegacyStub.java
deleted file mode 100644
index 2e0f945..0000000
--- a/media/src/main/java/androidx/media/MediaSessionLegacyStub.java
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media;
-
-import static androidx.media.MediaConstants2.ARGUMENT_ALLOWED_COMMANDS;
-import static androidx.media.MediaConstants2.ARGUMENT_ARGUMENTS;
-import static androidx.media.MediaConstants2.ARGUMENT_BUFFERING_STATE;
-import static androidx.media.MediaConstants2.ARGUMENT_COMMAND_BUTTONS;
-import static androidx.media.MediaConstants2.ARGUMENT_CUSTOM_COMMAND;
-import static androidx.media.MediaConstants2.ARGUMENT_ERROR_CODE;
-import static androidx.media.MediaConstants2.ARGUMENT_EXTRAS;
-import static androidx.media.MediaConstants2.ARGUMENT_ICONTROLLER_CALLBACK;
-import static androidx.media.MediaConstants2.ARGUMENT_ITEM_COUNT;
-import static androidx.media.MediaConstants2.ARGUMENT_MEDIA_ID;
-import static androidx.media.MediaConstants2.ARGUMENT_MEDIA_ITEM;
-import static androidx.media.MediaConstants2.ARGUMENT_PACKAGE_NAME;
-import static androidx.media.MediaConstants2.ARGUMENT_PID;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYBACK_INFO;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYBACK_STATE_COMPAT;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYER_STATE;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYLIST;
-import static androidx.media.MediaConstants2.ARGUMENT_PLAYLIST_METADATA;
-import static androidx.media.MediaConstants2.ARGUMENT_QUERY;
-import static androidx.media.MediaConstants2.ARGUMENT_REPEAT_MODE;
-import static androidx.media.MediaConstants2.ARGUMENT_RESULT_RECEIVER;
-import static androidx.media.MediaConstants2.ARGUMENT_ROUTE_BUNDLE;
-import static androidx.media.MediaConstants2.ARGUMENT_SEEK_POSITION;
-import static androidx.media.MediaConstants2.ARGUMENT_SHUFFLE_MODE;
-import static androidx.media.MediaConstants2.ARGUMENT_UID;
-import static androidx.media.MediaConstants2.CONNECT_RESULT_CONNECTED;
-import static androidx.media.MediaConstants2.CONNECT_RESULT_DISCONNECTED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ALLOWED_COMMANDS_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_BUFFERING_STATE_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_CHILDREN_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_CURRENT_MEDIA_ITEM_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ERROR;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYBACK_INFO_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYBACK_SPEED_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYER_STATE_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_REPEAT_MODE_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ROUTES_INFO_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SEARCH_RESULT_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SEEK_COMPLETED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED;
-import static androidx.media.MediaConstants2.SESSION_EVENT_SEND_CUSTOM_COMMAND;
-import static androidx.media.MediaConstants2.SESSION_EVENT_SET_CUSTOM_LAYOUT;
-import static androidx.media.SessionCommand2.COMMAND_CODE_CUSTOM;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_GET_CURRENT_MEDIA_ITEM;
-import static androidx.media.SessionCommand2.COMMAND_CODE_PLAYLIST_GET_LIST;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.support.v4.media.session.IMediaControllerCallback;
-import android.support.v4.media.session.MediaSessionCompat;
-import android.util.Log;
-import android.util.SparseArray;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.collection.ArrayMap;
-import androidx.core.app.BundleCompat;
-import androidx.media.MediaController2.PlaybackInfo;
-import androidx.media.MediaSession2.CommandButton;
-import androidx.media.MediaSession2.ControllerCb;
-import androidx.media.MediaSession2.ControllerInfo;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-@TargetApi(Build.VERSION_CODES.KITKAT)
-class MediaSessionLegacyStub extends MediaSessionCompat.Callback {
-
-    private static final String TAG = "MS2StubImplBase";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private static final SparseArray<SessionCommand2> sCommandsForOnCommandRequest =
-            new SparseArray<>();
-
-    static {
-        SessionCommandGroup2 group = new SessionCommandGroup2();
-        group.addAllPlaybackCommands();
-        group.addAllPlaylistCommands();
-        group.addAllVolumeCommands();
-        Set<SessionCommand2> commands = group.getCommands();
-        for (SessionCommand2 command : commands) {
-            sCommandsForOnCommandRequest.append(command.getCommandCode(), command);
-        }
-    }
-
-    private final Object mLock = new Object();
-
-    final MediaSession2.SupportLibraryImpl mSession;
-    final Context mContext;
-
-    @GuardedBy("mLock")
-    private final ArrayMap<IBinder, ControllerInfo> mControllers = new ArrayMap<>();
-    @GuardedBy("mLock")
-    private final Set<IBinder> mConnectingControllers = new HashSet<>();
-    @GuardedBy("mLock")
-    private final ArrayMap<ControllerInfo, SessionCommandGroup2> mAllowedCommandGroupMap =
-            new ArrayMap<>();
-
-    MediaSessionLegacyStub(MediaSession2.SupportLibraryImpl session) {
-        mSession = session;
-        mContext = mSession.getContext();
-    }
-
-    @Override
-    public void onPrepare() {
-        mSession.getCallbackExecutor().execute(new Runnable() {
-            @Override
-            public void run() {
-                if (mSession.isClosed()) {
-                    return;
-                }
-                mSession.prepare();
-            }
-        });
-    }
-
-    @Override
-    public void onPlay() {
-        mSession.getCallbackExecutor().execute(new Runnable() {
-            @Override
-            public void run() {
-                if (mSession.isClosed()) {
-                    return;
-                }
-                mSession.play();
-            }
-        });
-    }
-
-    @Override
-    public void onPause() {
-        mSession.getCallbackExecutor().execute(new Runnable() {
-            @Override
-            public void run() {
-                if (mSession.isClosed()) {
-                    return;
-                }
-                mSession.pause();
-            }
-        });
-    }
-
-    @Override
-    public void onStop() {
-        mSession.getCallbackExecutor().execute(new Runnable() {
-            @Override
-            public void run() {
-                if (mSession.isClosed()) {
-                    return;
-                }
-                mSession.reset();
-            }
-        });
-    }
-
-    @Override
-    public void onSeekTo(final long pos) {
-        mSession.getCallbackExecutor().execute(new Runnable() {
-            @Override
-            public void run() {
-                if (mSession.isClosed()) {
-                    return;
-                }
-                mSession.seekTo(pos);
-            }
-        });
-    }
-
-    List<ControllerInfo> getConnectedControllers() {
-        ArrayList<ControllerInfo> controllers = new ArrayList<>();
-        synchronized (mLock) {
-            for (int i = 0; i < mControllers.size(); i++) {
-                controllers.add(mControllers.valueAt(i));
-            }
-        }
-        return controllers;
-    }
-
-    void setAllowedCommands(ControllerInfo controller, final SessionCommandGroup2 commands) {
-        synchronized (mLock) {
-            mAllowedCommandGroupMap.put(controller, commands);
-        }
-    }
-
-    private boolean isAllowedCommand(ControllerInfo controller, SessionCommand2 command) {
-        SessionCommandGroup2 allowedCommands;
-        synchronized (mLock) {
-            allowedCommands = mAllowedCommandGroupMap.get(controller);
-        }
-        return allowedCommands != null && allowedCommands.hasCommand(command);
-    }
-
-    private boolean isAllowedCommand(ControllerInfo controller, int commandCode) {
-        SessionCommandGroup2 allowedCommands;
-        synchronized (mLock) {
-            allowedCommands = mAllowedCommandGroupMap.get(controller);
-        }
-        return allowedCommands != null && allowedCommands.hasCommand(commandCode);
-    }
-
-    private void onCommand2(@NonNull IBinder caller, final int commandCode,
-            @NonNull final Session2Runnable runnable) {
-        onCommand2Internal(caller, null, commandCode, runnable);
-    }
-
-    private void onCommand2(@NonNull IBinder caller, @NonNull final SessionCommand2 sessionCommand,
-            @NonNull final Session2Runnable runnable) {
-        onCommand2Internal(caller, sessionCommand, COMMAND_CODE_CUSTOM, runnable);
-    }
-
-    private void onCommand2Internal(@NonNull IBinder caller,
-            @Nullable final SessionCommand2 sessionCommand, final int commandCode,
-            @NonNull final Session2Runnable runnable) {
-        final ControllerInfo controller;
-        synchronized (mLock) {
-            controller = mControllers.get(caller);
-        }
-        if (mSession == null || controller == null) {
-            return;
-        }
-        mSession.getCallbackExecutor().execute(new Runnable() {
-            @Override
-            public void run() {
-                SessionCommand2 command;
-                if (sessionCommand != null) {
-                    if (!isAllowedCommand(controller, sessionCommand)) {
-                        return;
-                    }
-                    command = sCommandsForOnCommandRequest.get(sessionCommand.getCommandCode());
-                } else {
-                    if (!isAllowedCommand(controller, commandCode)) {
-                        return;
-                    }
-                    command = sCommandsForOnCommandRequest.get(commandCode);
-                }
-                if (command != null) {
-                    boolean accepted = mSession.getCallback().onCommandRequest(
-                            mSession.getInstance(), controller, command);
-                    if (!accepted) {
-                        // Don't run rejected command.
-                        if (DEBUG) {
-                            Log.d(TAG, "Command (" + command + ") from "
-                                    + controller + " was rejected by " + mSession);
-                        }
-                        return;
-                    }
-                }
-                try {
-                    runnable.run(controller);
-                } catch (RemoteException e) {
-                    // Currently it's TransactionTooLargeException or DeadSystemException.
-                    // We'd better to leave log for those cases because
-                    //   - TransactionTooLargeException means that we may need to fix our code.
-                    //     (e.g. add pagination or special way to deliver Bitmap)
-                    //   - DeadSystemException means that errors around it can be ignored.
-                    Log.w(TAG, "Exception in " + controller.toString(), e);
-                }
-            }
-        });
-    }
-
-    void removeControllerInfo(ControllerInfo controller) {
-        synchronized (mLock) {
-            controller = mControllers.remove(controller.getId());
-            if (DEBUG) {
-                Log.d(TAG, "releasing " + controller);
-            }
-        }
-    }
-
-    private ControllerInfo createControllerInfo(Bundle extras) {
-        IMediaControllerCallback callback = IMediaControllerCallback.Stub.asInterface(
-                BundleCompat.getBinder(extras, ARGUMENT_ICONTROLLER_CALLBACK));
-        String packageName = extras.getString(ARGUMENT_PACKAGE_NAME);
-        int uid = extras.getInt(ARGUMENT_UID);
-        int pid = extras.getInt(ARGUMENT_PID);
-        return new ControllerInfo(packageName, pid, uid, new ControllerLegacyCb(callback));
-    }
-
-    private void connect(Bundle extras, final ResultReceiver cb) {
-        final ControllerInfo controllerInfo = createControllerInfo(extras);
-        mSession.getCallbackExecutor().execute(new Runnable() {
-            @Override
-            public void run() {
-                if (mSession.isClosed()) {
-                    return;
-                }
-                synchronized (mLock) {
-                    // Keep connecting controllers.
-                    // This helps sessions to call APIs in the onConnect()
-                    // (e.g. setCustomLayout()) instead of pending them.
-                    mConnectingControllers.add(controllerInfo.getId());
-                }
-                SessionCommandGroup2 allowedCommands = mSession.getCallback().onConnect(
-                        mSession.getInstance(), controllerInfo);
-                // Don't reject connection for the request from trusted app.
-                // Otherwise server will fail to retrieve session's information to dispatch
-                // media keys to.
-                boolean accept = allowedCommands != null || controllerInfo.isTrusted();
-                if (accept) {
-                    if (DEBUG) {
-                        Log.d(TAG, "Accepting connection, controllerInfo=" + controllerInfo
-                                + " allowedCommands=" + allowedCommands);
-                    }
-                    if (allowedCommands == null) {
-                        // For trusted apps, send non-null allowed commands to keep
-                        // connection.
-                        allowedCommands = new SessionCommandGroup2();
-                    }
-                    synchronized (mLock) {
-                        mConnectingControllers.remove(controllerInfo.getId());
-                        mControllers.put(controllerInfo.getId(), controllerInfo);
-                        mAllowedCommandGroupMap.put(controllerInfo, allowedCommands);
-                    }
-                    // If connection is accepted, notify the current state to the
-                    // controller. It's needed because we cannot call synchronous calls
-                    // between session/controller.
-                    // Note: We're doing this after the onConnectionChanged(), but there's
-                    //       no guarantee that events here are notified after the
-                    //       onConnected() because IMediaController2 is oneway (i.e. async
-                    //       call) and Stub will use thread poll for incoming calls.
-                    final Bundle resultData = new Bundle();
-                    resultData.putBundle(ARGUMENT_ALLOWED_COMMANDS,
-                            allowedCommands.toBundle());
-                    resultData.putInt(ARGUMENT_PLAYER_STATE, mSession.getPlayerState());
-                    resultData.putInt(ARGUMENT_BUFFERING_STATE, mSession.getBufferingState());
-                    resultData.putParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT,
-                            mSession.getPlaybackStateCompat());
-                    resultData.putInt(ARGUMENT_REPEAT_MODE, mSession.getRepeatMode());
-                    resultData.putInt(ARGUMENT_SHUFFLE_MODE, mSession.getShuffleMode());
-                    final List<MediaItem2> playlist = allowedCommands.hasCommand(
-                            COMMAND_CODE_PLAYLIST_GET_LIST) ? mSession.getPlaylist() : null;
-                    if (playlist != null) {
-                        resultData.putParcelableArray(ARGUMENT_PLAYLIST,
-                                MediaUtils2.toMediaItem2ParcelableArray(playlist));
-                    }
-                    final MediaItem2 currentMediaItem =
-                            allowedCommands.hasCommand(COMMAND_CODE_PLAYLIST_GET_CURRENT_MEDIA_ITEM)
-                                    ? mSession.getCurrentMediaItem() : null;
-                    if (currentMediaItem != null) {
-                        resultData.putBundle(ARGUMENT_MEDIA_ITEM, currentMediaItem.toBundle());
-                    }
-                    resultData.putBundle(ARGUMENT_PLAYBACK_INFO,
-                            mSession.getPlaybackInfo().toBundle());
-                    final MediaMetadata2 playlistMetadata = mSession.getPlaylistMetadata();
-                    if (playlistMetadata != null) {
-                        resultData.putBundle(ARGUMENT_PLAYLIST_METADATA,
-                                playlistMetadata.toBundle());
-                    }
-                    // Double check if session is still there, because close() can be
-                    // called in another thread.
-                    if (mSession.isClosed()) {
-                        return;
-                    }
-                    cb.send(CONNECT_RESULT_CONNECTED, resultData);
-                } else {
-                    synchronized (mLock) {
-                        mConnectingControllers.remove(controllerInfo.getId());
-                    }
-                    if (DEBUG) {
-                        Log.d(TAG, "Rejecting connection, controllerInfo=" + controllerInfo);
-                    }
-                    cb.send(CONNECT_RESULT_DISCONNECTED, null);
-                }
-            }
-        });
-    }
-
-    private void disconnect(Bundle extras) {
-        final ControllerInfo controllerInfo = createControllerInfo(extras);
-        mSession.getCallbackExecutor().execute(new Runnable() {
-            @Override
-            public void run() {
-                if (mSession.isClosed()) {
-                    return;
-                }
-                mSession.getCallback().onDisconnected(mSession.getInstance(), controllerInfo);
-            }
-        });
-    }
-
-    @FunctionalInterface
-    private interface Session2Runnable {
-        void run(ControllerInfo controller) throws RemoteException;
-    }
-
-    final class ControllerLegacyCb extends ControllerCb {
-        private final IMediaControllerCallback mIControllerCallback;
-
-        ControllerLegacyCb(@NonNull IMediaControllerCallback callback) {
-            mIControllerCallback = callback;
-        }
-
-        @Override
-        @NonNull IBinder getId() {
-            return mIControllerCallback.asBinder();
-        }
-
-        @Override
-        void onCustomLayoutChanged(List<CommandButton> layout) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putParcelableArray(ARGUMENT_COMMAND_BUTTONS,
-                    MediaUtils2.toCommandButtonParcelableArray(layout));
-            mIControllerCallback.onEvent(SESSION_EVENT_SET_CUSTOM_LAYOUT, bundle);
-        }
-
-        @Override
-        void onPlaybackInfoChanged(PlaybackInfo info) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_PLAYBACK_INFO, info.toBundle());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_PLAYBACK_INFO_CHANGED, bundle);
-
-        }
-
-        @Override
-        void onAllowedCommandsChanged(SessionCommandGroup2 commands) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_ALLOWED_COMMANDS, commands.toBundle());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_ALLOWED_COMMANDS_CHANGED, bundle);
-        }
-
-        @Override
-        void onCustomCommand(SessionCommand2 command, Bundle args, ResultReceiver receiver)
-                throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_CUSTOM_COMMAND, command.toBundle());
-            bundle.putBundle(ARGUMENT_ARGUMENTS, args);
-            bundle.putParcelable(ARGUMENT_RESULT_RECEIVER, receiver);
-            mIControllerCallback.onEvent(SESSION_EVENT_SEND_CUSTOM_COMMAND, bundle);
-        }
-
-        @Override
-        void onPlayerStateChanged(int playerState)
-                throws RemoteException {
-            // Note: current position should be also sent to the controller here for controller
-            // to calculate the position more correctly.
-            Bundle bundle = new Bundle();
-            bundle.putInt(ARGUMENT_PLAYER_STATE, playerState);
-            bundle.putParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT, mSession.getPlaybackStateCompat());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_PLAYER_STATE_CHANGED, bundle);
-        }
-
-        @Override
-        void onPlaybackSpeedChanged(float speed) throws RemoteException {
-            // Note: current position should be also sent to the controller here for controller
-            // to calculate the position more correctly.
-            Bundle bundle = new Bundle();
-            bundle.putParcelable(
-                    ARGUMENT_PLAYBACK_STATE_COMPAT, mSession.getPlaybackStateCompat());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_PLAYBACK_SPEED_CHANGED, bundle);
-        }
-
-        @Override
-        void onBufferingStateChanged(MediaItem2 item, int state) throws RemoteException {
-            // Note: buffered position should be also sent to the controller here. It's to
-            // follow the behavior of MediaPlayerInterface.PlayerEventCallback.
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_MEDIA_ITEM, item.toBundle());
-            bundle.putInt(ARGUMENT_BUFFERING_STATE, state);
-            bundle.putParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT,
-                    mSession.getPlaybackStateCompat());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_BUFFERING_STATE_CHANGED, bundle);
-
-        }
-
-        @Override
-        void onSeekCompleted(long position) throws RemoteException {
-            // Note: current position should be also sent to the controller here because the
-            // position here may refer to the parameter of the previous seek() API calls.
-            Bundle bundle = new Bundle();
-            bundle.putLong(ARGUMENT_SEEK_POSITION, position);
-            bundle.putParcelable(ARGUMENT_PLAYBACK_STATE_COMPAT,
-                    mSession.getPlaybackStateCompat());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_SEEK_COMPLETED, bundle);
-        }
-
-        @Override
-        void onError(int errorCode, Bundle extras) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putInt(ARGUMENT_ERROR_CODE, errorCode);
-            bundle.putBundle(ARGUMENT_EXTRAS, extras);
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_ERROR, bundle);
-        }
-
-        @Override
-        void onCurrentMediaItemChanged(MediaItem2 item) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_MEDIA_ITEM, (item == null) ? null : item.toBundle());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_CURRENT_MEDIA_ITEM_CHANGED, bundle);
-        }
-
-        @Override
-        void onPlaylistChanged(List<MediaItem2> playlist, MediaMetadata2 metadata)
-                throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putParcelableArray(ARGUMENT_PLAYLIST,
-                    MediaUtils2.toMediaItem2ParcelableArray(playlist));
-            bundle.putBundle(ARGUMENT_PLAYLIST_METADATA,
-                    metadata == null ? null : metadata.toBundle());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_PLAYLIST_CHANGED, bundle);
-        }
-
-        @Override
-        void onPlaylistMetadataChanged(MediaMetadata2 metadata) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putBundle(ARGUMENT_PLAYLIST_METADATA,
-                    metadata == null ? null : metadata.toBundle());
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED, bundle);
-        }
-
-        @Override
-        void onShuffleModeChanged(int shuffleMode) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putInt(ARGUMENT_SHUFFLE_MODE, shuffleMode);
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED, bundle);
-        }
-
-        @Override
-        void onRepeatModeChanged(int repeatMode) throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putInt(ARGUMENT_REPEAT_MODE, repeatMode);
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_REPEAT_MODE_CHANGED, bundle);
-        }
-
-        @Override
-        void onRoutesInfoChanged(List<Bundle> routes) throws RemoteException {
-            Bundle bundle = null;
-            if (routes != null) {
-                bundle = new Bundle();
-                bundle.putParcelableArray(ARGUMENT_ROUTE_BUNDLE, routes.toArray(new Bundle[0]));
-            }
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_ROUTES_INFO_CHANGED, bundle);
-        }
-
-        @Override
-        void onChildrenChanged(String parentId, int itemCount, Bundle extras)
-                throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putString(ARGUMENT_MEDIA_ID, parentId);
-            bundle.putInt(ARGUMENT_ITEM_COUNT, itemCount);
-            bundle.putBundle(ARGUMENT_EXTRAS, extras);
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_CHILDREN_CHANGED, bundle);
-        }
-
-        @Override
-        void onSearchResultChanged(String query, int itemCount, Bundle extras)
-                throws RemoteException {
-            Bundle bundle = new Bundle();
-            bundle.putString(ARGUMENT_QUERY, query);
-            bundle.putInt(ARGUMENT_ITEM_COUNT, itemCount);
-            bundle.putBundle(ARGUMENT_EXTRAS, extras);
-            mIControllerCallback.onEvent(SESSION_EVENT_ON_SEARCH_RESULT_CHANGED, bundle);
-        }
-    }
-}
diff --git a/media/src/main/java/androidx/media/MediaSessionManager.java b/media/src/main/java/androidx/media/MediaSessionManager.java
deleted file mode 100644
index 8c11228..0000000
--- a/media/src/main/java/androidx/media/MediaSessionManager.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media;
-
-import android.content.Context;
-import android.os.Build;
-import android.support.v4.media.session.MediaControllerCompat;
-import android.support.v4.media.session.MediaSessionCompat;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.os.BuildCompat;
-
-/**
- * Provides support for interacting with {@link MediaSessionCompat media sessions} that
- * applications have published to express their ongoing media playback state.
- *
- * @see MediaSessionCompat
- * @see MediaControllerCompat
- */
-public final class MediaSessionManager {
-    static final String TAG = "MediaSessionManager";
-    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private static final Object sLock = new Object();
-    private static volatile MediaSessionManager sSessionManager;
-
-    MediaSessionManagerImpl mImpl;
-
-    /**
-     * Gets an instance of the media session manager associated with the context.
-     *
-     * @return The MediaSessionManager instance for this context.
-     */
-    public static @NonNull MediaSessionManager getSessionManager(@NonNull Context context) {
-        MediaSessionManager manager = sSessionManager;
-        if (manager == null) {
-            synchronized (sLock) {
-                manager = sSessionManager;
-                if (manager == null) {
-                    sSessionManager = new MediaSessionManager(context.getApplicationContext());
-                    manager = sSessionManager;
-                }
-            }
-        }
-        return manager;
-    }
-
-    private MediaSessionManager(Context context) {
-        if (BuildCompat.isAtLeastP()) {
-            mImpl = new MediaSessionManagerImplApi28(context);
-        } else if (Build.VERSION.SDK_INT >= 21) {
-            mImpl = new MediaSessionManagerImplApi21(context);
-        } else {
-            mImpl = new MediaSessionManagerImplBase(context);
-        }
-    }
-
-    /**
-     * Checks whether the remote user is a trusted app.
-     * <p>
-     * An app is trusted if the app holds the android.Manifest.permission.MEDIA_CONTENT_CONTROL
-     * permission or has an enabled notification listener.
-     *
-     * @param userInfo The remote user info from either
-     *            {@link MediaSessionCompat#getCurrentControllerInfo()} and
-     *            {@link MediaBrowserServiceCompat#getCurrentBrowserInfo()}.
-     * @return {@code true} if the remote user is trusted and its package name matches with the UID.
-     *            {@code false} otherwise.
-     */
-    public boolean isTrustedForMediaControl(@NonNull RemoteUserInfo userInfo) {
-        if (userInfo == null) {
-            throw new IllegalArgumentException("userInfo should not be null");
-        }
-        return mImpl.isTrustedForMediaControl(userInfo.mImpl);
-    }
-
-    Context getContext() {
-        return mImpl.getContext();
-    }
-
-    interface MediaSessionManagerImpl {
-        Context getContext();
-        boolean isTrustedForMediaControl(RemoteUserInfoImpl userInfo);
-    }
-
-    interface RemoteUserInfoImpl {
-        String getPackageName();
-        int getPid();
-        int getUid();
-    }
-
-    /**
-     * Information of a remote user of {@link android.support.v4.media.session.MediaSessionCompat}
-     * or {@link MediaBrowserServiceCompat}.
-     * This can be used to decide whether the remote user is trusted app.
-     *
-     * @see #isTrustedForMediaControl(RemoteUserInfo)
-     */
-    public static final class RemoteUserInfo {
-        /**
-         * Used by {@link #getPackageName()} when the session is connected to the legacy controller
-         * whose exact package name cannot be obtained.
-         */
-        public static String LEGACY_CONTROLLER = "android.media.session.MediaController";
-
-        RemoteUserInfoImpl mImpl;
-
-        public RemoteUserInfo(@NonNull String packageName, int pid, int uid) {
-            if (BuildCompat.isAtLeastP()) {
-                mImpl = new MediaSessionManagerImplApi28.RemoteUserInfo(packageName, pid, uid);
-            } else {
-                mImpl = new MediaSessionManagerImplBase.RemoteUserInfo(packageName, pid, uid);
-            }
-        }
-
-        /**
-         * @return package name of the controller. Can be {@link #LEGACY_CONTROLLER} if the package
-         *         name cannot be obtained.
-         */
-        public @NonNull String getPackageName() {
-            return mImpl.getPackageName();
-        }
-
-        /**
-         * @return pid of the controller
-         */
-        public int getPid() {
-            return mImpl.getPid();
-        }
-
-        /**
-         * @return uid of the controller
-         */
-        public int getUid() {
-            return mImpl.getUid();
-        }
-
-        @Override
-        public boolean equals(@Nullable Object obj) {
-            return mImpl.equals(obj);
-        }
-
-        @Override
-        public int hashCode() {
-            return mImpl.hashCode();
-        }
-    }
-}
diff --git a/media/src/main/java/androidx/media/MediaSessionManagerImplApi21.java b/media/src/main/java/androidx/media/MediaSessionManagerImplApi21.java
deleted file mode 100644
index 4fefe70..0000000
--- a/media/src/main/java/androidx/media/MediaSessionManagerImplApi21.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-
-@RequiresApi(21)
-class MediaSessionManagerImplApi21 extends MediaSessionManagerImplBase {
-    MediaSessionManagerImplApi21(Context context) {
-        super(context);
-        mContext = context;
-    }
-
-    @Override
-    public boolean isTrustedForMediaControl(
-            @NonNull MediaSessionManager.RemoteUserInfoImpl userInfo) {
-
-        return hasMediaControlPermission(userInfo) || super.isTrustedForMediaControl(userInfo);
-    }
-
-    /**
-     * Checks the caller has android.Manifest.permission.MEDIA_CONTENT_CONTROL permission.
-     */
-    private boolean hasMediaControlPermission(
-            @NonNull MediaSessionManager.RemoteUserInfoImpl userInfo) {
-        return getContext().checkPermission(
-                android.Manifest.permission.MEDIA_CONTENT_CONTROL,
-                userInfo.getPid(), userInfo.getUid()) == PackageManager.PERMISSION_GRANTED;
-    }
-}
diff --git a/media/src/main/java/androidx/media/MediaSessionManagerImplApi28.java b/media/src/main/java/androidx/media/MediaSessionManagerImplApi28.java
deleted file mode 100644
index 48344fa..0000000
--- a/media/src/main/java/androidx/media/MediaSessionManagerImplApi28.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media;
-
-import android.content.Context;
-
-import androidx.annotation.RequiresApi;
-
-@RequiresApi(28)
-class MediaSessionManagerImplApi28 extends MediaSessionManagerImplApi21 {
-    android.media.session.MediaSessionManager mObject;
-
-    MediaSessionManagerImplApi28(Context context) {
-        super(context);
-        mObject = (android.media.session.MediaSessionManager) context
-                .getSystemService(Context.MEDIA_SESSION_SERVICE);
-    }
-
-    @Override
-    public boolean isTrustedForMediaControl(MediaSessionManager.RemoteUserInfoImpl userInfo) {
-        if (userInfo instanceof RemoteUserInfo) {
-            return mObject.isTrustedForMediaControl(((RemoteUserInfo) userInfo).mObject);
-        }
-        return false;
-    }
-
-    static final class RemoteUserInfo implements MediaSessionManager.RemoteUserInfoImpl {
-        android.media.session.MediaSessionManager.RemoteUserInfo mObject;
-
-        RemoteUserInfo(String packageName, int pid, int uid) {
-            mObject = new android.media.session.MediaSessionManager.RemoteUserInfo(
-                    packageName, pid, uid);
-        }
-
-        @Override
-        public String getPackageName() {
-            return mObject.getPackageName();
-        }
-
-        @Override
-        public int getPid() {
-            return mObject.getPid();
-        }
-
-        @Override
-        public int getUid() {
-            return mObject.getUid();
-        }
-    }
-}
diff --git a/media/src/main/java/androidx/media/MediaSessionManagerImplBase.java b/media/src/main/java/androidx/media/MediaSessionManagerImplBase.java
deleted file mode 100644
index 3fc21f1..0000000
--- a/media/src/main/java/androidx/media/MediaSessionManagerImplBase.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media;
-
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Process;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.core.util.ObjectsCompat;
-
-class MediaSessionManagerImplBase implements MediaSessionManager.MediaSessionManagerImpl {
-    private static final String TAG = MediaSessionManager.TAG;
-    private static final boolean DEBUG = MediaSessionManager.DEBUG;
-
-    private static final String PERMISSION_STATUS_BAR_SERVICE =
-            "android.permission.STATUS_BAR_SERVICE";
-    private static final String PERMISSION_MEDIA_CONTENT_CONTROL =
-            "android.permission.MEDIA_CONTENT_CONTROL";
-    private static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
-
-    Context mContext;
-    ContentResolver mContentResolver;
-
-    MediaSessionManagerImplBase(Context context) {
-        mContext = context;
-        mContentResolver = mContext.getContentResolver();
-    }
-
-    @Override
-    public Context getContext() {
-        return mContext;
-    }
-
-    @Override
-    public boolean isTrustedForMediaControl(
-            @NonNull MediaSessionManager.RemoteUserInfoImpl userInfo) {
-        ApplicationInfo applicationInfo;
-        try {
-            applicationInfo = mContext.getPackageManager().getApplicationInfo(
-                    userInfo.getPackageName(), 0);
-        } catch (PackageManager.NameNotFoundException e) {
-            if (DEBUG) {
-                Log.d(TAG, "Package " + userInfo.getPackageName() + " doesn't exist");
-            }
-            return false;
-        }
-
-        if (applicationInfo.uid != userInfo.getUid()) {
-            if (DEBUG) {
-                Log.d(TAG, "Package name " + userInfo.getPackageName()
-                        + " doesn't match with the uid " + userInfo.getUid());
-            }
-            return false;
-        }
-        return isPermissionGranted(userInfo, PERMISSION_STATUS_BAR_SERVICE)
-                || isPermissionGranted(userInfo, PERMISSION_MEDIA_CONTENT_CONTROL)
-                || userInfo.getUid() == Process.SYSTEM_UID
-                || isEnabledNotificationListener(userInfo);
-    }
-
-    private boolean isPermissionGranted(MediaSessionManager.RemoteUserInfoImpl userInfo,
-            String permission) {
-        if (userInfo.getPid() < 0) {
-            // This may happen for the MediaBrowserServiceCompat#onGetRoot().
-            return mContext.getPackageManager().checkPermission(
-                    permission, userInfo.getPackageName()) == PackageManager.PERMISSION_GRANTED;
-        }
-        return mContext.checkPermission(permission, userInfo.getPid(), userInfo.getUid())
-                == PackageManager.PERMISSION_GRANTED;
-    }
-
-    /**
-     * This checks if the component is an enabled notification listener for the
-     * specified user. Enabled components may only operate on behalf of the user
-     * they're running as.
-     *
-     * @return True if the component is enabled, false otherwise
-     */
-    @SuppressWarnings("StringSplitter")
-    boolean isEnabledNotificationListener(
-            @NonNull MediaSessionManager.RemoteUserInfoImpl userInfo) {
-        final String enabledNotifListeners = Settings.Secure.getString(mContentResolver,
-                ENABLED_NOTIFICATION_LISTENERS);
-        if (enabledNotifListeners != null) {
-            final String[] components = enabledNotifListeners.split(":");
-            for (int i = 0; i < components.length; i++) {
-                final ComponentName component =
-                        ComponentName.unflattenFromString(components[i]);
-                if (component != null) {
-                    if (component.getPackageName().equals(userInfo.getPackageName())) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    static class RemoteUserInfo implements MediaSessionManager.RemoteUserInfoImpl {
-        private String mPackageName;
-        private int mPid;
-        private int mUid;
-
-        RemoteUserInfo(String packageName, int pid, int uid) {
-            mPackageName = packageName;
-            mPid = pid;
-            mUid = uid;
-        }
-
-        @Override
-        public String getPackageName() {
-            return mPackageName;
-        }
-
-        @Override
-        public int getPid() {
-            return mPid;
-        }
-
-        @Override
-        public int getUid() {
-            return mUid;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof RemoteUserInfo)) {
-                return false;
-            }
-            RemoteUserInfo otherUserInfo = (RemoteUserInfo) obj;
-            return TextUtils.equals(mPackageName, otherUserInfo.mPackageName)
-                    && mPid == otherUserInfo.mPid
-                    && mUid == otherUserInfo.mUid;
-        }
-
-        @Override
-        public int hashCode() {
-            return ObjectsCompat.hash(mPackageName, mPid, mUid);
-        }
-    }
-}
-
diff --git a/media/src/main/java/androidx/media/MediaSessionService2.java b/media/src/main/java/androidx/media/MediaSessionService2.java
index 03bb086..7bad65c 100644
--- a/media/src/main/java/androidx/media/MediaSessionService2.java
+++ b/media/src/main/java/androidx/media/MediaSessionService2.java
@@ -16,6 +16,8 @@
 
 package androidx.media;
 
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.Service;
@@ -29,6 +31,7 @@
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
 import androidx.media.MediaBrowserServiceCompat.BrowserRoot;
 import androidx.media.MediaSession2.ControllerInfo;
 import androidx.media.SessionToken2.TokenType;
@@ -36,6 +39,7 @@
 import java.util.List;
 
 /**
+ * @hide
  * Base class for media session services, which is the service version of the {@link MediaSession2}.
  * <p>
  * It's highly recommended for an app to use this instead of {@link MediaSession2} if it wants
@@ -93,6 +97,7 @@
  * <p>
  * After the binding, session's
  * {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)}
+ *
  * will be called to accept or reject connection request from a controller. If the connection is
  * rejected, the controller will unbind. If it's accepted, the controller will be available to use
  * and keep binding.
@@ -101,9 +106,6 @@
  * is called and service would become a foreground service. It's needed to keep playback after the
  * controller is destroyed. The session service becomes background service when the playback is
  * stopped.
- * <p>
- * The service is destroyed when the session is closed, or no media controller is bounded to the
- * session while the service is not running as a foreground service.
  * <a name="Permissions"></a>
  * <h3>Permissions</h3>
  * <p>
@@ -111,7 +113,10 @@
  * the session service accepted the connection request through
  * {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)}.
  */
+@RestrictTo(LIBRARY_GROUP)
 public abstract class MediaSessionService2 extends Service {
+    //private final MediaSessionService2Provider mProvider;
+
     /**
      * This is the interface name that a service implementing a session service should say that it
      * support -- that is, this is the action it uses for its intent filter.
@@ -311,6 +316,8 @@
             //   2. MediaSessionService2 is defined as the simplified version of the library
             //      service with no browsing feature, so shouldn't allow MediaBrowserServiceCompat
             //      specific operations.
+            // TODO: Revisit here API not to return stub root here. The fake media ID here may be
+            //       used by the browser service for real.
             return sDefaultBrowserRoot;
         }
 
diff --git a/media/src/main/java/androidx/media/MediaUtils2.java b/media/src/main/java/androidx/media/MediaUtils2.java
index 6a011f2..657e24d 100644
--- a/media/src/main/java/androidx/media/MediaUtils2.java
+++ b/media/src/main/java/androidx/media/MediaUtils2.java
@@ -16,6 +16,8 @@
 
 package androidx.media;
 
+import static androidx.media.AudioAttributesCompat.CONTENT_TYPE_UNKNOWN;
+import static androidx.media.AudioAttributesCompat.USAGE_UNKNOWN;
 import static androidx.media.MediaMetadata2.METADATA_KEY_DISPLAY_DESCRIPTION;
 import static androidx.media.MediaMetadata2.METADATA_KEY_DISPLAY_ICON;
 import static androidx.media.MediaMetadata2.METADATA_KEY_DISPLAY_ICON_URI;
@@ -42,7 +44,9 @@
 import java.util.List;
 
 class MediaUtils2 {
-    static final String TAG = "MediaUtils2";
+    static final String AUDIO_ATTRIBUTES_USAGE = "androidx.media.audio_attrs.USAGE";
+    static final String AUDIO_ATTRIBUTES_CONTENT_TYPE = "androidx.media.audio_attrs.CONTENT_TYPE";
+    static final String AUDIO_ATTRIBUTES_FLAGS = "androidx.media.audio_attrs.FLAGS";
 
     private MediaUtils2() {
     }
@@ -112,28 +116,6 @@
                 .build();
     }
 
-    static List<MediaItem> fromMediaItem2List(List<MediaItem2> items) {
-        if (items == null) {
-            return null;
-        }
-        List<MediaItem> result = new ArrayList<>();
-        for (int i = 0; i < items.size(); i++) {
-            result.add(createMediaItem(items.get(i)));
-        }
-        return result;
-    }
-
-    static List<MediaItem2> toMediaItem2List(List<MediaItem> items) {
-        if (items == null) {
-            return null;
-        }
-        List<MediaItem2> result = new ArrayList<>();
-        for (int i = 0; i < items.size(); i++) {
-            result.add(createMediaItem2(items.get(i)));
-        }
-        return result;
-    }
-
     /**
      * Creates a {@link MediaMetadata2} from the {@link MediaDescriptionCompat}.
      *
@@ -369,6 +351,28 @@
         return layout;
     }
 
+    static Bundle toAudioAttributesBundle(AudioAttributesCompat attrs) {
+        if (attrs == null) {
+            return null;
+        }
+        Bundle bundle = new Bundle();
+        bundle.putInt(AUDIO_ATTRIBUTES_USAGE, attrs.getUsage());
+        bundle.putInt(AUDIO_ATTRIBUTES_CONTENT_TYPE, attrs.getContentType());
+        bundle.putInt(AUDIO_ATTRIBUTES_FLAGS, attrs.getFlags());
+        return bundle;
+    }
+
+    static AudioAttributesCompat fromAudioAttributesBundle(Bundle bundle) {
+        if (bundle == null) {
+            return null;
+        }
+        return new AudioAttributesCompat.Builder()
+                .setUsage(bundle.getInt(AUDIO_ATTRIBUTES_USAGE, USAGE_UNKNOWN))
+                .setContentType(bundle.getInt(AUDIO_ATTRIBUTES_CONTENT_TYPE, CONTENT_TYPE_UNKNOWN))
+                .setFlags(bundle.getInt(AUDIO_ATTRIBUTES_FLAGS, 0))
+                .build();
+    }
+
     static List<Bundle> toBundleList(Parcelable[] array) {
         if (array == null) {
             return null;
@@ -382,17 +386,17 @@
 
     static int createPlaybackStateCompatState(int playerState, int bufferingState) {
         switch (playerState) {
-            case MediaPlayerInterface.PLAYER_STATE_PLAYING:
+            case MediaPlayerBase.PLAYER_STATE_PLAYING:
                 switch (bufferingState) {
-                    case MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_STARVED:
+                    case MediaPlayerBase.BUFFERING_STATE_BUFFERING_AND_STARVED:
                         return PlaybackStateCompat.STATE_BUFFERING;
                 }
                 return PlaybackStateCompat.STATE_PLAYING;
-            case MediaPlayerInterface.PLAYER_STATE_PAUSED:
+            case MediaPlayerBase.PLAYER_STATE_PAUSED:
                 return PlaybackStateCompat.STATE_PAUSED;
-            case MediaPlayerInterface.PLAYER_STATE_IDLE:
+            case MediaPlayerBase.PLAYER_STATE_IDLE:
                 return PlaybackStateCompat.STATE_NONE;
-            case MediaPlayerInterface.PLAYER_STATE_ERROR:
+            case MediaPlayerBase.PLAYER_STATE_ERROR:
                 return PlaybackStateCompat.STATE_ERROR;
         }
         // For unknown value
@@ -402,13 +406,13 @@
     static int toPlayerState(int playbackStateCompatState) {
         switch (playbackStateCompatState) {
             case PlaybackStateCompat.STATE_ERROR:
-                return MediaPlayerInterface.PLAYER_STATE_ERROR;
+                return MediaPlayerBase.PLAYER_STATE_ERROR;
             case PlaybackStateCompat.STATE_NONE:
-                return MediaPlayerInterface.PLAYER_STATE_IDLE;
+                return MediaPlayerBase.PLAYER_STATE_IDLE;
             case PlaybackStateCompat.STATE_PAUSED:
             case PlaybackStateCompat.STATE_STOPPED:
             case PlaybackStateCompat.STATE_BUFFERING: // means paused for buffering.
-                return MediaPlayerInterface.PLAYER_STATE_PAUSED;
+                return MediaPlayerBase.PLAYER_STATE_PAUSED;
             case PlaybackStateCompat.STATE_FAST_FORWARDING:
             case PlaybackStateCompat.STATE_PLAYING:
             case PlaybackStateCompat.STATE_REWINDING:
@@ -416,16 +420,12 @@
             case PlaybackStateCompat.STATE_SKIPPING_TO_PREVIOUS:
             case PlaybackStateCompat.STATE_SKIPPING_TO_QUEUE_ITEM:
             case PlaybackStateCompat.STATE_CONNECTING: // Note: there's no perfect match for this.
-                return MediaPlayerInterface.PLAYER_STATE_PLAYING;
+                return MediaPlayerBase.PLAYER_STATE_PLAYING;
         }
-        return MediaPlayerInterface.PLAYER_STATE_ERROR;
+        return MediaPlayerBase.PLAYER_STATE_ERROR;
     }
 
     static boolean isDefaultLibraryRootHint(Bundle bundle) {
         return bundle != null && bundle.getBoolean(MediaConstants2.ROOT_EXTRA_DEFAULT, false);
     }
-
-    static Bundle createBundle(Bundle bundle) {
-        return (bundle == null) ? new Bundle() : new Bundle(bundle);
-    }
 }
diff --git a/media/src/main/java/androidx/media/SessionCommand2.java b/media/src/main/java/androidx/media/SessionCommand2.java
index 353688a..f017941 100644
--- a/media/src/main/java/androidx/media/SessionCommand2.java
+++ b/media/src/main/java/androidx/media/SessionCommand2.java
@@ -276,38 +276,52 @@
     public static final int COMMAND_CODE_SESSION_SELECT_ROUTE = 38;
 
     /**
+     * @hide
      * Command code for {@link MediaBrowser2#getChildren(String, int, int, Bundle)}.
      */
+    @RestrictTo(LIBRARY_GROUP)
     public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 29;
 
     /**
+     * @hide
      * Command code for {@link MediaBrowser2#getItem(String)}.
      */
+    @RestrictTo(LIBRARY_GROUP)
     public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 30;
 
     /**
+     * @hide
      * Command code for {@link MediaBrowser2#getLibraryRoot(Bundle)}.
      */
+    @RestrictTo(LIBRARY_GROUP)
     public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 31;
 
     /**
+     * @hide
      * Command code for {@link MediaBrowser2#getSearchResult(String, int, int, Bundle)}.
      */
+    @RestrictTo(LIBRARY_GROUP)
     public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 32;
 
     /**
+     * @hide
      * Command code for {@link MediaBrowser2#search(String, Bundle)}.
      */
+    @RestrictTo(LIBRARY_GROUP)
     public static final int COMMAND_CODE_LIBRARY_SEARCH = 33;
 
     /**
+     * @hide
      * Command code for {@link MediaBrowser2#subscribe(String, Bundle)}.
      */
+    @RestrictTo(LIBRARY_GROUP)
     public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 34;
 
     /**
+     * @hide
      * Command code for {@link MediaBrowser2#unsubscribe(String)}.
      */
+    @RestrictTo(LIBRARY_GROUP)
     public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 35;
 
     /**
diff --git a/media/src/main/java/androidx/media/SessionCommandGroup2.java b/media/src/main/java/androidx/media/SessionCommandGroup2.java
index db15bb3..691eb70 100644
--- a/media/src/main/java/androidx/media/SessionCommandGroup2.java
+++ b/media/src/main/java/androidx/media/SessionCommandGroup2.java
@@ -42,7 +42,7 @@
     private static final String KEY_COMMANDS = "android.media.mediasession2.commandgroup.commands";
     // Prefix for all command codes
     private static final String PREFIX_COMMAND_CODE = "COMMAND_CODE_";
-    // Prefix for command codes that will be sent directly to the MediaPlayerInterface
+    // Prefix for command codes that will be sent directly to the MediaPlayerBase
     private static final String PREFIX_COMMAND_CODE_PLAYBACK = "COMMAND_CODE_PLAYBACK_";
     // Prefix for command codes that will be sent directly to the MediaPlaylistAgent
     private static final String PREFIX_COMMAND_CODE_PLAYLIST = "COMMAND_CODE_PLAYLIST_";
diff --git a/media/src/main/java/androidx/media/SessionPlaylistAgentImplBase.java b/media/src/main/java/androidx/media/SessionPlaylistAgentImplBase.java
index 2cdc9ab..431b188 100644
--- a/media/src/main/java/androidx/media/SessionPlaylistAgentImplBase.java
+++ b/media/src/main/java/androidx/media/SessionPlaylistAgentImplBase.java
@@ -18,13 +18,13 @@
 
 import android.annotation.TargetApi;
 import android.os.Build;
+import android.util.ArrayMap;
 
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
-import androidx.collection.ArrayMap;
-import androidx.media.MediaPlayerInterface.PlayerEventCallback;
+import androidx.media.MediaPlayerBase.PlayerEventCallback;
 import androidx.media.MediaSession2.OnDataSourceMissingHelper;
 
 import java.util.ArrayList;
@@ -46,7 +46,7 @@
     private final MyPlayerEventCallback mPlayerCallback;
 
     @GuardedBy("mLock")
-    private MediaPlayerInterface mPlayer;
+    private MediaPlayerBase mPlayer;
     @GuardedBy("mLock")
     private OnDataSourceMissingHelper mDsmHelper;
     // TODO: Check if having the same item is okay (b/74090741)
@@ -68,7 +68,7 @@
     // Called on session callback executor.
     private class MyPlayerEventCallback extends PlayerEventCallback {
         @Override
-        public void onCurrentDataSourceChanged(@NonNull MediaPlayerInterface mpb,
+        public void onCurrentDataSourceChanged(@NonNull MediaPlayerBase mpb,
                 @Nullable DataSourceDesc dsd) {
             synchronized (mLock) {
                 if (mPlayer != mpb) {
@@ -133,7 +133,7 @@
     }
 
     SessionPlaylistAgentImplBase(@NonNull MediaSession2ImplBase session,
-            @NonNull MediaPlayerInterface player) {
+            @NonNull MediaPlayerBase player) {
         super();
         if (session == null) {
             throw new IllegalArgumentException("sessionImpl shouldn't be null");
@@ -147,7 +147,7 @@
         mPlayer.registerPlayerEventCallback(mSession.getCallbackExecutor(), mPlayerCallback);
     }
 
-    public void setPlayer(@NonNull MediaPlayerInterface player) {
+    public void setPlayer(@NonNull MediaPlayerBase player) {
         if (player == null) {
             throw new IllegalArgumentException("player shouldn't be null");
         }
diff --git a/media/src/main/java/androidx/media/SessionToken2.java b/media/src/main/java/androidx/media/SessionToken2.java
index cae6c9b..eb42297 100644
--- a/media/src/main/java/androidx/media/SessionToken2.java
+++ b/media/src/main/java/androidx/media/SessionToken2.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.media.session.MediaSessionManager;
 import android.os.Bundle;
 import android.support.v4.media.session.MediaSessionCompat;
 import android.text.TextUtils;
@@ -37,8 +38,7 @@
 import java.util.List;
 
 /**
- * Represents an ongoing {@link MediaSession2} or a {@link MediaSessionService2}.
- * If it's representing a session service, it may not be ongoing.
+ * Represents an ongoing {@link MediaSession2}.
  * <p>
  * This may be passed to apps by the session owner to allow them to create a
  * {@link MediaController2} to communicate with the session.
@@ -65,13 +65,15 @@
     public static final int TYPE_SESSION = 0;
 
     /**
-     * Type for {@link MediaSessionService2}.
+     * @hide
      */
+    @RestrictTo(LIBRARY_GROUP)
     public static final int TYPE_SESSION_SERVICE = 1;
 
     /**
-     * Type for {@link MediaLibraryService2}.
+     * @hide
      */
+    @RestrictTo(LIBRARY_GROUP)
     public static final int TYPE_LIBRARY_SERVICE = 2;
 
     //private final SessionToken2Provider mProvider;
@@ -95,12 +97,14 @@
     private final ComponentName mComponentName;
 
     /**
+     * @hide
      * Constructor for the token. You can only create token for session service or library service
      * to use by {@link MediaController2} or {@link MediaBrowser2}.
      *
      * @param context The context.
      * @param serviceComponent The component name of the media browser service.
      */
+    @RestrictTo(LIBRARY_GROUP)
     public SessionToken2(@NonNull Context context, @NonNull ComponentName serviceComponent) {
         this(context, serviceComponent, UID_UNKNOWN);
     }
@@ -238,8 +242,6 @@
     /**
      * @return type of the token
      * @see #TYPE_SESSION
-     * @see #TYPE_SESSION_SERVICE
-     * @see #TYPE_LIBRARY_SERVICE
      */
     public @TokenType int getType() {
         return mType;
diff --git a/media/src/main/java/androidx/media/subtitle/Cea608CCParser.java b/media/src/main/java/androidx/media/subtitle/Cea608CCParser.java
deleted file mode 100644
index 9205fba..0000000
--- a/media/src/main/java/androidx/media/subtitle/Cea608CCParser.java
+++ /dev/null
@@ -1,987 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.subtitle;
-
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.TextPaint;
-import android.text.style.CharacterStyle;
-import android.text.style.StyleSpan;
-import android.text.style.UnderlineSpan;
-import android.text.style.UpdateAppearance;
-import android.util.Log;
-import android.view.accessibility.CaptioningManager.CaptionStyle;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * CCParser processes CEA-608 closed caption data.
- *
- * It calls back into OnDisplayChangedListener upon
- * display change with styled text for rendering.
- *
- */
-class Cea608CCParser {
-    public static final int MAX_ROWS = 15;
-    public static final int MAX_COLS = 32;
-
-    private static final String TAG = "Cea608CCParser";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private static final int INVALID = -1;
-
-    // EIA-CEA-608: Table 70 - Control Codes
-    private static final int RCL = 0x20;
-    private static final int BS  = 0x21;
-    private static final int AOF = 0x22;
-    private static final int AON = 0x23;
-    private static final int DER = 0x24;
-    private static final int RU2 = 0x25;
-    private static final int RU3 = 0x26;
-    private static final int RU4 = 0x27;
-    private static final int FON = 0x28;
-    private static final int RDC = 0x29;
-    private static final int TR  = 0x2a;
-    private static final int RTD = 0x2b;
-    private static final int EDM = 0x2c;
-    private static final int CR  = 0x2d;
-    private static final int ENM = 0x2e;
-    private static final int EOC = 0x2f;
-
-    // Transparent Space
-    private static final char TS = '\u00A0';
-
-    // Captioning Modes
-    private static final int MODE_UNKNOWN = 0;
-    private static final int MODE_PAINT_ON = 1;
-    private static final int MODE_ROLL_UP = 2;
-    private static final int MODE_POP_ON = 3;
-    private static final int MODE_TEXT = 4;
-
-    private final DisplayListener mListener;
-
-    private int mMode = MODE_PAINT_ON;
-    private int mRollUpSize = 4;
-    private int mPrevCtrlCode = INVALID;
-
-    private CCMemory mDisplay = new CCMemory();
-    private CCMemory mNonDisplay = new CCMemory();
-    private CCMemory mTextMem = new CCMemory();
-
-    Cea608CCParser(DisplayListener listener) {
-        mListener = listener;
-    }
-
-    public void parse(byte[] data) {
-        CCData[] ccData = CCData.fromByteArray(data);
-
-        for (int i = 0; i < ccData.length; i++) {
-            if (DEBUG) {
-                Log.d(TAG, ccData[i].toString());
-            }
-
-            if (handleCtrlCode(ccData[i])
-                    || handleTabOffsets(ccData[i])
-                    || handlePACCode(ccData[i])
-                    || handleMidRowCode(ccData[i])) {
-                continue;
-            }
-
-            handleDisplayableChars(ccData[i]);
-        }
-    }
-
-    interface DisplayListener {
-        void onDisplayChanged(SpannableStringBuilder[] styledTexts);
-        CaptionStyle getCaptionStyle();
-    }
-
-    private CCMemory getMemory() {
-        // get the CC memory to operate on for current mode
-        switch (mMode) {
-            case MODE_POP_ON:
-                return mNonDisplay;
-            case MODE_TEXT:
-                // TODO(chz): support only caption mode for now,
-                // in text mode, dump everything to text mem.
-                return mTextMem;
-            case MODE_PAINT_ON:
-            case MODE_ROLL_UP:
-                return mDisplay;
-            default:
-                Log.w(TAG, "unrecoginized mode: " + mMode);
-        }
-        return mDisplay;
-    }
-
-    private boolean handleDisplayableChars(CCData ccData) {
-        if (!ccData.isDisplayableChar()) {
-            return false;
-        }
-
-        // Extended char includes 1 automatic backspace
-        if (ccData.isExtendedChar()) {
-            getMemory().bs();
-        }
-
-        getMemory().writeText(ccData.getDisplayText());
-
-        if (mMode == MODE_PAINT_ON || mMode == MODE_ROLL_UP) {
-            updateDisplay();
-        }
-
-        return true;
-    }
-
-    private boolean handleMidRowCode(CCData ccData) {
-        StyleCode m = ccData.getMidRow();
-        if (m != null) {
-            getMemory().writeMidRowCode(m);
-            return true;
-        }
-        return false;
-    }
-
-    private boolean handlePACCode(CCData ccData) {
-        PAC pac = ccData.getPAC();
-
-        if (pac != null) {
-            if (mMode == MODE_ROLL_UP) {
-                getMemory().moveBaselineTo(pac.getRow(), mRollUpSize);
-            }
-            getMemory().writePAC(pac);
-            return true;
-        }
-
-        return false;
-    }
-
-    private boolean handleTabOffsets(CCData ccData) {
-        int tabs = ccData.getTabOffset();
-
-        if (tabs > 0) {
-            getMemory().tab(tabs);
-            return true;
-        }
-
-        return false;
-    }
-
-    private boolean handleCtrlCode(CCData ccData) {
-        int ctrlCode = ccData.getCtrlCode();
-
-        if (mPrevCtrlCode != INVALID && mPrevCtrlCode == ctrlCode) {
-            // discard double ctrl codes (but if there's a 3rd one, we still take that)
-            mPrevCtrlCode = INVALID;
-            return true;
-        }
-
-        switch(ctrlCode) {
-            case RCL:
-                // select pop-on style
-                mMode = MODE_POP_ON;
-                break;
-            case BS:
-                getMemory().bs();
-                break;
-            case DER:
-                getMemory().der();
-                break;
-            case RU2:
-            case RU3:
-            case RU4:
-                mRollUpSize = (ctrlCode - 0x23);
-                // erase memory if currently in other style
-                if (mMode != MODE_ROLL_UP) {
-                    mDisplay.erase();
-                    mNonDisplay.erase();
-                }
-                // select roll-up style
-                mMode = MODE_ROLL_UP;
-                break;
-            case FON:
-                Log.i(TAG, "Flash On");
-                break;
-            case RDC:
-                // select paint-on style
-                mMode = MODE_PAINT_ON;
-                break;
-            case TR:
-                mMode = MODE_TEXT;
-                mTextMem.erase();
-                break;
-            case RTD:
-                mMode = MODE_TEXT;
-                break;
-            case EDM:
-                // erase display memory
-                mDisplay.erase();
-                updateDisplay();
-                break;
-            case CR:
-                if (mMode == MODE_ROLL_UP) {
-                    getMemory().rollUp(mRollUpSize);
-                } else {
-                    getMemory().cr();
-                }
-                if (mMode == MODE_ROLL_UP) {
-                    updateDisplay();
-                }
-                break;
-            case ENM:
-                // erase non-display memory
-                mNonDisplay.erase();
-                break;
-            case EOC:
-                // swap display/non-display memory
-                swapMemory();
-                // switch to pop-on style
-                mMode = MODE_POP_ON;
-                updateDisplay();
-                break;
-            case INVALID:
-            default:
-                mPrevCtrlCode = INVALID;
-                return false;
-        }
-
-        mPrevCtrlCode = ctrlCode;
-
-        // handled
-        return true;
-    }
-
-    private void updateDisplay() {
-        if (mListener != null) {
-            CaptionStyle captionStyle = mListener.getCaptionStyle();
-            mListener.onDisplayChanged(mDisplay.getStyledText(captionStyle));
-        }
-    }
-
-    private void swapMemory() {
-        CCMemory temp = mDisplay;
-        mDisplay = mNonDisplay;
-        mNonDisplay = temp;
-    }
-
-    private static class StyleCode {
-        static final int COLOR_WHITE = 0;
-        static final int COLOR_GREEN = 1;
-        static final int COLOR_BLUE = 2;
-        static final int COLOR_CYAN = 3;
-        static final int COLOR_RED = 4;
-        static final int COLOR_YELLOW = 5;
-        static final int COLOR_MAGENTA = 6;
-        static final int COLOR_INVALID = 7;
-
-        static final int STYLE_ITALICS   = 0x00000001;
-        static final int STYLE_UNDERLINE = 0x00000002;
-
-        static final String[] sColorMap = {
-            "WHITE", "GREEN", "BLUE", "CYAN", "RED", "YELLOW", "MAGENTA", "INVALID"
-        };
-
-        final int mStyle;
-        final int mColor;
-
-        static StyleCode fromByte(byte data2) {
-            int style = 0;
-            int color = (data2 >> 1) & 0x7;
-
-            if ((data2 & 0x1) != 0) {
-                style |= STYLE_UNDERLINE;
-            }
-
-            if (color == COLOR_INVALID) {
-                // WHITE ITALICS
-                color = COLOR_WHITE;
-                style |= STYLE_ITALICS;
-            }
-
-            return new StyleCode(style, color);
-        }
-
-        StyleCode(int style, int color) {
-            mStyle = style;
-            mColor = color;
-        }
-
-        boolean isItalics() {
-            return (mStyle & STYLE_ITALICS) != 0;
-        }
-
-        boolean isUnderline() {
-            return (mStyle & STYLE_UNDERLINE) != 0;
-        }
-
-        int getColor() {
-            return mColor;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder str = new StringBuilder();
-            str.append("{");
-            str.append(sColorMap[mColor]);
-            if ((mStyle & STYLE_ITALICS) != 0) {
-                str.append(", ITALICS");
-            }
-            if ((mStyle & STYLE_UNDERLINE) != 0) {
-                str.append(", UNDERLINE");
-            }
-            str.append("}");
-
-            return str.toString();
-        }
-    }
-
-    private static class PAC extends StyleCode {
-        final int mRow;
-        final int mCol;
-
-        static PAC fromBytes(byte data1, byte data2) {
-            int[] rowTable = {11, 1, 3, 12, 14, 5, 7, 9};
-            int row = rowTable[data1 & 0x07] + ((data2 & 0x20) >> 5);
-            int style = 0;
-            if ((data2 & 1) != 0) {
-                style |= STYLE_UNDERLINE;
-            }
-            if ((data2 & 0x10) != 0) {
-                // indent code
-                int indent = (data2 >> 1) & 0x7;
-                return new PAC(row, indent * 4, style, COLOR_WHITE);
-            } else {
-                // style code
-                int color = (data2 >> 1) & 0x7;
-
-                if (color == COLOR_INVALID) {
-                    // WHITE ITALICS
-                    color = COLOR_WHITE;
-                    style |= STYLE_ITALICS;
-                }
-                return new PAC(row, -1, style, color);
-            }
-        }
-
-        PAC(int row, int col, int style, int color) {
-            super(style, color);
-            mRow = row;
-            mCol = col;
-        }
-
-        boolean isIndentPAC() {
-            return (mCol >= 0);
-        }
-
-        int getRow() {
-            return mRow;
-        }
-
-        int getCol() {
-            return mCol;
-        }
-
-        @Override
-        public String toString() {
-            return String.format("{%d, %d}, %s",
-                    mRow, mCol, super.toString());
-        }
-    }
-
-    /**
-     * Mutable version of BackgroundSpan to facilitate text rendering with edge styles.
-     */
-    public static class MutableBackgroundColorSpan extends CharacterStyle
-            implements UpdateAppearance {
-        private int mColor;
-
-        MutableBackgroundColorSpan(int color) {
-            mColor = color;
-        }
-
-        public void setBackgroundColor(int color) {
-            mColor = color;
-        }
-
-        public int getBackgroundColor() {
-            return mColor;
-        }
-
-        @Override
-        public void updateDrawState(TextPaint ds) {
-            ds.bgColor = mColor;
-        }
-    }
-
-    /* CCLineBuilder keeps track of displayable chars, as well as
-     * MidRow styles and PACs, for a single line of CC memory.
-     *
-     * It generates styled text via getStyledText() method.
-     */
-    private static class CCLineBuilder {
-        private final StringBuilder mDisplayChars;
-        private final StyleCode[] mMidRowStyles;
-        private final StyleCode[] mPACStyles;
-
-        CCLineBuilder(String str) {
-            mDisplayChars = new StringBuilder(str);
-            mMidRowStyles = new StyleCode[mDisplayChars.length()];
-            mPACStyles = new StyleCode[mDisplayChars.length()];
-        }
-
-        void setCharAt(int index, char ch) {
-            mDisplayChars.setCharAt(index, ch);
-            mMidRowStyles[index] = null;
-        }
-
-        void setMidRowAt(int index, StyleCode m) {
-            mDisplayChars.setCharAt(index, ' ');
-            mMidRowStyles[index] = m;
-        }
-
-        void setPACAt(int index, PAC pac) {
-            mPACStyles[index] = pac;
-        }
-
-        char charAt(int index) {
-            return mDisplayChars.charAt(index);
-        }
-
-        int length() {
-            return mDisplayChars.length();
-        }
-
-        void applyStyleSpan(
-                SpannableStringBuilder styledText,
-                StyleCode s, int start, int end) {
-            if (s.isItalics()) {
-                styledText.setSpan(
-                        new StyleSpan(android.graphics.Typeface.ITALIC),
-                        start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            }
-            if (s.isUnderline()) {
-                styledText.setSpan(
-                        new UnderlineSpan(),
-                        start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            }
-        }
-
-        SpannableStringBuilder getStyledText(CaptionStyle captionStyle) {
-            SpannableStringBuilder styledText = new SpannableStringBuilder(mDisplayChars);
-            int start = -1, next = 0;
-            int styleStart = -1;
-            StyleCode curStyle = null;
-            while (next < mDisplayChars.length()) {
-                StyleCode newStyle = null;
-                if (mMidRowStyles[next] != null) {
-                    // apply mid-row style change
-                    newStyle = mMidRowStyles[next];
-                } else if (mPACStyles[next] != null && (styleStart < 0 || start < 0)) {
-                    // apply PAC style change, only if:
-                    // 1. no style set, or
-                    // 2. style set, but prev char is none-displayable
-                    newStyle = mPACStyles[next];
-                }
-                if (newStyle != null) {
-                    curStyle = newStyle;
-                    if (styleStart >= 0 && start >= 0) {
-                        applyStyleSpan(styledText, newStyle, styleStart, next);
-                    }
-                    styleStart = next;
-                }
-
-                if (mDisplayChars.charAt(next) != TS) {
-                    if (start < 0) {
-                        start = next;
-                    }
-                } else if (start >= 0) {
-                    int expandedStart = mDisplayChars.charAt(start) == ' ' ? start : start - 1;
-                    int expandedEnd = mDisplayChars.charAt(next - 1) == ' ' ? next : next + 1;
-                    styledText.setSpan(
-                            new MutableBackgroundColorSpan(captionStyle.backgroundColor),
-                            expandedStart, expandedEnd,
-                            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-                    if (styleStart >= 0) {
-                        applyStyleSpan(styledText, curStyle, styleStart, expandedEnd);
-                    }
-                    start = -1;
-                }
-                next++;
-            }
-
-            return styledText;
-        }
-    }
-
-    /*
-     * CCMemory models a console-style display.
-     */
-    private static class CCMemory {
-        private final String mBlankLine;
-        private final CCLineBuilder[] mLines = new CCLineBuilder[MAX_ROWS + 2];
-        private int mRow;
-        private int mCol;
-
-        CCMemory() {
-            char[] blank = new char[MAX_COLS + 2];
-            Arrays.fill(blank, TS);
-            mBlankLine = new String(blank);
-        }
-
-        void erase() {
-            // erase all lines
-            for (int i = 0; i < mLines.length; i++) {
-                mLines[i] = null;
-            }
-            mRow = MAX_ROWS;
-            mCol = 1;
-        }
-
-        void der() {
-            if (mLines[mRow] != null) {
-                for (int i = 0; i < mCol; i++) {
-                    if (mLines[mRow].charAt(i) != TS) {
-                        for (int j = mCol; j < mLines[mRow].length(); j++) {
-                            mLines[j].setCharAt(j, TS);
-                        }
-                        return;
-                    }
-                }
-                mLines[mRow] = null;
-            }
-        }
-
-        void tab(int tabs) {
-            moveCursorByCol(tabs);
-        }
-
-        void bs() {
-            moveCursorByCol(-1);
-            if (mLines[mRow] != null) {
-                mLines[mRow].setCharAt(mCol, TS);
-                if (mCol == MAX_COLS - 1) {
-                    // Spec recommendation:
-                    // if cursor was at col 32, move cursor
-                    // back to col 31 and erase both col 31&32
-                    mLines[mRow].setCharAt(MAX_COLS, TS);
-                }
-            }
-        }
-
-        void cr() {
-            moveCursorTo(mRow + 1, 1);
-        }
-
-        void rollUp(int windowSize) {
-            int i;
-            for (i = 0; i <= mRow - windowSize; i++) {
-                mLines[i] = null;
-            }
-            int startRow = mRow - windowSize + 1;
-            if (startRow < 1) {
-                startRow = 1;
-            }
-            for (i = startRow; i < mRow; i++) {
-                mLines[i] = mLines[i + 1];
-            }
-            for (i = mRow; i < mLines.length; i++) {
-                // clear base row
-                mLines[i] = null;
-            }
-            // default to col 1, in case PAC is not sent
-            mCol = 1;
-        }
-
-        void writeText(String text) {
-            for (int i = 0; i < text.length(); i++) {
-                getLineBuffer(mRow).setCharAt(mCol, text.charAt(i));
-                moveCursorByCol(1);
-            }
-        }
-
-        void writeMidRowCode(StyleCode m) {
-            getLineBuffer(mRow).setMidRowAt(mCol, m);
-            moveCursorByCol(1);
-        }
-
-        void writePAC(PAC pac) {
-            if (pac.isIndentPAC()) {
-                moveCursorTo(pac.getRow(), pac.getCol());
-            } else {
-                moveCursorTo(pac.getRow(), 1);
-            }
-            getLineBuffer(mRow).setPACAt(mCol, pac);
-        }
-
-        SpannableStringBuilder[] getStyledText(CaptionStyle captionStyle) {
-            ArrayList<SpannableStringBuilder> rows = new ArrayList<>(MAX_ROWS);
-            for (int i = 1; i <= MAX_ROWS; i++) {
-                rows.add(mLines[i] != null ? mLines[i].getStyledText(captionStyle) : null);
-            }
-            return rows.toArray(new SpannableStringBuilder[MAX_ROWS]);
-        }
-
-        private static int clamp(int x, int min, int max) {
-            return x < min ? min : (x > max ? max : x);
-        }
-
-        private void moveCursorTo(int row, int col) {
-            mRow = clamp(row, 1, MAX_ROWS);
-            mCol = clamp(col, 1, MAX_COLS);
-        }
-
-        private void moveCursorToRow(int row) {
-            mRow = clamp(row, 1, MAX_ROWS);
-        }
-
-        private void moveCursorByCol(int col) {
-            mCol = clamp(mCol + col, 1, MAX_COLS);
-        }
-
-        private void moveBaselineTo(int baseRow, int windowSize) {
-            if (mRow == baseRow) {
-                return;
-            }
-            int actualWindowSize = windowSize;
-            if (baseRow < actualWindowSize) {
-                actualWindowSize = baseRow;
-            }
-            if (mRow < actualWindowSize) {
-                actualWindowSize = mRow;
-            }
-
-            int i;
-            if (baseRow < mRow) {
-                // copy from bottom to top row
-                for (i = actualWindowSize - 1; i >= 0; i--) {
-                    mLines[baseRow - i] = mLines[mRow - i];
-                }
-            } else {
-                // copy from top to bottom row
-                for (i = 0; i < actualWindowSize; i++) {
-                    mLines[baseRow - i] = mLines[mRow - i];
-                }
-            }
-            // clear rest of the rows
-            for (i = 0; i <= baseRow - windowSize; i++) {
-                mLines[i] = null;
-            }
-            for (i = baseRow + 1; i < mLines.length; i++) {
-                mLines[i] = null;
-            }
-        }
-
-        private CCLineBuilder getLineBuffer(int row) {
-            if (mLines[row] == null) {
-                mLines[row] = new CCLineBuilder(mBlankLine);
-            }
-            return mLines[row];
-        }
-    }
-
-    /*
-     * CCData parses the raw CC byte pair into displayable chars,
-     * misc control codes, Mid-Row or Preamble Address Codes.
-     */
-    private static class CCData {
-        private final byte mType;
-        private final byte mData1;
-        private final byte mData2;
-
-        private static final String[] sCtrlCodeMap = {
-            "RCL", "BS" , "AOF", "AON",
-            "DER", "RU2", "RU3", "RU4",
-            "FON", "RDC", "TR" , "RTD",
-            "EDM", "CR" , "ENM", "EOC",
-        };
-
-        private static final String[] sSpecialCharMap = {
-            "\u00AE",
-            "\u00B0",
-            "\u00BD",
-            "\u00BF",
-            "\u2122",
-            "\u00A2",
-            "\u00A3",
-            "\u266A", // Eighth note
-            "\u00E0",
-            "\u00A0", // Transparent space
-            "\u00E8",
-            "\u00E2",
-            "\u00EA",
-            "\u00EE",
-            "\u00F4",
-            "\u00FB",
-        };
-
-        private static final String[] sSpanishCharMap = {
-            // Spanish and misc chars
-            "\u00C1", // A
-            "\u00C9", // E
-            "\u00D3", // I
-            "\u00DA", // O
-            "\u00DC", // U
-            "\u00FC", // u
-            "\u2018", // opening single quote
-            "\u00A1", // inverted exclamation mark
-            "*",
-            "'",
-            "\u2014", // em dash
-            "\u00A9", // Copyright
-            "\u2120", // Servicemark
-            "\u2022", // round bullet
-            "\u201C", // opening double quote
-            "\u201D", // closing double quote
-            // French
-            "\u00C0",
-            "\u00C2",
-            "\u00C7",
-            "\u00C8",
-            "\u00CA",
-            "\u00CB",
-            "\u00EB",
-            "\u00CE",
-            "\u00CF",
-            "\u00EF",
-            "\u00D4",
-            "\u00D9",
-            "\u00F9",
-            "\u00DB",
-            "\u00AB",
-            "\u00BB"
-        };
-
-        private static final String[] sProtugueseCharMap = {
-            // Portuguese
-            "\u00C3",
-            "\u00E3",
-            "\u00CD",
-            "\u00CC",
-            "\u00EC",
-            "\u00D2",
-            "\u00F2",
-            "\u00D5",
-            "\u00F5",
-            "{",
-            "}",
-            "\\",
-            "^",
-            "_",
-            "|",
-            "~",
-            // German and misc chars
-            "\u00C4",
-            "\u00E4",
-            "\u00D6",
-            "\u00F6",
-            "\u00DF",
-            "\u00A5",
-            "\u00A4",
-            "\u2502", // vertical bar
-            "\u00C5",
-            "\u00E5",
-            "\u00D8",
-            "\u00F8",
-            "\u250C", // top-left corner
-            "\u2510", // top-right corner
-            "\u2514", // lower-left corner
-            "\u2518", // lower-right corner
-        };
-
-        static CCData[] fromByteArray(byte[] data) {
-            CCData[] ccData = new CCData[data.length / 3];
-
-            for (int i = 0; i < ccData.length; i++) {
-                ccData[i] = new CCData(
-                        data[i * 3],
-                        data[i * 3 + 1],
-                        data[i * 3 + 2]);
-            }
-
-            return ccData;
-        }
-
-        CCData(byte type, byte data1, byte data2) {
-            mType = type;
-            mData1 = data1;
-            mData2 = data2;
-        }
-
-        int getCtrlCode() {
-            if ((mData1 == 0x14 || mData1 == 0x1c)
-                    && mData2 >= 0x20 && mData2 <= 0x2f) {
-                return mData2;
-            }
-            return INVALID;
-        }
-
-        StyleCode getMidRow() {
-            // only support standard Mid-row codes, ignore
-            // optional background/foreground mid-row codes
-            if ((mData1 == 0x11 || mData1 == 0x19)
-                    && mData2 >= 0x20 && mData2 <= 0x2f) {
-                return StyleCode.fromByte(mData2);
-            }
-            return null;
-        }
-
-        PAC getPAC() {
-            if ((mData1 & 0x70) == 0x10
-                    && (mData2 & 0x40) == 0x40
-                    && ((mData1 & 0x07) != 0 || (mData2 & 0x20) == 0)) {
-                return PAC.fromBytes(mData1, mData2);
-            }
-            return null;
-        }
-
-        int getTabOffset() {
-            if ((mData1 == 0x17 || mData1 == 0x1f)
-                    && mData2 >= 0x21 && mData2 <= 0x23) {
-                return mData2 & 0x3;
-            }
-            return 0;
-        }
-
-        boolean isDisplayableChar() {
-            return isBasicChar() || isSpecialChar() || isExtendedChar();
-        }
-
-        String getDisplayText() {
-            String str = getBasicChars();
-
-            if (str == null) {
-                str =  getSpecialChar();
-
-                if (str == null) {
-                    str = getExtendedChar();
-                }
-            }
-
-            return str;
-        }
-
-        private String ctrlCodeToString(int ctrlCode) {
-            return sCtrlCodeMap[ctrlCode - 0x20];
-        }
-
-        private boolean isBasicChar() {
-            return mData1 >= 0x20 && mData1 <= 0x7f;
-        }
-
-        private boolean isSpecialChar() {
-            return ((mData1 == 0x11 || mData1 == 0x19)
-                    && mData2 >= 0x30 && mData2 <= 0x3f);
-        }
-
-        private boolean isExtendedChar() {
-            return ((mData1 == 0x12 || mData1 == 0x1A
-                    || mData1 == 0x13 || mData1 == 0x1B)
-                    && mData2 >= 0x20 && mData2 <= 0x3f);
-        }
-
-        private char getBasicChar(byte data) {
-            char c;
-            // replace the non-ASCII ones
-            switch (data) {
-                case 0x2A: c = '\u00E1'; break;
-                case 0x5C: c = '\u00E9'; break;
-                case 0x5E: c = '\u00ED'; break;
-                case 0x5F: c = '\u00F3'; break;
-                case 0x60: c = '\u00FA'; break;
-                case 0x7B: c = '\u00E7'; break;
-                case 0x7C: c = '\u00F7'; break;
-                case 0x7D: c = '\u00D1'; break;
-                case 0x7E: c = '\u00F1'; break;
-                case 0x7F: c = '\u2588'; break; // Full block
-                default: c = (char) data; break;
-            }
-            return c;
-        }
-
-        private String getBasicChars() {
-            if (mData1 >= 0x20 && mData1 <= 0x7f) {
-                StringBuilder builder = new StringBuilder(2);
-                builder.append(getBasicChar(mData1));
-                if (mData2 >= 0x20 && mData2 <= 0x7f) {
-                    builder.append(getBasicChar(mData2));
-                }
-                return builder.toString();
-            }
-
-            return null;
-        }
-
-        private String getSpecialChar() {
-            if ((mData1 == 0x11 || mData1 == 0x19)
-                    && mData2 >= 0x30 && mData2 <= 0x3f) {
-                return sSpecialCharMap[mData2 - 0x30];
-            }
-
-            return null;
-        }
-
-        private String getExtendedChar() {
-            if ((mData1 == 0x12 || mData1 == 0x1A) && mData2 >= 0x20 && mData2 <= 0x3f) {
-                // 1 Spanish/French char
-                return sSpanishCharMap[mData2 - 0x20];
-            } else if ((mData1 == 0x13 || mData1 == 0x1B) && mData2 >= 0x20 && mData2 <= 0x3f) {
-                // 1 Portuguese/German/Danish char
-                return sProtugueseCharMap[mData2 - 0x20];
-            }
-
-            return null;
-        }
-
-        @Override
-        public String toString() {
-            String str;
-
-            if (mData1 < 0x10 && mData2 < 0x10) {
-                // Null Pad, ignore
-                return String.format("[%d]Null: %02x %02x", mType, mData1, mData2);
-            }
-
-            int ctrlCode = getCtrlCode();
-            if (ctrlCode != INVALID) {
-                return String.format("[%d]%s", mType, ctrlCodeToString(ctrlCode));
-            }
-
-            int tabOffset = getTabOffset();
-            if (tabOffset > 0) {
-                return String.format("[%d]Tab%d", mType, tabOffset);
-            }
-
-            PAC pac = getPAC();
-            if (pac != null) {
-                return String.format("[%d]PAC: %s", mType, pac.toString());
-            }
-
-            StyleCode m = getMidRow();
-            if (m != null) {
-                return String.format("[%d]Mid-row: %s", mType, m.toString());
-            }
-
-            if (isDisplayableChar()) {
-                return String.format("[%d]Displayable: %s (%02x %02x)",
-                        mType, getDisplayText(), mData1, mData2);
-            }
-
-            return String.format("[%d]Invalid: %02x %02x", mType, mData1, mData2);
-        }
-    }
-}
diff --git a/media/src/main/java/androidx/media/subtitle/ClosedCaptionRenderer.java b/media/src/main/java/androidx/media/subtitle/ClosedCaptionRenderer.java
deleted file mode 100644
index 90ff516f..0000000
--- a/media/src/main/java/androidx/media/subtitle/ClosedCaptionRenderer.java
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.subtitle;
-
-import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import android.media.MediaFormat;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.TextPaint;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.View;
-import android.view.accessibility.CaptioningManager.CaptionStyle;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
-import androidx.media.R;
-
-import java.util.ArrayList;
-
-// Note: This is forked from android.media.ClosedCaptionRenderer since P
-/**
- * @hide
- */
-@RequiresApi(28)
-@RestrictTo(LIBRARY_GROUP)
-public class ClosedCaptionRenderer extends SubtitleController.Renderer {
-    private final Context mContext;
-    private Cea608CCWidget mCCWidget;
-
-    public ClosedCaptionRenderer(Context context) {
-        mContext = context;
-    }
-
-    @Override
-    public boolean supports(MediaFormat format) {
-        if (format.containsKey(MediaFormat.KEY_MIME)) {
-            String mimeType = format.getString(MediaFormat.KEY_MIME);
-            return MediaFormat.MIMETYPE_TEXT_CEA_608.equals(mimeType);
-        }
-        return false;
-    }
-
-    @Override
-    public SubtitleTrack createTrack(MediaFormat format) {
-        String mimeType = format.getString(MediaFormat.KEY_MIME);
-        if (MediaFormat.MIMETYPE_TEXT_CEA_608.equals(mimeType)) {
-            if (mCCWidget == null) {
-                mCCWidget = new Cea608CCWidget(mContext);
-            }
-            return new Cea608CaptionTrack(mCCWidget, format);
-        }
-        throw new RuntimeException("No matching format: " + format.toString());
-    }
-
-    static class Cea608CaptionTrack extends SubtitleTrack {
-        private final Cea608CCParser mCCParser;
-        private final Cea608CCWidget mRenderingWidget;
-
-        Cea608CaptionTrack(Cea608CCWidget renderingWidget, MediaFormat format) {
-            super(format);
-
-            mRenderingWidget = renderingWidget;
-            mCCParser = new Cea608CCParser(mRenderingWidget);
-        }
-
-        @Override
-        public void onData(byte[] data, boolean eos, long runID) {
-            mCCParser.parse(data);
-        }
-
-        @Override
-        public RenderingWidget getRenderingWidget() {
-            return mRenderingWidget;
-        }
-
-        @Override
-        public void updateView(ArrayList<Cue> activeCues) {
-            // Overriding with NO-OP, CC rendering by-passes this
-        }
-    }
-
-    /**
-     * Widget capable of rendering CEA-608 closed captions.
-     */
-    class Cea608CCWidget extends ClosedCaptionWidget implements Cea608CCParser.DisplayListener {
-        private static final String DUMMY_TEXT = "1234567890123456789012345678901234";
-        private final Rect mTextBounds = new Rect();
-
-        Cea608CCWidget(Context context) {
-            this(context, null);
-        }
-
-        Cea608CCWidget(Context context, AttributeSet attrs) {
-            this(context, attrs, 0);
-        }
-
-        Cea608CCWidget(Context context, AttributeSet attrs, int defStyle) {
-            this(context, attrs, defStyle, 0);
-        }
-
-        Cea608CCWidget(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-            super(context, attrs, defStyleAttr, defStyleRes);
-        }
-
-        @Override
-        public ClosedCaptionLayout createCaptionLayout(Context context) {
-            return new CCLayout(context);
-        }
-
-        @Override
-        public void onDisplayChanged(SpannableStringBuilder[] styledTexts) {
-            ((CCLayout) mClosedCaptionLayout).update(styledTexts);
-
-            if (mListener != null) {
-                mListener.onChanged(this);
-            }
-        }
-
-        @Override
-        public CaptionStyle getCaptionStyle() {
-            return mCaptionStyle;
-        }
-
-        private class CCLineBox extends TextView {
-            private static final float FONT_PADDING_RATIO = 0.75f;
-            private static final float EDGE_OUTLINE_RATIO = 0.1f;
-            private static final float EDGE_SHADOW_RATIO = 0.05f;
-            private float mOutlineWidth;
-            private float mShadowRadius;
-            private float mShadowOffset;
-
-            private int mTextColor = Color.WHITE;
-            private int mBgColor = Color.BLACK;
-            private int mEdgeType = CaptionStyle.EDGE_TYPE_NONE;
-            private int mEdgeColor = Color.TRANSPARENT;
-
-            CCLineBox(Context context) {
-                super(context);
-                setGravity(Gravity.CENTER);
-                setBackgroundColor(Color.TRANSPARENT);
-                setTextColor(Color.WHITE);
-                setTypeface(Typeface.MONOSPACE);
-                setVisibility(View.INVISIBLE);
-
-                final Resources res = getContext().getResources();
-
-                // get the default (will be updated later during measure)
-                mOutlineWidth = res.getDimensionPixelSize(
-                        R.dimen.subtitle_outline_width);
-                mShadowRadius = res.getDimensionPixelSize(
-                        R.dimen.subtitle_shadow_radius);
-                mShadowOffset = res.getDimensionPixelSize(
-                        R.dimen.subtitle_shadow_offset);
-            }
-
-            void setCaptionStyle(CaptionStyle captionStyle) {
-                mTextColor = captionStyle.foregroundColor;
-                mBgColor = captionStyle.backgroundColor;
-                mEdgeType = captionStyle.edgeType;
-                mEdgeColor = captionStyle.edgeColor;
-
-                setTextColor(mTextColor);
-                if (mEdgeType == CaptionStyle.EDGE_TYPE_DROP_SHADOW) {
-                    setShadowLayer(mShadowRadius, mShadowOffset, mShadowOffset, mEdgeColor);
-                } else {
-                    setShadowLayer(0, 0, 0, 0);
-                }
-                invalidate();
-            }
-
-            @Override
-            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-                float fontSize = MeasureSpec.getSize(heightMeasureSpec) * FONT_PADDING_RATIO;
-                setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
-
-                mOutlineWidth = EDGE_OUTLINE_RATIO * fontSize + 1.0f;
-                mShadowRadius = EDGE_SHADOW_RATIO * fontSize + 1.0f;
-                mShadowOffset = mShadowRadius;
-
-                // set font scale in the X direction to match the required width
-                setScaleX(1.0f);
-                getPaint().getTextBounds(DUMMY_TEXT, 0, DUMMY_TEXT.length(), mTextBounds);
-                float actualTextWidth = mTextBounds.width();
-                float requiredTextWidth = MeasureSpec.getSize(widthMeasureSpec);
-                setScaleX(requiredTextWidth / actualTextWidth);
-
-                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-            }
-
-            @Override
-            protected void onDraw(Canvas c) {
-                if (mEdgeType == CaptionStyle.EDGE_TYPE_UNSPECIFIED
-                        || mEdgeType == CaptionStyle.EDGE_TYPE_NONE
-                        || mEdgeType == CaptionStyle.EDGE_TYPE_DROP_SHADOW) {
-                    // these edge styles don't require a second pass
-                    super.onDraw(c);
-                    return;
-                }
-
-                if (mEdgeType == CaptionStyle.EDGE_TYPE_OUTLINE) {
-                    drawEdgeOutline(c);
-                } else {
-                    // Raised or depressed
-                    drawEdgeRaisedOrDepressed(c);
-                }
-            }
-
-            @SuppressWarnings("WrongCall")
-            private void drawEdgeOutline(Canvas c) {
-                TextPaint textPaint = getPaint();
-
-                Paint.Style previousStyle = textPaint.getStyle();
-                Paint.Join previousJoin = textPaint.getStrokeJoin();
-                float previousWidth = textPaint.getStrokeWidth();
-
-                setTextColor(mEdgeColor);
-                textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
-                textPaint.setStrokeJoin(Paint.Join.ROUND);
-                textPaint.setStrokeWidth(mOutlineWidth);
-
-                // Draw outline and background only.
-                super.onDraw(c);
-
-                // Restore original settings.
-                setTextColor(mTextColor);
-                textPaint.setStyle(previousStyle);
-                textPaint.setStrokeJoin(previousJoin);
-                textPaint.setStrokeWidth(previousWidth);
-
-                // Remove the background.
-                setBackgroundSpans(Color.TRANSPARENT);
-                // Draw foreground only.
-                super.onDraw(c);
-                // Restore the background.
-                setBackgroundSpans(mBgColor);
-            }
-
-            @SuppressWarnings("WrongCall")
-            private void drawEdgeRaisedOrDepressed(Canvas c) {
-                TextPaint textPaint = getPaint();
-
-                Paint.Style previousStyle = textPaint.getStyle();
-                textPaint.setStyle(Paint.Style.FILL);
-
-                final boolean raised = mEdgeType == CaptionStyle.EDGE_TYPE_RAISED;
-                final int colorUp = raised ? Color.WHITE : mEdgeColor;
-                final int colorDown = raised ? mEdgeColor : Color.WHITE;
-                final float offset = mShadowRadius / 2f;
-
-                // Draw background and text with shadow up
-                setShadowLayer(mShadowRadius, -offset, -offset, colorUp);
-                super.onDraw(c);
-
-                // Remove the background.
-                setBackgroundSpans(Color.TRANSPARENT);
-
-                // Draw text with shadow down
-                setShadowLayer(mShadowRadius, +offset, +offset, colorDown);
-                super.onDraw(c);
-
-                // Restore settings
-                textPaint.setStyle(previousStyle);
-
-                // Restore the background.
-                setBackgroundSpans(mBgColor);
-            }
-
-            private void setBackgroundSpans(int color) {
-                CharSequence text = getText();
-                if (text instanceof Spannable) {
-                    Spannable spannable = (Spannable) text;
-                    Cea608CCParser.MutableBackgroundColorSpan[] bgSpans = spannable.getSpans(
-                            0, spannable.length(), Cea608CCParser.MutableBackgroundColorSpan.class);
-                    for (int i = 0; i < bgSpans.length; i++) {
-                        bgSpans[i].setBackgroundColor(color);
-                    }
-                }
-            }
-        }
-
-        private class CCLayout extends LinearLayout implements ClosedCaptionLayout {
-            private static final int MAX_ROWS = Cea608CCParser.MAX_ROWS;
-            private static final float SAFE_AREA_RATIO = 0.9f;
-
-            private final CCLineBox[] mLineBoxes = new CCLineBox[MAX_ROWS];
-
-            CCLayout(Context context) {
-                super(context);
-                setGravity(Gravity.START);
-                setOrientation(LinearLayout.VERTICAL);
-                for (int i = 0; i < MAX_ROWS; i++) {
-                    mLineBoxes[i] = new CCLineBox(getContext());
-                    addView(mLineBoxes[i], LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-                }
-            }
-
-            @Override
-            public void setCaptionStyle(CaptionStyle captionStyle) {
-                for (int i = 0; i < MAX_ROWS; i++) {
-                    mLineBoxes[i].setCaptionStyle(captionStyle);
-                }
-            }
-
-            @Override
-            public void setFontScale(float fontScale) {
-                // Ignores the font scale changes of the system wide CC preference.
-            }
-
-            void update(SpannableStringBuilder[] textBuffer) {
-                for (int i = 0; i < MAX_ROWS; i++) {
-                    if (textBuffer[i] != null) {
-                        mLineBoxes[i].setText(textBuffer[i], TextView.BufferType.SPANNABLE);
-                        mLineBoxes[i].setVisibility(View.VISIBLE);
-                    } else {
-                        mLineBoxes[i].setVisibility(View.INVISIBLE);
-                    }
-                }
-            }
-
-            @Override
-            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
-                int safeWidth = getMeasuredWidth();
-                int safeHeight = getMeasuredHeight();
-
-                // CEA-608 assumes 4:3 video
-                if (safeWidth * 3 >= safeHeight * 4) {
-                    safeWidth = safeHeight * 4 / 3;
-                } else {
-                    safeHeight = safeWidth * 3 / 4;
-                }
-                safeWidth = (int) (safeWidth * SAFE_AREA_RATIO);
-                safeHeight = (int) (safeHeight * SAFE_AREA_RATIO);
-
-                int lineHeight = safeHeight / MAX_ROWS;
-                int lineHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
-                        lineHeight, MeasureSpec.EXACTLY);
-                int lineWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
-                        safeWidth, MeasureSpec.EXACTLY);
-
-                for (int i = 0; i < MAX_ROWS; i++) {
-                    mLineBoxes[i].measure(lineWidthMeasureSpec, lineHeightMeasureSpec);
-                }
-            }
-
-            @Override
-            protected void onLayout(boolean changed, int l, int t, int r, int b) {
-                // safe caption area
-                int viewPortWidth = r - l;
-                int viewPortHeight = b - t;
-                int safeWidth, safeHeight;
-                // CEA-608 assumes 4:3 video
-                if (viewPortWidth * 3 >= viewPortHeight * 4) {
-                    safeWidth = viewPortHeight * 4 / 3;
-                    safeHeight = viewPortHeight;
-                } else {
-                    safeWidth = viewPortWidth;
-                    safeHeight = viewPortWidth * 3 / 4;
-                }
-                safeWidth = (int) (safeWidth * SAFE_AREA_RATIO);
-                safeHeight = (int) (safeHeight * SAFE_AREA_RATIO);
-                int left = (viewPortWidth - safeWidth) / 2;
-                int top = (viewPortHeight - safeHeight) / 2;
-
-                for (int i = 0; i < MAX_ROWS; i++) {
-                    mLineBoxes[i].layout(
-                            left,
-                            top + safeHeight * i / MAX_ROWS,
-                            left + safeWidth,
-                            top + safeHeight * (i + 1) / MAX_ROWS);
-                }
-            }
-        }
-    }
-}
diff --git a/media/src/main/java/androidx/media/subtitle/ClosedCaptionWidget.java b/media/src/main/java/androidx/media/subtitle/ClosedCaptionWidget.java
deleted file mode 100644
index a3d3e47..0000000
--- a/media/src/main/java/androidx/media/subtitle/ClosedCaptionWidget.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.subtitle;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.accessibility.CaptioningManager;
-import android.view.accessibility.CaptioningManager.CaptionStyle;
-import android.view.accessibility.CaptioningManager.CaptioningChangeListener;
-
-import androidx.annotation.RequiresApi;
-
-/**
- * Abstract widget class to render a closed caption track.
- */
-@RequiresApi(28)
-abstract class ClosedCaptionWidget extends ViewGroup implements SubtitleTrack.RenderingWidget {
-
-    interface ClosedCaptionLayout {
-        void setCaptionStyle(CaptionStyle captionStyle);
-        void setFontScale(float scale);
-    }
-
-    /** Captioning manager, used to obtain and track caption properties. */
-    private final CaptioningManager mManager;
-
-    /** Current caption style. */
-    protected CaptionStyle mCaptionStyle;
-
-    /** Callback for rendering changes. */
-    protected OnChangedListener mListener;
-
-    /** Concrete layout of CC. */
-    protected ClosedCaptionLayout mClosedCaptionLayout;
-
-    /** Whether a caption style change listener is registered. */
-    private boolean mHasChangeListener;
-
-    ClosedCaptionWidget(Context context) {
-        this(context, null);
-    }
-
-    ClosedCaptionWidget(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    ClosedCaptionWidget(Context context, AttributeSet attrs, int defStyle) {
-        this(context, attrs, defStyle, 0);
-    }
-
-    ClosedCaptionWidget(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-
-        // Cannot render text over video when layer type is hardware.
-        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
-
-        mManager = (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);
-        mCaptionStyle = mManager.getUserStyle();
-
-        mClosedCaptionLayout = createCaptionLayout(context);
-        mClosedCaptionLayout.setCaptionStyle(mCaptionStyle);
-        mClosedCaptionLayout.setFontScale(mManager.getFontScale());
-        addView((ViewGroup) mClosedCaptionLayout, LayoutParams.MATCH_PARENT,
-                LayoutParams.MATCH_PARENT);
-
-        requestLayout();
-    }
-
-    public abstract ClosedCaptionLayout createCaptionLayout(Context context);
-
-    @Override
-    public void setOnChangedListener(OnChangedListener listener) {
-        mListener = listener;
-    }
-
-    @Override
-    public void setSize(int width, int height) {
-        final int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
-        final int heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
-
-        measure(widthSpec, heightSpec);
-        layout(0, 0, width, height);
-    }
-
-    @Override
-    public void setVisible(boolean visible) {
-        if (visible) {
-            setVisibility(View.VISIBLE);
-        } else {
-            setVisibility(View.GONE);
-        }
-
-        manageChangeListener();
-    }
-
-    @Override
-    public void onAttachedToWindow() {
-        super.onAttachedToWindow();
-
-        manageChangeListener();
-    }
-
-    @Override
-    public void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-
-        manageChangeListener();
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        ((ViewGroup) mClosedCaptionLayout).measure(widthMeasureSpec, heightMeasureSpec);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        ((ViewGroup) mClosedCaptionLayout).layout(l, t, r, b);
-    }
-
-    /**
-     * Manages whether this renderer is listening for caption style changes.
-     */
-    private final CaptioningChangeListener mCaptioningListener = new CaptioningChangeListener() {
-        @Override
-        public void onUserStyleChanged(CaptionStyle userStyle) {
-            mCaptionStyle = userStyle;
-            mClosedCaptionLayout.setCaptionStyle(mCaptionStyle);
-        }
-
-        @Override
-        public void onFontScaleChanged(float fontScale) {
-            mClosedCaptionLayout.setFontScale(fontScale);
-        }
-    };
-
-    private void manageChangeListener() {
-        final boolean needsListener = isAttachedToWindow() && getVisibility() == View.VISIBLE;
-        if (mHasChangeListener != needsListener) {
-            mHasChangeListener = needsListener;
-
-            if (needsListener) {
-                mManager.addCaptioningChangeListener(mCaptioningListener);
-            } else {
-                mManager.removeCaptioningChangeListener(mCaptioningListener);
-            }
-        }
-    }
-}
-
diff --git a/media/src/main/java/androidx/media/subtitle/MediaTimeProvider.java b/media/src/main/java/androidx/media/subtitle/MediaTimeProvider.java
deleted file mode 100644
index b6f0a14..0000000
--- a/media/src/main/java/androidx/media/subtitle/MediaTimeProvider.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.subtitle;
-
-import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import androidx.annotation.RestrictTo;
-
-// Note: This is just copied from android.media.MediaTimeProvider.
-/**
- * @hide
- */
-@RestrictTo(LIBRARY_GROUP)
-public interface MediaTimeProvider {
-    // we do not allow negative media time
-    /**
-     * Presentation time value if no timed event notification is requested.
-     */
-    long NO_TIME = -1;
-
-    /**
-     * Cancels all previous notification request from this listener if any.  It
-     * registers the listener to get seek and stop notifications.  If timeUs is
-     * not negative, it also registers the listener for a timed event
-     * notification when the presentation time reaches (becomes greater) than
-     * the value specified.  This happens immediately if the current media time
-     * is larger than or equal to timeUs.
-     *
-     * @param timeUs presentation time to get timed event callback at (or
-     *               {@link #NO_TIME})
-     */
-    void notifyAt(long timeUs, OnMediaTimeListener listener);
-
-    /**
-     * Cancels all previous notification request from this listener if any.  It
-     * registers the listener to get seek and stop notifications.  If the media
-     * is stopped, the listener will immediately receive a stop notification.
-     * Otherwise, it will receive a timed event notificaton.
-     */
-    void scheduleUpdate(OnMediaTimeListener listener);
-
-    /**
-     * Cancels all previous notification request from this listener if any.
-     */
-    void cancelNotifications(OnMediaTimeListener listener);
-
-    /**
-     * Get the current presentation time.
-     *
-     * @param precise   Whether getting a precise time is important. This is
-     *                  more costly.
-     * @param monotonic Whether returned time should be monotonic: that is,
-     *                  greater than or equal to the last returned time.  Don't
-     *                  always set this to true.  E.g. this has undesired
-     *                  consequences if the media is seeked between calls.
-     * @throws IllegalStateException if the media is not initialized
-     */
-    long getCurrentTimeUs(boolean precise, boolean monotonic)
-            throws IllegalStateException;
-
-    /**
-     * Mediatime listener
-     */
-    public interface OnMediaTimeListener {
-        /**
-         * Called when the registered time was reached naturally.
-         *
-         * @param timeUs current media time
-         */
-        void onTimedEvent(long timeUs);
-
-        /**
-         * Called when the media time changed due to seeking.
-         *
-         * @param timeUs current media time
-         */
-        void onSeek(long timeUs);
-
-        /**
-         * Called when the playback stopped.  This is not called on pause, only
-         * on full stop, at which point there is no further current media time.
-         */
-        void onStop();
-    }
-}
-
diff --git a/media/src/main/java/androidx/media/subtitle/SubtitleController.java b/media/src/main/java/androidx/media/subtitle/SubtitleController.java
deleted file mode 100644
index b6dfc2b..0000000
--- a/media/src/main/java/androidx/media/subtitle/SubtitleController.java
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.subtitle;
-
-import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.content.Context;
-import android.media.MediaFormat;
-import android.media.MediaPlayer;
-import android.media.MediaPlayer.TrackInfo;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.view.accessibility.CaptioningManager;
-
-import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
-import androidx.media.subtitle.SubtitleTrack.RenderingWidget;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-// Note: This is forked from android.media.SubtitleController since P
-/**
- * The subtitle controller provides the architecture to display subtitles for a
- * media source.  It allows specifying which tracks to display, on which anchor
- * to display them, and also allows adding external, out-of-band subtitle tracks.
- *
- * @hide
- */
-@RequiresApi(28)
-@RestrictTo(LIBRARY_GROUP)
-public class SubtitleController {
-    private MediaTimeProvider mTimeProvider;
-    private ArrayList<Renderer> mRenderers;
-    private ArrayList<SubtitleTrack> mTracks;
-    private final Object mRenderersLock = new Object();
-    private final Object mTracksLock = new Object();
-    private SubtitleTrack mSelectedTrack;
-    private boolean mShowing;
-    private CaptioningManager mCaptioningManager;
-    private Handler mHandler;
-
-    private static final int WHAT_SHOW = 1;
-    private static final int WHAT_HIDE = 2;
-    private static final int WHAT_SELECT_TRACK = 3;
-    private static final int WHAT_SELECT_DEFAULT_TRACK = 4;
-
-    private final Handler.Callback mCallback = new Handler.Callback() {
-        @Override
-        public boolean handleMessage(Message msg) {
-            switch (msg.what) {
-                case WHAT_SHOW:
-                    doShow();
-                    return true;
-                case WHAT_HIDE:
-                    doHide();
-                    return true;
-                case WHAT_SELECT_TRACK:
-                    doSelectTrack((SubtitleTrack) msg.obj);
-                    return true;
-                case WHAT_SELECT_DEFAULT_TRACK:
-                    doSelectDefaultTrack();
-                    return true;
-                default:
-                    return false;
-            }
-        }
-    };
-
-    private CaptioningManager.CaptioningChangeListener mCaptioningChangeListener =
-            new CaptioningManager.CaptioningChangeListener() {
-                @Override
-                public void onEnabledChanged(boolean enabled) {
-                    selectDefaultTrack();
-                }
-
-                @Override
-                public void onLocaleChanged(Locale locale) {
-                    selectDefaultTrack();
-                }
-            };
-
-    public SubtitleController(Context context) {
-        this(context, null, null);
-    }
-
-    /**
-     * Creates a subtitle controller for a media playback object that implements
-     * the MediaTimeProvider interface.
-     *
-     * @param timeProvider
-     */
-    public SubtitleController(
-            Context context,
-            MediaTimeProvider timeProvider,
-            Listener listener) {
-        mTimeProvider = timeProvider;
-        mListener = listener;
-
-        mRenderers = new ArrayList<Renderer>();
-        mShowing = false;
-        mTracks = new ArrayList<SubtitleTrack>();
-        mCaptioningManager =
-            (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        mCaptioningManager.removeCaptioningChangeListener(
-                mCaptioningChangeListener);
-        super.finalize();
-    }
-
-    /**
-     * @return the available subtitle tracks for this media. These include
-     * the tracks found by {@link MediaPlayer} as well as any tracks added
-     * manually via {@link #addTrack}.
-     */
-    public SubtitleTrack[] getTracks() {
-        synchronized (mTracksLock) {
-            SubtitleTrack[] tracks = new SubtitleTrack[mTracks.size()];
-            mTracks.toArray(tracks);
-            return tracks;
-        }
-    }
-
-    /**
-     * @return the currently selected subtitle track
-     */
-    public SubtitleTrack getSelectedTrack() {
-        return mSelectedTrack;
-    }
-
-    private RenderingWidget getRenderingWidget() {
-        if (mSelectedTrack == null) {
-            return null;
-        }
-        return mSelectedTrack.getRenderingWidget();
-    }
-
-    /**
-     * Selects a subtitle track.  As a result, this track will receive
-     * in-band data from the {@link MediaPlayer}.  However, this does
-     * not change the subtitle visibility.
-     *
-     * Should be called from the anchor's (UI) thread. {@see #Anchor.getSubtitleLooper}
-     *
-     * @param track The subtitle track to select.  This must be one of the
-     *              tracks in {@link #getTracks}.
-     * @return true if the track was successfully selected.
-     */
-    public boolean selectTrack(SubtitleTrack track) {
-        if (track != null && !mTracks.contains(track)) {
-            return false;
-        }
-
-        processOnAnchor(mHandler.obtainMessage(WHAT_SELECT_TRACK, track));
-        return true;
-    }
-
-    private void doSelectTrack(SubtitleTrack track) {
-        mTrackIsExplicit = true;
-        if (mSelectedTrack == track) {
-            return;
-        }
-
-        if (mSelectedTrack != null) {
-            mSelectedTrack.hide();
-            mSelectedTrack.setTimeProvider(null);
-        }
-
-        mSelectedTrack = track;
-        if (mAnchor != null) {
-            mAnchor.setSubtitleWidget(getRenderingWidget());
-        }
-
-        if (mSelectedTrack != null) {
-            mSelectedTrack.setTimeProvider(mTimeProvider);
-            mSelectedTrack.show();
-        }
-
-        if (mListener != null) {
-            mListener.onSubtitleTrackSelected(track);
-        }
-    }
-
-    /**
-     * @return the default subtitle track based on system preferences, or null,
-     * if no such track exists in this manager.
-     *
-     * Supports HLS-flags: AUTOSELECT, FORCED & DEFAULT.
-     *
-     * 1. If captioning is disabled, only consider FORCED tracks. Otherwise,
-     * consider all tracks, but prefer non-FORCED ones.
-     * 2. If user selected "Default" caption language:
-     *   a. If there is a considered track with DEFAULT=yes, returns that track
-     *      (favor the first one in the current language if there are more than
-     *      one default tracks, or the first in general if none of them are in
-     *      the current language).
-     *   b. Otherwise, if there is a track with AUTOSELECT=yes in the current
-     *      language, return that one.
-     *   c. If there are no default tracks, and no autoselectable tracks in the
-     *      current language, return null.
-     * 3. If there is a track with the caption language, select that one.  Prefer
-     * the one with AUTOSELECT=no.
-     *
-     * The default values for these flags are DEFAULT=no, AUTOSELECT=yes
-     * and FORCED=no.
-     */
-    public SubtitleTrack getDefaultTrack() {
-        SubtitleTrack bestTrack = null;
-        int bestScore = -1;
-
-        Locale selectedLocale = mCaptioningManager.getLocale();
-        Locale locale = selectedLocale;
-        if (locale == null) {
-            locale = Locale.getDefault();
-        }
-        boolean selectForced = !mCaptioningManager.isEnabled();
-
-        synchronized (mTracksLock) {
-            for (SubtitleTrack track: mTracks) {
-                MediaFormat format = track.getFormat();
-                String language = format.getString(MediaFormat.KEY_LANGUAGE);
-                boolean forced = MediaFormatUtil
-                        .getInteger(format, MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0;
-                boolean autoselect = MediaFormatUtil
-                        .getInteger(format, MediaFormat.KEY_IS_AUTOSELECT, 1) != 0;
-                boolean is_default = MediaFormatUtil
-                        .getInteger(format, MediaFormat.KEY_IS_DEFAULT, 0) != 0;
-
-                boolean languageMatches = locale == null
-                        || locale.getLanguage().equals("")
-                        || locale.getISO3Language().equals(language)
-                        || locale.getLanguage().equals(language);
-                // is_default is meaningless unless caption language is 'default'
-                int score = (forced ? 0 : 8)
-                        + (((selectedLocale == null) && is_default) ? 4 : 0)
-                        + (autoselect ? 0 : 2) + (languageMatches ? 1 : 0);
-
-                if (selectForced && !forced) {
-                    continue;
-                }
-
-                // we treat null locale/language as matching any language
-                if ((selectedLocale == null && is_default)
-                        || (languageMatches && (autoselect || forced || selectedLocale != null))) {
-                    if (score > bestScore) {
-                        bestScore = score;
-                        bestTrack = track;
-                    }
-                }
-            }
-        }
-        return bestTrack;
-    }
-
-    static class MediaFormatUtil {
-        MediaFormatUtil() { }
-        static int getInteger(MediaFormat format, String name, int defaultValue) {
-            try {
-                return format.getInteger(name);
-            } catch (NullPointerException | ClassCastException e) {
-                /* no such field or field of different type */
-            }
-            return defaultValue;
-        }
-    }
-
-    private boolean mTrackIsExplicit = false;
-    private boolean mVisibilityIsExplicit = false;
-
-    /** should be called from anchor thread */
-    public void selectDefaultTrack() {
-        processOnAnchor(mHandler.obtainMessage(WHAT_SELECT_DEFAULT_TRACK));
-    }
-
-    private void doSelectDefaultTrack() {
-        if (mTrackIsExplicit) {
-            if (mVisibilityIsExplicit) {
-                return;
-            }
-            // If track selection is explicit, but visibility
-            // is not, it falls back to the captioning setting
-            if (mCaptioningManager.isEnabled()
-                    || (mSelectedTrack != null && MediaFormatUtil.getInteger(
-                            mSelectedTrack.getFormat(),
-                            MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0)) {
-                show();
-            } else if (mSelectedTrack != null
-                    && mSelectedTrack.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
-                hide();
-            }
-            mVisibilityIsExplicit = false;
-        }
-
-        // We can have a default (forced) track even if captioning
-        // is not enabled.  This is handled by getDefaultTrack().
-        // Show this track unless subtitles were explicitly hidden.
-        SubtitleTrack track = getDefaultTrack();
-        if (track != null) {
-            selectTrack(track);
-            mTrackIsExplicit = false;
-            if (!mVisibilityIsExplicit) {
-                show();
-                mVisibilityIsExplicit = false;
-            }
-        }
-    }
-
-    /** must be called from anchor thread */
-    public void reset() {
-        checkAnchorLooper();
-        hide();
-        selectTrack(null);
-        mTracks.clear();
-        mTrackIsExplicit = false;
-        mVisibilityIsExplicit = false;
-        mCaptioningManager.removeCaptioningChangeListener(
-                mCaptioningChangeListener);
-    }
-
-    /**
-     * Adds a new, external subtitle track to the manager.
-     *
-     * @param format the format of the track that will include at least
-     *               the MIME type {@link MediaFormat@KEY_MIME}.
-     * @return the created {@link SubtitleTrack} object
-     */
-    public SubtitleTrack addTrack(MediaFormat format) {
-        synchronized (mRenderersLock) {
-            for (Renderer renderer: mRenderers) {
-                if (renderer.supports(format)) {
-                    SubtitleTrack track = renderer.createTrack(format);
-                    if (track != null) {
-                        synchronized (mTracksLock) {
-                            if (mTracks.size() == 0) {
-                                mCaptioningManager.addCaptioningChangeListener(
-                                        mCaptioningChangeListener);
-                            }
-                            mTracks.add(track);
-                        }
-                        return track;
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Show the selected (or default) subtitle track.
-     *
-     * Should be called from the anchor's (UI) thread. {@see #Anchor.getSubtitleLooper}
-     */
-    public void show() {
-        processOnAnchor(mHandler.obtainMessage(WHAT_SHOW));
-    }
-
-    private void doShow() {
-        mShowing = true;
-        mVisibilityIsExplicit = true;
-        if (mSelectedTrack != null) {
-            mSelectedTrack.show();
-        }
-    }
-
-    /**
-     * Hide the selected (or default) subtitle track.
-     *
-     * Should be called from the anchor's (UI) thread. {@see #Anchor.getSubtitleLooper}
-     */
-    public void hide() {
-        processOnAnchor(mHandler.obtainMessage(WHAT_HIDE));
-    }
-
-    private void doHide() {
-        mVisibilityIsExplicit = true;
-        if (mSelectedTrack != null) {
-            mSelectedTrack.hide();
-        }
-        mShowing = false;
-    }
-
-    /**
-     * Interface for supporting a single or multiple subtitle types in {@link MediaPlayer}.
-     */
-    public abstract static class Renderer {
-        /**
-         * Called by {@link MediaPlayer}'s {@link SubtitleController} when a new
-         * subtitle track is detected, to see if it should use this object to
-         * parse and display this subtitle track.
-         *
-         * @param format the format of the track that will include at least
-         *               the MIME type {@link MediaFormat@KEY_MIME}.
-         *
-         * @return true if and only if the track format is supported by this
-         * renderer
-         */
-        public abstract boolean supports(MediaFormat format);
-
-        /**
-         * Called by {@link MediaPlayer}'s {@link SubtitleController} for each
-         * subtitle track that was detected and is supported by this object to
-         * create a {@link SubtitleTrack} object.  This object will be created
-         * for each track that was found.  If the track is selected for display,
-         * this object will be used to parse and display the track data.
-         *
-         * @param format the format of the track that will include at least
-         *               the MIME type {@link MediaFormat@KEY_MIME}.
-         * @return a {@link SubtitleTrack} object that will be used to parse
-         * and render the subtitle track.
-         */
-        public abstract SubtitleTrack createTrack(MediaFormat format);
-    }
-
-    /**
-     * Add support for a subtitle format in {@link MediaPlayer}.
-     *
-     * @param renderer a {@link SubtitleController.Renderer} object that adds
-     *                 support for a subtitle format.
-     */
-    public void registerRenderer(Renderer renderer) {
-        synchronized (mRenderersLock) {
-            // TODO how to get available renderers in the system
-            if (!mRenderers.contains(renderer)) {
-                // TODO should added renderers override existing ones (to allow replacing?)
-                mRenderers.add(renderer);
-            }
-        }
-    }
-
-    /**
-     * Returns true if one of the registered renders supports given media format.
-     *
-     * @param format a {@link MediaFormat} object
-     * @return true if this SubtitleController has a renderer that supports
-     * the media format.
-     */
-    public boolean hasRendererFor(MediaFormat format) {
-        synchronized (mRenderersLock) {
-            // TODO how to get available renderers in the system
-            for (Renderer renderer: mRenderers) {
-                if (renderer.supports(format)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    /**
-     * Subtitle anchor, an object that is able to display a subtitle renderer,
-     * e.g. a VideoView.
-     */
-    public interface Anchor {
-        /**
-         * Anchor should use the supplied subtitle rendering widget, or
-         * none if it is null.
-         */
-        void setSubtitleWidget(RenderingWidget subtitleWidget);
-
-        /**
-         * Anchors provide the looper on which all track visibility changes
-         * (track.show/hide, setSubtitleWidget) will take place.
-         */
-        Looper getSubtitleLooper();
-    }
-
-    private Anchor mAnchor;
-
-    /**
-     *  called from anchor's looper (if any, both when unsetting and
-     *  setting)
-     */
-    public void setAnchor(Anchor anchor) {
-        if (mAnchor == anchor) {
-            return;
-        }
-
-        if (mAnchor != null) {
-            checkAnchorLooper();
-            mAnchor.setSubtitleWidget(null);
-        }
-        mAnchor = anchor;
-        mHandler = null;
-        if (mAnchor != null) {
-            mHandler = new Handler(mAnchor.getSubtitleLooper(), mCallback);
-            checkAnchorLooper();
-            mAnchor.setSubtitleWidget(getRenderingWidget());
-        }
-    }
-
-    private void checkAnchorLooper() {
-        assert mHandler != null : "Should have a looper already";
-        assert Looper.myLooper() == mHandler.getLooper()
-                : "Must be called from the anchor's looper";
-    }
-
-    private void processOnAnchor(Message m) {
-        assert mHandler != null : "Should have a looper already";
-        if (Looper.myLooper() == mHandler.getLooper()) {
-            mHandler.dispatchMessage(m);
-        } else {
-            mHandler.sendMessage(m);
-        }
-    }
-
-    interface Listener {
-        /**
-         * Called when a subtitle track has been selected.
-         *
-         * @param track selected subtitle track or null
-         */
-        void onSubtitleTrackSelected(SubtitleTrack track);
-    }
-
-    private Listener mListener;
-}
diff --git a/media/src/main/java/androidx/media/subtitle/SubtitleTrack.java b/media/src/main/java/androidx/media/subtitle/SubtitleTrack.java
deleted file mode 100644
index 30c1316..0000000
--- a/media/src/main/java/androidx/media/subtitle/SubtitleTrack.java
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.subtitle;
-
-import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.graphics.Canvas;
-import android.media.MediaFormat;
-import android.media.MediaPlayer.TrackInfo;
-import android.media.SubtitleData;
-import android.os.Handler;
-import android.util.Log;
-import android.util.LongSparseArray;
-import android.util.Pair;
-
-import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-// Note: This is forked from android.media.SubtitleTrack since P
-/**
- * A subtitle track abstract base class that is responsible for parsing and displaying
- * an instance of a particular type of subtitle.
- *
- * @hide
- */
-@RequiresApi(28)
-@RestrictTo(LIBRARY_GROUP)
-public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeListener {
-    private static final String TAG = "SubtitleTrack";
-    private long mLastUpdateTimeMs;
-    private long mLastTimeMs;
-
-    private Runnable mRunnable;
-
-    private final LongSparseArray<Run> mRunsByEndTime = new LongSparseArray<Run>();
-    private final LongSparseArray<Run> mRunsByID = new LongSparseArray<Run>();
-
-    private CueList mCues;
-    private final ArrayList<Cue> mActiveCues = new ArrayList<Cue>();
-    protected boolean mVisible;
-
-    public boolean DEBUG = false;
-
-    protected Handler mHandler = new Handler();
-
-    private MediaFormat mFormat;
-
-    public SubtitleTrack(MediaFormat format) {
-        mFormat = format;
-        mCues = new CueList();
-        clearActiveCues();
-        mLastTimeMs = -1;
-    }
-
-    public final MediaFormat getFormat() {
-        return mFormat;
-    }
-
-    private long mNextScheduledTimeMs = -1;
-
-    /**
-     * Called when there is input data for the subtitle track.
-     */
-    public void onData(SubtitleData data) {
-        long runID = data.getStartTimeUs() + 1;
-        onData(data.getData(), true /* eos */, runID);
-        setRunDiscardTimeMs(
-                runID,
-                (data.getStartTimeUs() + data.getDurationUs()) / 1000);
-    }
-
-    /**
-     * Called when there is input data for the subtitle track.  The
-     * complete subtitle for a track can include multiple whole units
-     * (runs).  Each of these units can have multiple sections.  The
-     * contents of a run are submitted in sequential order, with eos
-     * indicating the last section of the run.  Calls from different
-     * runs must not be intermixed.
-     *
-     * @param data subtitle data byte buffer
-     * @param eos true if this is the last section of the run.
-     * @param runID mostly-unique ID for this run of data.  Subtitle cues
-     *              with runID of 0 are discarded immediately after
-     *              display.  Cues with runID of ~0 are discarded
-     *              only at the deletion of the track object.  Cues
-     *              with other runID-s are discarded at the end of the
-     *              run, which defaults to the latest timestamp of
-     *              any of its cues (with this runID).
-     */
-    protected abstract void onData(byte[] data, boolean eos, long runID);
-
-    /**
-     * Called when adding the subtitle rendering widget to the view hierarchy,
-     * as well as when showing or hiding the subtitle track, or when the video
-     * surface position has changed.
-     *
-     * @return the widget that renders this subtitle track. For most renderers
-     *         there should be a single shared instance that is used for all
-     *         tracks supported by that renderer, as at most one subtitle track
-     *         is visible at one time.
-     */
-    public abstract RenderingWidget getRenderingWidget();
-
-    /**
-     * Called when the active cues have changed, and the contents of the subtitle
-     * view should be updated.
-     */
-    public abstract void updateView(ArrayList<Cue> activeCues);
-
-    protected synchronized void updateActiveCues(boolean rebuild, long timeMs) {
-        // out-of-order times mean seeking or new active cues being added
-        // (during their own timespan)
-        if (rebuild || mLastUpdateTimeMs > timeMs) {
-            clearActiveCues();
-        }
-
-        for (Iterator<Pair<Long, Cue>> it =
-                mCues.entriesBetween(mLastUpdateTimeMs, timeMs).iterator(); it.hasNext(); ) {
-            Pair<Long, Cue> event = it.next();
-            Cue cue = event.second;
-
-            if (cue.mEndTimeMs == event.first) {
-                // remove past cues
-                if (DEBUG) Log.v(TAG, "Removing " + cue);
-                mActiveCues.remove(cue);
-                if (cue.mRunID == 0) {
-                    it.remove();
-                }
-            } else if (cue.mStartTimeMs == event.first) {
-                // add new cues
-                // TRICKY: this will happen in start order
-                if (DEBUG) Log.v(TAG, "Adding " + cue);
-                if (cue.mInnerTimesMs != null) {
-                    cue.onTime(timeMs);
-                }
-                mActiveCues.add(cue);
-            } else if (cue.mInnerTimesMs != null) {
-                // cue is modified
-                cue.onTime(timeMs);
-            }
-        }
-
-        /* complete any runs */
-        while (mRunsByEndTime.size() > 0 && mRunsByEndTime.keyAt(0) <= timeMs) {
-            removeRunsByEndTimeIndex(0); // removes element
-        }
-        mLastUpdateTimeMs = timeMs;
-    }
-
-    private void removeRunsByEndTimeIndex(int ix) {
-        Run run = mRunsByEndTime.valueAt(ix);
-        while (run != null) {
-            Cue cue = run.mFirstCue;
-            while (cue != null) {
-                mCues.remove(cue);
-                Cue nextCue = cue.mNextInRun;
-                cue.mNextInRun = null;
-                cue = nextCue;
-            }
-            mRunsByID.remove(run.mRunID);
-            Run nextRun = run.mNextRunAtEndTimeMs;
-            run.mPrevRunAtEndTimeMs = null;
-            run.mNextRunAtEndTimeMs = null;
-            run = nextRun;
-        }
-        mRunsByEndTime.removeAt(ix);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        /* remove all cues (untangle all cross-links) */
-        int size = mRunsByEndTime.size();
-        for (int ix = size - 1; ix >= 0; ix--) {
-            removeRunsByEndTimeIndex(ix);
-        }
-
-        super.finalize();
-    }
-
-    private synchronized void takeTime(long timeMs) {
-        mLastTimeMs = timeMs;
-    }
-
-    protected synchronized void clearActiveCues() {
-        if (DEBUG) Log.v(TAG, "Clearing " + mActiveCues.size() + " active cues");
-        mActiveCues.clear();
-        mLastUpdateTimeMs = -1;
-    }
-
-    protected void scheduleTimedEvents() {
-        /* get times for the next event */
-        if (mTimeProvider != null) {
-            mNextScheduledTimeMs = mCues.nextTimeAfter(mLastTimeMs);
-            if (DEBUG) Log.d(TAG, "sched @" + mNextScheduledTimeMs + " after " + mLastTimeMs);
-            mTimeProvider.notifyAt(mNextScheduledTimeMs >= 0
-                    ? (mNextScheduledTimeMs * 1000) : MediaTimeProvider.NO_TIME, this);
-        }
-    }
-
-    @Override
-    public void onTimedEvent(long timeUs) {
-        if (DEBUG) Log.d(TAG, "onTimedEvent " + timeUs);
-        synchronized (this) {
-            long timeMs = timeUs / 1000;
-            updateActiveCues(false, timeMs);
-            takeTime(timeMs);
-        }
-        updateView(mActiveCues);
-        scheduleTimedEvents();
-    }
-
-    @Override
-    public void onSeek(long timeUs) {
-        if (DEBUG) Log.d(TAG, "onSeek " + timeUs);
-        synchronized (this) {
-            long timeMs = timeUs / 1000;
-            updateActiveCues(true, timeMs);
-            takeTime(timeMs);
-        }
-        updateView(mActiveCues);
-        scheduleTimedEvents();
-    }
-
-    @Override
-    public void onStop() {
-        synchronized (this) {
-            if (DEBUG) Log.d(TAG, "onStop");
-            clearActiveCues();
-            mLastTimeMs = -1;
-        }
-        updateView(mActiveCues);
-        mNextScheduledTimeMs = -1;
-        mTimeProvider.notifyAt(MediaTimeProvider.NO_TIME, this);
-    }
-
-    protected MediaTimeProvider mTimeProvider;
-
-    /**
-     * Shows subtitle rendering widget
-     */
-    public void show() {
-        if (mVisible) {
-            return;
-        }
-
-        mVisible = true;
-        RenderingWidget renderingWidget = getRenderingWidget();
-        if (renderingWidget != null) {
-            renderingWidget.setVisible(true);
-        }
-        if (mTimeProvider != null) {
-            mTimeProvider.scheduleUpdate(this);
-        }
-    }
-
-    /**
-     * Hides subtitle rendering widget
-     */
-    public void hide() {
-        if (!mVisible) {
-            return;
-        }
-
-        if (mTimeProvider != null) {
-            mTimeProvider.cancelNotifications(this);
-        }
-        RenderingWidget renderingWidget = getRenderingWidget();
-        if (renderingWidget != null) {
-            renderingWidget.setVisible(false);
-        }
-        mVisible = false;
-    }
-
-    protected synchronized boolean addCue(Cue cue) {
-        mCues.add(cue);
-
-        if (cue.mRunID != 0) {
-            Run run = mRunsByID.get(cue.mRunID);
-            if (run == null) {
-                run = new Run();
-                mRunsByID.put(cue.mRunID, run);
-                run.mEndTimeMs = cue.mEndTimeMs;
-            } else if (run.mEndTimeMs < cue.mEndTimeMs) {
-                run.mEndTimeMs = cue.mEndTimeMs;
-            }
-
-            // link-up cues in the same run
-            cue.mNextInRun = run.mFirstCue;
-            run.mFirstCue = cue;
-        }
-
-        // if a cue is added that should be visible, need to refresh view
-        long nowMs = -1;
-        if (mTimeProvider != null) {
-            try {
-                nowMs = mTimeProvider.getCurrentTimeUs(
-                        false /* precise */, true /* monotonic */) / 1000;
-            } catch (IllegalStateException e) {
-                // handle as it we are not playing
-            }
-        }
-
-        if (DEBUG) {
-            Log.v(TAG, "mVisible=" + mVisible + ", "
-                    + cue.mStartTimeMs + " <= " + nowMs + ", "
-                    + cue.mEndTimeMs + " >= " + mLastTimeMs);
-        }
-
-        if (mVisible && cue.mStartTimeMs <= nowMs
-                // we don't trust nowMs, so check any cue since last callback
-                && cue.mEndTimeMs >= mLastTimeMs) {
-            if (mRunnable != null) {
-                mHandler.removeCallbacks(mRunnable);
-            }
-            final SubtitleTrack track = this;
-            final long thenMs = nowMs;
-            mRunnable = new Runnable() {
-                @Override
-                public void run() {
-                    // even with synchronized, it is possible that we are going
-                    // to do multiple updates as the runnable could be already
-                    // running.
-                    synchronized (track) {
-                        mRunnable = null;
-                        updateActiveCues(true, thenMs);
-                        updateView(mActiveCues);
-                    }
-                }
-            };
-            // delay update so we don't update view on every cue.  TODO why 10?
-            if (mHandler.postDelayed(mRunnable, 10 /* delay */)) {
-                if (DEBUG) Log.v(TAG, "scheduling update");
-            } else {
-                if (DEBUG) Log.w(TAG, "failed to schedule subtitle view update");
-            }
-            return true;
-        }
-
-        if (mVisible && cue.mEndTimeMs >= mLastTimeMs
-                && (cue.mStartTimeMs < mNextScheduledTimeMs || mNextScheduledTimeMs < 0)) {
-            scheduleTimedEvents();
-        }
-
-        return false;
-    }
-
-    /**
-     * Sets MediaTimeProvider
-     */
-    public synchronized void setTimeProvider(MediaTimeProvider timeProvider) {
-        if (mTimeProvider == timeProvider) {
-            return;
-        }
-        if (mTimeProvider != null) {
-            mTimeProvider.cancelNotifications(this);
-        }
-        mTimeProvider = timeProvider;
-        if (mTimeProvider != null) {
-            mTimeProvider.scheduleUpdate(this);
-        }
-    }
-
-
-    static class CueList {
-        private static final String TAG = "CueList";
-        // simplistic, inefficient implementation
-        private SortedMap<Long, ArrayList<Cue>> mCues;
-        public boolean DEBUG = false;
-
-        private boolean addEvent(Cue cue, long timeMs) {
-            ArrayList<Cue> cues = mCues.get(timeMs);
-            if (cues == null) {
-                cues = new ArrayList<Cue>(2);
-                mCues.put(timeMs, cues);
-            } else if (cues.contains(cue)) {
-                // do not duplicate cues
-                return false;
-            }
-
-            cues.add(cue);
-            return true;
-        }
-
-        private void removeEvent(Cue cue, long timeMs) {
-            ArrayList<Cue> cues = mCues.get(timeMs);
-            if (cues != null) {
-                cues.remove(cue);
-                if (cues.size() == 0) {
-                    mCues.remove(timeMs);
-                }
-            }
-        }
-
-        public void add(Cue cue) {
-            // ignore non-positive-duration cues
-            if (cue.mStartTimeMs >= cue.mEndTimeMs) return;
-
-            if (!addEvent(cue, cue.mStartTimeMs)) {
-                return;
-            }
-
-            long lastTimeMs = cue.mStartTimeMs;
-            if (cue.mInnerTimesMs != null) {
-                for (long timeMs: cue.mInnerTimesMs) {
-                    if (timeMs > lastTimeMs && timeMs < cue.mEndTimeMs) {
-                        addEvent(cue, timeMs);
-                        lastTimeMs = timeMs;
-                    }
-                }
-            }
-
-            addEvent(cue, cue.mEndTimeMs);
-        }
-
-        public void remove(Cue cue) {
-            removeEvent(cue, cue.mStartTimeMs);
-            if (cue.mInnerTimesMs != null) {
-                for (long timeMs: cue.mInnerTimesMs) {
-                    removeEvent(cue, timeMs);
-                }
-            }
-            removeEvent(cue, cue.mEndTimeMs);
-        }
-
-        public Iterable<Pair<Long, Cue>> entriesBetween(
-                final long lastTimeMs, final long timeMs) {
-            return new Iterable<Pair<Long, Cue>>() {
-                @Override
-                public Iterator<Pair<Long, Cue>> iterator() {
-                    if (DEBUG) Log.d(TAG, "slice (" + lastTimeMs + ", " + timeMs + "]=");
-                    try {
-                        return new EntryIterator(
-                                mCues.subMap(lastTimeMs + 1, timeMs + 1));
-                    } catch (IllegalArgumentException e) {
-                        return new EntryIterator(null);
-                    }
-                }
-            };
-        }
-
-        public long nextTimeAfter(long timeMs) {
-            SortedMap<Long, ArrayList<Cue>> tail = null;
-            try {
-                tail = mCues.tailMap(timeMs + 1);
-                if (tail != null) {
-                    return tail.firstKey();
-                } else {
-                    return -1;
-                }
-            } catch (IllegalArgumentException e) {
-                return -1;
-            } catch (NoSuchElementException e) {
-                return -1;
-            }
-        }
-
-        class EntryIterator implements Iterator<Pair<Long, Cue>> {
-            @Override
-            public boolean hasNext() {
-                return !mDone;
-            }
-
-            @Override
-            public Pair<Long, Cue> next() {
-                if (mDone) {
-                    throw new NoSuchElementException("");
-                }
-                mLastEntry = new Pair<Long, Cue>(
-                        mCurrentTimeMs, mListIterator.next());
-                mLastListIterator = mListIterator;
-                if (!mListIterator.hasNext()) {
-                    nextKey();
-                }
-                return mLastEntry;
-            }
-
-            @Override
-            public void remove() {
-                // only allow removing end tags
-                if (mLastListIterator == null
-                        || mLastEntry.second.mEndTimeMs != mLastEntry.first) {
-                    throw new IllegalStateException("");
-                }
-
-                // remove end-cue
-                mLastListIterator.remove();
-                mLastListIterator = null;
-                if (mCues.get(mLastEntry.first).size() == 0) {
-                    mCues.remove(mLastEntry.first);
-                }
-
-                // remove rest of the cues
-                Cue cue = mLastEntry.second;
-                removeEvent(cue, cue.mStartTimeMs);
-                if (cue.mInnerTimesMs != null) {
-                    for (long timeMs: cue.mInnerTimesMs) {
-                        removeEvent(cue, timeMs);
-                    }
-                }
-            }
-
-            EntryIterator(SortedMap<Long, ArrayList<Cue>> cues) {
-                if (DEBUG) Log.v(TAG, cues + "");
-                mRemainingCues = cues;
-                mLastListIterator = null;
-                nextKey();
-            }
-
-            private void nextKey() {
-                do {
-                    try {
-                        if (mRemainingCues == null) {
-                            throw new NoSuchElementException("");
-                        }
-                        mCurrentTimeMs = mRemainingCues.firstKey();
-                        mListIterator =
-                            mRemainingCues.get(mCurrentTimeMs).iterator();
-                        try {
-                            mRemainingCues =
-                                mRemainingCues.tailMap(mCurrentTimeMs + 1);
-                        } catch (IllegalArgumentException e) {
-                            mRemainingCues = null;
-                        }
-                        mDone = false;
-                    } catch (NoSuchElementException e) {
-                        mDone = true;
-                        mRemainingCues = null;
-                        mListIterator = null;
-                        return;
-                    }
-                } while (!mListIterator.hasNext());
-            }
-
-            private long mCurrentTimeMs;
-            private Iterator<Cue> mListIterator;
-            private boolean mDone;
-            private SortedMap<Long, ArrayList<Cue>> mRemainingCues;
-            private Iterator<Cue> mLastListIterator;
-            private Pair<Long, Cue> mLastEntry;
-        }
-
-        CueList() {
-            mCues = new TreeMap<Long, ArrayList<Cue>>();
-        }
-    }
-
-    static class Cue {
-        public long mStartTimeMs;
-        public long mEndTimeMs;
-        public long[] mInnerTimesMs;
-        public long mRunID;
-
-        public Cue mNextInRun;
-
-        /**
-         * Called to inform current timeMs to the cue
-         */
-        public void onTime(long timeMs) { }
-    }
-
-    /** update mRunsByEndTime (with default end time) */
-    protected void finishedRun(long runID) {
-        if (runID != 0 && runID != ~0) {
-            Run run = mRunsByID.get(runID);
-            if (run != null) {
-                run.storeByEndTimeMs(mRunsByEndTime);
-            }
-        }
-    }
-
-    /** update mRunsByEndTime with given end time */
-    public void setRunDiscardTimeMs(long runID, long timeMs) {
-        if (runID != 0 && runID != ~0) {
-            Run run = mRunsByID.get(runID);
-            if (run != null) {
-                run.mEndTimeMs = timeMs;
-                run.storeByEndTimeMs(mRunsByEndTime);
-            }
-        }
-    }
-
-    /** whether this is a text track who fires events instead getting rendered */
-    public int getTrackType() {
-        return getRenderingWidget() == null
-                ? TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT
-                : TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE;
-    }
-
-
-    private static class Run {
-        public Cue mFirstCue;
-        public Run mNextRunAtEndTimeMs;
-        public Run mPrevRunAtEndTimeMs;
-        public long mEndTimeMs = -1;
-        public long mRunID = 0;
-        private long mStoredEndTimeMs = -1;
-
-        public void storeByEndTimeMs(LongSparseArray<Run> runsByEndTime) {
-            // remove old value if any
-            int ix = runsByEndTime.indexOfKey(mStoredEndTimeMs);
-            if (ix >= 0) {
-                if (mPrevRunAtEndTimeMs == null) {
-                    assert (this == runsByEndTime.valueAt(ix));
-                    if (mNextRunAtEndTimeMs == null) {
-                        runsByEndTime.removeAt(ix);
-                    } else {
-                        runsByEndTime.setValueAt(ix, mNextRunAtEndTimeMs);
-                    }
-                }
-                removeAtEndTimeMs();
-            }
-
-            // add new value
-            if (mEndTimeMs >= 0) {
-                mPrevRunAtEndTimeMs = null;
-                mNextRunAtEndTimeMs = runsByEndTime.get(mEndTimeMs);
-                if (mNextRunAtEndTimeMs != null) {
-                    mNextRunAtEndTimeMs.mPrevRunAtEndTimeMs = this;
-                }
-                runsByEndTime.put(mEndTimeMs, this);
-                mStoredEndTimeMs = mEndTimeMs;
-            }
-        }
-
-        public void removeAtEndTimeMs() {
-            Run prev = mPrevRunAtEndTimeMs;
-
-            if (mPrevRunAtEndTimeMs != null) {
-                mPrevRunAtEndTimeMs.mNextRunAtEndTimeMs = mNextRunAtEndTimeMs;
-                mPrevRunAtEndTimeMs = null;
-            }
-            if (mNextRunAtEndTimeMs != null) {
-                mNextRunAtEndTimeMs.mPrevRunAtEndTimeMs = prev;
-                mNextRunAtEndTimeMs = null;
-            }
-        }
-    }
-
-    /**
-     * Interface for rendering subtitles onto a Canvas.
-     */
-    public interface RenderingWidget {
-        /**
-         * Sets the widget's callback, which is used to send updates when the
-         * rendered data has changed.
-         *
-         * @param callback update callback
-         */
-        void setOnChangedListener(OnChangedListener callback);
-
-        /**
-         * Sets the widget's size.
-         *
-         * @param width width in pixels
-         * @param height height in pixels
-         */
-        void setSize(int width, int height);
-
-        /**
-         * Sets whether the widget should draw subtitles.
-         *
-         * @param visible true if subtitles should be drawn, false otherwise
-         */
-        void setVisible(boolean visible);
-
-        /**
-         * Renders subtitles onto a {@link Canvas}.
-         *
-         * @param c canvas on which to render subtitles
-         */
-        void draw(Canvas c);
-
-        /**
-         * Called when the widget is attached to a window.
-         */
-        void onAttachedToWindow();
-
-        /**
-         * Called when the widget is detached from a window.
-         */
-        void onDetachedFromWindow();
-
-        /**
-         * Callback used to send updates about changes to rendering data.
-         */
-        public interface OnChangedListener {
-            /**
-             * Called when the rendering data has changed.
-             *
-             * @param renderingWidget the widget whose data has changed
-             */
-            void onChanged(RenderingWidget renderingWidget);
-        }
-    }
-}
diff --git a/media/src/main/res/values/dimens.xml b/media/src/main/res/values/dimens.xml
deleted file mode 100644
index be50378..0000000
--- a/media/src/main/res/values/dimens.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT 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>
-    <!-- Shadow radius for video subtitles. -->
-    <dimen name="subtitle_shadow_radius">2dp</dimen>
-
-    <!-- Shadow offset for video subtitles. -->
-    <dimen name="subtitle_shadow_offset">2dp</dimen>
-
-    <!-- Outline width for video subtitles. -->
-    <dimen name="subtitle_outline_width">2dp</dimen>
-</resources>
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MediaController2Test_copied.java b/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MediaController2Test_copied.java
deleted file mode 100644
index a096160..0000000
--- a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MediaController2Test_copied.java
+++ /dev/null
@@ -1,1512 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.client;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.os.ResultReceiver;
-import android.support.mediacompat.testlib.util.PollingCheck;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SdkSuppress;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import androidx.annotation.NonNull;
-import androidx.media.AudioAttributesCompat;
-import androidx.media.MediaController2;
-import androidx.media.MediaController2.ControllerCallback;
-import androidx.media.MediaController2.PlaybackInfo;
-import androidx.media.MediaItem2;
-import androidx.media.MediaMetadata2;
-import androidx.media.MediaPlayerInterface;
-import androidx.media.MediaPlaylistAgent;
-import androidx.media.MediaSession2;
-import androidx.media.MediaSession2.ControllerInfo;
-import androidx.media.MediaSession2.SessionCallback;
-import androidx.media.Rating2;
-import androidx.media.SessionCommand2;
-import androidx.media.SessionCommandGroup2;
-import androidx.media.VolumeProviderCompat;
-import androidx.media.test.client.TestUtils.SyncHandler;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Tests {@link MediaController2}.
- */
-// TODO(jaewan): Implement host-side test so controller and session can run in different processes.
-// TODO(jaewan): Fix flaky failure -- see MediaController2Impl.getController()
-// TODO(jaeawn): Revisit create/close session in the sHandler. It's no longer necessary.
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-@FlakyTest
-@Ignore
-public class MediaController2Test_copied extends MediaSession2TestBase {
-    private static final String TAG = "MediaController2Test_copied";
-
-    PendingIntent mIntent;
-    MediaSession2 mSession;
-    MediaController2 mController;
-    MockPlayer mPlayer;
-    MockPlaylistAgent mMockAgent;
-    AudioManager mAudioManager;
-
-    @Before
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        final Intent sessionActivity = new Intent(mContext, MockActivity.class);
-        // Create this test specific MediaSession2 to use our own Handler.
-        mIntent = PendingIntent.getActivity(mContext, 0, sessionActivity, 0);
-
-        mPlayer = new MockPlayer(1);
-        mMockAgent = new MockPlaylistAgent();
-        mSession = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setPlaylistAgent(mMockAgent)
-                .setSessionCallback(sHandlerExecutor, new SessionCallback() {
-                    @Override
-                    public SessionCommandGroup2 onConnect(MediaSession2 session,
-                            ControllerInfo controller) {
-                        if (Process.myUid() == controller.getUid()) {
-                            return super.onConnect(session, controller);
-                        }
-                        return null;
-                    }
-
-                    @Override
-                    public void onPlaylistMetadataChanged(MediaSession2 session,
-                            MediaPlaylistAgent playlistAgent,
-                            MediaMetadata2 metadata) {
-                        super.onPlaylistMetadataChanged(session, playlistAgent, metadata);
-                    }
-                })
-                .setSessionActivity(mIntent)
-                .setId(TAG).build();
-        mController = createController(mSession.getToken());
-        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        TestServiceRegistry.getInstance().setHandler(sHandler);
-    }
-
-    @After
-    @Override
-    public void cleanUp() throws Exception {
-        super.cleanUp();
-        if (mSession != null) {
-            mSession.close();
-        }
-        TestServiceRegistry.getInstance().cleanUp();
-    }
-
-    /**
-     * Test if the {@link MediaSession2TestBase.TestControllerCallback} wraps the callback proxy
-     * without missing any method.
-     */
-    @Test
-    public void testTestControllerCallback() {
-        prepareLooper();
-        Method[] methods = TestControllerCallback.class.getMethods();
-        assertNotNull(methods);
-        for (int i = 0; i < methods.length; i++) {
-            // For any methods in the controller callback, TestControllerCallback should have
-            // overriden the method and call matching API in the callback proxy.
-            assertNotEquals("TestControllerCallback should override " + methods[i]
-                            + " and call callback proxy",
-                    ControllerCallback.class, methods[i].getDeclaringClass());
-        }
-    }
-
-    @Test
-    public void testPlay() {
-        prepareLooper();
-        mController.play();
-        try {
-            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-        } catch (InterruptedException e) {
-            fail(e.getMessage());
-        }
-        assertTrue(mPlayer.mPlayCalled);
-    }
-
-    @Test
-    public void testPause() {
-        prepareLooper();
-        mController.pause();
-        try {
-            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-        } catch (InterruptedException e) {
-            fail(e.getMessage());
-        }
-        assertTrue(mPlayer.mPauseCalled);
-    }
-
-    @Test
-    public void testReset() {
-        prepareLooper();
-        mController.reset();
-        try {
-            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-        } catch (InterruptedException e) {
-            fail(e.getMessage());
-        }
-        assertTrue(mPlayer.mResetCalled);
-    }
-
-    @Test
-    public void testPrepare() {
-        prepareLooper();
-        mController.prepare();
-        try {
-            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-        } catch (InterruptedException e) {
-            fail(e.getMessage());
-        }
-        assertTrue(mPlayer.mPrepareCalled);
-    }
-
-    @Test
-    public void testSeekTo() {
-        prepareLooper();
-        final long seekPosition = 12125L;
-        mController.seekTo(seekPosition);
-        try {
-            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-        } catch (InterruptedException e) {
-            fail(e.getMessage());
-        }
-        assertTrue(mPlayer.mSeekToCalled);
-        assertEquals(seekPosition, mPlayer.mSeekPosition);
-    }
-
-    @Test
-    public void testGettersAfterConnected() throws InterruptedException {
-        prepareLooper();
-        final int state = MediaPlayerInterface.PLAYER_STATE_PLAYING;
-        final int bufferingState = MediaPlayerInterface.BUFFERING_STATE_BUFFERING_COMPLETE;
-        final long position = 150000;
-        final long bufferedPosition = 900000;
-        final float speed = 0.5f;
-        final long timeDiff = 102;
-        final MediaItem2 currentMediaItem = TestUtils.createMediaItemWithMetadata();
-
-        mPlayer.mLastPlayerState = state;
-        mPlayer.mLastBufferingState = bufferingState;
-        mPlayer.mCurrentPosition = position;
-        mPlayer.mBufferedPosition = bufferedPosition;
-        mPlayer.mPlaybackSpeed = speed;
-        mMockAgent.mCurrentMediaItem = currentMediaItem;
-
-        MediaController2 controller = createController(mSession.getToken());
-        // setTimeDiff is package-private, so cannot be called here.
-//        controller.setTimeDiff(timeDiff);
-        assertEquals(state, controller.getPlayerState());
-        assertEquals(bufferedPosition, controller.getBufferedPosition());
-        assertEquals(speed, controller.getPlaybackSpeed(), 0.0f);
-        assertEquals(position + (long) (speed * timeDiff), controller.getCurrentPosition());
-        assertEquals(currentMediaItem, controller.getCurrentMediaItem());
-    }
-
-    @Test
-    public void testUpdatePlayer() throws InterruptedException {
-        prepareLooper();
-        final int testState = MediaPlayerInterface.PLAYER_STATE_PLAYING;
-        final List<MediaItem2> testPlaylist = TestUtils.createPlaylist(3);
-        final AudioAttributesCompat testAudioAttributes = new AudioAttributesCompat.Builder()
-                .setLegacyStreamType(AudioManager.STREAM_RING).build();
-        final CountDownLatch latch = new CountDownLatch(3);
-        mController = createController(mSession.getToken(), true, new ControllerCallback() {
-            @Override
-            public void onPlayerStateChanged(MediaController2 controller, int state) {
-                assertEquals(mController, controller);
-                assertEquals(testState, state);
-                latch.countDown();
-            }
-
-            @Override
-            public void onPlaylistChanged(MediaController2 controller, List<MediaItem2> list,
-                    MediaMetadata2 metadata) {
-                assertEquals(mController, controller);
-                assertEquals(testPlaylist, list);
-                assertNull(metadata);
-                latch.countDown();
-            }
-
-            @Override
-            public void onPlaybackInfoChanged(MediaController2 controller, PlaybackInfo info) {
-                assertEquals(mController, controller);
-                assertEquals(testAudioAttributes, info.getAudioAttributes());
-                latch.countDown();
-            }
-        });
-
-        MockPlayer player = new MockPlayer(0);
-        player.mLastPlayerState = testState;
-        player.setAudioAttributes(testAudioAttributes);
-
-        MockPlaylistAgent agent = new MockPlaylistAgent();
-        agent.mPlaylist = testPlaylist;
-
-        mSession.updatePlayer(player, agent, null);
-        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testGetSessionActivity() {
-        prepareLooper();
-        PendingIntent sessionActivity = mController.getSessionActivity();
-        assertEquals(mContext.getPackageName(), sessionActivity.getCreatorPackage());
-        assertEquals(Process.myUid(), sessionActivity.getCreatorUid());
-    }
-
-    @Test
-    public void testSetPlaylist() throws InterruptedException {
-        prepareLooper();
-        final List<MediaItem2> list = TestUtils.createPlaylist(2);
-        mController.setPlaylist(list, null /* Metadata */);
-        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
-        assertTrue(mMockAgent.mSetPlaylistCalled);
-        assertNull(mMockAgent.mMetadata);
-
-        assertNotNull(mMockAgent.mPlaylist);
-        assertEquals(list.size(), mMockAgent.mPlaylist.size());
-        for (int i = 0; i < list.size(); i++) {
-            // MediaController2.setPlaylist does not ensure the equality of the items.
-            assertEquals(list.get(i).getMediaId(), mMockAgent.mPlaylist.get(i).getMediaId());
-        }
-    }
-
-    /**
-     * This also tests {@link ControllerCallback#onPlaylistChanged(
-     * MediaController2, List, MediaMetadata2)}.
-     */
-    @Test
-    public void testGetPlaylist() throws InterruptedException {
-        prepareLooper();
-        final List<MediaItem2> testList = TestUtils.createPlaylist(2);
-        final AtomicReference<List<MediaItem2>> listFromCallback = new AtomicReference<>();
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onPlaylistChanged(MediaController2 controller,
-                    List<MediaItem2> playlist, MediaMetadata2 metadata) {
-                assertNotNull(playlist);
-                assertEquals(testList.size(), playlist.size());
-                for (int i = 0; i < playlist.size(); i++) {
-                    assertEquals(testList.get(i).getMediaId(), playlist.get(i).getMediaId());
-                }
-                listFromCallback.set(playlist);
-                latch.countDown();
-            }
-        };
-        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
-            @Override
-            public List<MediaItem2> getPlaylist() {
-                return testList;
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setId("testControllerCallback_onPlaylistChanged")
-                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
-                .setPlaylistAgent(agent)
-                .build()) {
-            MediaController2 controller = createController(
-                    session.getToken(), true, callback);
-            agent.notifyPlaylistChanged();
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-            assertEquals(listFromCallback.get(), controller.getPlaylist());
-        }
-    }
-
-    @Test
-    public void testUpdatePlaylistMetadata() throws InterruptedException {
-        prepareLooper();
-        final MediaMetadata2 testMetadata = TestUtils.createMetadata();
-        mController.updatePlaylistMetadata(testMetadata);
-        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
-        assertTrue(mMockAgent.mUpdatePlaylistMetadataCalled);
-        assertNotNull(mMockAgent.mMetadata);
-        assertEquals(testMetadata.getMediaId(), mMockAgent.mMetadata.getMediaId());
-    }
-
-    @Test
-    public void testGetPlaylistMetadata() throws InterruptedException {
-        prepareLooper();
-        final MediaMetadata2 testMetadata = TestUtils.createMetadata();
-        final AtomicReference<MediaMetadata2> metadataFromCallback = new AtomicReference<>();
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onPlaylistMetadataChanged(MediaController2 controller,
-                    MediaMetadata2 metadata) {
-                assertNotNull(testMetadata);
-                assertEquals(testMetadata.getMediaId(), metadata.getMediaId());
-                metadataFromCallback.set(metadata);
-                latch.countDown();
-            }
-        };
-        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
-            @Override
-            public MediaMetadata2 getPlaylistMetadata() {
-                return testMetadata;
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setId("testGetPlaylistMetadata")
-                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
-                .setPlaylistAgent(agent)
-                .build()) {
-            MediaController2 controller = createController(session.getToken(), true, callback);
-            agent.notifyPlaylistMetadataChanged();
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-            assertEquals(metadataFromCallback.get().getMediaId(),
-                    controller.getPlaylistMetadata().getMediaId());
-        }
-    }
-
-    @Test
-    public void testSetPlaybackSpeed() throws Exception {
-        prepareLooper();
-        final float speed = 1.5f;
-        mController.setPlaybackSpeed(speed);
-        assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        assertEquals(speed, mPlayer.mPlaybackSpeed, 0.0f);
-    }
-
-    /**
-     * Test whether {@link MediaSession2#setPlaylist(List, MediaMetadata2)} is notified
-     * through the
-     * {@link ControllerCallback#onPlaylistMetadataChanged(MediaController2, MediaMetadata2)}
-     * if the controller doesn't have {@link SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST} but
-     * {@link SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST_METADATA}.
-     */
-    @Test
-    public void testControllerCallback_onPlaylistMetadataChanged() throws InterruptedException {
-        prepareLooper();
-        final MediaItem2 item = TestUtils.createMediaItemWithMetadata();
-        final List<MediaItem2> list = TestUtils.createPlaylist(2);
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onPlaylistMetadataChanged(MediaController2 controller,
-                    MediaMetadata2 metadata) {
-                assertNotNull(metadata);
-                assertEquals(item.getMediaId(), metadata.getMediaId());
-                latch.countDown();
-            }
-        };
-        final SessionCallback sessionCallback = new SessionCallback() {
-            @Override
-            public SessionCommandGroup2 onConnect(MediaSession2 session,
-                    ControllerInfo controller) {
-                if (Process.myUid() == controller.getUid()) {
-                    SessionCommandGroup2 commands = new SessionCommandGroup2();
-                    commands.addCommand(new SessionCommand2(
-                              SessionCommand2.COMMAND_CODE_PLAYLIST_GET_LIST_METADATA));
-                    return commands;
-                }
-                return super.onConnect(session, controller);
-            }
-        };
-        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
-            @Override
-            public MediaMetadata2 getPlaylistMetadata() {
-                return item.getMetadata();
-            }
-
-            @Override
-            public List<MediaItem2> getPlaylist() {
-                return list;
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setId("testControllerCallback_onPlaylistMetadataChanged")
-                .setSessionCallback(sHandlerExecutor, sessionCallback)
-                .setPlaylistAgent(agent)
-                .build()) {
-            MediaController2 controller = createController(session.getToken(), true, callback);
-            agent.notifyPlaylistMetadataChanged();
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-
-    @Test
-    public void testControllerCallback_onSeekCompleted() throws InterruptedException {
-        prepareLooper();
-        final long testSeekPosition = 400;
-        final long testPosition = 500;
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onSeekCompleted(MediaController2 controller, long position) {
-                // setTimeDiff is package-private, so cannot be called here.
-//                controller.setTimeDiff(Long.valueOf(0));
-                assertEquals(testSeekPosition, position);
-                assertEquals(testPosition, controller.getCurrentPosition());
-                latch.countDown();
-            }
-        };
-        final MediaController2 controller = createController(mSession.getToken(), true, callback);
-        mPlayer.mCurrentPosition = testPosition;
-        mPlayer.notifySeekCompleted(testSeekPosition);
-        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testControllerCallback_onBufferingStateChanged() throws InterruptedException {
-        prepareLooper();
-        final List<MediaItem2> testPlaylist = TestUtils.createPlaylist(3);
-        final MediaItem2 testItem = testPlaylist.get(0);
-        final int testBufferingState = MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_PLAYABLE;
-        final long testBufferingPosition = 500;
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onBufferingStateChanged(MediaController2 controller, MediaItem2 item,
-                    int state) {
-                // setTimeDiff is package-private, so cannot be called here.
-//                controller.setTimeDiff(Long.valueOf(0));
-                assertEquals(testItem, item);
-                assertEquals(testBufferingState, state);
-                assertEquals(testBufferingState, controller.getBufferingState());
-                assertEquals(testBufferingPosition, controller.getBufferedPosition());
-                latch.countDown();
-            }
-        };
-        final MediaController2 controller = createController(mSession.getToken(), true, callback);
-        mSession.setPlaylist(testPlaylist, null);
-        mPlayer.mBufferedPosition = testBufferingPosition;
-        mPlayer.notifyBufferingStateChanged(testItem.getDataSourceDesc(), testBufferingState);
-        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testControllerCallback_onPlayerStateChanged() throws InterruptedException {
-        prepareLooper();
-        final int testPlayerState = MediaPlayerInterface.PLAYER_STATE_PLAYING;
-        final long testPosition = 500;
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onPlayerStateChanged(MediaController2 controller, int state) {
-                // setTimeDiff is package-private, so cannot be called here.
-//                controller.setTimeDiff(Long.valueOf(0));
-                assertEquals(testPlayerState, state);
-                assertEquals(testPlayerState, controller.getPlayerState());
-                assertEquals(testPosition, controller.getCurrentPosition());
-                latch.countDown();
-            }
-        };
-        final MediaController2 controller = createController(mSession.getToken(), true, callback);
-        mPlayer.mCurrentPosition = testPosition;
-        mPlayer.notifyPlaybackState(testPlayerState);
-        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testAddPlaylistItem() throws InterruptedException {
-        prepareLooper();
-        final int testIndex = 12;
-        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
-        mController.addPlaylistItem(testIndex, testMediaItem);
-        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
-        assertTrue(mMockAgent.mAddPlaylistItemCalled);
-        assertEquals(testIndex, mMockAgent.mIndex);
-        // MediaController2.addPlaylistItem does not ensure the equality of the items.
-        assertEquals(testMediaItem.getMediaId(), mMockAgent.mItem.getMediaId());
-    }
-
-    @Test
-    public void testRemovePlaylistItem() throws InterruptedException {
-        prepareLooper();
-        mMockAgent.mPlaylist = TestUtils.createPlaylist(2);
-
-        // Recreate controller for sending removePlaylistItem.
-        // It's easier to ensure that MediaController2.getPlaylist() returns the playlist from the
-        // agent.
-        MediaController2 controller = createController(mSession.getToken());
-        MediaItem2 targetItem = controller.getPlaylist().get(0);
-        controller.removePlaylistItem(targetItem);
-        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
-        assertTrue(mMockAgent.mRemovePlaylistItemCalled);
-        assertEquals(targetItem, mMockAgent.mItem);
-    }
-
-    @Test
-    public void testReplacePlaylistItem() throws InterruptedException {
-        prepareLooper();
-        final int testIndex = 12;
-        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
-        mController.replacePlaylistItem(testIndex, testMediaItem);
-        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
-        assertTrue(mMockAgent.mReplacePlaylistItemCalled);
-        // MediaController2.replacePlaylistItem does not ensure the equality of the items.
-        assertEquals(testMediaItem.getMediaId(), mMockAgent.mItem.getMediaId());
-    }
-
-    @Test
-    public void testSkipToPreviousItem() throws InterruptedException {
-        prepareLooper();
-        mController.skipToPreviousItem();
-        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        assertTrue(mMockAgent.mSkipToPreviousItemCalled);
-    }
-
-    @Test
-    public void testSkipToNextItem() throws InterruptedException {
-        prepareLooper();
-        mController.skipToNextItem();
-        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        assertTrue(mMockAgent.mSkipToNextItemCalled);
-    }
-
-    @Test
-    public void testSkipToPlaylistItem() throws InterruptedException {
-        prepareLooper();
-        MediaController2 controller = createController(mSession.getToken());
-        MediaItem2 targetItem = TestUtils.createMediaItemWithMetadata();
-        controller.skipToPlaylistItem(targetItem);
-        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
-        assertTrue(mMockAgent.mSkipToPlaylistItemCalled);
-        assertEquals(targetItem, mMockAgent.mItem);
-    }
-
-    /**
-     * This also tests {@link ControllerCallback#onShuffleModeChanged(MediaController2, int)}.
-     */
-    @Test
-    public void testGetShuffleMode() throws InterruptedException {
-        prepareLooper();
-        final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
-        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
-            @Override
-            public int getShuffleMode() {
-                return testShuffleMode;
-            }
-        };
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
-                assertEquals(testShuffleMode, shuffleMode);
-                latch.countDown();
-            }
-        };
-        mSession.updatePlayer(mPlayer, agent, null);
-        MediaController2 controller = createController(mSession.getToken(), true, callback);
-        agent.notifyShuffleModeChanged();
-        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        assertEquals(testShuffleMode, controller.getShuffleMode());
-    }
-
-    @Test
-    public void testSetShuffleMode() throws InterruptedException {
-        prepareLooper();
-        final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
-        mController.setShuffleMode(testShuffleMode);
-        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
-        assertTrue(mMockAgent.mSetShuffleModeCalled);
-        assertEquals(testShuffleMode, mMockAgent.mShuffleMode);
-    }
-
-    /**
-     * This also tests {@link ControllerCallback#onRepeatModeChanged(MediaController2, int)}.
-     */
-    @Test
-    public void testGetRepeatMode() throws InterruptedException {
-        prepareLooper();
-        final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
-        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
-            @Override
-            public int getRepeatMode() {
-                return testRepeatMode;
-            }
-        };
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ControllerCallback callback = new ControllerCallback() {
-            @Override
-            public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
-                assertEquals(testRepeatMode, repeatMode);
-                latch.countDown();
-            }
-        };
-        mSession.updatePlayer(mPlayer, agent, null);
-        MediaController2 controller = createController(mSession.getToken(), true, callback);
-        agent.notifyRepeatModeChanged();
-        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        assertEquals(testRepeatMode, controller.getRepeatMode());
-    }
-
-    @Test
-    public void testSetRepeatMode() throws InterruptedException {
-        prepareLooper();
-        final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
-        mController.setRepeatMode(testRepeatMode);
-        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
-        assertTrue(mMockAgent.mSetRepeatModeCalled);
-        assertEquals(testRepeatMode, mMockAgent.mRepeatMode);
-    }
-
-    @Test
-    public void testSetVolumeTo() throws Exception {
-        prepareLooper();
-        final int maxVolume = 100;
-        final int currentVolume = 23;
-        final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
-        TestVolumeProvider volumeProvider =
-                new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
-
-        mSession.updatePlayer(new MockPlayer(0), null, volumeProvider);
-        final MediaController2 controller = createController(mSession.getToken(), true, null);
-
-        final int targetVolume = 50;
-        controller.setVolumeTo(targetVolume, 0 /* flags */);
-        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-        assertTrue(volumeProvider.mSetVolumeToCalled);
-        assertEquals(targetVolume, volumeProvider.mVolume);
-    }
-
-    @Test
-    public void testAdjustVolume() throws Exception {
-        prepareLooper();
-        final int maxVolume = 100;
-        final int currentVolume = 23;
-        final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
-        TestVolumeProvider volumeProvider =
-                new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
-
-        mSession.updatePlayer(new MockPlayer(0), null, volumeProvider);
-        final MediaController2 controller = createController(mSession.getToken(), true, null);
-
-        final int direction = AudioManager.ADJUST_RAISE;
-        controller.adjustVolume(direction, 0 /* flags */);
-        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-        assertTrue(volumeProvider.mAdjustVolumeCalled);
-        assertEquals(direction, volumeProvider.mDirection);
-    }
-
-    @Test
-    public void testSetVolumeWithLocalVolume() throws Exception {
-        prepareLooper();
-        if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
-            // This test is not eligible for this device.
-            return;
-        }
-
-        // Here, we intentionally choose STREAM_ALARM in order not to consider
-        // 'Do Not Disturb' or 'Volume limit'.
-        final int stream = AudioManager.STREAM_ALARM;
-        final int maxVolume = mAudioManager.getStreamMaxVolume(stream);
-        final int minVolume = 0;
-        if (maxVolume <= minVolume) {
-            return;
-        }
-
-        // Set stream of the session.
-        AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
-                .setLegacyStreamType(stream)
-                .build();
-        mPlayer.setAudioAttributes(attrs);
-        mSession.updatePlayer(mPlayer, null, null);
-
-        final int originalVolume = mAudioManager.getStreamVolume(stream);
-        final int targetVolume = originalVolume == minVolume
-                ? originalVolume + 1 : originalVolume - 1;
-
-        mController.setVolumeTo(targetVolume, AudioManager.FLAG_SHOW_UI);
-        new PollingCheck(WAIT_TIME_MS) {
-            @Override
-            protected boolean check() {
-                return targetVolume == mAudioManager.getStreamVolume(stream);
-            }
-        }.run();
-
-        // Set back to original volume.
-        mAudioManager.setStreamVolume(stream, originalVolume, 0 /* flags */);
-    }
-
-    @Test
-    public void testAdjustVolumeWithLocalVolume() throws Exception {
-        prepareLooper();
-        if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
-            // This test is not eligible for this device.
-            return;
-        }
-
-        // Here, we intentionally choose STREAM_ALARM in order not to consider
-        // 'Do Not Disturb' or 'Volume limit'.
-        final int stream = AudioManager.STREAM_ALARM;
-        final int maxVolume = mAudioManager.getStreamMaxVolume(stream);
-        final int minVolume = 0;
-        if (maxVolume <= minVolume) {
-            return;
-        }
-
-        // Set stream of the session.
-        AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
-                .setLegacyStreamType(stream)
-                .build();
-        mPlayer.setAudioAttributes(attrs);
-        mSession.updatePlayer(mPlayer, null, null);
-
-        final int originalVolume = mAudioManager.getStreamVolume(stream);
-        final int direction = originalVolume == minVolume
-                ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER;
-        final int targetVolume = originalVolume + direction;
-
-        mController.adjustVolume(direction, AudioManager.FLAG_SHOW_UI);
-        new PollingCheck(WAIT_TIME_MS) {
-            @Override
-            protected boolean check() {
-                return targetVolume == mAudioManager.getStreamVolume(stream);
-            }
-        }.run();
-
-        // Set back to original volume.
-        mAudioManager.setStreamVolume(stream, originalVolume, 0 /* flags */);
-    }
-
-    @Test
-    public void testGetPackageName() {
-        prepareLooper();
-        assertEquals(mContext.getPackageName(), mController.getSessionToken().getPackageName());
-    }
-
-    @Test
-    public void testSendCustomCommand() throws InterruptedException {
-        prepareLooper();
-        // TODO(jaewan): Need to revisit with the permission.
-        final SessionCommand2 testCommand =
-                new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PREPARE);
-        final Bundle testArgs = new Bundle();
-        testArgs.putString("args", "testSendCustomCommand");
-
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onCustomCommand(MediaSession2 session, ControllerInfo controller,
-                    SessionCommand2 customCommand, Bundle args, ResultReceiver cb) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                assertEquals(testCommand, customCommand);
-                assertTrue(TestUtils.equals(testArgs, args));
-                assertNull(cb);
-                latch.countDown();
-            }
-        };
-        mSession.close();
-        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
-        final MediaController2 controller = createController(mSession.getToken());
-        controller.sendCustomCommand(testCommand, testArgs, null);
-        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testControllerCallback_onConnected() throws InterruptedException {
-        prepareLooper();
-        // createController() uses controller callback to wait until the controller becomes
-        // available.
-        MediaController2 controller = createController(mSession.getToken());
-        assertNotNull(controller);
-    }
-
-    @Test
-    public void testControllerCallback_sessionRejects() throws InterruptedException {
-        prepareLooper();
-        final MediaSession2.SessionCallback sessionCallback = new SessionCallback() {
-            @Override
-            public SessionCommandGroup2 onConnect(MediaSession2 session,
-                    ControllerInfo controller) {
-                return null;
-            }
-        };
-        sHandler.postAndSync(new Runnable() {
-            @Override
-            public void run() {
-                mSession.close();
-                mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
-                        .setSessionCallback(sHandlerExecutor, sessionCallback).build();
-            }
-        });
-        MediaController2 controller =
-                createController(mSession.getToken(), false, null);
-        assertNotNull(controller);
-        waitForConnect(controller, false);
-        waitForDisconnect(controller, true);
-    }
-
-    @Test
-    public void testControllerCallback_releaseSession() throws InterruptedException {
-        prepareLooper();
-        mSession.close();
-        waitForDisconnect(mController, true);
-    }
-
-    @Test
-    public void testControllerCallback_close() throws InterruptedException {
-        prepareLooper();
-        mController.close();
-        waitForDisconnect(mController, true);
-    }
-
-    @Test
-    public void testFastForward() throws InterruptedException {
-        prepareLooper();
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onFastForward(MediaSession2 session, ControllerInfo controller) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                latch.countDown();
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback)
-                .setId("testFastForward").build()) {
-            MediaController2 controller = createController(session.getToken());
-            controller.fastForward();
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
-    public void testRewind() throws InterruptedException {
-        prepareLooper();
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onRewind(MediaSession2 session, ControllerInfo controller) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                latch.countDown();
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback)
-                .setId("testRewind").build()) {
-            MediaController2 controller = createController(session.getToken());
-            controller.rewind();
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
-    public void testPlayFromSearch() throws InterruptedException {
-        prepareLooper();
-        final String request = "random query";
-        final Bundle bundle = new Bundle();
-        bundle.putString("key", "value");
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onPlayFromSearch(MediaSession2 session, ControllerInfo controller,
-                    String query, Bundle extras) {
-                super.onPlayFromSearch(session, controller, query, extras);
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                assertEquals(request, query);
-                assertTrue(TestUtils.equals(bundle, extras));
-                latch.countDown();
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback)
-                .setId("testPlayFromSearch").build()) {
-            MediaController2 controller = createController(session.getToken());
-            controller.playFromSearch(request, bundle);
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
-    public void testPlayFromUri() throws InterruptedException {
-        prepareLooper();
-        final Uri request = Uri.parse("foo://boo");
-        final Bundle bundle = new Bundle();
-        bundle.putString("key", "value");
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onPlayFromUri(MediaSession2 session, ControllerInfo controller, Uri uri,
-                    Bundle extras) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                assertEquals(request, uri);
-                assertTrue(TestUtils.equals(bundle, extras));
-                latch.countDown();
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback)
-                .setId("testPlayFromUri").build()) {
-            MediaController2 controller = createController(session.getToken());
-            controller.playFromUri(request, bundle);
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
-    public void testPlayFromMediaId() throws InterruptedException {
-        prepareLooper();
-        final String request = "media_id";
-        final Bundle bundle = new Bundle();
-        bundle.putString("key", "value");
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onPlayFromMediaId(MediaSession2 session, ControllerInfo controller,
-                    String mediaId, Bundle extras) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                assertEquals(request, mediaId);
-                assertTrue(TestUtils.equals(bundle, extras));
-                latch.countDown();
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback)
-                .setId("testPlayFromMediaId").build()) {
-            MediaController2 controller = createController(session.getToken());
-            controller.playFromMediaId(request, bundle);
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
-    public void testPrepareFromSearch() throws InterruptedException {
-        prepareLooper();
-        final String request = "random query";
-        final Bundle bundle = new Bundle();
-        bundle.putString("key", "value");
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onPrepareFromSearch(MediaSession2 session, ControllerInfo controller,
-                    String query, Bundle extras) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                assertEquals(request, query);
-                assertTrue(TestUtils.equals(bundle, extras));
-                latch.countDown();
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback)
-                .setId("testPrepareFromSearch").build()) {
-            MediaController2 controller = createController(session.getToken());
-            controller.prepareFromSearch(request, bundle);
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
-    public void testPrepareFromUri() throws InterruptedException {
-        prepareLooper();
-        final Uri request = Uri.parse("foo://boo");
-        final Bundle bundle = new Bundle();
-        bundle.putString("key", "value");
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onPrepareFromUri(MediaSession2 session, ControllerInfo controller, Uri uri,
-                    Bundle extras) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                assertEquals(request, uri);
-                assertTrue(TestUtils.equals(bundle, extras));
-                latch.countDown();
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback)
-                .setId("testPrepareFromUri").build()) {
-            MediaController2 controller = createController(session.getToken());
-            controller.prepareFromUri(request, bundle);
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
-    public void testPrepareFromMediaId() throws InterruptedException {
-        prepareLooper();
-        final String request = "media_id";
-        final Bundle bundle = new Bundle();
-        bundle.putString("key", "value");
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onPrepareFromMediaId(MediaSession2 session, ControllerInfo controller,
-                    String mediaId, Bundle extras) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                assertEquals(request, mediaId);
-                assertTrue(TestUtils.equals(bundle, extras));
-                latch.countDown();
-            }
-        };
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback)
-                .setId("testPrepareFromMediaId").build()) {
-            MediaController2 controller = createController(session.getToken());
-            controller.prepareFromMediaId(request, bundle);
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
-    public void testSetRating() throws InterruptedException {
-        prepareLooper();
-        final int ratingType = Rating2.RATING_5_STARS;
-        final float ratingValue = 3.5f;
-        final Rating2 rating = Rating2.newStarRating(ratingType, ratingValue);
-        final String mediaId = "media_id";
-
-        final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
-            @Override
-            public void onSetRating(MediaSession2 session, ControllerInfo controller,
-                    String mediaIdOut, Rating2 ratingOut) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                assertEquals(mediaId, mediaIdOut);
-                assertEquals(rating, ratingOut);
-                latch.countDown();
-            }
-        };
-
-        try (MediaSession2 session = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback)
-                .setId("testSetRating").build()) {
-            MediaController2 controller = createController(session.getToken());
-            controller.setRating(mediaId, rating);
-            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
-    @Test
-    public void testIsConnected() throws InterruptedException {
-        prepareLooper();
-        assertTrue(mController.isConnected());
-        sHandler.postAndSync(new Runnable() {
-            @Override
-            public void run() {
-                mSession.close();
-            }
-        });
-        waitForDisconnect(mController, true);
-        assertFalse(mController.isConnected());
-    }
-
-    /**
-     * Test potential deadlock for calls between controller and session.
-     */
-    @Test
-    public void testDeadlock() throws InterruptedException {
-        prepareLooper();
-        sHandler.postAndSync(new Runnable() {
-            @Override
-            public void run() {
-                mSession.close();
-                mSession = null;
-            }
-        });
-
-        // Two more threads are needed not to block test thread nor test wide thread (sHandler).
-        final HandlerThread sessionThread = new HandlerThread("testDeadlock_session");
-        final HandlerThread testThread = new HandlerThread("testDeadlock_test");
-        sessionThread.start();
-        testThread.start();
-        final SyncHandler sessionHandler = new SyncHandler(sessionThread.getLooper());
-        final Handler testHandler = new Handler(testThread.getLooper());
-        final CountDownLatch latch = new CountDownLatch(1);
-        try {
-            final MockPlayer player = new MockPlayer(0);
-            sessionHandler.postAndSync(new Runnable() {
-                @Override
-                public void run() {
-                    mSession = new MediaSession2.Builder(mContext)
-                            .setPlayer(mPlayer)
-                            .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
-                            .setId("testDeadlock").build();
-                }
-            });
-            final MediaController2 controller = createController(mSession.getToken());
-            testHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    final int state = MediaPlayerInterface.PLAYER_STATE_ERROR;
-                    for (int i = 0; i < 100; i++) {
-                        // triggers call from session to controller.
-                        player.notifyPlaybackState(state);
-                        // triggers call from controller to session.
-                        controller.play();
-
-                        // Repeat above
-                        player.notifyPlaybackState(state);
-                        controller.pause();
-                        player.notifyPlaybackState(state);
-                        controller.reset();
-                        player.notifyPlaybackState(state);
-                        controller.skipToNextItem();
-                        player.notifyPlaybackState(state);
-                        controller.skipToPreviousItem();
-                    }
-                    // This may hang if deadlock happens.
-                    latch.countDown();
-                }
-            });
-            assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-        } finally {
-            if (mSession != null) {
-                sessionHandler.postAndSync(new Runnable() {
-                    @Override
-                    public void run() {
-                        // Clean up here because sessionHandler will be removed afterwards.
-                        mSession.close();
-                        mSession = null;
-                    }
-                });
-            }
-
-            if (Build.VERSION.SDK_INT >= 18) {
-                sessionThread.quitSafely();
-                testThread.quitSafely();
-            } else {
-                sessionThread.quit();
-                testThread.quit();
-            }
-        }
-    }
-
-    // Temporaily commenting out, since we don't have the Mock services yet.
-//    @Test
-//    public void testGetServiceToken() {
-//        prepareLooper();
-//        SessionToken2 token = TestUtils.getServiceToken(mContext, MockMediaSessionService2.ID);
-//        assertNotNull(token);
-//        assertEquals(mContext.getPackageName(), token.getPackageName());
-//        assertEquals(MockMediaSessionService2.ID, token.getId());
-//        assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
-//    }
-//
-//    @Test
-//    public void testConnectToService_sessionService() throws InterruptedException {
-//        prepareLooper();
-//        testConnectToService(MockMediaSessionService2.ID);
-//    }
-//
-//    @Test
-//    public void testConnectToService_libraryService() throws InterruptedException {
-//        prepareLooper();
-//        testConnectToService(MockMediaLibraryService2.ID);
-//    }
-//
-//    public void testConnectToService(String id) throws InterruptedException {
-//        prepareLooper();
-//        final CountDownLatch latch = new CountDownLatch(1);
-//        final MediaLibrarySessionCallback sessionCallback = new MediaLibrarySessionCallback() {
-//            @Override
-//            public SessionCommandGroup2 onConnect(@NonNull MediaSession2 session,
-//                    @NonNull ControllerInfo controller) {
-//                if (Process.myUid() == controller.getUid()) {
-//                    if (mSession != null) {
-//                        mSession.close();
-//                    }
-//                    mSession = session;
-//                    mPlayer = (MockPlayer) session.getPlayer();
-//                    assertEquals(mContext.getPackageName(), controller.getPackageName());
-//                    assertFalse(controller.isTrusted());
-//                    latch.countDown();
-//                }
-//                return super.onConnect(session, controller);
-//            }
-//        };
-//        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
-//
-//        final SessionCommand2 testCommand = new SessionCommand2("testConnectToService", null);
-//        final CountDownLatch controllerLatch = new CountDownLatch(1);
-//        mController = createController(TestUtils.getServiceToken(mContext, id), true,
-//                new ControllerCallback() {
-//                    @Override
-//                    public void onCustomCommand(MediaController2 controller,
-//                            SessionCommand2 command, Bundle args, ResultReceiver receiver) {
-//                        if (testCommand.equals(command)) {
-//                            controllerLatch.countDown();
-//                        }
-//                    }
-//                }
-//        );
-//        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-//
-//        // Test command from controller to session service.
-//        mController.play();
-//        assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-//        assertTrue(mPlayer.mPlayCalled);
-//
-//        // Test command from session service to controller.
-//        mSession.sendCustomCommand(testCommand, null);
-//        assertTrue(controllerLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-//    }
-
-    @Test
-    public void testControllerAfterSessionIsGone_session() throws InterruptedException {
-        prepareLooper();
-        testControllerAfterSessionIsClosed(mSession.getToken().getId());
-    }
-
-    // Temporaily commenting out, since we don't have the Mock services yet.
-//    @Test
-//    public void testControllerAfterSessionIsClosed_sessionService() throws InterruptedException {
-//        prepareLooper();
-//        testConnectToService(MockMediaSessionService2.ID);
-//        testControllerAfterSessionIsClosed(MockMediaSessionService2.ID);
-//    }
-
-    @Test
-    public void testSubscribeRouteInfo() throws InterruptedException {
-        prepareLooper();
-        final TestSessionCallback callback = new TestSessionCallback() {
-            @Override
-            public void onSubscribeRoutesInfo(@NonNull MediaSession2 session,
-                    @NonNull ControllerInfo controller) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                mLatch.countDown();
-            }
-
-            @Override
-            public void onUnsubscribeRoutesInfo(@NonNull MediaSession2 session,
-                    @NonNull ControllerInfo controller) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                mLatch.countDown();
-            }
-        };
-        mSession.close();
-        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
-        final MediaController2 controller = createController(mSession.getToken());
-
-        callback.resetLatchCount(1);
-        controller.subscribeRoutesInfo();
-        assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
-        callback.resetLatchCount(1);
-        controller.unsubscribeRoutesInfo();
-        assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testSelectRouteInfo() throws InterruptedException {
-        prepareLooper();
-        final Bundle testRoute = new Bundle();
-        testRoute.putString("id", "testRoute");
-        final TestSessionCallback callback = new TestSessionCallback() {
-            @Override
-            public void onSelectRoute(@NonNull MediaSession2 session,
-                    @NonNull ControllerInfo controller, @NonNull Bundle route) {
-                assertEquals(mContext.getPackageName(), controller.getPackageName());
-                assertTrue(TestUtils.equals(route, testRoute));
-                mLatch.countDown();
-            }
-        };
-        mSession.close();
-        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
-        final MediaController2 controller = createController(mSession.getToken());
-
-        callback.resetLatchCount(1);
-        controller.selectRoute(testRoute);
-        assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testClose_beforeConnected() throws InterruptedException {
-        prepareLooper();
-        MediaController2 controller =
-                createController(mSession.getToken(), false, null);
-        controller.close();
-    }
-
-    @Test
-    public void testClose_twice() {
-        prepareLooper();
-        mController.close();
-        mController.close();
-    }
-
-    @Test
-    public void testClose_session() throws InterruptedException {
-        prepareLooper();
-        final String id = mSession.getToken().getId();
-        mController.close();
-        // close is done immediately for session.
-        testNoInteraction();
-
-        // Test whether the controller is notified about later close of the session or
-        // re-creation.
-        testControllerAfterSessionIsClosed(id);
-    }
-
-    // Temporaily commenting out, since we don't have the Mock services yet.
-//    @Test
-//    public void testClose_sessionService() throws InterruptedException {
-//        prepareLooper();
-//        testCloseFromService(MockMediaSessionService2.ID);
-//    }
-//
-//    @Test
-//    public void testClose_libraryService() throws InterruptedException {
-//        prepareLooper();
-//        testCloseFromService(MockMediaLibraryService2.ID);
-//    }
-//
-//    private void testCloseFromService(String id) throws InterruptedException {
-//        final CountDownLatch latch = new CountDownLatch(1);
-//        TestServiceRegistry.getInstance().setSessionServiceCallback(new SessionServiceCallback() {
-//            @Override
-//            public void onCreated() {
-//                // Do nothing.
-//            }
-//
-//            @Override
-//            public void onDestroyed() {
-//                latch.countDown();
-//            }
-//        });
-//        mController = createController(TestUtils.getServiceToken(mContext, id));
-//        mController.close();
-//        // Wait until close triggers onDestroy() of the session service.
-//        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-//        assertNull(TestServiceRegistry.getInstance().getServiceInstance());
-//        testNoInteraction();
-//
-//        // Test whether the controller is notified about later close of the session or
-//        // re-creation.
-//        testControllerAfterSessionIsClosed(id);
-//    }
-
-    private void testControllerAfterSessionIsClosed(final String id) throws InterruptedException {
-        // This cause session service to be died.
-        mSession.close();
-        waitForDisconnect(mController, true);
-        testNoInteraction();
-
-        // Ensure that the controller cannot use newly create session with the same ID.
-        // Recreated session has different session stub, so previously created controller
-        // shouldn't be available.
-        mSession = new MediaSession2.Builder(mContext)
-                .setPlayer(mPlayer)
-                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
-                .setId(id).build();
-        testNoInteraction();
-    }
-
-    // Test that mSession and mController doesn't interact.
-    // Note that this method can be called after the mSession is died, so mSession may not have
-    // valid player.
-    private void testNoInteraction() throws InterruptedException {
-        // TODO: check that calls from the controller to session shouldn't be delivered.
-
-        // Calls from the session to controller shouldn't be delivered.
-        final CountDownLatch latch = new CountDownLatch(1);
-        setRunnableForOnCustomCommand(mController, new Runnable() {
-            @Override
-            public void run() {
-                latch.countDown();
-            }
-        });
-        SessionCommand2 customCommand = new SessionCommand2("testNoInteraction", null);
-        mSession.sendCustomCommand(customCommand, null);
-        assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-        setRunnableForOnCustomCommand(mController, null);
-    }
-
-    // TODO(jaewan): Add  test for service connect rejection, when we differentiate session
-    //               active/inactive and connection accept/refuse
-
-    class TestVolumeProvider extends VolumeProviderCompat {
-        final CountDownLatch mLatch = new CountDownLatch(1);
-        boolean mSetVolumeToCalled;
-        boolean mAdjustVolumeCalled;
-        int mVolume;
-        int mDirection;
-
-        TestVolumeProvider(int controlType, int maxVolume, int currentVolume) {
-            super(controlType, maxVolume, currentVolume);
-        }
-
-        @Override
-        public void onSetVolumeTo(int volume) {
-            mSetVolumeToCalled = true;
-            mVolume = volume;
-            mLatch.countDown();
-        }
-
-        @Override
-        public void onAdjustVolume(int direction) {
-            mAdjustVolumeCalled = true;
-            mDirection = direction;
-            mLatch.countDown();
-        }
-    }
-
-    class TestSessionCallback extends SessionCallback {
-        CountDownLatch mLatch;
-
-        void resetLatchCount(int count) {
-            mLatch = new CountDownLatch(count);
-        }
-    }
-}
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MediaSession2TestBase.java b/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MediaSession2TestBase.java
deleted file mode 100644
index a8da0b1..0000000
--- a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MediaSession2TestBase.java
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.client;
-
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
-import android.content.Context;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.ResultReceiver;
-import android.support.test.InstrumentationRegistry;
-
-import androidx.annotation.CallSuper;
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.media.MediaController2;
-import androidx.media.MediaController2.ControllerCallback;
-import androidx.media.MediaItem2;
-import androidx.media.MediaMetadata2;
-import androidx.media.MediaSession2.CommandButton;
-import androidx.media.SessionCommand2;
-import androidx.media.SessionCommandGroup2;
-import androidx.media.SessionToken2;
-import androidx.media.test.client.TestUtils.SyncHandler;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Base class for session test.
- * <p>
- * For all subclasses, all individual tests should begin with the {@link #prepareLooper()}. See
- * {@link #prepareLooper} for details.
- */
-abstract class MediaSession2TestBase {
-    // Expected success
-    static final int WAIT_TIME_MS = 1000;
-
-    // Expected timeout
-    static final int TIMEOUT_MS = 500;
-
-    static SyncHandler sHandler;
-    static Executor sHandlerExecutor;
-
-    Context mContext;
-    private List<MediaController2> mControllers = new ArrayList<>();
-
-    interface TestControllerInterface {
-        ControllerCallback getCallback();
-    }
-
-    interface TestControllerCallbackInterface {
-        void waitForConnect(boolean expect) throws InterruptedException;
-        void waitForDisconnect(boolean expect) throws InterruptedException;
-        void setRunnableForOnCustomCommand(Runnable runnable);
-    }
-
-    /**
-     * All tests methods should start with this.
-     * <p>
-     * MediaControllerCompat, which is wrapped by the MediaSession2, can be only created by the
-     * thread whose Looper is prepared. However, when the presubmit tests runs on the server,
-     * test runs with the {@link org.junit.internal.runners.statements.FailOnTimeout} which creates
-     * dedicated thread for running test methods while methods annotated with @After or @Before
-     * runs on the different thread. This ensures that the current Looper is prepared.
-     * <p>
-     * To address the issue .
-     */
-    public static void prepareLooper() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
-    @BeforeClass
-    public static void setUpThread() {
-        synchronized (MediaSession2TestBase.class) {
-            if (sHandler != null) {
-                return;
-            }
-            prepareLooper();
-            HandlerThread handlerThread = new HandlerThread("MediaSession2TestBase");
-            handlerThread.start();
-            sHandler = new SyncHandler(handlerThread.getLooper());
-            sHandlerExecutor = new Executor() {
-                @Override
-                public void execute(Runnable runnable) {
-                    SyncHandler handler;
-                    synchronized (MediaSession2TestBase.class) {
-                        handler = sHandler;
-                    }
-                    if (handler != null) {
-                        handler.post(runnable);
-                    }
-                }
-            };
-        }
-    }
-
-    @AfterClass
-    public static void cleanUpThread() {
-        synchronized (MediaSession2TestBase.class) {
-            if (sHandler == null) {
-                return;
-            }
-            if (Build.VERSION.SDK_INT >= 18) {
-                sHandler.getLooper().quitSafely();
-            } else {
-                sHandler.getLooper().quit();
-            }
-            sHandler = null;
-            sHandlerExecutor = null;
-        }
-    }
-
-    @CallSuper
-    public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getTargetContext();
-    }
-
-    @CallSuper
-    public void cleanUp() throws Exception {
-        for (int i = 0; i < mControllers.size(); i++) {
-            mControllers.get(i).close();
-        }
-    }
-
-    final MediaController2 createController(SessionToken2 token) throws InterruptedException {
-        return createController(token, true, null);
-    }
-
-    final MediaController2 createController(@NonNull SessionToken2 token,
-            boolean waitForConnect, @Nullable ControllerCallback callback)
-            throws InterruptedException {
-        TestControllerInterface instance = onCreateController(token, callback);
-        if (!(instance instanceof MediaController2)) {
-            throw new RuntimeException("Test has a bug. Expected MediaController2 but returned "
-                    + instance);
-        }
-        MediaController2 controller = (MediaController2) instance;
-        mControllers.add(controller);
-        if (waitForConnect) {
-            waitForConnect(controller, true);
-        }
-        return controller;
-    }
-
-    private static TestControllerCallbackInterface getTestControllerCallbackInterface(
-            MediaController2 controller) {
-        if (!(controller instanceof TestControllerInterface)) {
-            throw new RuntimeException("Test has a bug. Expected controller implemented"
-                    + " TestControllerInterface but got " + controller);
-        }
-        ControllerCallback callback = ((TestControllerInterface) controller).getCallback();
-        if (!(callback instanceof TestControllerCallbackInterface)) {
-            throw new RuntimeException("Test has a bug. Expected controller with callback "
-                    + " implemented TestControllerCallbackInterface but got " + controller);
-        }
-        return (TestControllerCallbackInterface) callback;
-    }
-
-    public static void waitForConnect(MediaController2 controller, boolean expected)
-            throws InterruptedException {
-        getTestControllerCallbackInterface(controller).waitForConnect(expected);
-    }
-
-    public static void waitForDisconnect(MediaController2 controller, boolean expected)
-            throws InterruptedException {
-        getTestControllerCallbackInterface(controller).waitForDisconnect(expected);
-    }
-
-    public static void setRunnableForOnCustomCommand(MediaController2 controller,
-            Runnable runnable) {
-        getTestControllerCallbackInterface(controller).setRunnableForOnCustomCommand(runnable);
-    }
-
-    TestControllerInterface onCreateController(final @NonNull SessionToken2 token,
-            @Nullable ControllerCallback callback) throws InterruptedException {
-        final ControllerCallback controllerCallback =
-                callback != null ? callback : new ControllerCallback() {};
-        final AtomicReference<TestControllerInterface> controller = new AtomicReference<>();
-        sHandler.postAndSync(new Runnable() {
-            @Override
-            public void run() {
-                // Create controller on the test handler, for changing MediaBrowserCompat's Handler
-                // Looper. Otherwise, MediaBrowserCompat will post all the commands to the handler
-                // and commands wouldn't be run if tests codes waits on the test handler.
-                controller.set(new TestMediaController(
-                        mContext, token, new TestControllerCallback(controllerCallback)));
-            }
-        });
-        return controller.get();
-    }
-
-    // TODO(jaewan): (Can be Post-P): Deprecate this
-    public static class TestControllerCallback extends MediaController2.ControllerCallback
-            implements TestControllerCallbackInterface {
-        public final ControllerCallback mCallbackProxy;
-        public final CountDownLatch connectLatch = new CountDownLatch(1);
-        public final CountDownLatch disconnectLatch = new CountDownLatch(1);
-        @GuardedBy("this")
-        private Runnable mOnCustomCommandRunnable;
-
-        TestControllerCallback(@NonNull ControllerCallback callbackProxy) {
-            if (callbackProxy == null) {
-                throw new IllegalArgumentException("Callback proxy shouldn't be null. Test bug");
-            }
-            mCallbackProxy = callbackProxy;
-        }
-
-        @CallSuper
-        @Override
-        public void onConnected(MediaController2 controller, SessionCommandGroup2 commands) {
-            connectLatch.countDown();
-        }
-
-        @CallSuper
-        @Override
-        public void onDisconnected(MediaController2 controller) {
-            disconnectLatch.countDown();
-        }
-
-        @Override
-        public void waitForConnect(boolean expect) throws InterruptedException {
-            if (expect) {
-                assertTrue(connectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-            } else {
-                assertFalse(connectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-            }
-        }
-
-        @Override
-        public void waitForDisconnect(boolean expect) throws InterruptedException {
-            if (expect) {
-                assertTrue(disconnectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-            } else {
-                assertFalse(disconnectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-            }
-        }
-
-        @Override
-        public void onCustomCommand(MediaController2 controller, SessionCommand2 command,
-                Bundle args, ResultReceiver receiver) {
-            mCallbackProxy.onCustomCommand(controller, command, args, receiver);
-            synchronized (this) {
-                if (mOnCustomCommandRunnable != null) {
-                    mOnCustomCommandRunnable.run();
-                }
-            }
-        }
-
-        @Override
-        public void onPlaybackInfoChanged(MediaController2 controller,
-                MediaController2.PlaybackInfo info) {
-            mCallbackProxy.onPlaybackInfoChanged(controller, info);
-        }
-
-        @Override
-        public void onCustomLayoutChanged(MediaController2 controller, List<CommandButton> layout) {
-            mCallbackProxy.onCustomLayoutChanged(controller, layout);
-        }
-
-        @Override
-        public void onAllowedCommandsChanged(MediaController2 controller,
-                SessionCommandGroup2 commands) {
-            mCallbackProxy.onAllowedCommandsChanged(controller, commands);
-        }
-
-        @Override
-        public void onPlayerStateChanged(MediaController2 controller, int state) {
-            mCallbackProxy.onPlayerStateChanged(controller, state);
-        }
-
-        @Override
-        public void onSeekCompleted(MediaController2 controller, long position) {
-            mCallbackProxy.onSeekCompleted(controller, position);
-        }
-
-        @Override
-        public void onPlaybackSpeedChanged(MediaController2 controller, float speed) {
-            mCallbackProxy.onPlaybackSpeedChanged(controller, speed);
-        }
-
-        @Override
-        public void onBufferingStateChanged(MediaController2 controller, MediaItem2 item,
-                int state) {
-            mCallbackProxy.onBufferingStateChanged(controller, item, state);
-        }
-
-        @Override
-        public void onError(MediaController2 controller, int errorCode, Bundle extras) {
-            mCallbackProxy.onError(controller, errorCode, extras);
-        }
-
-        @Override
-        public void onCurrentMediaItemChanged(MediaController2 controller, MediaItem2 item) {
-            mCallbackProxy.onCurrentMediaItemChanged(controller, item);
-        }
-
-        @Override
-        public void onPlaylistChanged(MediaController2 controller,
-                List<MediaItem2> list, MediaMetadata2 metadata) {
-            mCallbackProxy.onPlaylistChanged(controller, list, metadata);
-        }
-
-        @Override
-        public void onPlaylistMetadataChanged(MediaController2 controller,
-                MediaMetadata2 metadata) {
-            mCallbackProxy.onPlaylistMetadataChanged(controller, metadata);
-        }
-
-        @Override
-        public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
-            mCallbackProxy.onShuffleModeChanged(controller, shuffleMode);
-        }
-
-        @Override
-        public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
-            mCallbackProxy.onRepeatModeChanged(controller, repeatMode);
-        }
-
-        @Override
-        public void setRunnableForOnCustomCommand(Runnable runnable) {
-            synchronized (this) {
-                mOnCustomCommandRunnable = runnable;
-            }
-        }
-
-        @Override
-        public void onRoutesInfoChanged(@NonNull MediaController2 controller,
-                @Nullable List<Bundle> routes) {
-            mCallbackProxy.onRoutesInfoChanged(controller, routes);
-        }
-    }
-
-    public class TestMediaController extends MediaController2 implements TestControllerInterface {
-        private final ControllerCallback mCallback;
-
-        TestMediaController(@NonNull Context context, @NonNull SessionToken2 token,
-                @NonNull ControllerCallback callback) {
-            super(context, token, sHandlerExecutor, callback);
-            mCallback = callback;
-        }
-
-        @Override
-        public ControllerCallback getCallback() {
-            return mCallback;
-        }
-    }
-}
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MockActivity.java b/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MockActivity.java
deleted file mode 100644
index 1bcb93a..0000000
--- a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MockActivity.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.client;
-
-import android.app.Activity;
-
-public class MockActivity extends Activity {
-}
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MockPlayer.java b/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MockPlayer.java
deleted file mode 100644
index 7a61184..0000000
--- a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MockPlayer.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.client;
-
-import androidx.annotation.NonNull;
-import androidx.collection.ArrayMap;
-import androidx.media.AudioAttributesCompat;
-import androidx.media.DataSourceDesc;
-import androidx.media.MediaPlayerInterface;
-
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-
-/**
- * A mock implementation of {@link MediaPlayerInterface} for testing.
- */
-public class MockPlayer extends MediaPlayerInterface {
-    public final CountDownLatch mCountDownLatch;
-
-    public boolean mPlayCalled;
-    public boolean mPauseCalled;
-    public boolean mResetCalled;
-    public boolean mPrepareCalled;
-    public boolean mSeekToCalled;
-    public boolean mSetPlaybackSpeedCalled;
-    public long mSeekPosition;
-    public long mCurrentPosition;
-    public long mBufferedPosition;
-    public float mPlaybackSpeed = 1.0f;
-    public @PlayerState int mLastPlayerState;
-    public @BuffState int mLastBufferingState;
-    public long mDuration;
-
-    public ArrayMap<PlayerEventCallback, Executor> mCallbacks = new ArrayMap<>();
-
-    private AudioAttributesCompat mAudioAttributes;
-
-    public MockPlayer(int count) {
-        mCountDownLatch = (count > 0) ? new CountDownLatch(count) : null;
-    }
-
-    @Override
-    public void close() {
-        // no-op
-    }
-
-    @Override
-    public void reset() {
-        mResetCalled = true;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void play() {
-        mPlayCalled = true;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void pause() {
-        mPauseCalled = true;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void prepare() {
-        mPrepareCalled = true;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void seekTo(long pos) {
-        mSeekToCalled = true;
-        mSeekPosition = pos;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void skipToNext() {
-        // No-op. This skipToNext() means 'skip to next item in the setNextDataSources()'
-    }
-
-    @Override
-    public int getPlayerState() {
-        return mLastPlayerState;
-    }
-
-    @Override
-    public long getCurrentPosition() {
-        return mCurrentPosition;
-    }
-
-    @Override
-    public long getBufferedPosition() {
-        return mBufferedPosition;
-    }
-
-    @Override
-    public float getPlaybackSpeed() {
-        return mPlaybackSpeed;
-    }
-
-    @Override
-    public int getBufferingState() {
-        return mLastBufferingState;
-    }
-
-    @Override
-    public long getDuration() {
-        return mDuration;
-    }
-
-    @Override
-    public void registerPlayerEventCallback(@NonNull Executor executor,
-            @NonNull PlayerEventCallback callback) {
-        if (callback == null || executor == null) {
-            throw new IllegalArgumentException("callback=" + callback + " executor=" + executor);
-        }
-        mCallbacks.put(callback, executor);
-    }
-
-    @Override
-    public void unregisterPlayerEventCallback(@NonNull PlayerEventCallback callback) {
-        mCallbacks.remove(callback);
-    }
-
-    public void notifyPlaybackState(final int state) {
-        mLastPlayerState = state;
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onPlayerStateChanged(MockPlayer.this, state);
-                }
-            });
-        }
-    }
-
-    public void notifyCurrentDataSourceChanged(final DataSourceDesc dsd) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onCurrentDataSourceChanged(MockPlayer.this, dsd);
-                }
-            });
-        }
-    }
-
-    public void notifyMediaPrepared(final DataSourceDesc dsd) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onMediaPrepared(MockPlayer.this, dsd);
-                }
-            });
-        }
-    }
-
-    public void notifyBufferingStateChanged(final DataSourceDesc dsd,
-            final @BuffState int buffState) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onBufferingStateChanged(MockPlayer.this, dsd, buffState);
-                }
-            });
-        }
-    }
-
-    public void notifyPlaybackSpeedChanged(final float speed) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onPlaybackSpeedChanged(MockPlayer.this, speed);
-                }
-            });
-        }
-    }
-
-    public void notifySeekCompleted(final long position) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onSeekCompleted(MockPlayer.this, position);
-                }
-            });
-        }
-    }
-
-    public void notifyError(int what) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            // TODO: Uncomment or remove
-            //executor.execute(() -> callback.onError(null, what, 0));
-        }
-    }
-
-    @Override
-    public void setAudioAttributes(AudioAttributesCompat attributes) {
-        mAudioAttributes = attributes;
-    }
-
-    @Override
-    public AudioAttributesCompat getAudioAttributes() {
-        return mAudioAttributes;
-    }
-
-    @Override
-    public void setDataSource(@NonNull DataSourceDesc dsd) {
-        // TODO: Implement this
-    }
-
-    @Override
-    public void setNextDataSource(@NonNull DataSourceDesc dsd) {
-        // TODO: Implement this
-    }
-
-    @Override
-    public void setNextDataSources(@NonNull List<DataSourceDesc> dsds) {
-        // TODO: Implement this
-    }
-
-    @Override
-    public DataSourceDesc getCurrentDataSource() {
-        // TODO: Implement this
-        return null;
-    }
-
-    @Override
-    public void loopCurrent(boolean loop) {
-        // TODO: implement this
-    }
-
-    @Override
-    public void setPlaybackSpeed(float speed) {
-        mSetPlaybackSpeedCalled = true;
-        mPlaybackSpeed = speed;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void setPlayerVolume(float volume) {
-        // TODO: implement this
-    }
-
-    @Override
-    public float getPlayerVolume() {
-        // TODO: implement this
-        return -1;
-    }
-}
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MockPlaylistAgent.java b/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MockPlaylistAgent.java
deleted file mode 100644
index 1ed6cd7..0000000
--- a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/MockPlaylistAgent.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.client;
-
-import androidx.media.MediaItem2;
-import androidx.media.MediaMetadata2;
-import androidx.media.MediaPlaylistAgent;
-
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * A mock implementation of {@link MediaPlaylistAgent} for testing.
- * <p>
- * Do not use mockito for {@link MediaPlaylistAgent}. Instead, use this.
- * Mocks created from mockito should not be shared across different threads.
- */
-public class MockPlaylistAgent extends MediaPlaylistAgent {
-    public final CountDownLatch mCountDownLatch = new CountDownLatch(1);
-
-    public List<MediaItem2> mPlaylist;
-    public MediaMetadata2 mMetadata;
-    public MediaItem2 mCurrentMediaItem;
-    public MediaItem2 mItem;
-    public int mIndex = -1;
-    public @RepeatMode int mRepeatMode = -1;
-    public @ShuffleMode int mShuffleMode = -1;
-
-    public boolean mSetPlaylistCalled;
-    public boolean mUpdatePlaylistMetadataCalled;
-    public boolean mAddPlaylistItemCalled;
-    public boolean mRemovePlaylistItemCalled;
-    public boolean mReplacePlaylistItemCalled;
-    public boolean mSkipToPlaylistItemCalled;
-    public boolean mSkipToPreviousItemCalled;
-    public boolean mSkipToNextItemCalled;
-    public boolean mSetRepeatModeCalled;
-    public boolean mSetShuffleModeCalled;
-
-    @Override
-    public List<MediaItem2> getPlaylist() {
-        return mPlaylist;
-    }
-
-    @Override
-    public void setPlaylist(List<MediaItem2> list, MediaMetadata2 metadata) {
-        mSetPlaylistCalled = true;
-        mPlaylist = list;
-        mMetadata = metadata;
-        mCountDownLatch.countDown();
-    }
-
-    @Override
-    public MediaMetadata2 getPlaylistMetadata() {
-        return mMetadata;
-    }
-
-    @Override
-    public void updatePlaylistMetadata(MediaMetadata2 metadata) {
-        mUpdatePlaylistMetadataCalled = true;
-        mMetadata = metadata;
-        mCountDownLatch.countDown();
-    }
-
-    @Override
-    public MediaItem2 getCurrentMediaItem() {
-        return mCurrentMediaItem;
-    }
-
-    @Override
-    public void addPlaylistItem(int index, MediaItem2 item) {
-        mAddPlaylistItemCalled = true;
-        mIndex = index;
-        mItem = item;
-        mCountDownLatch.countDown();
-    }
-
-    @Override
-    public void removePlaylistItem(MediaItem2 item) {
-        mRemovePlaylistItemCalled = true;
-        mItem = item;
-        mCountDownLatch.countDown();
-    }
-
-    @Override
-    public void replacePlaylistItem(int index, MediaItem2 item) {
-        mReplacePlaylistItemCalled = true;
-        mIndex = index;
-        mItem = item;
-        mCountDownLatch.countDown();
-    }
-
-    @Override
-    public void skipToPlaylistItem(MediaItem2 item) {
-        mSkipToPlaylistItemCalled = true;
-        mItem = item;
-        mCountDownLatch.countDown();
-    }
-
-    @Override
-    public void skipToPreviousItem() {
-        mSkipToPreviousItemCalled = true;
-        mCountDownLatch.countDown();
-    }
-
-    @Override
-    public void skipToNextItem() {
-        mSkipToNextItemCalled = true;
-        mCountDownLatch.countDown();
-    }
-
-    @Override
-    public int getRepeatMode() {
-        return mRepeatMode;
-    }
-
-    @Override
-    public void setRepeatMode(int repeatMode) {
-        mSetRepeatModeCalled = true;
-        mRepeatMode = repeatMode;
-        mCountDownLatch.countDown();
-    }
-
-    @Override
-    public int getShuffleMode() {
-        return mShuffleMode;
-    }
-
-    @Override
-    public void setShuffleMode(int shuffleMode) {
-        mSetShuffleModeCalled = true;
-        mShuffleMode = shuffleMode;
-        mCountDownLatch.countDown();
-    }
-}
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestHelper.java b/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestHelper.java
deleted file mode 100644
index 76c7758..0000000
--- a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestHelper.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.client;
-
-import static androidx.media.test.lib.TestHelperUtil.ACTION_TEST_HELPER;
-import static androidx.media.test.lib.TestHelperUtil.SERVICE_TEST_HELPER_COMPONENT_NAME;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.support.mediacompat.testlib.ITestHelperForServiceApp;
-import android.util.Log;
-
-import androidx.media.MediaSession2;
-import androidx.media.SessionToken2;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Interacts with service app's TestHelperService.
- */
-public class TestHelper {
-
-    private static final String TAG = "TestHelper";
-
-    private Context mContext;
-    private ServiceConnection mServiceConnection;
-    private ITestHelperForServiceApp mBinder;
-
-    private CountDownLatch mCountDownLatch;
-
-    public TestHelper(Context context) {
-        mContext = context;
-        mCountDownLatch = new CountDownLatch(1);
-    }
-
-    /**
-     * Connects to service app's TestHelperService. Should NOT be called in main thread.
-     *
-     * @return true if connected successfully, false if failed to connect.
-     */
-    public boolean connect(int timeoutMs) {
-        mServiceConnection = new MyServiceConnection();
-
-        final Intent intent = new Intent(ACTION_TEST_HELPER);
-        intent.setComponent(SERVICE_TEST_HELPER_COMPONENT_NAME);
-
-        boolean bound = false;
-        try {
-            bound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
-        } catch (Exception ex) {
-            Log.e(TAG, "Failed binding to the test helper service of service app");
-        }
-
-        if (bound) {
-            try {
-                mCountDownLatch.await(timeoutMs, TimeUnit.MILLISECONDS);
-            } catch (InterruptedException ex) {
-                Log.e(TAG, "InterruptedException while waiting for onServiceConnected.", ex);
-            }
-        }
-        return mBinder != null;
-    }
-
-    /**
-     * Create a session2 in the service app, and gets its token.
-     *
-     * @return A {@link SessionToken2} object if succeeded, {@code null} if failed.
-     */
-    public SessionToken2 getSessionToken2(String testName) {
-        SessionToken2 token = null;
-        try {
-            Bundle bundle = mBinder.getSessionToken2(testName);
-            if (bundle != null) {
-                bundle.setClassLoader(MediaSession2.class.getClassLoader());
-            }
-            token = SessionToken2.fromBundle(bundle);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "Failed to get session token. testName=" + testName);
-        }
-        return token;
-    }
-
-    // These methods will run on main thread.
-    class MyServiceConnection implements ServiceConnection {
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            Log.d(TAG, "Connected to service app's TestHelperService.");
-            mBinder = ITestHelperForServiceApp.Stub.asInterface(service);
-            mCountDownLatch.countDown();
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            Log.d(TAG, "Disconnected from the service.");
-        }
-    }
-}
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestHelperTest.java b/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestHelperTest.java
deleted file mode 100644
index af5b1ed..0000000
--- a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestHelperTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.client;
-
-import static android.support.mediacompat.testlib.VersionConstants.KEY_SERVICE_VERSION;
-import static android.support.mediacompat.testlib.VersionConstants.VERSION_TOT;
-import static android.support.mediacompat.testlib.util.IntentUtil.SERVICE_PACKAGE_NAME;
-import static android.support.test.InstrumentationRegistry.getArguments;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-import android.content.Context;
-import android.os.Looper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import androidx.media.MediaController2;
-import androidx.media.SessionToken2;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.Executor;
-
-/** Test {@link TestHelper}. */
-@RunWith(AndroidJUnit4.class)
-public class TestHelperTest {
-    private static final int TIME_OUT_MS = 3000;
-
-    private Context mContext;
-    private TestHelper mTestHelper;
-    private String mServiceVersion;
-
-    @Before
-    public void setUp() {
-        // The version of the service app is provided through the instrumentation arguments.
-        mServiceVersion = getArguments().getString(KEY_SERVICE_VERSION, "");
-        if (!VERSION_TOT.equals(mServiceVersion)) {
-            return;
-        }
-
-        mContext = InstrumentationRegistry.getTargetContext();
-        mTestHelper = new TestHelper(mContext);
-        boolean connected = mTestHelper.connect(TIME_OUT_MS);
-        if (!connected) {
-            fail("Failed to connect to Test helper service.");
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testGettingToken() {
-        if (!VERSION_TOT.equals(mServiceVersion)) {
-            return;
-        }
-        SessionToken2 token = mTestHelper.getSessionToken2("testGettingToken");
-        assertNotNull(token);
-        assertEquals(SERVICE_PACKAGE_NAME, token.getPackageName());
-    }
-
-    @Test
-    @SmallTest
-    public void testCreatingController() {
-        if (!VERSION_TOT.equals(mServiceVersion)) {
-            return;
-        }
-        Looper.prepare();
-        SessionToken2 token = mTestHelper.getSessionToken2("testCreatingController");
-        assertNotNull(token);
-        MediaController2 controller = new MediaController2(mContext, token, new Executor() {
-            @Override
-            public void execute(Runnable command) {
-                command.run();
-            }
-        }, new MediaController2.ControllerCallback() {});
-    }
-}
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestServiceRegistry.java b/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestServiceRegistry.java
deleted file mode 100644
index 8c87073..0000000
--- a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestServiceRegistry.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.client;
-
-import static org.junit.Assert.fail;
-
-import android.os.Handler;
-
-import androidx.annotation.GuardedBy;
-import androidx.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
-import androidx.media.MediaSessionService2;
-import androidx.media.test.client.TestUtils.SyncHandler;
-
-/**
- * Keeps the instance of currently running {@link MockMediaSessionService2}. And also provides
- * a way to control them in one place.
- * <p>
- * It only support only one service at a time.
- */
-public class TestServiceRegistry {
-    @GuardedBy("TestServiceRegistry.class")
-    private static TestServiceRegistry sInstance;
-    @GuardedBy("TestServiceRegistry.class")
-    private MediaSessionService2 mService;
-    @GuardedBy("TestServiceRegistry.class")
-    private SyncHandler mHandler;
-    @GuardedBy("TestServiceRegistry.class")
-    private MediaLibrarySessionCallback mSessionCallback;
-    @GuardedBy("TestServiceRegistry.class")
-    private SessionServiceCallback mSessionServiceCallback;
-
-    /**
-     * Callback for session service's lifecyle (onCreate() / onDestroy())
-     */
-    public interface SessionServiceCallback {
-        void onCreated();
-        void onDestroyed();
-    }
-
-    public static TestServiceRegistry getInstance() {
-        synchronized (TestServiceRegistry.class) {
-            if (sInstance == null) {
-                sInstance = new TestServiceRegistry();
-            }
-            return sInstance;
-        }
-    }
-
-    public void setHandler(Handler handler) {
-        synchronized (TestServiceRegistry.class) {
-            mHandler = new SyncHandler(handler.getLooper());
-        }
-    }
-
-    public Handler getHandler() {
-        synchronized (TestServiceRegistry.class) {
-            return mHandler;
-        }
-    }
-
-    public void setSessionServiceCallback(SessionServiceCallback sessionServiceCallback) {
-        synchronized (TestServiceRegistry.class) {
-            mSessionServiceCallback = sessionServiceCallback;
-        }
-    }
-
-    public void setSessionCallback(MediaLibrarySessionCallback sessionCallback) {
-        synchronized (TestServiceRegistry.class) {
-            mSessionCallback = sessionCallback;
-        }
-    }
-
-    public MediaLibrarySessionCallback getSessionCallback() {
-        synchronized (TestServiceRegistry.class) {
-            return mSessionCallback;
-        }
-    }
-
-    public void setServiceInstance(MediaSessionService2 service) {
-        synchronized (TestServiceRegistry.class) {
-            if (mService != null) {
-                fail("Previous service instance is still running. Clean up manually to ensure"
-                        + " previoulsy running service doesn't break current test");
-            }
-            mService = service;
-            if (mSessionServiceCallback != null) {
-                mSessionServiceCallback.onCreated();
-            }
-        }
-    }
-
-    public MediaSessionService2 getServiceInstance() {
-        synchronized (TestServiceRegistry.class) {
-            return mService;
-        }
-    }
-
-    public void cleanUp() {
-        synchronized (TestServiceRegistry.class) {
-            if (mService != null) {
-                // TODO(jaewan): Remove this, and override SessionService#onDestroy() to do this
-                mService.getSession().close();
-                // stopSelf() would not kill service while the binder connection established by
-                // bindService() exists, and close() above will do the job instead.
-                // So stopSelf() isn't really needed, but just for sure.
-                mService.stopSelf();
-                mService = null;
-            }
-            if (mHandler != null) {
-                mHandler.removeCallbacksAndMessages(null);
-            }
-            mSessionCallback = null;
-            if (mSessionServiceCallback != null) {
-                mSessionServiceCallback.onDestroyed();
-                mSessionServiceCallback = null;
-            }
-        }
-    }
-}
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestUtils.java b/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestUtils.java
deleted file mode 100644
index 3cd7f68..0000000
--- a/media/version-compat-tests/current/client/src/androidTest/java/androidx/media/test/client/TestUtils.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.client;
-
-import static org.junit.Assert.assertTrue;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-
-import androidx.core.util.ObjectsCompat;
-import androidx.media.DataSourceDesc;
-import androidx.media.MediaItem2;
-import androidx.media.MediaMetadata2;
-
-import java.io.FileDescriptor;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Utilities for tests.
- */
-public final class TestUtils {
-    private static final int WAIT_TIME_MS = 1000;
-    private static final int WAIT_SERVICE_TIME_MS = 5000;
-
-    // Temporaily commenting out, since we don't have the Mock services yet.
-//    /**
-//     * Finds the session with id in this test package.
-//     *
-//     * @param context
-//     * @param id
-//     * @return
-//     */
-//    public static SessionToken2 getServiceToken(Context context, String id) {
-//        switch (id) {
-//            case MockMediaSessionService2.ID:
-//                return new SessionToken2(context, new ComponentName(
-//                        context.getPackageName(), MockMediaSessionService2.class.getName()));
-//            case MockMediaLibraryService2.ID:
-//                return new SessionToken2(context, new ComponentName(
-//                        context.getPackageName(), MockMediaLibraryService2.class.getName()));
-//        }
-//        fail("Unknown id=" + id);
-//        return null;
-//    }
-
-    /**
-     * Compares contents of two bundles.
-     *
-     * @param a a bundle
-     * @param b another bundle
-     * @return {@code true} if two bundles are the same. {@code false} otherwise. This may be
-     *     incorrect if any bundle contains a bundle.
-     */
-    public static boolean equals(Bundle a, Bundle b) {
-        return contains(a, b) && contains(b, a);
-    }
-
-    /**
-     * Checks whether a Bundle contains another bundle.
-     *
-     * @param a a bundle
-     * @param b another bundle
-     * @return {@code true} if a contains b. {@code false} otherwise. This may be incorrect if any
-     *      bundle contains a bundle.
-     */
-    public static boolean contains(Bundle a, Bundle b) {
-        if (a == b) {
-            return true;
-        }
-        if (a == null || b == null) {
-            return b == null;
-        }
-        if (!a.keySet().containsAll(b.keySet())) {
-            return false;
-        }
-        for (String key : b.keySet()) {
-            if (!ObjectsCompat.equals(a.get(key), b.get(key))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Create a playlist for testing purpose
-     * <p>
-     * Caller's method name will be used for prefix of each media item's media id.
-     *
-     * @param size list size
-     * @return the newly created playlist
-     */
-    public static List<MediaItem2> createPlaylist(int size) {
-        final List<MediaItem2> list = new ArrayList<>();
-        String caller = Thread.currentThread().getStackTrace()[1].getMethodName();
-        for (int i = 0; i < size; i++) {
-            list.add(new MediaItem2.Builder(MediaItem2.FLAG_PLAYABLE)
-                    .setMediaId(caller + "_item_" + (size + 1))
-                    .setDataSourceDesc(createDSD()).build());
-        }
-        return list;
-    }
-
-    /**
-     * Create a media item with the metadata for testing purpose.
-     *
-     * @return the newly created media item
-     * @see #createMetadata()
-     */
-    public static MediaItem2 createMediaItemWithMetadata() {
-        return new MediaItem2.Builder(MediaItem2.FLAG_PLAYABLE)
-                .setMetadata(createMetadata()).setDataSourceDesc(createDSD()).build();
-    }
-
-    /**
-     * Create a media metadata for testing purpose.
-     * <p>
-     * Caller's method name will be used for the media id.
-     *
-     * @return the newly created media item
-     */
-    public static MediaMetadata2 createMetadata() {
-        String mediaId = Thread.currentThread().getStackTrace()[1].getMethodName();
-        return new MediaMetadata2.Builder()
-                .putString(MediaMetadata2.METADATA_KEY_MEDIA_ID, mediaId).build();
-    }
-
-    private static DataSourceDesc createDSD() {
-        return new DataSourceDesc.Builder().setDataSource(new FileDescriptor()).build();
-    }
-
-    /**
-     * Create a bundle for testing purpose.
-     *
-     * @return the newly created bundle.
-     */
-    public static Bundle createTestBundle() {
-        Bundle bundle = new Bundle();
-        bundle.putString("test_key", "test_value");
-        return bundle;
-    }
-
-    /**
-     * Handler that always waits until the Runnable finishes.
-     */
-    public static class SyncHandler extends Handler {
-        public SyncHandler(Looper looper) {
-            super(looper);
-        }
-
-        public void postAndSync(final Runnable runnable) throws InterruptedException {
-            if (getLooper() == Looper.myLooper()) {
-                runnable.run();
-            } else {
-                final CountDownLatch latch = new CountDownLatch(1);
-                post(new Runnable() {
-                    @Override
-                    public void run() {
-                        runnable.run();
-                        latch.countDown();
-                    }
-                });
-                assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-            }
-        }
-    }
-}
diff --git a/media/version-compat-tests/current/service/src/androidTest/AndroidManifest.xml b/media/version-compat-tests/current/service/src/androidTest/AndroidManifest.xml
index 0ca78fc..13c22ae 100644
--- a/media/version-compat-tests/current/service/src/androidTest/AndroidManifest.xml
+++ b/media/version-compat-tests/current/service/src/androidTest/AndroidManifest.xml
@@ -41,12 +41,5 @@
                 <action android:name="android.media.browse.MediaBrowserService"/>
             </intent-filter>
         </service>
-
-        <service android:name="androidx.media.test.service.TestHelperService">
-            <intent-filter>
-                <!-- Keep sync with TestHelperUtil.java -->
-                <action android:name="androidx.media.test.action.TEST_HELPER"/>
-            </intent-filter>
-        </service>
     </application>
 </manifest>
diff --git a/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java b/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
index 82e55ed..3519f2f 100644
--- a/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
+++ b/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
@@ -85,7 +85,6 @@
 import android.os.Parcel;
 import android.os.ResultReceiver;
 import android.os.SystemClock;
-import android.support.mediacompat.testlib.util.PollingCheck;
 import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -723,80 +722,7 @@
 
     @Test
     @SmallTest
-    public void testSetVolumeWithLocalVolume() throws Exception {
-        if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
-            // This test is not eligible for this device.
-            return;
-        }
-
-        // Here, we intentionally choose STREAM_ALARM in order not to consider
-        // 'Do Not Disturb' or 'Volume limit'.
-        final int stream = AudioManager.STREAM_ALARM;
-        final int maxVolume = mAudioManager.getStreamMaxVolume(stream);
-        final int minVolume = 0;
-        if (maxVolume <= minVolume) {
-            return;
-        }
-
-        mSession.setPlaybackToLocal(stream);
-
-        final int originalVolume = mAudioManager.getStreamVolume(stream);
-        final int targetVolume = originalVolume == minVolume
-                ? originalVolume + 1 : originalVolume - 1;
-
-        callMediaControllerMethod(SET_VOLUME_TO, targetVolume, getContext(),
-                mSession.getSessionToken());
-        new PollingCheck(TIME_OUT_MS) {
-            @Override
-            protected boolean check() {
-                return targetVolume == mAudioManager.getStreamVolume(stream);
-            }
-        }.run();
-
-        // Set back to original volume.
-        mAudioManager.setStreamVolume(stream, originalVolume, 0 /* flags */);
-    }
-
-    @Test
-    @SmallTest
-    public void testAdjustVolumeWithLocalVolume() throws Exception {
-        if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
-            // This test is not eligible for this device.
-            return;
-        }
-
-        // Here, we intentionally choose STREAM_ALARM in order not to consider
-        // 'Do Not Disturb' or 'Volume limit'.
-        final int stream = AudioManager.STREAM_ALARM;
-        final int maxVolume = mAudioManager.getStreamMaxVolume(stream);
-        final int minVolume = 0;
-        if (maxVolume <= minVolume) {
-            return;
-        }
-
-        mSession.setPlaybackToLocal(stream);
-
-        final int originalVolume = mAudioManager.getStreamVolume(stream);
-        final int direction = originalVolume == minVolume
-                ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER;
-        final int targetVolume = originalVolume + direction;
-
-        callMediaControllerMethod(ADJUST_VOLUME, direction, getContext(),
-                mSession.getSessionToken());
-        new PollingCheck(TIME_OUT_MS) {
-            @Override
-            protected boolean check() {
-                return targetVolume == mAudioManager.getStreamVolume(stream);
-            }
-        }.run();
-
-        // Set back to original volume.
-        mAudioManager.setStreamVolume(stream, originalVolume, 0 /* flags */);
-    }
-
-    @Test
-    @SmallTest
-    public void testRemoteVolumeControl() throws Exception {
+    public void testVolumeControl() throws Exception {
         if (android.os.Build.VERSION.SDK_INT < 27) {
             // This test causes an Exception on System UI in API < 27.
             return;
diff --git a/media/version-compat-tests/current/service/src/androidTest/java/androidx/media/test/service/MockPlayer.java b/media/version-compat-tests/current/service/src/androidTest/java/androidx/media/test/service/MockPlayer.java
deleted file mode 100644
index 14f1a96..0000000
--- a/media/version-compat-tests/current/service/src/androidTest/java/androidx/media/test/service/MockPlayer.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.service;
-
-import androidx.annotation.NonNull;
-import androidx.collection.ArrayMap;
-import androidx.media.AudioAttributesCompat;
-import androidx.media.DataSourceDesc;
-import androidx.media.MediaPlayerInterface;
-
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-
-/**
- * A mock implementation of {@link MediaPlayerInterface} for testing.
- */
-public class MockPlayer extends MediaPlayerInterface {
-    public final CountDownLatch mCountDownLatch;
-
-    public boolean mPlayCalled;
-    public boolean mPauseCalled;
-    public boolean mResetCalled;
-    public boolean mPrepareCalled;
-    public boolean mSeekToCalled;
-    public boolean mSetPlaybackSpeedCalled;
-    public long mSeekPosition;
-    public long mCurrentPosition;
-    public long mBufferedPosition;
-    public float mPlaybackSpeed = 1.0f;
-    public @PlayerState int mLastPlayerState;
-    public @BuffState int mLastBufferingState;
-    public long mDuration;
-
-    public ArrayMap<PlayerEventCallback, Executor> mCallbacks = new ArrayMap<>();
-
-    private AudioAttributesCompat mAudioAttributes;
-
-    public MockPlayer(int count) {
-        mCountDownLatch = (count > 0) ? new CountDownLatch(count) : null;
-    }
-
-    @Override
-    public void close() {
-        // no-op
-    }
-
-    @Override
-    public void reset() {
-        mResetCalled = true;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void play() {
-        mPlayCalled = true;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void pause() {
-        mPauseCalled = true;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void prepare() {
-        mPrepareCalled = true;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void seekTo(long pos) {
-        mSeekToCalled = true;
-        mSeekPosition = pos;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void skipToNext() {
-        // No-op. This skipToNext() means 'skip to next item in the setNextDataSources()'
-    }
-
-    @Override
-    public int getPlayerState() {
-        return mLastPlayerState;
-    }
-
-    @Override
-    public long getCurrentPosition() {
-        return mCurrentPosition;
-    }
-
-    @Override
-    public long getBufferedPosition() {
-        return mBufferedPosition;
-    }
-
-    @Override
-    public float getPlaybackSpeed() {
-        return mPlaybackSpeed;
-    }
-
-    @Override
-    public int getBufferingState() {
-        return mLastBufferingState;
-    }
-
-    @Override
-    public long getDuration() {
-        return mDuration;
-    }
-
-    @Override
-    public void registerPlayerEventCallback(@NonNull Executor executor,
-            @NonNull PlayerEventCallback callback) {
-        if (callback == null || executor == null) {
-            throw new IllegalArgumentException("callback=" + callback + " executor=" + executor);
-        }
-        mCallbacks.put(callback, executor);
-    }
-
-    @Override
-    public void unregisterPlayerEventCallback(@NonNull PlayerEventCallback callback) {
-        mCallbacks.remove(callback);
-    }
-
-    public void notifyPlaybackState(final int state) {
-        mLastPlayerState = state;
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onPlayerStateChanged(MockPlayer.this, state);
-                }
-            });
-        }
-    }
-
-    public void notifyCurrentDataSourceChanged(final DataSourceDesc dsd) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onCurrentDataSourceChanged(MockPlayer.this, dsd);
-                }
-            });
-        }
-    }
-
-    public void notifyMediaPrepared(final DataSourceDesc dsd) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onMediaPrepared(MockPlayer.this, dsd);
-                }
-            });
-        }
-    }
-
-    public void notifyBufferingStateChanged(final DataSourceDesc dsd,
-            final @BuffState int buffState) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onBufferingStateChanged(MockPlayer.this, dsd, buffState);
-                }
-            });
-        }
-    }
-
-    public void notifyPlaybackSpeedChanged(final float speed) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onPlaybackSpeedChanged(MockPlayer.this, speed);
-                }
-            });
-        }
-    }
-
-    public void notifySeekCompleted(final long position) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onSeekCompleted(MockPlayer.this, position);
-                }
-            });
-        }
-    }
-
-    public void notifyError(int what) {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            final PlayerEventCallback callback = mCallbacks.keyAt(i);
-            final Executor executor = mCallbacks.valueAt(i);
-            // TODO: Uncomment or remove
-            //executor.execute(() -> callback.onError(null, what, 0));
-        }
-    }
-
-    @Override
-    public void setAudioAttributes(AudioAttributesCompat attributes) {
-        mAudioAttributes = attributes;
-    }
-
-    @Override
-    public AudioAttributesCompat getAudioAttributes() {
-        return mAudioAttributes;
-    }
-
-    @Override
-    public void setDataSource(@NonNull DataSourceDesc dsd) {
-        // TODO: Implement this
-    }
-
-    @Override
-    public void setNextDataSource(@NonNull DataSourceDesc dsd) {
-        // TODO: Implement this
-    }
-
-    @Override
-    public void setNextDataSources(@NonNull List<DataSourceDesc> dsds) {
-        // TODO: Implement this
-    }
-
-    @Override
-    public DataSourceDesc getCurrentDataSource() {
-        // TODO: Implement this
-        return null;
-    }
-
-    @Override
-    public void loopCurrent(boolean loop) {
-        // TODO: implement this
-    }
-
-    @Override
-    public void setPlaybackSpeed(float speed) {
-        mSetPlaybackSpeedCalled = true;
-        mPlaybackSpeed = speed;
-        if (mCountDownLatch != null) {
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Override
-    public void setPlayerVolume(float volume) {
-        // TODO: implement this
-    }
-
-    @Override
-    public float getPlayerVolume() {
-        // TODO: implement this
-        return -1;
-    }
-}
diff --git a/media/version-compat-tests/current/service/src/androidTest/java/androidx/media/test/service/TestHelperService.java b/media/version-compat-tests/current/service/src/androidTest/java/androidx/media/test/service/TestHelperService.java
deleted file mode 100644
index 8df40b9..0000000
--- a/media/version-compat-tests/current/service/src/androidTest/java/androidx/media/test/service/TestHelperService.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.service;
-
-import static androidx.media.test.lib.TestHelperUtil.ACTION_TEST_HELPER;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.support.mediacompat.testlib.ITestHelperForServiceApp;
-
-import androidx.media.MediaSession2;
-
-/**
- * A Service that creates {@link MediaSession2} and calls its methods according to the client app's
- * requests.
- */
-public class TestHelperService extends Service {
-
-    MediaSession2 mSession2;
-    ServiceBinder mBinder;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mBinder = new ServiceBinder();
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        if (ACTION_TEST_HELPER.equals(intent.getAction())) {
-            return mBinder;
-        }
-        return null;
-    }
-
-    private class ServiceBinder extends ITestHelperForServiceApp.Stub {
-        @Override
-        public Bundle getSessionToken2(String testName) throws RemoteException {
-            if (Looper.myLooper() == null) {
-                Looper.prepare();
-            }
-
-            // TODO: Create the right session according to testName, and return its token here.
-            mSession2 = new MediaSession2.Builder(TestHelperService.this)
-                    .setPlayer(new MockPlayer(0))
-                    .build();
-            return mSession2.getToken().toBundle();
-        }
-
-        @Override
-        public void callMediaSession2Method(int method, Bundle args) throws RemoteException {
-            // TODO: Call appropriate method (mSession2.~~~)
-        }
-
-        // TODO: call(MediaPlayerBase/Agent)Method may be also needed.
-        // If so, do not create mPlayer/mAgent, but get them from mSession.getPlayer()/getAgent().
-    }
-}
diff --git a/media/version-compat-tests/lib/src/main/aidl/android/support/mediacompat/testlib/ITestHelperForServiceApp.aidl b/media/version-compat-tests/lib/src/main/aidl/android/support/mediacompat/testlib/ITestHelperForServiceApp.aidl
deleted file mode 100644
index d12e8ca..0000000
--- a/media/version-compat-tests/lib/src/main/aidl/android/support/mediacompat/testlib/ITestHelperForServiceApp.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.mediacompat.testlib;
-
-import android.os.Bundle;
-
-interface ITestHelperForServiceApp {
-
-    Bundle getSessionToken2(String testName);
-    void callMediaSession2Method(int method, in Bundle args);
-}
diff --git a/media/version-compat-tests/lib/src/main/java/androidx/media/test/lib/TestHelperUtil.java b/media/version-compat-tests/lib/src/main/java/androidx/media/test/lib/TestHelperUtil.java
deleted file mode 100644
index 9cc68b5..0000000
--- a/media/version-compat-tests/lib/src/main/java/androidx/media/test/lib/TestHelperUtil.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.media.test.lib;
-
-import android.content.ComponentName;
-import android.support.mediacompat.testlib.util.IntentUtil;
-
-/**
- * Methods and constants used for calling methods between client and service apps by using
- * TestHelper/TestHelperService.
- */
-public class TestHelperUtil {
-    public static final ComponentName SERVICE_TEST_HELPER_COMPONENT_NAME = new ComponentName(
-            IntentUtil.SERVICE_PACKAGE_NAME, "androidx.media.test.service.TestHelperService");
-
-    public static final String ACTION_TEST_HELPER = "androidx.media.action.test.TEST_HELPER";
-
-    private TestHelperUtil() {
-    }
-}
diff --git a/mediarouter/src/main/res/values-af/strings.xml b/mediarouter/src/main/res/values-af/strings.xml
index f2f054d..1968699 100644
--- a/mediarouter/src/main/res/values-af/strings.xml
+++ b/mediarouter/src/main/res/values-af/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Stelsel"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Toestelle"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Uitsaai-knoppie"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Uitsaai-knoppie. Ontkoppel"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Uitsaai-knoppie. Koppel tans"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Uitsaai-knoppie. Gekoppel"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Saai uit na"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Soek tans toestelle"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Ontkoppel"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Hou op uitsaai"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Maak toe"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Speel"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Onderbreek"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stop"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Vou uit"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Vou in"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albumkunswerk"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Volumeglyer"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Geen media is gekies nie"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Geen inligting is beskikbaar nie"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Saai tans skerm uit"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Stelsel"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Toestelle"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Uitsaai-knoppie"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Uitsaai-knoppie. Ontkoppel"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Uitsaai-knoppie. Koppel tans"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Uitsaai-knoppie. Gekoppel"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Saai uit na"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Soek tans toestelle"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Ontkoppel"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Hou op uitsaai"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Maak toe"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Speel"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Onderbreek"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Stop"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Vou uit"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Vou in"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albumkunswerk"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Volumeglyer"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Geen media is gekies nie"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Geen inligting is beskikbaar nie"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Saai tans skerm uit"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-am/strings.xml b/mediarouter/src/main/res/values-am/strings.xml
index 06ec198..5e4eb42 100644
--- a/mediarouter/src/main/res/values-am/strings.xml
+++ b/mediarouter/src/main/res/values-am/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"ሥርዓት"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"መሣሪያዎች"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"የCast አዝራር"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast አዝራር። ግንኙነት ተቋርጧል"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"የCast አዝራር። በመገናኘት ላይ"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"የCast አዝራር። ተገናኝቷል"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Cast አድርግ ወደ"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"መሣሪያዎችን በማግኘት ላይ"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"ግንኙነት አቋርጥ"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Cast ማድረግ አቁም"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"ዝጋ"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"አጫውት"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"ባለበት አቁም"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"አቁም"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"ዘርጋ"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"ሰብስብ"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"የአልበም ስነ-ጥበብ"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"ተንሸራታች የድምፅ መቆጣጠሪያ"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"ምንም ማህደረ መረጃ አልተመረጠም"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"ምንም መረጃ አይገኝም"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"ማያ ገጽን Cast በማድረግ ላይ"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"ሥርዓት"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"መሣሪያዎች"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"የCast አዝራር"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast አዝራር። ግንኙነት ተቋርጧል"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast አዝራር። በመገናኘት ላይ"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"የCast አዝራር። ተገናኝቷል"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Cast አድርግ ወደ"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"መሣሪያዎችን በማግኘት ላይ"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"ግንኙነት አቋርጥ"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Cast ማድረግ አቁም"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"ዝጋ"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"አጫውት"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"ለአፍታ አቁም"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"አቁም"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"ዘርጋ"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"ሰብስብ"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"የአልበም ስነ-ጥበብ"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"ተንሸራታች የድምፅ መቆጣጠሪያ"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"ምንም ማህደረ መረጃ አልተመረጠም"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"ምንም መረጃ አይገኝም"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"ማያ ገጽን Cast በማድረግ ላይ"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ar/strings.xml b/mediarouter/src/main/res/values-ar/strings.xml
index 6ff046b..12a6df3 100644
--- a/mediarouter/src/main/res/values-ar/strings.xml
+++ b/mediarouter/src/main/res/values-ar/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"النظام"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"الأجهزة"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"زر الإرسال"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"زر الإرسال. تم قطع الاتصال"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"زر الإرسال. جارٍ الاتصال"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"زر الإرسال. تم الاتصال"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"إرسال إلى"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"جارٍ البحث عن أجهزة"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"قطع اتصال"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"إيقاف الإرسال"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"إغلاق"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"تشغيل"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"إيقاف مؤقت"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"إيقاف"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"توسيع"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"تصغير"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"صورة الألبوم"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"شريط تمرير مستوى الصوت"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"لم يتم اختيار أي وسائط"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"لا تتوفر أي معلومات"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"جارٍ إرسال الشاشة"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"النظام"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"الأجهزة"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"زر الإرسال"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"زر الإرسال. تم قطع الاتصال"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"زر الإرسال. جارٍ الاتصال"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"زر الإرسال. تم الاتصال"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"إرسال إلى"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"جارٍ البحث عن أجهزة"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"قطع الاتصال"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"إيقاف الإرسال"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"إغلاق"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"تشغيل"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"إيقاف مؤقت"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"إيقاف"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"توسيع"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"تصغير"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"صورة الألبوم"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"شريط تمرير مستوى الصوت"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"لم يتم اختيار أي وسائط"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"لا تتوفر أي معلومات"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"جارٍ إرسال الشاشة"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-as/strings.xml b/mediarouter/src/main/res/values-as/strings.xml
deleted file mode 100644
index 792c255..0000000
--- a/mediarouter/src/main/res/values-as/strings.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"ছিষ্টেম"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"ডিভাইচসমূহ"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"কাষ্ট বুটাম"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"কাষ্ট বুটাম। সংযোগ বিচ্ছিন্ন কৰা হ’ল"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"কাষ্ট বুটাম। সংযোগ কৰি থকা হৈছে"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"কাষ্ট বুটাম। সংযোগ কৰা হ’ল"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"ইয়াত কাষ্ট কৰক"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"ডিভাইচ বিচাৰি থকা হৈছে"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"বিচ্ছিন্ন কৰক"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"কাষ্ট কৰা বন্ধ কৰক"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"বন্ধ কৰক"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"প্লে কৰক"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"পজ কৰক"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"ৰখাওক"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"বিস্তাৰ কৰক"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"সংকুচিত কৰক"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"এলবাম আৰ্ট"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"ধ্বনি শ্লাইডাৰ"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"কোনো মিডিয়া বাছনি কৰা হোৱা নাই"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"কোনো তথ্য নাই"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"স্ক্ৰীণ কাষ্ট কৰি থকা হৈছে"</string>
-</resources>
diff --git a/mediarouter/src/main/res/values-az/strings.xml b/mediarouter/src/main/res/values-az/strings.xml
index 8f3b518..651c84c 100644
--- a/mediarouter/src/main/res/values-az/strings.xml
+++ b/mediarouter/src/main/res/values-az/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistem"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Cihazlar"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Yayım düyməsi"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Yayım düyməsi. Bağlantı kəsildi"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Yayım düyməsi. Qoşulur"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Yayım düyməsi. Qoşuldu"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Bura yayımlayın"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Cihazlar axtarılır"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Əlaqəni silin"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Yayımı dayandırın"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Bağlayın"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Oyun"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pauza"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Dayandırın"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Genişləndirin"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Yığcamlaşdırın"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albom incəsənəti"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Səs ayarlayıcısı"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Media seçilməyib"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Əlçatan məlumat yoxdur"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Ekran yayımlanır"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistem"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Cihazlar"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Yayım düyməsi"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Yayım düyməsi. Bağlantı kəsildi"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Yayım düyməsi. Qoşulur"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Yayım düyməsi. Qoşuldu"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Bura yayımlayın"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Cihazlar axtarılır"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Ayırın"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Yayımı dayandırın"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Bağlayın"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Fasilə verin"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Dayandırın"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Dayandırın"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Genişləndirin"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Yığcamlaşdırın"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albom incəsənəti"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Səs ayarlayıcısı"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Media seçilməyib"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Əlçatan məlumat yoxdur"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Ekran yayımlanır"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-b+sr+Latn/strings.xml b/mediarouter/src/main/res/values-b+sr+Latn/strings.xml
index 91ee101..805709b 100644
--- a/mediarouter/src/main/res/values-b+sr+Latn/strings.xml
+++ b/mediarouter/src/main/res/values-b+sr+Latn/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistem"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Uređaji"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Dugme Prebaci"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Dugme Prebaci. Veza je prekinuta"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Dugme Prebaci. Povezuje se"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Dugme Prebaci. Povezan je"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Prebacite na"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Traže se uređaji"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Prekini vezu"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Zaustavi prebacivanje"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Zatvori"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Pusti"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pauziraj"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Zaustavi"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Proširi"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Skupi"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Omot albuma"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Klizač za jačinu zvuka"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nema izabranih medija"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nema dostupnih informacija"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Prebacuje se ekran"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistem"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Uređaji"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Dugme Prebaci"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Dugme Prebaci. Veza je prekinuta"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Dugme Prebaci. Povezuje se"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Dugme Prebaci. Povezan je"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Prebacite na"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Traže se uređaji"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Prekini vezu"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Zaustavi prebacivanje"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Zatvori"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Pusti"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pauziraj"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Zaustavi"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Proširi"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Skupi"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Omot albuma"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Klizač za jačinu zvuka"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nema izabranih medija"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nema dostupnih informacija"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Prebacuje se ekran"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-be/strings.xml b/mediarouter/src/main/res/values-be/strings.xml
index 208b225..b0ae4d5 100644
--- a/mediarouter/src/main/res/values-be/strings.xml
+++ b/mediarouter/src/main/res/values-be/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Сістэма"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Прылады"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Кнопка трансляцыі"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Кнопка трансляцыі. Прылада адлучана"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Кнопка трансляцыі. Прылада злучаецца"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Кнопка трансляцыі. Прылада злучана"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Трансліраваць на прыладу"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Пошук прылад"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Адлучыць"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Спыніць трансляцыю"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Закрыць"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Прайграць"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Прыпыніць"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Спыніць"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Разгарнуць"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Згарнуць"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Вокладка альбома"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Рэгулятар гучнасці"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Мультымедыя не выбрана"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Інфармацыя адсутнічае"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Трансліруецца змесціва экрана"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Сістэма"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Прылады"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Кнопка трансляцыі"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Кнопка трансляцыі. Прылада адключана"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Кнопка трансляцыі. Прылада падключаецца"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Кнопка трансляцыі. Прылада падключана"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Трансліраваць на прыладу"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Пошук прылад"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Адключыць"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Спыніць трансляцыю"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Закрыць"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Прайграць"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Паўза"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Спыніць"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Разгарнуць"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Згарнуць"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Вокладка альбома"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Рэгулятар гучнасці"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Медыяфайл не выбраны"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Інфармацыя адсутнічае"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Экран трансліруецца"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-bg/strings.xml b/mediarouter/src/main/res/values-bg/strings.xml
index 03048a1..7491533 100644
--- a/mediarouter/src/main/res/values-bg/strings.xml
+++ b/mediarouter/src/main/res/values-bg/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Система"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Устройства"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Бутон за предаване"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Бутон за предаване. Връзката е прекратена"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Бутон за предаване. Установява се връзка"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Бутон за предаване. Установена е връзка"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Предаване към"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Търсят се устройства"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Прекратяване на връзката"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Спиране на предаването"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Затваряне"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Възпроизвеждане"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Поставяне на пауза"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Спиране"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Разгъване"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Свиване"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Обложка на албума"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Плъзгач за силата на звука"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Няма избрана мултимедия"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Няма налична информация"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Екранът се предава"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Система"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Устройства"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Бутон за предаване"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Бутон за предаване. Връзката е прекратена"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Бутон за предаване. Установява се връзка"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Бутон за предаване. Установена е връзка"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Предаване към"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Търсят се устройства"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Прекратяване на връзката"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Спиране на предаването"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Затваряне"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Възпроизвеждане"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Поставяне на пауза"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Спиране"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Разгъване"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Свиване"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Обложка на албума"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Плъзгач за силата на звука"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Няма избрана мултимедия"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Няма налична информация"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Екранът се предава"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-bn/strings.xml b/mediarouter/src/main/res/values-bn/strings.xml
index 15f0f52..b3ed757 100644
--- a/mediarouter/src/main/res/values-bn/strings.xml
+++ b/mediarouter/src/main/res/values-bn/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"সিস্টেম"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"ডিভাইস"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"কাস্ট করার বোতাম"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"কাস্ট করার বোতাম। কানেক্ট করা নেই"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"কাস্ট করার বোতাম। কানেক্ট করা হচ্ছে"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"কাস্ট করার বোতাম। কানেক্ট হয়েছে"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"এখানে কাস্ট করুন:"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"ডিভাইস খোঁজা হচ্ছে"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"কানেকশন বিচ্ছিন্ন করুন"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"কাস্ট করা বন্ধ করুন"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"বন্ধ করুন"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"চালান"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"পজ করুন"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"থামান"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"বড় করে দেখুন"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"আড়াল করুন"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"অ্যালবাম আর্ট"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"ভলিউম স্লাইডার"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"কোনও মিডিয়া বেছে নেননি"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"কোনও তথ্য নেই"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"স্ক্রিন কাস্ট করা হচ্ছে"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"সিস্টেম"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"ডিভাইস"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"কাস্ট করার বোতাম"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"কাস্ট করার বোতাম। কানেক্ট করা নেই"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"কাস্ট করার বোতাম। কানেক্ট করা হচ্ছে"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"কাস্ট করার বোতাম। কানেক্ট হয়েছে"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"এখানে কাস্ট করুন"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"ডিভাইস খোঁজা হচ্ছে"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"ডিসকানেক্ট"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"কাস্ট করা বন্ধ করুন"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"বন্ধ করুন"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"চালান"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"পজ করুন"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"থামান"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"বড় করে দেখুন"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"আড়াল করুন"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"অ্যালবাম আর্ট"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"ভলিউম স্লাইডার"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"কোনও মিডিয়া বেছে নেওয়া হয়নি"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"কোনও তথ্য উপলভ্য নেই"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"স্ক্রিন কাস্ট করা হচ্ছে"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-bs/strings.xml b/mediarouter/src/main/res/values-bs/strings.xml
index 11ba502..553efdf 100644
--- a/mediarouter/src/main/res/values-bs/strings.xml
+++ b/mediarouter/src/main/res/values-bs/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistem"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Uređaji"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Dugme za emitiranje"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Dugme za emitiranje. Veza je prekinuta"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Dugme za emitiranje. Povezivanje"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Dugme za emitiranje. Povezano"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Emitiranje na"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Traženje uređaja"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Prekini vezu"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Zaustavi emitiranje"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Zatvori"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Pokreni"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pauziraj"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Zaustavi"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Proširi"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Suzi"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Omot albuma"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Klizač za jačinu zvuka"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nije odabran nijedan medij"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nema dostupnih informacija"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Emitiranje ekrana"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistem"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Uređaji"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Dugme za emitiranje"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Dugme za emitiranje. Veza je prekinuta"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Dugme za emitiranje. Povezivanje"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Dugme za emitiranje. Povezano"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Emitiranje na"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Traženje uređaja"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Prekini vezu"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Zaustavi emitiranje"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Zatvori"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Reproduciraj"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pauza"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Zaustavi"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Proširi"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Skupi"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Omot albuma"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Klizač za jačinu zvuka"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nije odabran nijedan medij"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nema dostupnih informacija"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Emitiranje ekrana"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ca/strings.xml b/mediarouter/src/main/res/values-ca/strings.xml
index d5ea5b6..e6a2f71 100644
--- a/mediarouter/src/main/res/values-ca/strings.xml
+++ b/mediarouter/src/main/res/values-ca/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistema"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Dispositius"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Botó d\'emetre"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Botó d\'emetre. Desconnectat."</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Botó d\'emetre. S\'està connectant."</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Botó d\'emetre. Connectat."</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Emet contingut a"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"S\'estan cercant dispositius"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Desconnecta"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Atura l\'emissió"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Tanca"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Reprodueix"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Posa en pausa"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Atura"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Desplega"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Replega"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Imatge de l\'àlbum"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Control lliscant de volum"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"No hi ha contingut multimèdia seleccionat"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"No hi ha informació disponible"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"S\'està emetent la pantalla"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistema"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Dispositius"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Botó d\'emetre"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Botó d\'emetre. Desconnectat."</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Botó d\'emetre. S\'està connectant."</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Botó d\'emetre. Connectat."</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Emet contingut a"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"S\'estan cercant dispositius"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Desconnecta"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Atura l\'emissió"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Tanca"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Reprodueix"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Posa en pausa"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Atura"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Desplega"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Replega"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Imatge de l\'àlbum"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Control lliscant de volum"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"No hi ha contingut multimèdia seleccionat"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"No hi ha informació disponible"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"S\'està emetent la pantalla"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-cs/strings.xml b/mediarouter/src/main/res/values-cs/strings.xml
index d8e6c6b..a914d34 100644
--- a/mediarouter/src/main/res/values-cs/strings.xml
+++ b/mediarouter/src/main/res/values-cs/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Systém"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Zařízení"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Tlačítko odesílání"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Tlačítko odesílání. Odpojeno"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Tlačítko odesílání. Připojování"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Tlačítko odesílání. Připojeno"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Odeslat do zařízení"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Hledání zařízení"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Odpojit"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Zastavit odesílání"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Zavřít"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Přehrát"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pozastavit"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Zastavit"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Rozbalit"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Sbalit"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Obal alba"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Posuvník hlasitosti"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Není vybrán žádný mediální obsah"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nejsou k dispozici žádné informace"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Odesílání obsahu obrazovky"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Systém"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Zařízení"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Tlačítko odesílání"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Tlačítko odesílání. Odpojeno"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Tlačítko odesílání. Připojování"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Tlačítko odesílání. Připojeno"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Odeslat do zařízení"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Hledání zařízení"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Odpojit"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Zastavit odesílání"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Zavřít"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Přehrát"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pozastavit"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Ukončit"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Rozbalit"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Sbalit"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Obal alba"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Posuvník hlasitosti"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Není vybrán žádný mediální obsah"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nejsou k dispozici žádné informace"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Odesílání obsahu obrazovky"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-da/strings.xml b/mediarouter/src/main/res/values-da/strings.xml
index 5a95576..5736cb5 100644
--- a/mediarouter/src/main/res/values-da/strings.xml
+++ b/mediarouter/src/main/res/values-da/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"System"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Enheder"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast-knap"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast-knap. Forbindelsen er afbrudt"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast-knap. Opretter forbindelse"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast-knap. Der er oprettet forbindelse"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Cast til"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Finder enheder"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Afbryd forbindelse"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Stop med at caste"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Luk"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Afspil"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Sæt på pause"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stop"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Udvid"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Skjul"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albumgrafik"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Lydstyrkeskyder"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Ingen medier er markeret"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Der er ingen tilgængelige oplysninger"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Skærmen castes"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"System"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Enheder"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast-knap"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast-knap. Forbindelsen er afbrudt"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast-knap. Opretter forbindelse"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast-knap. Tilsluttet"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Cast til"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Finder enheder"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Afbryd"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Stop med at caste"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Luk"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Afspil"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Sæt på pause"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Stop"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Udvid"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Skjul"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albumgrafik"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Lydstyrkeskyder"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Ingen medier er markeret"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Der er ingen tilgængelige oplysninger"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Skærmen castes"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-de/strings.xml b/mediarouter/src/main/res/values-de/strings.xml
index e2927da..bfab0be 100644
--- a/mediarouter/src/main/res/values-de/strings.xml
+++ b/mediarouter/src/main/res/values-de/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"System"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Geräte"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast-Symbol"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast-Symbol. Nicht verbunden."</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast-Symbol. Verbindung wird hergestellt."</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast-Symbol. Verbunden."</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Streamen auf"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Geräte werden gesucht"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Trennen"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Streaming beenden"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Schließen"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Wiedergabe"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pause"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stopp"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Maximieren"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Minimieren"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albumcover"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Schieberegler für die Lautstärke"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Keine Medien ausgewählt"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Keine Informationen verfügbar"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Bildschirm wird übertragen"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"System"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Geräte"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast-Symbol"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast-Symbol. Nicht verbunden"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast-Symbol. Verbindung wird hergestellt"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast-Symbol. Verbunden"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Streamen auf"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Keine Geräte gefunden"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Trennen"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Streaming beenden"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Schließen"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Wiedergeben"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pausieren"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Beenden"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Maximieren"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Minimieren"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albumcover"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Schieberegler für die Lautstärke"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Keine Medien ausgewählt"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Keine Informationen verfügbar"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Bildschirm wird übertragen"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-el/strings.xml b/mediarouter/src/main/res/values-el/strings.xml
index d689f25..6290c3d 100644
--- a/mediarouter/src/main/res/values-el/strings.xml
+++ b/mediarouter/src/main/res/values-el/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Σύστημα"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Συσκευές"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Κουμπί μετάδοσης"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Κουμπί μετάδοσης. Αποσυνδέθηκε"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Κουμπί μετάδοσης. Σύνδεση"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Κουμπί μετάδοσης. Συνδέθηκε"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Μετάδοση σε"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Εύρεση συσκευών"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Αποσύνδεση"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Διακοπή μετάδοσης"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Κλείσιμο"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Αναπαραγωγή"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Παύση"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Διακοπή"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Ανάπτυξη"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Σύμπτυξη"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Εξώφυλλο άλμπουμ"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Ρυθμιστικό έντασης ήχου"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Δεν επιλέχθηκαν μέσα"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Δεν υπάρχουν διαθέσιμες πληροφορίες"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Μετάδοση οθόνης"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Σύστημα"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Συσκευές"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Κουμπί μετάδοσης"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Κουμπί μετάδοσης. Αποσυνδέθηκε."</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Κουμπί μετάδοση. Σύνδεση."</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Κουμπί μετάδοσης. Συνδέθηκε."</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Μετάδοση σε"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Εύρεση συσκευών"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Αποσύνδεση"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Διακοπή μετάδοσης"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Κλείσιμο"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Αναπαραγωγή"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Παύση"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Διακοπή"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Ανάπτυξη"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Σύμπτυξη"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Εξώφυλλο άλμπουμ"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Ρυθμιστικό έντασης ήχου"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Δεν επιλέχθηκαν μέσα"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Δεν υπάρχουν διαθέσιμες πληροφορίες"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Μετάδοση οθόνης"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-en-rAU/strings.xml b/mediarouter/src/main/res/values-en-rAU/strings.xml
index df5801c..420d536 100644
--- a/mediarouter/src/main/res/values-en-rAU/strings.xml
+++ b/mediarouter/src/main/res/values-en-rAU/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"System"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Devices"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast button"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast button. Disconnected"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast button. Connecting"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast button. Connected"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Cast to"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Finding devices"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Disconnect"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Stop casting"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Close"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Play"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pause"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stop"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Expand"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Collapse"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Album art"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Volume slider"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"No media selected"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"No info available"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Casting screen"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"System"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Devices"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast button"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast button. Disconnected"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast button. Connecting"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast button. Connected"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Cast to"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Finding devices"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Disconnect"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Stop casting"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Close"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Play"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pause"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Stop"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Expand"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Collapse"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Album art"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Volume slider"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"No media selected"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"No info available"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Casting screen"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-en-rCA/strings.xml b/mediarouter/src/main/res/values-en-rCA/strings.xml
index df5801c..420d536 100644
--- a/mediarouter/src/main/res/values-en-rCA/strings.xml
+++ b/mediarouter/src/main/res/values-en-rCA/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"System"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Devices"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast button"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast button. Disconnected"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast button. Connecting"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast button. Connected"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Cast to"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Finding devices"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Disconnect"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Stop casting"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Close"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Play"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pause"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stop"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Expand"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Collapse"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Album art"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Volume slider"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"No media selected"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"No info available"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Casting screen"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"System"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Devices"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast button"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast button. Disconnected"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast button. Connecting"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast button. Connected"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Cast to"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Finding devices"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Disconnect"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Stop casting"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Close"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Play"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pause"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Stop"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Expand"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Collapse"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Album art"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Volume slider"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"No media selected"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"No info available"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Casting screen"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-en-rGB/strings.xml b/mediarouter/src/main/res/values-en-rGB/strings.xml
index df5801c..420d536 100644
--- a/mediarouter/src/main/res/values-en-rGB/strings.xml
+++ b/mediarouter/src/main/res/values-en-rGB/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"System"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Devices"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast button"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast button. Disconnected"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast button. Connecting"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast button. Connected"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Cast to"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Finding devices"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Disconnect"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Stop casting"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Close"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Play"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pause"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stop"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Expand"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Collapse"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Album art"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Volume slider"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"No media selected"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"No info available"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Casting screen"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"System"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Devices"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast button"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast button. Disconnected"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast button. Connecting"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast button. Connected"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Cast to"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Finding devices"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Disconnect"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Stop casting"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Close"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Play"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pause"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Stop"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Expand"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Collapse"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Album art"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Volume slider"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"No media selected"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"No info available"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Casting screen"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-en-rIN/strings.xml b/mediarouter/src/main/res/values-en-rIN/strings.xml
index df5801c..420d536 100644
--- a/mediarouter/src/main/res/values-en-rIN/strings.xml
+++ b/mediarouter/src/main/res/values-en-rIN/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"System"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Devices"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast button"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast button. Disconnected"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast button. Connecting"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast button. Connected"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Cast to"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Finding devices"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Disconnect"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Stop casting"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Close"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Play"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pause"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stop"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Expand"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Collapse"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Album art"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Volume slider"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"No media selected"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"No info available"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Casting screen"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"System"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Devices"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast button"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast button. Disconnected"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast button. Connecting"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast button. Connected"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Cast to"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Finding devices"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Disconnect"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Stop casting"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Close"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Play"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pause"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Stop"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Expand"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Collapse"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Album art"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Volume slider"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"No media selected"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"No info available"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Casting screen"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-en-rXC/strings.xml b/mediarouter/src/main/res/values-en-rXC/strings.xml
index 993d212..03083ad 100644
--- a/mediarouter/src/main/res/values-en-rXC/strings.xml
+++ b/mediarouter/src/main/res/values-en-rXC/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‎System‎‏‎‎‏‎"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎Devices‎‏‎‎‏‎"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎Cast button‎‏‎‎‏‎"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎Cast button. Disconnected‎‏‎‎‏‎"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎Cast button. Connecting‎‏‎‎‏‎"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‏‏‏‎Cast button. Connected‎‏‎‎‏‎"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎Cast to‎‏‎‎‏‎"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‎Finding devices‎‏‎‎‏‎"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‏‏‎‎‏‏‏‏‏‏‎Disconnect‎‏‎‎‏‎"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎Stop casting‎‏‎‎‏‎"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎Close‎‏‎‎‏‎"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎Play‎‏‎‎‏‎"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‏‎‎‏‎Pause‎‏‎‎‏‎"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‎Stop‎‏‎‎‏‎"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‎‎Expand‎‏‎‎‏‎"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‏‏‏‎‏‎Collapse‎‏‎‎‏‎"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎‎Album art‎‏‎‎‏‎"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‎‎Volume slider‎‏‎‎‏‎"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎No media selected‎‏‎‎‏‎"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‎‎No info available‎‏‎‎‏‎"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎Casting screen‎‏‎‎‏‎"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎System‎‏‎‎‏‎"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‎‏‎‏‎Devices‎‏‎‎‏‎"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‏‏‎Cast button‎‏‎‎‏‎"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎Cast button. Disconnected‎‏‎‎‏‎"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎Cast button. Connecting‎‏‎‎‏‎"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎Cast button. Connected‎‏‎‎‏‎"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‎‏‏‎Cast to‎‏‎‎‏‎"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‎Finding devices‎‏‎‎‏‎"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎Disconnect‎‏‎‎‏‎"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‎‎‏‎‎‎‎‎Stop casting‎‏‎‎‏‎"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎Close‎‏‎‎‏‎"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‏‎‎‏‎‎‎‎‎‎Play‎‏‎‎‏‎"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎‏‏‏‏‏‎‏‎Pause‎‏‎‎‏‎"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎Stop‎‏‎‎‏‎"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎Expand‎‏‎‎‏‎"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎Collapse‎‏‎‎‏‎"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‎‎‎‎Album art‎‏‎‎‏‎"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎Volume slider‎‏‎‎‏‎"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‎No media selected‎‏‎‎‏‎"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‎‎‎No info available‎‏‎‎‏‎"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎Casting screen‎‏‎‎‏‎"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-es-rUS/strings.xml b/mediarouter/src/main/res/values-es-rUS/strings.xml
index cec1175..51a2955 100644
--- a/mediarouter/src/main/res/values-es-rUS/strings.xml
+++ b/mediarouter/src/main/res/values-es-rUS/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistema"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Dispositivos"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Botón para transmitir"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Botón para transmitir (desconectado)"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Botón para transmitir (conectando)"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Botón para transmitir (conectado)"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Transmitir a"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Buscando dispositivos"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Desconectar"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Detener transmisión"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Cerrar"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Reproducir"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pausa"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Detener"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Expandir"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Contraer"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Imagen del álbum"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Control deslizante del volumen"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"No se seleccionó ningún contenido multimedia"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Sin información disponible"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Transmitiendo pantalla"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistema"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Dispositivos"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Botón para transmitir"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Botón para transmitir (desconectado)"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Botón para transmitir (conectando)"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Botón para transmitir (conectado)"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Transmitir a"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Buscando dispositivos"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Desconectar"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Detener transmisión"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Cerrar"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Reproducir"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pausar"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Detener"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Expandir"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Contraer"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Imagen del álbum"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Control deslizante del volumen"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"No se seleccionó ningún contenido multimedia"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Sin información disponible"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Transmitiendo pantalla"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-es/strings.xml b/mediarouter/src/main/res/values-es/strings.xml
index 34de0dc..e07a751 100644
--- a/mediarouter/src/main/res/values-es/strings.xml
+++ b/mediarouter/src/main/res/values-es/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistema"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Dispositivos"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Botón de enviar"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Botón de enviar. Desconectado"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Botón de enviar. Conectando"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Botón de enviar. Conectado"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Enviar a"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Buscando dispositivos"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Desconectar"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Detener envío"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Cerrar"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Reproducir"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pausar"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Detener"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Mostrar"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Ocultar"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Carátula del álbum"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Control deslizante de volumen"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"No se ha seleccionado contenido multimedia"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"No hay información disponible"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Enviando pantalla"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistema"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Dispositivos"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Botón de enviar"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Botón de enviar. Desconectado"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Botón de enviar. Conectando"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Botón de enviar. Conectado"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Enviar a"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Buscando dispositivos"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Desconectar"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Detener envío"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Cerrar"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Reproducir"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pausar"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Detener"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Mostrar"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Ocultar"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Carátula del álbum"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Control deslizante de volumen"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"No se ha seleccionado contenido multimedia"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"No hay información disponible"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Enviando pantalla"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-et/strings.xml b/mediarouter/src/main/res/values-et/strings.xml
index 386462a..4ff3f62 100644
--- a/mediarouter/src/main/res/values-et/strings.xml
+++ b/mediarouter/src/main/res/values-et/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Süsteem"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Seadmed"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Ülekandenupp"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Ülekandenupp. Ühendus on katkestatud"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Ülekandenupp. Ühendamine"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Ülekandenupp. Ühendatud"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Ülekandmine seadmesse"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Seadmete otsimine"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Katkesta ühendus"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Katkesta ülekandmine"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Sule"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Esita"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Peata"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Katkesta"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Laienda"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Ahenda"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albumi kujundus"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Helitugevuse liugur"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Meediat pole valitud"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Teave pole saadaval"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Ekraanikuva ülekandmine"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Süsteem"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Seadmed"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Ülekandenupp"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Ülekandenupp. Ühendus on katkestatud"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Ülekandenupp. Ühendamine"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Ülekandenupp. Ühendatud"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Ülekandmine seadmesse"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Seadmete otsimine"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Katkesta ühendus"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Peata ülekandmine"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Sulgemine"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Esitamine"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Peatamine"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Peatamine"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Laiendamine"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Ahendamine"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albumi kujundus"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Helitugevuse liugur"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Meediat pole valitud"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Teave pole saadaval"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Ekraanikuva ülekandmine"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-eu/strings.xml b/mediarouter/src/main/res/values-eu/strings.xml
index d8749f3..18aeed3 100644
--- a/mediarouter/src/main/res/values-eu/strings.xml
+++ b/mediarouter/src/main/res/values-eu/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistema"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Gailuak"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"\"Igorri\" botoia"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"\"Igorri\" botoia. Deskonektatuta."</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"\"Igorri\" botoia. Konektatzen."</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"\"Igorri\" botoia. Konektatuta."</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Igorri hona"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Gailuak bilatzen"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Deskonektatu"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Utzi igortzeari"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Itxi"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Erreproduzitu"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pausatu"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Gelditu"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Zabaldu"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Tolestu"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albumaren azala"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Bolumenaren graduatzailea"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Ez da hautatu multimedia-edukirik"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Ez dago informaziorik"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Pantaila igortzen"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistema"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Gailuak"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Igorri botoia"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Igortzeko botoia. Deskonektatuta"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Igortzeko botoia. Konektatzen"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Igortzeko botoia. Konektatuta"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Igorri hona"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Gailuak bilatzen"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Deskonektatu"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Utzi igortzeari"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Itxi"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Erreproduzitu"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pausatu"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Gelditu"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Zabaldu"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Tolestu"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albumaren azala"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Bolumenaren graduatzailea"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Ez da ezer hautatu"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Ez dago informaziorik"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Pantaila igortzen"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-fa/strings.xml b/mediarouter/src/main/res/values-fa/strings.xml
index 4c9928e..eb0ea6c 100644
--- a/mediarouter/src/main/res/values-fa/strings.xml
+++ b/mediarouter/src/main/res/values-fa/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"سیستم"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"دستگاه‌ها"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"دکمه فرستادن"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"دکمه فرستادن. اتصال قطع شد"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"دکمه فرستادن. درحال اتصال"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"دکمه فرستادن. متصل"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"ارسال محتوا به"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"درحال پیدا کردن دستگاه‌ها"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"قطع اتصال"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"توقف ارسال محتوا"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"بستن"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"پخش"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"مکث"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"توقف"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"بزرگ کردن"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"کوچک کردن"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"عکس روی جلد آلبوم"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"لغزنده میزان صدا"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"رسانه‌ای انتخاب نشده است"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"اطلاعاتی دردسترس نیست"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"صفحه ارسال محتوا"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"سیستم"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"دستگاه‌ها"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"دکمه ارسال محتوا"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"دکمه فرستادن. اتصال قطع شد"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"دکمه فرستادن. درحال اتصال"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"دکمه فرستادن. متصل"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"ارسال محتوا به"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"پیدا کردن دستگاه‌ها"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"قطع اتصال"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"توقف ارسال محتوا"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"بستن"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"پخش"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"مکث"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"توقف"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"بزرگ کردن"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"کوچک کردن"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"عکس روی جلد آلبوم"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"لغزنده میزان صدا"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"رسانه‌ای انتخاب نشده است"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"اطلاعات دردسترس نیست"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"صفحه ارسال محتوا"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-fi/strings.xml b/mediarouter/src/main/res/values-fi/strings.xml
index 6c51525..a365147 100644
--- a/mediarouter/src/main/res/values-fi/strings.xml
+++ b/mediarouter/src/main/res/values-fi/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Järjestelmä"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Laitteet"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast-painike"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast-painike. Yhteys katkaistu"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast-painike. Yhdistetään"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast-painike. Yhdistetty"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Suoratoiston kohde"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Etsitään laitteita"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Katkaise yhteys"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Lopeta suoratoisto"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Sulje"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Toista"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Keskeytä"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Pysäytä"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Laajenna"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Tiivistä"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albumin kansikuva"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Äänenvoimakkuuden liukusäädin"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Ei valittua mediaa"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Ei tietoja saatavilla"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Suoratoistetaan näyttöä"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Järjestelmä"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Laitteet"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast-painike"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast-painike. Yhteys katkaistu"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast-painike. Yhdistetään"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast-painike. Yhdistetty"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Suoratoiston kohde"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Etsitään laitteita"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Katkaise yhteys"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Lopeta suoratoisto"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Sulje"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Toista"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Keskeytä"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Lopeta"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Laajenna"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Tiivistä"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albumin kansikuva"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Äänenvoimakkuuden liukusäädin"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Ei valittua mediaa"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Ei tietoja saatavilla"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Suoratoistetaan näyttöä"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-fr-rCA/strings.xml b/mediarouter/src/main/res/values-fr-rCA/strings.xml
index e5cb25e..8df9031 100644
--- a/mediarouter/src/main/res/values-fr-rCA/strings.xml
+++ b/mediarouter/src/main/res/values-fr-rCA/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Système"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Appareils"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Bouton Diffuser"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Bouton Diffuser. Déconnecté"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Bouton Diffuser. Connexion en cours…"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Bouton Diffuser. Connecté"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Diffuser vers"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Recherche d\'appareils en cours…"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Déconnecter"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Arrêter la diffusion"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Fermer"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Lire"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pause"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Arrêter"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Développer"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Réduire"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Image de l\'album"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Curseur de réglage du volume"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Aucun média sélectionné"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Aucune donnée trouvée"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Diffusion de l\'écran en cours…"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Système"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Appareils"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Bouton Diffuser"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Bouton Diffuser. Déconnecté"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Bouton Diffuser. Connexion en cours…"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Bouton Diffuser. Connecté"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Diffuser vers"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Recherche d\'appareils"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Dissocier"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Arrêter la diffusion"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Fermer"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Lire"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pause"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Arrêter"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Développer"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Réduire"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Image de l\'album"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Curseur de réglage du volume"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Aucun média sélectionné"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Aucune donnée trouvée"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Diffusion de l\'écran en cours"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-fr/strings.xml b/mediarouter/src/main/res/values-fr/strings.xml
index 8518e0b..cfce49b 100644
--- a/mediarouter/src/main/res/values-fr/strings.xml
+++ b/mediarouter/src/main/res/values-fr/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Système"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Appareils"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Icône Cast"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Icône Cast. Déconnecté"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Icône Cast. Connexion…"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Icône Cast. Connecté"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Caster sur"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Recherche d\'appareils…"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Déconnecter"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Arrêter la diffusion"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Fermer"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Lecture"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pause"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Arrêt"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Développer"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Réduire"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Image de l\'album"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Curseur de volume"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Aucun contenu multimédia sélectionné"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Aucune information disponible"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Diffusion de l\'écran…"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Système"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Appareils"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Icône Cast"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Icône Cast. Déconnecté"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Icône Cast. Connexion…"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Icône Cast. Connecté"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Caster sur"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Recherche d\'appareils…"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Déconnecter"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Arrêter la diffusion"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Fermer"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Lecture"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pause"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Arrêt"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Développer"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Réduire"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Image de l\'album"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Curseur de volume"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Aucun contenu multimédia sélectionné"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Aucune information disponible"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Diffusion de l\'écran"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-gl/strings.xml b/mediarouter/src/main/res/values-gl/strings.xml
index df0480f..2eb5e04 100644
--- a/mediarouter/src/main/res/values-gl/strings.xml
+++ b/mediarouter/src/main/res/values-gl/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistema"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Dispositivos"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Botón de emitir"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Botón de emitir. Desconectado"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Botón de emitir. Conectando"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Botón de emitir. Conectado"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Emitir en"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Buscando dispositivos"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Desconectar"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Deter emisión"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Pechar"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Reproducir"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pór en pausa"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Deter"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Despregar"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Contraer"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Portada do álbum"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Control desprazable do volume"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Non se seleccionou ningún recurso multimedia"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Non hai información dispoñible"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Emitindo pantalla"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistema"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Dispositivos"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Botón de emitir"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Botón de emitir. Desconectado"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Botón de emitir. Conectando"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Botón de emitir. Conectado"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Emitir en"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Buscando dispositivos"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Desconectar"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Deter emisión"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Pechar"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Reproducir"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pausar"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Deter"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Despregar"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Contraer"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Portada do álbum"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Control desprazable do volume"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Non se seleccionou ningún recurso multimedia"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Non hai información dispoñible"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Emitindo a pantalla"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-gu/strings.xml b/mediarouter/src/main/res/values-gu/strings.xml
index e83daf2..8459bcd 100644
--- a/mediarouter/src/main/res/values-gu/strings.xml
+++ b/mediarouter/src/main/res/values-gu/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"સિસ્ટમ"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"ઉપકરણો"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"કાસ્ટ બટન"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"કાસ્ટ બટન. ડિસ્કનેક્ટેડ"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"કાસ્ટ બટન. કનેક્ટ કરી રહ્યાં છીએ"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"કાસ્ટ બટન. કનેક્ટેડ"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"આના પર કાસ્ટ કરો"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"ઉપકરણો શોધી રહ્યાં છીએ"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"ડિસ્કનેક્ટ કરો"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"કાસ્ટ કરવાનું રોકો"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"બંધ કરો"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"ચલાવો"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"થોભાવો"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"રોકો"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"વિસ્તાર કરો"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"સંકુચિત કરો"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"આલ્બમ આર્ટ"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"વૉલ્યુમ સ્લાઇડર"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"કોઈ મીડિયા પસંદ કરેલ નથી"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"કોઈ માહિતી ઉપલબ્ધ નથી"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"સ્ક્રીનને કાસ્ટ કરી રહ્યાં છીએ"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"સિસ્ટમ"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"ઉપકરણો"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"કાસ્ટ બટન"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"કાસ્ટ બટન. ડિસ્કનેક્ટેડ"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"કાસ્ટ બટન. કનેક્ટ કરી રહ્યાં છીએ"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"કાસ્ટ બટન. કનેક્ટેડ"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"આના પર કાસ્ટ કરો"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"ઉપકરણો શોધી રહ્યાં છીએ"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"ડિસ્કનેક્ટ કરો"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"કાસ્ટ કરવાનું રોકો"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"બંધ કરો"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"ચલાવો"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"થોભાવો"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"રોકો"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"વિસ્તાર કરો"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"સંકુચિત કરો"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"આલ્બમ આર્ટ"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"વૉલ્યુમ સ્લાઇડર"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"કોઈ મીડિયા પસંદ કરેલ નથી"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"કોઈ માહિતી ઉપલબ્ધ નથી"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"સ્ક્રીનને કાસ્ટ કરી રહ્યાં છીએ"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-hi/strings.xml b/mediarouter/src/main/res/values-hi/strings.xml
index 5026adc..891d765 100644
--- a/mediarouter/src/main/res/values-hi/strings.xml
+++ b/mediarouter/src/main/res/values-hi/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"सिस्टम"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"डिवाइस"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"कास्ट बटन"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"कास्ट बटन. डिसकनेक्ट हो गया"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"कास्ट बटन. कनेक्ट हो रहा है"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"कास्ट बटन. कनेक्ट हो गया"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"इस पर कास्‍ट करें"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"डिवाइस ढूंढे जा रहे हैं"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"डिसकनेक्ट करें"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"कास्ट करना रोकें"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"बंद करें"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"चलाएं"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"रोकें"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"बंद करें"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"बड़ा करके देखें"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"छोटा करें"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"एल्बम आर्ट"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"आवाज़ बढ़ाने या घटाने वाला स्लाइडर"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"कोई मीडिया नहीं चुना गया"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"कोई जानकारी मौजूद नहीं है"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"स्क्रीन कास्ट की जा रही है"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"सिस्‍टम"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"डिवाइस"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"कास्ट करें बटन"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"कास्ट करें बटन. नहीं जुड़ा है"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"कास्ट करें बटन. जुड़ रहा है"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"कास्ट करें बटन. जुड़ा है"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"इस पर कास्‍ट करें"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"डिवाइस ढूंढे जा रहे हैं"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"कनेक्शन हटाएं"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"कास्ट करना रोकें"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"बंद करें"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"चलाएं"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"रोकें"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"रुकें"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"सदस्याें की सूची को बड़ा करके देखें"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"सदस्याें की सूची छोटी करें"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"एल्बम आर्ट"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"आवाज़ बढ़ाने या घटाने वाला स्लाइडर"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"कोई मीडिया चुना नहीं गया"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"कोई जानकारी मौजूद नहीं है"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"स्क्रीन कास्ट की जा रही है"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-hr/strings.xml b/mediarouter/src/main/res/values-hr/strings.xml
index 425cf36..e17a0e7 100644
--- a/mediarouter/src/main/res/values-hr/strings.xml
+++ b/mediarouter/src/main/res/values-hr/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sustav"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Uređaji"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Gumb za emitiranje"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Gumb za emitiranje. Veza prekinuta"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Gumb za emitiranje. Povezivanje"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Gumb za emitiranje. Povezan"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Emitiranje na"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Traženje uređaja"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Prekini vezu"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Zaustavi emitiranje"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Zatvori"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Reproduciraj"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pauziraj"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Zaustavi"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Proširi"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Sažmi"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Naslovnica albuma"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Klizač za glasnoću"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nije odabran nijedan medij"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Informacije nisu dostupne"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Emitiranje zaslona"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sustav"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Uređaji"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Gumb za emitiranje"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Gumb za emitiranje. Veza prekinuta"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Gumb za emitiranje. Povezivanje"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Gumb za emitiranje. Povezan"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Emitiranje na"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Traženje uređaja"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Prekini"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Zaustavi emitiranje"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Zatvori"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Pokreni"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pauza"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Zaustavi"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Proširi"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Sažmi"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Naslovnica albuma"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Klizač za glasnoću"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nije odabran nijedan medij"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Informacije nisu dostupne"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Emitiranje zaslona"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-hu/strings.xml b/mediarouter/src/main/res/values-hu/strings.xml
index 7d47861..a9f80f4 100644
--- a/mediarouter/src/main/res/values-hu/strings.xml
+++ b/mediarouter/src/main/res/values-hu/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Rendszer"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Eszközök"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Átküldés gomb"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Átküldés gomb. Kapcsolat bontva"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Átküldés gomb. Csatlakozás"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Átküldés gomb. Csatlakoztatva"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Átküldés ide:"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Eszközök keresése"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Leválasztás"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Átküldés leállítása"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Bezárás"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Lejátszás"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Szünet"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Leállítás"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Kibontás"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Összecsukás"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Lemezborító"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Hangerőszabályzó"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nincs kiválasztott médiatartalom"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nincs információ"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Képernyőtartalom átküldése…"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Rendszer"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Eszközök"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Átküldés gomb"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Átküldés gomb. Kapcsolat bontva"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Átküldés gomb. Csatlakozás"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Átküldés gomb. Csatlakoztatva"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Átküldés ide:"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Eszközök keresése"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Leválasztás"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Átküldés leállítása"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Bezárás"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Lejátszás"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Szünet"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Leállítás"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Kibontás"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Összecsukás"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Lemezborító"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Hangerőszabályzó"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nincs médiatartalom kiválasztva"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nincs információ"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Képernyőtartalom átküldése…"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-hy/strings.xml b/mediarouter/src/main/res/values-hy/strings.xml
index 77cba70..e48fac5 100644
--- a/mediarouter/src/main/res/values-hy/strings.xml
+++ b/mediarouter/src/main/res/values-hy/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Համակարգ"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Սարքեր"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Հեռարձակման կոճակ"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Հեռարձակման կոճակ: Սարքն անջատած է:"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Հեռարձակման կոճակ: Սարքը միանում է:"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Հեռարձակման կոճակ: Սարքը միացված է:"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Ընտրեք սարք"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Սարքերի որոնում"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Անջատել"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Դադարեցնել հեռարձակումը"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Փակել"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Նվագարկել"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Դադարեցնել"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Կանգնեցնել"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Ծավալել"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Ծալել"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Ալբոմի շապիկ"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Ձայնի ուժգնության կարգավորիչ"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Մեդիա ֆայլ չի ընտրվել"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Տեղեկություններ չկան"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Էկրանի հեռարձակում"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Համակարգ"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Սարքեր"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Հեռարձակման կոճակ"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Հեռարձակման կոճակ: Սարքն անջատած է:"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Հեռարձակման կոճակ: Սարքը միանում է:"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Հեռարձակման կոճակ: Սարքը միացված է:"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Ընտրեք սարք"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Սարքերի որոնում"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Անջատել"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Դադարեցնել հեռարձակումը"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Փակել"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Նվագարկել"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Ընդհատել"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Դադարեցնել"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Ընդարձակել"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Կոծկել"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Ալբոմի շապիկ"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Ձայնի ուժգնության կարգավորիչ"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Մեդիա ֆայլ չի ընտրվել"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Հասանելի տեղեկություններ չկան"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Էկրանի հեռարձակում"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-in/strings.xml b/mediarouter/src/main/res/values-in/strings.xml
index 777f85b..5a19254 100644
--- a/mediarouter/src/main/res/values-in/strings.xml
+++ b/mediarouter/src/main/res/values-in/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistem"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Perangkat"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Tombol Cast"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Tombol Cast. Terputus"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Tombol Cast. Menghubungkan"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Tombol Cast. Terhubung"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Cast ke"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Mencari perangkat"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Putuskan hubungan"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Hentikan cast"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Tutup"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Putar"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Jeda"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Berhenti"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Luaskan"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Ciutkan"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Sampul album"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Penggeser volume"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Tidak ada media yang dipilih"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Tidak ada info yang tersedia"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Melakukan cast layar"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistem"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Perangkat"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Tombol Cast"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Tombol Cast. Terputus"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Tombol Cast. Menghubungkan"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Tombol Cast. Terhubung"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Cast ke"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Mencari perangkat"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Putuskan hubungan"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Hentikan cast"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Tutup"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Putar"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Jeda"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Berhenti"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Luaskan"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Ciutkan"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Sampul album"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Penggeser volume"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Tidak ada media yang dipilih"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Tidak ada info yang tersedia"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Melakukan cast layar"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-is/strings.xml b/mediarouter/src/main/res/values-is/strings.xml
index 66334e4..bc3c36d 100644
--- a/mediarouter/src/main/res/values-is/strings.xml
+++ b/mediarouter/src/main/res/values-is/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Kerfi"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Tæki"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Útsendingarhnappur"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Útsendingarhnappur. Aftengt"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Útsendingarhnappur. Tengist"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Útsendingarhnappur. Tengt"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Senda út í"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Leitað að tækjum"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Aftengja"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Stöðva útsendingu"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Loka"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Spila"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Gera hlé"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stöðva"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Stækka"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Draga saman"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Plötuumslag"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Hljóðstyrkssleði"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Ekkert efni valið"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Engar upplýsingar í boði"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Skjár sendur út"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Kerfi"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Tæki"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Útsendingarhnappur"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Útsendingarhnappur. Aftengt"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Útsendingarhnappur. Tengist"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Útsendingarhnappur. Tengt"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Senda út í"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Leitað að tækj"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Aftengja"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Stöðva útsendingu"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Loka"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Spila"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Hlé"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Stöðva"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Stækka"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Minnka"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Plötuumslag"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Hljóðstyrkssleði"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Ekkert efni valið"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Engar upplýsingar í boði"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Skjár sendur út"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-it/strings.xml b/mediarouter/src/main/res/values-it/strings.xml
index 845ce6f..3bbfecd 100644
--- a/mediarouter/src/main/res/values-it/strings.xml
+++ b/mediarouter/src/main/res/values-it/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistema"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Dispositivi"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Pulsante Trasmetti"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Pulsante Trasmetti. Disconnesso"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Pulsante Trasmetti. Connessione in corso"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Pulsante Trasmetti. Connesso"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Trasmetti a"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Ricerca di dispositivi"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Disconnetti"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Interrompi trasmissione"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Chiudi"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Riproduci"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Metti in pausa"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Interrompi"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Espandi"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Comprimi"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Copertina dell\'album"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Dispositivo di scorrimento del volume"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nessun contenuto multimediale selezionato"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nessuna informazione disponibile"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Trasmissione dello schermo attiva"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistema"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Dispositivi"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Pulsante Trasmetti"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Pulsante Trasmetti. Disconnesso"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Pulsante Trasmetti. Connessione in corso"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Pulsante Trasmetti. Connesso"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Trasmetti a"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Ricerca di dispositivi"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Disconnetti"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Interrompi trasmissione"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Chiudi"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Riproduci"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Metti in pausa"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Interrompi"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Espandi"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Comprimi"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Copertina"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Dispositivo di scorrimento del volume"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nessun contenuto multimediale selezionato"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nessuna informazione disponibile"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Trasmissione dello schermo"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-iw/strings.xml b/mediarouter/src/main/res/values-iw/strings.xml
index 30e60d5..72ebc9c 100644
--- a/mediarouter/src/main/res/values-iw/strings.xml
+++ b/mediarouter/src/main/res/values-iw/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"מערכת"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"מכשירים"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"‏לחצן הפעלת Cast"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"‏לחצן הפעלת Cast. מנותק"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"‏לחצן הפעלת Cast. מתחבר"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"‏לחצן הפעלת Cast. מחובר"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"העברה אל"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"מתבצע חיפוש מכשירים"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"ניתוק"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"עצירת העברה"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"סגירה"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"הפעלה"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"השהיה"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"הפסקה"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"הרחבה"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"כיווץ"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"עטיפת אלבום"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"מחוון עוצמה"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"לא נבחרה מדיה"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"אין מידע זמין"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"העברת מסך מתבצעת"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"מערכת"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"מכשירים"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"‏לחצן הפעלת Cast"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"‏לחצן הפעלת Cast. מנותק"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"‏לחצן הפעלת Cast. מתחבר"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"‏לחצן הפעלת Cast. מחובר"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"העברה אל"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"מחפש מכשירים"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"ניתוק"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"עצירת העברה"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"סגירה"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"הפעלה"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"השהיה"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"הפסקה"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"הרחבה"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"כיווץ"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"עטיפת אלבום"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"מחוון עוצמה"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"לא נבחרה מדיה"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"אין מידע זמין"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"העברת מסך מתבצעת"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ja/strings.xml b/mediarouter/src/main/res/values-ja/strings.xml
index 74bf75c..b33ffb9 100644
--- a/mediarouter/src/main/res/values-ja/strings.xml
+++ b/mediarouter/src/main/res/values-ja/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"システム"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"端末"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"キャスト アイコン"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"キャスト アイコン。接続解除済み"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"キャスト アイコン。接続中"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"キャスト アイコン。接続済み"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"キャスト先"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"端末を検出しています"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"接続を解除"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"キャストを停止"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"閉じる"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"再生"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"一時停止"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"停止"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"展開"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"折りたたむ"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"アルバムアート"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"音量スライダー"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"メディアが選択されていません"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"情報がありません"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"画面をキャストしています"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"システム"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"端末"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"キャスト アイコン"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"キャスト アイコン。接続解除済み"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"キャスト アイコン。接続中"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"キャスト アイコン。接続済み"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"キャスト先"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"端末を検索しています"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"接続を解除"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"キャストを停止"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"閉じる"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"再生"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"一時停止"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"停止"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"展開"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"折りたたむ"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"アルバムアート"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"音量スライダー"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"メディアを選択していません"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"情報がありません"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"画面をキャストしています"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ka/strings.xml b/mediarouter/src/main/res/values-ka/strings.xml
index 7ee094e..446a9e0 100644
--- a/mediarouter/src/main/res/values-ka/strings.xml
+++ b/mediarouter/src/main/res/values-ka/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"სისტემა"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"მოწყობილობები"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"ტრანსლირების ღილაკი"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"ტრანსლირების ღილაკი. გათიშული"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"ტრანსლირების ღილაკი. მიმდინარეობს დაკავშირება"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"ტრანსლირების ღილაკი. დაკავშირებული"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"ტრანსლირება"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"მიმდინარეობს მოწყობილობების მოძიება"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"გათიშვა"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"ტრანსლირების შეწყვეტა"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"დახურვა"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"დაკვრა"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"პაუზა"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"შეწყვეტა"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"გაშლა"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"ჩაკეცვა"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"ალბომის გარეკანი"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"ხმის სლაიდერი"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"მედია არჩეული არ არის"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"ინფორმაცია არ არის ხელმისაწვდომი"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"მიმდინარეობს ეკრანის ტრანსლირება"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"სისტემა"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"მოწყობილობები"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"ტრანსლირების ღილაკი"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"ტრანსლირების ღილაკი. გათიშული"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"ტრანსლირების ღილაკი. მიმდინარეობს დაკავშირება"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"ტრანსლირების ღილაკი. დაკავშირებული"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"ტრანსლირება:"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"მოწყობილობების მოძიება..."</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"გათიშვა"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"ტრანსლირების შეწყვეტა"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"დახურვა"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"დაკვრა"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"პაუზა"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"შეწყვეტა"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"გაშლა"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"ჩაკეცვა"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"ალბომის გარეკანი"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"ხმის სლაიდერი"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"მედია არჩეული არ არის"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"ინფორმაცია არ არის ხელმისაწვდომი"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"მიმდინარეობს ეკრანის ტრანსლირება"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-kk/strings.xml b/mediarouter/src/main/res/values-kk/strings.xml
index d107272..d512ff9 100644
--- a/mediarouter/src/main/res/values-kk/strings.xml
+++ b/mediarouter/src/main/res/values-kk/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Жүйе"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Құрылғылар"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Трансляциялау түймесі"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Трансляциялау түймесі. Ажыратылды"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Трансляциялау түймесі. Қосылуда"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Трансляциялау түймесі. Қосылды"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Келесіге трансляциялау:"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Құрылғылар ізделуде"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Ажырату"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Трансляцияны тоқтату"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Жабу"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Ойнату"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Кідірту"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Тоқтату"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Жаю"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Жию"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Альбомның мұқабасы"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Дыбыс деңгейінің жүгірткісі"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Ешқандай медиафайл таңдалмаған"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Ешқандай ақпарат жоқ"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Экран трансляциялануда"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Жүйе"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Құрылғылар"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Трансляциялау түймесі"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Трансляциялау түймесі. Ажыратылды"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Трансляциялау түймесі. Қосылуда"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Трансляциялау түймесі. Қосылды"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Трансляция:"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Құрылғылар ізделуде"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Ажырату"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Трансляцияны тоқтату"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Жабу"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Ойнату"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Кідірту"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Тоқтату"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Жаю"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Жию"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Альбомның мұқабасы"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Дыбыс деңгейінің жүгірткісі"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Ешқандай медиафайл таңдалмаған"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Қолжетімді ақпарат жоқ"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Экранды трансляциялау"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-km/strings.xml b/mediarouter/src/main/res/values-km/strings.xml
index eb8a3467..9303a1b 100644
--- a/mediarouter/src/main/res/values-km/strings.xml
+++ b/mediarouter/src/main/res/values-km/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"ប្រព័ន្ធ"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"ឧបករណ៍"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"ប៊ូតុង​បញ្ជូន"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"ប៊ូតុង​បញ្ជូន។ បាន​ផ្តាច់"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"ប៊ូតុង​បញ្ជូន។ កំពុង​ភ្ជាប់"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"ប៊ូតុង​បញ្ជូន។ បាន​ភ្ជាប់​ហើយ"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"បញ្ជូន​ទៅ"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"កំពុង​ស្វែងរក​ឧបករណ៍"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"ផ្ដាច់"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"ឈប់ភ្ជាប់"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"បិទ"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"លេង"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"ផ្អាក"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"ឈប់"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"ពង្រីក"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"បង្រួម"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"រូបភាព​សិល្បៈ​ក្រប​អាល់ប៊ុម"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"របារកម្រិតសំឡេង"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"មិនបាន​ជ្រើសរើស​មេឌៀ​ទេ"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"មិនមានព័ត៌មានទេ"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"កំពុង​បញ្ជូន​អេក្រង់"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"ប្រព័ន្ធ"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"ឧបករណ៍"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"ប៊ូតុង​បញ្ជូន"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"ប៊ូតុង​បញ្ជូន។ បាន​ផ្តាច់"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"ប៊ូតុង​បញ្ជូន។ កំពុង​ភ្ជាប់"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"ប៊ូតុង​បញ្ជូន។ បាន​ភ្ជាប់​ហើយ"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"បញ្ជូន​ទៅ"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"កំពុង​ស្វែងរក​ឧបករណ៍"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"ផ្ដាច់"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"បញ្ឈប់​ការបញ្ជូន"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"បិទ"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"ចាក់"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"ផ្អាក"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"បញ្ឈប់"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"ពង្រីក"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"បង្រួម"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"រូបភាព​សិល្បៈ​ក្រប​អាល់ប៊ុម"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"របារកម្រិតសំឡេង"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"មិនបាន​ជ្រើសរើស​មេឌៀ​ទេ"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"មិនមានព័ត៌មានទេ"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"កំពុង​បញ្ជូន​អេក្រង់"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-kn/strings.xml b/mediarouter/src/main/res/values-kn/strings.xml
index fd8b1fd..f495017 100644
--- a/mediarouter/src/main/res/values-kn/strings.xml
+++ b/mediarouter/src/main/res/values-kn/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"ಸಿಸ್ಟಂ"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"ಸಾಧನಗಳು"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"ಬಿತ್ತರಿಸು ಬಟನ್‌"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"ಬಿತ್ತರಿಸು ಬಟನ್‌. ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"ಬಿತ್ತರಿಸು ಬಟನ್‌. ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"ಬಿತ್ತರಿಸು ಬಟನ್‌. ಸಂಪರ್ಕಿತಗೊಂಡಿದೆ"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"ಇದಕ್ಕೆ ಬಿತ್ತರಿಸಿ"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"ಸಾಧನಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಿ"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"ಬಿತ್ತರಿಸುವುದನ್ನು ನಿಲ್ಲಿಸಿ"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"ಮುಚ್ಚಿ"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"ಪ್ಲೇ"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"ವಿರಾಮ"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"ನಿಲ್ಲಿಸಿ"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"ಹಿಗ್ಗಿಸಿ"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"ಕುಗ್ಗಿಸಿ"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"ಆಲ್ಬಮ್ ಕಲೆ"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"ವಾಲ್ಯೂಮ್ ಸ್ಲೈಡರ್"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"ಯಾವುದೇ ಮಾಧ್ಯಮವನ್ನು ಆಯ್ಕೆ ಮಾಡಿಲ್ಲ"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"ಯಾವುದೇ ಮಾಹಿತಿ ಲಭ್ಯವಿಲ್ಲ"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"ಪರದೆಯನ್ನು ಬಿತ್ತರಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"ಸಿಸ್ಟಂ"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"ಸಾಧನಗಳು"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"ಬಿತ್ತರಿಸು ಬಟನ್‌"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"ಬಿತ್ತರಿಸು ಬಟನ್‌. ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"ಬಿತ್ತರಿಸು ಬಟನ್‌. ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"ಬಿತ್ತರಿಸು ಬಟನ್‌. ಸಂಪರ್ಕಿತಗೊಂಡಿದೆ"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"ಇದಕ್ಕೆ ಬಿತ್ತರಿಸಿ"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"ಸಾಧನಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಿ"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"ಬಿತ್ತರಿಸುವುದನ್ನು ನಿಲ್ಲಿಸಿ"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"ಮುಚ್ಚಿ"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"ಪ್ಲೇ"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"ವಿರಾಮ"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"ನಿಲ್ಲಿಸಿ"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"ಹಿಗ್ಗಿಸಿ"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"ಕುಗ್ಗಿಸಿ"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"ಆಲ್ಬಮ್ ಕಲೆ"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"ವಾಲ್ಯೂಮ್ ಸ್ಲೈಡರ್"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"ಯಾವುದೇ ಮಾಧ್ಯಮ ಆಯ್ಕೆ ಮಾಡಿಲ್ಲ"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"ಯಾವುದೇ ಮಾಹಿತಿ ಲಭ್ಯವಿಲ್ಲ"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"ಪರದೆಯನ್ನು ಬಿತ್ತರಿಸಲಾಗುತ್ತಿದೆ"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ko/strings.xml b/mediarouter/src/main/res/values-ko/strings.xml
index f2e926f..178fab0 100644
--- a/mediarouter/src/main/res/values-ko/strings.xml
+++ b/mediarouter/src/main/res/values-ko/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"시스템"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"기기"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"전송 버튼"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"전송 버튼. 연결 해제됨"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"전송 버튼. 연결 중"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"전송 버튼. 연결됨"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"전송 대상"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"기기를 찾는 중"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"연결 해제"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"전송 중지"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"닫기"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"재생"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"일시중지"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"중지"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"펼치기"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"접기"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"앨범아트"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"볼륨 슬라이더"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"선택된 미디어 없음"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"사용할 수 있는 정보 없음"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"화면 전송 중"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"시스템"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"기기"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"전송 버튼"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"전송 버튼. 연결 해제됨"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"전송 버튼. 연결 중"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"전송 버튼. 연결됨"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"전송 대상"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"기기를 찾는 중"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"연결 끊기"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"전송 중지"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"닫기"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"재생"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"일시중지"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"중지"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"확대"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"접기"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"앨범아트"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"볼륨 슬라이더"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"선택된 미디어 없음"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"사용할 수 있는 정보 없음"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"화면 전송 중"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ky/strings.xml b/mediarouter/src/main/res/values-ky/strings.xml
index 2e4fcd8..100e5a5 100644
--- a/mediarouter/src/main/res/values-ky/strings.xml
+++ b/mediarouter/src/main/res/values-ky/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Тутум"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Түзмөктөр"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Тышкы экранга чыгаруу баскычы"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Тышкы экранга чыгаруу баскычы. Түзмөк ажырап турат."</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Тышкы экранга чыгаруу баскычы. Түзмөк туташууда"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Тышкы экранга чыгаруу баскычы. Түзмөк туташып турат"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Түзмөккө чыгаруу"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Түзмөктөр изделүүдө"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Ажыратуу"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Тышкы экранга чыгарууну токтотуу"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Жабуу"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Ойнотуу"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Тындыруу"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Токтотуу"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Жайып көрсөтүү"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Жыйыштыруу"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Альбом мукабасы"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Үн башкаруучу сыдырма"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Эч нерсе тандалган жок"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Эч маалымат жок"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Тышкы экранга чыгарылууда"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Тутум"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Түзмөктөр"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Тышкы экранга чыгаруу баскычы"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Тышкы экранга чыгаруу баскычы. Түзмөк ажырап турат."</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Тышкы экранга чыгаруу баскычы. Түзмөк туташууда"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Тышкы экранга чыгаруу баскычы. Түзмөк туташып турат"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Түзмөккө чыгаруу"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Түзмөктөр изделүүдө"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Ажыратуу"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Тышкы экранга чыгарууну токтотуу"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Жабуу"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Угуу"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Тыным"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Токтотуу"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Жайып көрсөтүү"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Жыйыштыруу"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Альбом мукабасы"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Үндү катуулатуучу сыдырма"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Эч нерсе тандалган жок"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Эч маалымат жок"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Тышкы экранга чыгарылууда"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-lo/strings.xml b/mediarouter/src/main/res/values-lo/strings.xml
index 0b52b24..79bd210 100644
--- a/mediarouter/src/main/res/values-lo/strings.xml
+++ b/mediarouter/src/main/res/values-lo/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"ລະບົບ"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"ອຸປະກອນ"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"ປຸ່ມສົ່ງສັນຍານ"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"ປຸ່ມສົ່ງສັນຍານ. ຕັດການເຊື່ອມຕໍ່ແລ້ວ"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"ປຸ່ມສົ່ງສັນຍານ. ກຳລັງເຊື່ອມຕໍ່"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"ປຸ່ມສົ່ງສັນຍານ. ເຊື່ອມຕໍ່ແລ້ວ"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"ສົ່ງສັນຍານໄປທີ່"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"ກຳລັງຊອກຫາອຸປະກອນ"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"ຕັດການເຊື່ອມຕໍ່"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"ຢຸດການສົ່ງສັນຍານ"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"ປິດ"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"ຫຼິ້ນ"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"ຢຸດຊົ່ວຄາວ"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"ຢຸດ"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"ຂະຫຍາຍ"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"ຫຍໍ້ລົງ"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"ໜ້າປົກອະລະບໍ້າ"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"ຕົວປັບລະດັບສຽງ"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"ບໍ່ໄດ້ເລືອກສື່ໃດ"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"ບໍ່ມີຂໍ້ມູນ"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"ກຳລັງສົ່ງສັນຍານພາບ"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"ລະບົບ"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"ອຸປະກອນ"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"ປຸ່ມສົ່ງສັນຍານ"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"ປຸ່ມສົ່ງສັນຍານ. ຕັດການເຊື່ອມຕໍ່ແລ້ວ"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"ປຸ່ມສົ່ງສັນຍານ. ກຳລັງເຊື່ອມຕໍ່"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"ປຸ່ມສົ່ງສັນຍານ. ເຊື່ອມຕໍ່ແລ້ວ"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"ສົ່ງສັນຍານໄປທີ່"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"ກຳລັງຊອກຫາອຸປະກອນ"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"ຕັດການເຊື່ອມຕໍ່"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"ຢຸດການສົ່ງສັນຍານ"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"ປິດ"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"ຫຼິ້ນ"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"ຢຸດຊົ່ວຄາວ"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"ຢຸດ"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"ຂະຫຍາຍ"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"ຫຍໍ້ລົງ"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"ໜ້າປົກອະລະບໍ້າ"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"ຕົວປັບລະດັບສຽງ"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"ບໍ່ໄດ້ເລືອກສື່ໃດ"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"ບໍ່ມີຂໍ້ມູນ"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"ກຳລັງສົ່ງສັນຍານພາບ"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-lt/strings.xml b/mediarouter/src/main/res/values-lt/strings.xml
index 1108c32..6f1ce9f 100644
--- a/mediarouter/src/main/res/values-lt/strings.xml
+++ b/mediarouter/src/main/res/values-lt/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistema"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Įrenginiai"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Perdavimo mygtukas"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Perdavimo mygtukas. Atsijungta"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Perdavimo mygtukas. Prisijungiama"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Perdavimo mygtukas. Prisijungta"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Perduoti į"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Randami įrenginiai"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Atjungti"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Sustabdyti perdavimą"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Uždaryti"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Leisti"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pristabdyti"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Sustabdyti"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Išskleisti"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Sutraukti"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albumo viršelis"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Garsumo šliaužiklis"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nepasirinkta jokios medijos"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Informacija nepasiekiama"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Perduodamas ekranas"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistema"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Įrenginiai"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Perdavimo mygtukas"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Perdavimo mygtukas. Atsijungta"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Perdavimo mygtukas. Prisijungiama"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Perdavimo mygtukas. Prisijungta"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Perduoti į"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Randami įrenginiai"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Atsijungti"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Sustabdyti perdavimą"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Uždaryti"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Leisti"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pristabdyti"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Sustabdyti"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Išskleisti"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Sutraukti"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albumo viršelis"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Garsumo šliaužiklis"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nepasirinkta jokios medijos"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Informacija nepasiekiama"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Perduodamas ekranas"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-lv/strings.xml b/mediarouter/src/main/res/values-lv/strings.xml
index 950b3dc..56432f8 100644
--- a/mediarouter/src/main/res/values-lv/strings.xml
+++ b/mediarouter/src/main/res/values-lv/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistēma"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Ierīces"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Apraides poga"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Apraides poga. Savienojums pārtraukts."</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Apraides poga. Notiek savienojuma izveide."</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Apraides poga. Savienojums izveidots."</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Apraides veikšana uz ierīci"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Notiek ierīču meklēšana"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Atvienot"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Pārtraukt apraidi"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Aizvērt"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Atskaņot"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pauzēt"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Apturēt"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Izvērst"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Sakļaut"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albuma noformējums"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Skaļuma slīdnis"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nav atlasīts multivides saturs"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nav informācijas"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Notiek ekrāna apraide"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistēma"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Ierīces"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Apraides poga"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Apraides poga. Savienojums pārtraukts."</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Apraides poga. Notiek savienojuma izveide."</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Apraides poga. Savienojums izveidots."</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Apraides veikšana uz ierīci"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Ierīču meklēšana"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Atvienot"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Apturēt apraidi"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Aizvērt"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Atskaņot"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pauzēt"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Apturēt"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Izvērst"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Sakļaut"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albuma vāciņš"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Skaļuma slīdnis"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nav atlasīts multivides saturs"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nav informācijas"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Notiek ekrāna apraide"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-mk/strings.xml b/mediarouter/src/main/res/values-mk/strings.xml
index 5739525..e4572c5 100644
--- a/mediarouter/src/main/res/values-mk/strings.xml
+++ b/mediarouter/src/main/res/values-mk/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Систем"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Уреди"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Копче за Cast"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Копче за Cast. Исклучено"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Копче за Cast. Се поврзува"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Копче за Cast. Поврзано"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Емитување на"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Се бараат уреди"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Исклучи"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Сопри со емитување"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Затвори"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Пушти"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Пауза"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Запри"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Прошири"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Собери"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Омот на албум"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Лизгач за јачина на звук"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Не се избрани аудиовизуелни датотеки"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Нема достапни информации"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Се емитува екран"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Систем"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Уреди"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Копче за Cast"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Копче за Cast. Исклучено"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Копче за Cast. Се поврзува"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Копче за Cast. Поврзано"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Емитување на"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Се бараат уреди"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Исклучи"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Сопри со емитување"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Затвори"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Пушти"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Паузирај"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Сопри"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Прошири"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Собери"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Корица на албум"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Лизгач за јачина на звук"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Не се избрани аудиовизуелни датотеки"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Нема достапни информации"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Се емитува екран"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ml/strings.xml b/mediarouter/src/main/res/values-ml/strings.xml
index 7d48372..d7c987b 100644
--- a/mediarouter/src/main/res/values-ml/strings.xml
+++ b/mediarouter/src/main/res/values-ml/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"സിസ്റ്റം"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"ഉപകരണങ്ങൾ"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"കാസ്റ്റ് ബട്ടൺ"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"കാസ്റ്റ് ബട്ടൺ. വിച്ഛേദിച്ചു"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"കാസ്‌റ്റ് ബട്ടൺ. കണക്‌റ്റ് ചെയ്യുന്നു"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"കാസ്റ്റ് ബട്ടൺ. കണക്‌റ്റ് ചെയ്തു"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"ഇതിലേക്ക് കാസ്‌റ്റ് ചെയ്യുക"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"ഉപകരണങ്ങൾ കണ്ടെത്തുന്നു"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"വിച്ഛേദിക്കുക"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"കാസ്റ്റ് ചെയ്യുന്നത് നിർത്തുക"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"അടയ്ക്കുക"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"പ്ലേ ചെയ്യുക"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"തൽക്കാലം നിർത്തുക"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"നിര്‍ത്തുക"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"വികസിപ്പിക്കുക"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"ചുരുക്കുക"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"ആൽബം ആർട്ട്"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"വോളിയം സ്ലൈഡർ"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"മീഡിയയൊന്നും തിരഞ്ഞെടുത്തിട്ടില്ല"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"വിവരങ്ങളൊന്നും ലഭ്യമല്ല"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"സ്‌ക്രീൻ കാസ്‌റ്റ് ചെയ്യുന്നു"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"സിസ്റ്റം"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"ഉപകരണങ്ങൾ"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"കാസ്റ്റ് ബട്ടൺ"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"കാസ്റ്റ് ബട്ടൺ. വിച്ഛേദിച്ചു"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"കാസ്‌റ്റ് ബട്ടൺ. കണക്‌റ്റ് ചെയ്യുന്നു"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"കാസ്റ്റ് ബട്ടൺ. കണക്‌റ്റ് ചെയ്തു"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"ഇതിലേക്ക് കാസ്‌റ്റ് ചെയ്യുക"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"ഉപകരണങ്ങൾ കണ്ടെത്തുന്നു"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"വിച്ഛേദിക്കുക"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"കാസ്റ്റ് ചെയ്യുന്നത് നിർത്തുക"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"അവസാനിപ്പിക്കുക"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"പ്ലേ ചെയ്യുക"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"താൽക്കാലികമായി നിർത്തുക"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"നിര്‍ത്തുക"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"വികസിപ്പിക്കുക"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"ചുരുക്കുക"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"ആൽബം ആർട്ട്"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"ശബ്‌ദ സ്ലൈഡർ"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"മീഡിയയൊന്നും തിരഞ്ഞെടുത്തിട്ടില്ല"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"വിവരങ്ങളൊന്നും ലഭ്യമല്ല"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"സ്‌ക്രീൻ കാസ്‌റ്റ് ചെയ്യുന്നു"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-mn/strings.xml b/mediarouter/src/main/res/values-mn/strings.xml
index 84d128f..9f03518 100644
--- a/mediarouter/src/main/res/values-mn/strings.xml
+++ b/mediarouter/src/main/res/values-mn/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Систем"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Төхөөрөмжүүд"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Дамжуулах товчлуур"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Дамжуулах товчлуур. Салсан"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Дамжуулах товчлуур. Холбогдож байна"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Дамжуулах товчлуур. Холбогдсон"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Дараахад дамжуулах"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Төхөөрөмжүүдийг хайж байна"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Салгах"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Дамжуулахыг зогсоох"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Хаах"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Тоглуулах"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Түр зогсоох"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Зогсоох"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Дэлгэх"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Буулгах"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Цомгийн зураг"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Дууны түвшин тохируулагч"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Ямар ч медиа сонгоогүй байна"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Мэдээлэл алга"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Дэлгэцийг дамжуулж байна"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Систем"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Төхөөрөмж"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Дамжуулах товч"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Дамжуулах товч. Салсан"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Дамжуулах товч. Холбогдож байна"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Дамжуулах товч. Холбогдсон"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Дамжуулах"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Төхөөрөмжийг хайж байна"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Салгах"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Дамжуулахыг зогсоох"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Хаах"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Тоглуулах"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Түр зогсоох"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Зогсоох"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Дэлгэх"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Хумих"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Цомгийн зураг"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Дууны түвшин тааруулагч"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Ямар ч медиа сонгоогүй байна"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Мэдээлэл байхгүй байна"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Дэлгэцийг дамжуулж байна"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-mr/strings.xml b/mediarouter/src/main/res/values-mr/strings.xml
index d3a0736..f3ccbb9 100644
--- a/mediarouter/src/main/res/values-mr/strings.xml
+++ b/mediarouter/src/main/res/values-mr/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"सिस्टम"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"डिव्हाइस"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"कास्ट बटण"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"कास्ट बटण. डिस्कनेक्ट केले आहे"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"कास्ट बटण. कनेक्ट करत आहे"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"कास्ट बटण. कनेक्ट केले आहे"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"यावर कास्ट करा"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"डिव्हाइस शोधत आहे"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"‍डिस्कनेक्ट करा"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"कास्ट करणे थांबवा"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"बंद"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"खेळा"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"थांबवा"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"थांबा"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"विस्तार करा"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"कोलॅप्स"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"अल्बम कला"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"व्हॉल्यूम स्लायडर"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"मीडिया निवडला नाही"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"कोणतीही माहिती उपलब्ध नाही"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"स्क्रीन कास्‍ट करत आहे"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"सिस्टम"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"डिव्हाइस"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"कास्ट बटण"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"कास्ट बटण. डिस्कनेक्ट केले"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"कास्ट बटण. कनेक्ट करत आहे"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"कास्ट बटण. कनेक्ट केले"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"यावर कास्ट करा"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"डिव्हाइस शोधत आहे"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"‍डिस्कनेक्ट करा"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"कास्ट करणे थांबवा"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"बंद"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"खेळा"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"विराम द्या"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"थांबा"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"विस्तार करा"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"कोलॅप्स"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"अल्बम कला"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"व्हॉल्यूम स्लायडर"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"मीडिया निवडला नाही"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"कोणतीही माहिती उपलब्ध नाही"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"स्क्रीन कास्‍ट करत आहे"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ms/strings.xml b/mediarouter/src/main/res/values-ms/strings.xml
index f7c0840..5096704 100644
--- a/mediarouter/src/main/res/values-ms/strings.xml
+++ b/mediarouter/src/main/res/values-ms/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistem"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Peranti"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Butang hantar"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Butang hantar. Sambungan diputuskan"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Butang hantar. Menyambung"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Butang hantar. Disambungkan"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Hantar ke"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Mencari peranti"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Putuskan sambungan"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Berhenti menghantar"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Tutup"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Main"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Jeda"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Berhenti"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Kembangkan"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Runtuhkan"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Seni album"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Peluncur kelantangan"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Tiada media yang dipilih"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Maklumat tidak tersedia"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Menghantar skrin"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistem"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Peranti"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Butang hantar"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Butang hantar. Sambungan diputuskan"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Butang hantar. Menyambung"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Butang hantar. Disambungkan"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Hantar ke"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Mencari peranti"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Putuskan sambungan"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Berhenti menghantar"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Tutup"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Main"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Jeda"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Berhenti"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Kembangkan"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Runtuhkan"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Seni album"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Peluncur kelantangan"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Tiada media yang dipilih"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Maklumat tidak tersedia"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Menghantar skrin"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-my/strings.xml b/mediarouter/src/main/res/values-my/strings.xml
index c6698f1..5e843a0 100644
--- a/mediarouter/src/main/res/values-my/strings.xml
+++ b/mediarouter/src/main/res/values-my/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"စနစ်"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"စက်များ"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"ကာစ်ခလုတ်"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"ကာစ်ခလုတ်။ ချိတ်ဆက်မထားပါ"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"ကာစ်ခလုတ်။ ချိတ်ဆက်နေသည်"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"ကာစ်ခလုတ်။ ချိတ်ဆက်ထားသည်"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"ဤစက်သို့ ကာစ်လုပ်ရန်"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"စက်များကို ရှာနေသည်"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"ချိတ်ဆက်မှု ဖြုတ်ရန်"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"ကာစ်လုပ်ခြင်းကို ရပ်ရန်"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"ပိတ်ရန်"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"ကစားရန်"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"ခဏရပ်ရန်"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"ရပ်ရန်"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"ချဲ့ရန်"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"လျှော့ပြရန်"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"အယ်လ်ဘမ်ပုံ"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"အသံအတိုးအကျယ်ချိန်သည့် ရွှေ့တုံး"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"မီဒီယာ ရွေးမထားပါ"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"အချက်အလက် မရရှိနိုင်ပါ"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"ကာစ်တ်လုပ်သည့် မျက်နှာပြင်"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"စနစ်"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"စက်များ"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"ကာစ်ခလုတ်"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"ကာစ်ခလုတ်။ ချိတ်ဆက်မထားပါ"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"ကာစ်ခလုတ်။ ချိတ်ဆက်နေသည်"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"ကာစ်ခလုတ်။ ချိတ်ဆက်ထားသည်"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"ဤစက်သို့ ကာစ်လုပ်ရန်"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"စက်များ ရှာနေသည်"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"ချိတ်ဆက်မှု ဖြုတ်ရန်"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"ကာစ်လုပ်ခြင်းကို ရပ်ရန်"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"ပိတ်ရန်"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"ဖွင့်ရန်"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"ခဏရပ်ရန်"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"ရပ်ရန်"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"ချဲ့ရန်"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"လျှော့ပြရန်"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"အယ်လ်ဘမ်ပုံ"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"အသံအတိုးအကျယ်ချိန်သည့် ဆလိုက်ဒါ"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"မီဒီယာ ရွေးမထားပါ"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"အချက်အလက် မရရှိနိုင်ပါ"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"ကာစ်တ်လုပ်သည့် မျက်နှာပြင်"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-nb/strings.xml b/mediarouter/src/main/res/values-nb/strings.xml
index a4a04f5..487b9d5 100644
--- a/mediarouter/src/main/res/values-nb/strings.xml
+++ b/mediarouter/src/main/res/values-nb/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"System"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Enheter"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast-ikonet"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast-ikonet. Frakoblet"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast-ikonet. Kobler til"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast-ikonet. Tilkoblet"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Cast til"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Finner enheter"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Koble fra"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Stopp castingen"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Lukk"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Spill av"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Sett på pause"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stopp"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Vis"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Skjul"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albumgrafikk"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Glidebryter for volum"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Ingen medier er valgt"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Ingen informasjon er tilgjengelig"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Caster skjermen"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"System"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Enheter"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast-ikonet"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast-ikonet. Frakoblet"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast-ikonet. Kobler til"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast-ikonet. Tilkoblet"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Cast til"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Finner enheter"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Koble fra"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Stopp castingen"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Lukk"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Spill av"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Sett på pause"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Stopp"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Vis"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Skjul"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albumgrafikk"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Glidebryter for volum"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Ingen medier er valgt"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Ingen informasjon er tilgjengelig"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Caster skjermen"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ne/strings.xml b/mediarouter/src/main/res/values-ne/strings.xml
index b844aa3..8a13ac7 100644
--- a/mediarouter/src/main/res/values-ne/strings.xml
+++ b/mediarouter/src/main/res/values-ne/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"प्रणाली"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"यन्त्रहरू"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast बटन"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast बटन। जडान विच्छेद गरियो"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast बटन। जडान गरिँदै छ"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast बटन। जडान गरियो"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"यसमा Cast गर्नुहोस्"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"यन्त्रहरू पत्ता लगाइँदै छ"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"विच्छेद गर्नुहोस्"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"casting रोक्नुहोस्"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"बन्द गर्नुहोस्"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"खेल्नुहोस्"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"पज गर्नुहोस्‌"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"रोक्नुहोस्"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"विस्तृत गर्नुहोस्"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"संक्षिप्त गर्नुहोस्"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"एल्बम आर्ट"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"भोल्युमको स्लाइडर"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"कुनै पनि मिडिया चयन गरिएन"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"कुनै पनि जानकारी उपलब्ध छैन"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"स्क्रिन Cast गरिँदै छ"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"प्रणाली"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"यन्त्रहरू"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast बटन"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast बटन। जडान विच्छेद गरियो"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast बटन। जडान गरिँदै छ"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast बटन। जडान गरियो"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"यसमा Cast गर्नुहोस्"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"यन्त्रहरू पत्ता लगाइँदै छ"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"विच्छेद गर्नुहोस्"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Cast गर्न छाड्नुहोस्"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"बन्द गर्नुहोस्"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"प्ले गर्नुहोस्"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"पज गर्नुहोस्"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"रोक्नुहोस्"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"विस्तृत गर्नुहोस्"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"संक्षिप्त गर्नुहोस्"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"एल्बम आर्ट"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"भोल्युमको स्लाइडर"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"कुनै पनि मिडिया चयन गरिएन"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"कुनै पनि जानकारी उपलब्ध छैन"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"स्क्रिन Cast गरिँदै छ"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-nl/strings.xml b/mediarouter/src/main/res/values-nl/strings.xml
index c1279aa..eb19187 100644
--- a/mediarouter/src/main/res/values-nl/strings.xml
+++ b/mediarouter/src/main/res/values-nl/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Systeem"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Apparaten"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast-icoon"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast-icoon. Verbinding verbroken"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast-icoon. Verbinding maken"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast-icoon. Verbonden"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Casten naar"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Apparaten zoeken"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Verbinding verbreken"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Casten stoppen"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Sluiten"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Afspelen"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pauzeren"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stoppen"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Uitvouwen"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Samenvouwen"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albumhoes"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Volumeschuifregelaar"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Geen media geselecteerd"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Geen informatie beschikbaar"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Scherm casten"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Systeem"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Apparaten"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast-knop"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast-icoon. Verbinding verbroken"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast-icoon. Verbinding maken"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast-icoon. Verbonden"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Casten naar"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Apparaten zoeken"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Loskoppelen"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Casten stoppen"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Sluiten"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Afspelen"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pauzeren"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Stoppen"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Uitvouwen"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Samenvouwen"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albumhoes"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Volumeschuifregelaar"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Geen media geselecteerd"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Geen informatie beschikbaar"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Scherm casten"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-or/strings.xml b/mediarouter/src/main/res/values-or/strings.xml
deleted file mode 100644
index 05a309b..0000000
--- a/mediarouter/src/main/res/values-or/strings.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"ସିଷ୍ଟମ୍‌"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"ଡିଭାଇସ୍‌"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"କାଷ୍ଟ ବଟନ୍‍"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"କାଷ୍ଟ ବଟନ୍‍। ଡିସ୍‌କନେକ୍ଟ ହୋଇଗଲା"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"କାଷ୍ଟ ବଟନ୍‍। କନେକ୍ଟ କରାଯାଉଛି"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"କାଷ୍ଟ ବଟନ୍‍। କନେକ୍ଟ ହୋ‌ଇଛି"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"ଏଥିରେ କାଷ୍ଟ କରନ୍ତୁ"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"ଡିଭାଇସ୍‍ ଖୋଜାଯାଉଛି"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"ଡିସ୍‌କନେକ୍ଟ କରନ୍ତୁ"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"କାଷ୍ଟ କରିବା ବନ୍ଦ କରନ୍ତୁ"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"ବନ୍ଦ କରନ୍ତୁ"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"ଚଲାନ୍ତୁ"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"ପଜ୍‍ କରନ୍ତୁ"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"ରୋକନ୍ତୁ"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"ବିସ୍ତାର କରନ୍ତୁ"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"ସଂକୁଚିତ କରନ୍ତୁ"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"ଆଲବମ୍ ଆର୍ଟ"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"ଭଲ୍ୟୁମ୍‍ ସ୍ଲାଇଡର୍‍"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"କୌଣସି ମିଡିଆ ଚୟନ କରାଯାଇନାହିଁ"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"କୌଣସି ସୂଚନା ଉପଲବ୍ଧ ନାହିଁ"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"ସ୍କ୍ରୀନ୍‍ କାଷ୍ଟ କରାଯାଉଛି"</string>
-</resources>
diff --git a/mediarouter/src/main/res/values-pa/strings.xml b/mediarouter/src/main/res/values-pa/strings.xml
index 45eb814..5092ae0 100644
--- a/mediarouter/src/main/res/values-pa/strings.xml
+++ b/mediarouter/src/main/res/values-pa/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"ਸਿਸਟਮ"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"ਡੀਵਾਈਸਾਂ"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"\'ਕਾਸਟ ਕਰੋ\' ਬਟਨ"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"\'ਕਾਸਟ ਕਰੋ\' ਬਟਨ। ਡਿਸਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"\'ਕਾਸਟ ਕਰੋ\' ਬਟਨ। ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"\'ਕਾਸਟ ਕਰੋ\' ਬਟਨ। ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"ਏਥੇ ਕਾਸਟ ਕਰੋ"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"ਡੀਵਾਈਸ ਲੱਭੇ ਜਾ ਰਹੇ ਹਨ"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"ਕਾਸਟ ਕਰਨਾ ਬੰਦ ਕਰੋ"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"ਬੰਦ ਕਰੋ"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"ਚਲਾਓ"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"ਰੋਕੋ"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"ਬੰਦ ਕਰੋ"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"ਵਿਸਤਾਰ ਕਰੋ"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"ਸਮੇਟੋ"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"ਐਲਬਮ ਕਲਾ"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"ਵੌਲਿਊਮ ਸਲਾਈਡਰ"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ ਚੁਣਿਆ ਗਿਆ"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"ਕੋਈ ਜਾਣਕਾਰੀ ਉਪਲਬਧ ਨਹੀਂ"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"ਸਕ੍ਰੀਨ \'ਤੇ ਕਾਸਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"ਸਿਸਟਮ"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"ਡੀਵਾਈਸ"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"\'ਕਾਸਟ ਕਰੋ\' ਬਟਨ"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"\'ਕਾਸਟ ਕਰੋ\' ਬਟਨ। ਡਿਸਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"\'ਕਾਸਟ ਕਰੋ\' ਬਟਨ। ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"\'ਕਾਸਟ ਕਰੋ\' ਬਟਨ। ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"ਏਥੇ ਕਾਸਟ ਕਰੋ"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"ਡੀਵਾਈਸ ਲੱਭੇ ਜਾ ਰਹੇ ਹਨ"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"ਕਾਸਟ ਕਰਨਾ ਬੰਦ ਕਰੋ"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"ਬੰਦ ਕਰੋ"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"ਚਲਾਓ"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"ਰੋਕੋ"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"ਬੰਦ ਕਰੋ"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"ਵਿਸਤਾਰ ਕਰੋ"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"ਸਮੇਟੋ"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"ਐਲਬਮ ਕਲਾ"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"ਵੌਲਯੂਮ ਸਲਾਈਡਰ"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ ਚੁਣਿਆ ਗਿਆ"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"ਕੋਈ ਜਾਣਕਾਰੀ ਉਪਲਬਧ ਨਹੀਂ"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"ਸਕ੍ਰੀਨ \'ਤੇ ਕਾਸਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-pl/strings.xml b/mediarouter/src/main/res/values-pl/strings.xml
index b0bf098..6f52faf 100644
--- a/mediarouter/src/main/res/values-pl/strings.xml
+++ b/mediarouter/src/main/res/values-pl/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"System"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Urządzenia"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Przycisk Cast"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Przycisk Cast – rozłączono"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Przycisk Cast – łączę"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Przycisk Cast – połączono"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Przesyłaj na"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Szukam urządzeń"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Odłącz"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Zatrzymaj przesyłanie"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Zamknij"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Odtwórz"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Wstrzymaj"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Zatrzymaj"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Rozwiń"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Zwiń"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Okładka albumu"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Suwak głośności"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nie wybrano multimediów"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Brak informacji"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Przesyłam ekran"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"System"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Urządzenia"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Przycisk Cast"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Przycisk Cast. Rozłączono"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Przycisk Cast. Łączę"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Przycisk Cast. Połączono"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Przesyłaj na"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Znajdowanie urządzeń"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Odłącz"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Zatrzymaj przesyłanie"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Zamknij"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Odtwórz"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Wstrzymaj"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Zatrzymaj"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Rozwiń"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Zwiń"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Okładka albumu"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Suwak głośności"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nie wybrano multimediów"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Brak informacji"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Przesyłanie ekranu"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-pt-rBR/strings.xml b/mediarouter/src/main/res/values-pt-rBR/strings.xml
index e527f35..213424a 100644
--- a/mediarouter/src/main/res/values-pt-rBR/strings.xml
+++ b/mediarouter/src/main/res/values-pt-rBR/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistema"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Dispositivos"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Botão \"Transmitir\""</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Botão \"Transmitir\". Desconectado"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Botão \"Transmitir\". Conectando"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Botão \"Transmitir\". Conectado"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Transmitir para"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Localizando dispositivos"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Desconectar"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Parar transmissão"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Fechar"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Reproduzir"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pausar"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Parar"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Expandir"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Recolher"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Arte do álbum"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Controle deslizante de volume"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nenhuma mídia selecionada"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nenhuma informação disponível"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Transmitindo tela"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistema"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Dispositivos"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Botão \"Transmitir\""</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Botão \"Transmitir\". Desconectado"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Botão \"Transmitir\". Conectando"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Botão \"Transmitir\". Conectado"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Transmitir para"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Localizando dispositivos"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Desconectar"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Parar transmissão"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Fechar"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Reproduzir"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pausar"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Parar"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Expandir"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Recolher"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Arte do álbum"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Controle deslizante de volume"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nenhuma mídia selecionada"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nenhuma informação disponível"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Transmitindo tela"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-pt-rPT/strings.xml b/mediarouter/src/main/res/values-pt-rPT/strings.xml
index 1a2d2ba..4780144 100644
--- a/mediarouter/src/main/res/values-pt-rPT/strings.xml
+++ b/mediarouter/src/main/res/values-pt-rPT/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistema"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Dispositivos"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Botão Transmitir"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Botão Transmitir. Desligado."</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Botão Transmitir. A ligar..."</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Botão Transmitir. Ligado."</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Transmitir para"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"A localizar dispositivos..."</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Desligar"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Parar transmissão"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Fechar"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Reproduzir"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Colocar em pausa"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Parar"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Expandir"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Reduzir"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Imagem do álbum"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Controlo de deslize do volume"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nenhum conteúdo multimédia selecionado."</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nenhuma informação disponível."</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"A transmitir o ecrã..."</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistema"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Dispositivos"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Botão Transmitir"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Botão Transmitir. Desligado."</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Botão Transmitir. A ligar..."</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Botão Transmitir. Ligado"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Transmitir para"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"A localizar dispositivos..."</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Desligar"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Parar transmissão"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Fechar"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Reproduzir"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Interromper"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Parar"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Expandir"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Reduzir"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Imagem do álbum"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Controlo de deslize do volume"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nenhum conteúdo multimédia selecionado."</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nenhuma informação disponível."</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"A transmitir o ecrã..."</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-pt/strings.xml b/mediarouter/src/main/res/values-pt/strings.xml
index e527f35..213424a 100644
--- a/mediarouter/src/main/res/values-pt/strings.xml
+++ b/mediarouter/src/main/res/values-pt/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistema"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Dispositivos"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Botão \"Transmitir\""</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Botão \"Transmitir\". Desconectado"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Botão \"Transmitir\". Conectando"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Botão \"Transmitir\". Conectado"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Transmitir para"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Localizando dispositivos"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Desconectar"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Parar transmissão"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Fechar"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Reproduzir"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pausar"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Parar"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Expandir"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Recolher"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Arte do álbum"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Controle deslizante de volume"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nenhuma mídia selecionada"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nenhuma informação disponível"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Transmitindo tela"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistema"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Dispositivos"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Botão \"Transmitir\""</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Botão \"Transmitir\". Desconectado"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Botão \"Transmitir\". Conectando"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Botão \"Transmitir\". Conectado"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Transmitir para"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Localizando dispositivos"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Desconectar"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Parar transmissão"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Fechar"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Reproduzir"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pausar"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Parar"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Expandir"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Recolher"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Arte do álbum"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Controle deslizante de volume"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nenhuma mídia selecionada"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nenhuma informação disponível"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Transmitindo tela"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ro/strings.xml b/mediarouter/src/main/res/values-ro/strings.xml
index c3292b4..82660fc 100644
--- a/mediarouter/src/main/res/values-ro/strings.xml
+++ b/mediarouter/src/main/res/values-ro/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistem"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Dispozitive"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Butonul de proiecție"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Butonul de proiecție. Deconectat"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Butonul de proiecție. Se conectează"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Butonul de proiecție. Conectat"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Proiectați pe"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Se caută dispozitive"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Deconectați"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Nu mai proiectați"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Închideți"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Redați"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Întrerupeți"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Opriți"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Extindeți"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Restrângeți"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Grafica albumului"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Glisor pentru volum"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Niciun conținut media selectat"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nu sunt disponibile informații"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Se proiectează ecranul"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistem"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Dispozitive"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Butonul de proiecție"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Butonul de proiecție. Deconectat"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Butonul de proiecție. Se conectează"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Butonul de proiecție. Conectat"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Proiectați pe"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Se caută dispozitive"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Deconectați"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Nu mai proiectați"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Închideți"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Redați"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Întrerupeți"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Opriți"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Extindeți"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Restrângeți"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Grafica albumului"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Glisor pentru volum"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Niciun conținut media selectat"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nu sunt disponibile informații"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Se proiectează ecranul"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ru/strings.xml b/mediarouter/src/main/res/values-ru/strings.xml
index de0fe64..b3e5e16 100644
--- a/mediarouter/src/main/res/values-ru/strings.xml
+++ b/mediarouter/src/main/res/values-ru/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Система"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Устройства"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Кнопка трансляции"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Кнопка трансляции. Устройство отключено."</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Кнопка трансляции. Устройство подключается."</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Кнопка трансляции. Устройство подключено."</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Транслировать на устройство"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Поиск устройств…"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Отключить"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Остановить трансляцию"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Закрыть"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Воспроизвести"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Приостановить"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Остановить"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Показать"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Скрыть"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Обложка"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Регулятор громкости"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Медиафайл не выбран"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Данных нет"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Трансляция экрана…"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Система"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Устройства"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Кнопка Google Cast"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Кнопка трансляции. Устройство отключено."</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Кнопка трансляции. Устройство подключается."</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Кнопка трансляции. Устройство подключено."</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Транслировать на устройство"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Поиск устройств…"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Отключить"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Прекратить трансляцию"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Закрыть"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Воспроизвести"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Пауза"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Остановить"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Развернуть"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Скрыть"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Обложка"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Регулятор громкости"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Контент не выбран"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Данных нет"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Подключение к удаленному монитору"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-si/strings.xml b/mediarouter/src/main/res/values-si/strings.xml
index 95bd78c..044f1a37 100644
--- a/mediarouter/src/main/res/values-si/strings.xml
+++ b/mediarouter/src/main/res/values-si/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"පද්ධතිය"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"උපාංග"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"විකාශ බොත්තම"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"විකාශ බොත්තම. විසන්ධි කරන ලදී"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"විකාශ බොත්තම සම්බන්ධ කරමින්"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"විකාශ බොත්තම සම්බන්ධ කරන ලදී"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"විකාශය"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"උපාංග සෙවීම"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"විසන්ධි කරන්න"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"විකාශය නවතන්න"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"වසන්න"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"ධාවනය කරන්න"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"විරාමය"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"නවත්වන්න"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"දිග හරින්න"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"හකුළන්න"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"ඇල්බම කලාව"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"හඬ පරිමා ස්ලයිඩරය"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"මාධ්‍ය තෝරා නැත"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"ලබා ගත හැකි තොරතුරු නොමැත"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"විකාශ තිරය"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"පද්ධතිය"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"උපාංග"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"විකාශ බොත්තම"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"විකාශ බොත්තම. විසන්ධි කරන ලදී"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"විකාශ බොත්තම සම්බන්ධ කරමින්"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"විකාශ බොත්තම සම්බන්ධ කරන ලදී"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"විකාශය"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"උපාංග සෙවීම"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"විසන්ධි කරන්න"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"විකාශය නවතන්න"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"වසන්න"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"ධාවනය කරන්න"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"විරාම කරන්න"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"නවත්වන්න"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"දිග හරින්න"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"හකුළන්න"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"ඇල්බම කලාව"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"හඬ පරිමා ස්ලයිඩරය"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"මාධ්‍ය තෝරා නැත"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"ලබා ගත හැකි තොරතුරු නොමැත"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"විකාශ තිරය"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-sk/strings.xml b/mediarouter/src/main/res/values-sk/strings.xml
index 765ff2c..bb81d011 100644
--- a/mediarouter/src/main/res/values-sk/strings.xml
+++ b/mediarouter/src/main/res/values-sk/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Systém"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Zariadenia"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Tlačidlo prenosu"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Tlačidlo prenosu. Odpojené"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Tlačidlo prenosu. Pripája sa"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Tlačidlo prenosu. Pripojené"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Prenos do zariadenia"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Hľadajú sa zariadenia"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Odpojiť"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Zastaviť prenos"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Zavrieť"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Prehrať"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pozastaviť"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Zastaviť"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Rozbaliť"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Zbaliť"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Obrázok albumu"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Posúvač hlasitosti"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nie sú vybraté žiadne médiá"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nie sú k dispozícii žiadne informácie"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Prenáša sa obrazovka"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Systém"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Zariadenia"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Tlačidlo prenosu"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Tlačidlo prenosu. Odpojené"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Tlačidlo prenosu. Pripája sa"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Tlačidlo prenosu. Pripojené"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Prenos do zariadenia"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Hľadajú sa zariadenia"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Odpojiť"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Zastaviť prenos"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Zavrieť"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Prehrať"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pozastaviť"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Ukončiť"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Rozbaliť"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Zbaliť"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Obrázok albumu"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Posúvač hlasitosti"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nie sú vybrané žiadne médiá"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nie sú k dispozícii žiadne informácie"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Prenáša sa obrazovka"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-sl/strings.xml b/mediarouter/src/main/res/values-sl/strings.xml
index fe83391..2b0eeb8 100644
--- a/mediarouter/src/main/res/values-sl/strings.xml
+++ b/mediarouter/src/main/res/values-sl/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistem"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Naprave"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Gumb za predvajanje"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Gumb za predvajanje. Povezava je prekinjena."</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Gumb za predvajanje. Vzpostavljanje povezave."</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Gumb za predvajanje. Povezava je vzpostavljena."</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Predvajanje v napravi:"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Iskanje naprav"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Prekini povezavo"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Ustavi predvajanje"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Zapri"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Predvajaj"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Začasno ustavi"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Ustavi"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Razširi"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Strni"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Naslovnica albuma"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Drsnik za glasnost"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Predstavnost ni izbrana"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Ni podatkov"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Predvajanje vsebine zaslona"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistem"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Naprave"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Gumb za predvajanje"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Gumb za predvajanje. Povezava je prekinjena."</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Gumb za predvajanje. Vzpostavljanje povezave."</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Gumb za predvajanje. Povezava je vzpostavljena."</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Predvajanje prek:"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Iskanje naprav"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Prekini povezavo"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Ustavi predvajanje"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Zapri"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Predvajaj"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Začasno ustavi"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Ustavi"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Razširi"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Strni"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Naslovnica albuma"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Drsnik za glasnost"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Predstavnost ni izbrana"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Ni podatkov"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Predvajanje vsebine zaslona"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-sq/strings.xml b/mediarouter/src/main/res/values-sq/strings.xml
index aec71e7..f172212 100644
--- a/mediarouter/src/main/res/values-sq/strings.xml
+++ b/mediarouter/src/main/res/values-sq/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistemi"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Pajisjet"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Butoni i transmetimit"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Butoni i transmetimit. Je i shkëputur"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Butoni i transmetimit. Po lidhet"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Butoni i transmetimit. Je i lidhur"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Transmeto te"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Po kërkon pajisje"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Shkëput"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Ndalo transmetimin"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Mbyll"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Luaj"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pauzë"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Ndalo"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Zgjero"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Palos"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Kopertina e albumit"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Rrëshqitësi i volumit"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Nuk është zgjedhur asnjë media"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Nuk jepet asnjë informacion"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Po transmeton ekranin"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistemi"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Pajisjet"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Butoni i transmetimit"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Butoni i transmetimit. Je i shkëputur"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Butoni i transmetimit. Po lidhet"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Butoni i transmetimit. Je i lidhur"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Transmeto te"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Po kërkon pajisje"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Shkëput"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Ndalo transmetimin"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Mbyll"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Luaj"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pauzë"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Ndalo"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Zgjero"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Palos"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Kopertina e albumit"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Rrëshqitësi i volumit"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Nuk është zgjedhur asnjë media"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Nuk jepet asnjë informacion"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Po transmeton ekranin"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-sr/strings.xml b/mediarouter/src/main/res/values-sr/strings.xml
index 31abee0..e5d35776 100644
--- a/mediarouter/src/main/res/values-sr/strings.xml
+++ b/mediarouter/src/main/res/values-sr/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Систем"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Уређаји"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Дугме Пребаци"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Дугме Пребаци. Веза је прекинута"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Дугме Пребаци. Повезује се"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Дугме Пребаци. Повезан је"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Пребаците на"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Траже се уређаји"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Прекини везу"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Заустави пребацивање"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Затвори"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Пусти"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Паузирај"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Заустави"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Прошири"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Скупи"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Омот албума"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Клизач за јачину звука"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Нема изабраних медија"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Нема доступних информација"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Пребацује се екран"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Систем"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Уређаји"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Дугме Пребаци"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Дугме Пребаци. Веза је прекинута"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Дугме Пребаци. Повезује се"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Дугме Пребаци. Повезан је"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Пребаците на"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Траже се уређаји"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Прекини везу"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Заустави пребацивање"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Затвори"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Пусти"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Паузирај"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Заустави"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Прошири"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Скупи"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Омот албума"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Клизач за јачину звука"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Нема изабраних медија"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Нема доступних информација"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Пребацује се екран"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-sv/strings.xml b/mediarouter/src/main/res/values-sv/strings.xml
index 4b04e77..3ed8212 100644
--- a/mediarouter/src/main/res/values-sv/strings.xml
+++ b/mediarouter/src/main/res/values-sv/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"System"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Enheter"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast-knappen"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast-knappen. Frånkopplad"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast-knappen. Ansluter"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast-knappen. Ansluten"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Casta till"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Letar efter enheter"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Koppla från"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Sluta casta"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Stäng"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Spela upp"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pausa"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Stopp"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Utöka"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Dölj"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Skivomslag"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Volymreglage"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Ingen media har valts"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Det finns ingen information"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Skärmen castas"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"System"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Enheter"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast-knappen"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast-knappen. Frånkopplad"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast-knappen. Ansluter"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast-knappen. Ansluten"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Casta till"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Letar efter enheter"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Koppla från"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Sluta casta"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Stäng"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Spela upp"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pausa"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Stoppa"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Utöka"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Komprimera"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Skivomslag"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Volymreglage"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Ingen media har valts"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Det finns ingen information"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Skärmen castas"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-sw/strings.xml b/mediarouter/src/main/res/values-sw/strings.xml
index 03228c3..2a7af85 100644
--- a/mediarouter/src/main/res/values-sw/strings.xml
+++ b/mediarouter/src/main/res/values-sw/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Mfumo"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Vifaa"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Kitufe cha kutuma"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Kitufe cha kutuma. Kimeondolewa"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Kitufe cha kutuma. Kinaunganishwa"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Kitufe cha kutuma. Kimeunganishwa"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Tuma kwenye"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Inatafuta vifaa"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Ondoa"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Acha kutuma"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Funga"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Cheza"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Sitisha"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Acha kucheza"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Panua"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Kunja"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Sanaa ya albamu"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Kidhibiti cha sauti"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Hakuna maudhui yaliyochaguliwa"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Hakuna maelezo yaliyopatikana"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Inatuma skrini"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Mfumo"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Vifaa"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Kitufe cha kutuma"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Kitufe cha kutuma. Kimeondolewa"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Kitufe cha kutuma. Kinaunganishwa"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Kitufe cha kutuma. Kimeunganishwa"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Tuma kwenye"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Inatafuta vifaa"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Ondoa"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Acha kutuma"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Funga"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Cheza"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Sitisha"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Simamisha"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Panua"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Kunja"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Sanaa ya albamu"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Kidhibiti cha sauti"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Hakuna maudhui yaliyochaguliwa"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Hakuna maelezo yaliyopatikana"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Inatuma skrini"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ta/strings.xml b/mediarouter/src/main/res/values-ta/strings.xml
index 0b00c84..6b4f896 100644
--- a/mediarouter/src/main/res/values-ta/strings.xml
+++ b/mediarouter/src/main/res/values-ta/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"சிஸ்டம்"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"சாதனங்கள்"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"அலைபரப்பும் பட்டன்"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"அலைபரப்பும் பட்டன். துண்டிக்கப்பட்டது"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"அலைபரப்பும் பட்டன். இணைக்கிறது"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"அலைபரப்பும் பட்டன். இணைக்கப்பட்டது"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"இதற்கு அலைபரப்பு:"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"சாதனங்களைத் தேடுகிறது"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"தொடர்பைத் துண்டி"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"அலைபரப்புவதை நிறுத்து"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"மூடுவதற்கான பட்டன்"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"இயக்குவதற்கான பட்டன்"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"இடைநிறுத்துவதற்கான பட்டன்"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"நிறுத்துவதற்கான பட்டன்"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"விரிப்பதற்கான பட்டன்"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"சுருக்குவதற்கான பட்டன்"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"ஆல்பம் ஆர்ட்"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"ஒலியளவு ஸ்லைடர்"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"மீடியா எதுவும் தேர்ந்தெடுக்கப்படவில்லை"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"தகவல் எதுவுமில்லை"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"திரையை அலைபரப்புகிறது"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"சிஸ்டம்"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"சாதனங்கள்"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"அலைபரப்பும் பட்டன்"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"அலைபரப்பும் பட்டன். துண்டிக்கப்பட்டது"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"அலைபரப்பும் பட்டன். இணைக்கிறது"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"அலைபரப்பும் பட்டன். இணைக்கப்பட்டது"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"இதற்கு அலைபரப்பு:"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"சாதனங்களைத் தேடுகிறது"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"துண்டி"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"அலைபரப்புவதை நிறுத்து"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"மூடுவதற்கான பட்டன்"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"இயக்குவதற்கான பட்டன்"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"இடைநிறுத்துவதற்கான பட்டன்"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"நிறுத்துவதற்கான பட்டன்"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"விரிவாக்குவதற்கான பட்டன்"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"சுருக்குவதற்கான பட்டன்"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"ஆல்பம் ஆர்ட்"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"ஒலியளவு ஸ்லைடர்"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"மீடியா எதுவும் தேர்ந்தெடுக்கப்படவில்லை"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"தகவல் எதுவுமில்லை"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"திரையை அலைபரப்புகிறது"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-te/strings.xml b/mediarouter/src/main/res/values-te/strings.xml
index a8fe99a6..0d4168f 100644
--- a/mediarouter/src/main/res/values-te/strings.xml
+++ b/mediarouter/src/main/res/values-te/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"సిస్టమ్"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"పరికరాలు"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Cast బటన్"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Cast బటన్. డిస్‌కనెక్ట్ చేయబడింది"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Cast బటన్. కనెక్ట్ చేస్తోంది"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Cast బటన్. కనెక్ట్ చేయబడింది"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"దీనికి ప్రసారం చేయండి"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"పరికరాలను కనుగొంటోంది"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"డిస్‌కనెక్ట్ చేయి"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"ప్రసారాన్ని ఆపివేయి"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"మూసివేయి"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"ఆడండి"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"పాజ్ చేయి"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"ఆపు"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"విస్తరించు"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"కుదించు"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"ఆల్బమ్ ఆర్ట్"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"వాల్యూమ్ స్లయిడర్"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"మీడియా ఏదీ ఎంచుకోలేదు"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"సమాచారం అందుబాటులో లేదు"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"స్క్రీన్‌ను ప్రసారం చేస్తోంది"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"సిస్టమ్"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"పరికరాలు"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Cast బటన్"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Cast బటన్. డిస్‌కనెక్ట్ చేయబడింది"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Cast బటన్. కనెక్ట్ చేస్తోంది"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Cast బటన్. కనెక్ట్ చేయబడింది"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"దీనికి ప్రసారం చేయండి"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"పరికరాలను కనుగొంటోంది"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"డిస్‌కనెక్ట్ చేయి"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"ప్రసారాన్ని ఆపివేయి"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"మూసివేయి"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"ప్లే చేయి"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"పాజ్ చేయి"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"ఆపివేయి"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"విస్తరించు"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"కుదించు"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"ఆల్బమ్ ఆర్ట్"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"వాల్యూమ్ స్లయిడర్"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"మీడియా ఏదీ ఎంచుకోలేదు"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"సమాచారం అందుబాటులో లేదు"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"స్క్రీన్‌ను ప్రసారం చేస్తోంది"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-th/strings.xml b/mediarouter/src/main/res/values-th/strings.xml
index 4a388ed..b360779 100644
--- a/mediarouter/src/main/res/values-th/strings.xml
+++ b/mediarouter/src/main/res/values-th/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"ระบบ"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"อุปกรณ์"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"ปุ่ม \"แคสต์\""</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"ปุ่ม \"แคสต์\" ยกเลิกการเชื่อมต่อแล้ว"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"ปุ่ม \"แคสต์\" กำลังเชื่อมต่อ"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"ปุ่ม \"แคสต์\" เชื่อมต่อแล้ว"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"แคสต์ไปยัง"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"กำลังค้นหาอุปกรณ์"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"ยกเลิกการเชื่อมต่อ"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"หยุดแคสต์"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"ปิด"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"เปิด"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"หยุดชั่วคราว"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"หยุด"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"ขยาย"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"ยุบ"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"ปกอัลบั้ม"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"แถบเลื่อนปรับระดับเสียง"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"ไม่ได้เลือกสื่อไว้"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"ไม่มีข้อมูล"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"กำลังแคสต์หน้าจอ"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"ระบบ"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"อุปกรณ์"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"ปุ่ม \"แคสต์\""</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"ปุ่ม \"แคสต์\" ยกเลิกการเชื่อมต่อแล้ว"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"ปุ่ม \"แคสต์\" กำลังเชื่อมต่อ"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"ปุ่ม \"แคสต์\" เชื่อมต่อแล้ว"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"แคสต์ไปยัง"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"กำลังค้นหาอุปกรณ์"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"ยกเลิกการเชื่อมต่อ"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"หยุดแคสต์"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"ปิด"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"เล่น"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"หยุดชั่วคราว"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"หยุด"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"ขยาย"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"ยุบ"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"ปกอัลบั้ม"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"แถบเลื่อนปรับระดับเสียง"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"ไม่ได้เลือกสื่อไว้"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"ไม่มีข้อมูล"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"กำลังแคสต์หน้าจอ"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-tl/strings.xml b/mediarouter/src/main/res/values-tl/strings.xml
index 0e450f3..4d21125 100644
--- a/mediarouter/src/main/res/values-tl/strings.xml
+++ b/mediarouter/src/main/res/values-tl/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"System"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Mga Device"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Button na I-cast"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Button na I-cast. Nadiskonekta"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Button na I-cast. Kumokonekta"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Button na I-cast. Nakakonekta"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"I-cast sa"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Naghahanap ng mga device"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Idiskonekta"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Ihinto ang pag-cast"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Isara"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"I-play"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"I-pause"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Ihinto"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"I-expand"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"I-collapse"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Album art"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Slider ng volume"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Walang napiling media"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Walang available na impormasyon"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Ikina-cast ang screen"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"System"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Mga Device"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Button na I-cast"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Button na I-cast. Nadiskonekta"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Button na I-cast. Kumokonekta"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Button na I-cast. Nakakonekta"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"I-cast sa"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Naghahanap ng mga device"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Idiskonekta"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Ihinto ang pag-cast"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Isara"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"I-play"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"I-pause"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Ihinto"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"I-expand"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"I-collapse"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Album art"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Slider ng volume"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Walang napiling media"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Walang available na impormasyon"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Ikina-cast ang screen"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-tr/strings.xml b/mediarouter/src/main/res/values-tr/strings.xml
index 5c8882f..e44f443 100644
--- a/mediarouter/src/main/res/values-tr/strings.xml
+++ b/mediarouter/src/main/res/values-tr/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Sistem"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Cihazlar"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Yayınla düğmesi"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Yayınla düğmesi. Bağlantı kesildi"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Yayınla düğmesi. Bağlanıyor"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Yayınla düğmesi. Bağlandı"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Yayınlanacak yer:"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Cihazlar bulunuyor"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Bağlantıyı kes"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Yayını durdur"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Kapat"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Oynat"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Duraklat"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Durdur"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Genişlet"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Daralt"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albüm kapağı"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Ses düzeyi kaydırma çubuğu"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Medya seçilmedi"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Bilgi yok"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Ekran yayınlanıyor"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Sistem"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Cihazlar"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Yayınla düğmesi"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Yayınla düğmesi. Bağlantı kesildi"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Yayınla düğmesi. Bağlanıyor"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Yayınla düğmesi. Bağlandı"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Şuraya yayınla:"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Cihazlar bulunuyor"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Bağlantıyı kes"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Yayını durdur"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Kapat"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Oynat"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Duraklat"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Durdur"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Genişlet"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Daralt"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albüm kapağı"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Ses düzeyi kaydırma çubuğu"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Medya seçilmedi"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Bilgi yok"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Ekran yayınlanıyor"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-uk/strings.xml b/mediarouter/src/main/res/values-uk/strings.xml
index c90ece6..28e09bd 100644
--- a/mediarouter/src/main/res/values-uk/strings.xml
+++ b/mediarouter/src/main/res/values-uk/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Система"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Пристрої"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Кнопка трансляції"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Кнопка трансляції. Від’єднано"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Кнопка трансляції. Під’єднання"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Кнопка трансляції. Під’єднано"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Транслювати на пристрій"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Пошук пристроїв"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Від’єднати"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Припинити трансляцію"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Закрити"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Відтворити"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Призупинити"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Зупинити"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Розгорнути"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Згорнути"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Обкладинка альбому"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Повзунок гучності"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Не вибрано медіа-вміст"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Немає даних"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Трансляція екрана"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Система"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Пристрої"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Кнопка трансляції"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Кнопка трансляції. Від’єднано"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Кнопка трансляції. Під’єднання"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Кнопка трансляції. Під’єднано"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Транслювати на"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Пошук пристроїв"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Від’єднати"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Припинити трансляцію"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Закрити"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Відтворити"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Призупинити"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Припинити"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Розгорнути"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Згорнути"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Обкладинка альбому"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Повзунок гучності"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Не вибрано медіа"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Немає даних"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Трансляція екрана"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-ur/strings.xml b/mediarouter/src/main/res/values-ur/strings.xml
index 4ae82e6..8c09830 100644
--- a/mediarouter/src/main/res/values-ur/strings.xml
+++ b/mediarouter/src/main/res/values-ur/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"سسٹم"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"آلات"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"کاسٹ کرنے کا بٹن"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"کاسٹ کرنے کا بٹن۔ غیر منسلک ہے"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"کاسٹ کرنے کا بٹن۔ منسلک ہو رہا ہے"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"کاسٹ کرنے کا بٹن۔ منسلک ہے"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"اس میں کاسٹ کریں"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"آلات تلاش کیے جا رہے ہیں"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"غیر منسلک کریں"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"کاسٹ کرنا بند کریں"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"بند کریں"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"چلائیں"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"موقوف کریں"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"روکیں"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"پھیلائیں"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"سکیڑیں"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"البم آرٹ"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"والیوم سلائیڈر"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"کوئی میڈیا منتخب نہیں ہے"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"کوئی معلومات دستیاب نہیں ہے"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"اسکرین کاسٹ ہو رہی ہے"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"سسٹم"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"آلات"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"کاسٹ کرنے کا بٹن"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"کاسٹ کرنے کا بٹن۔ غیر منسلک ہے"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"کاسٹ کرنے کا بٹن۔ منسلک ہو رہا ہے"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"کاسٹ کرنے کا بٹن۔ منسلک ہے"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"اس میں کاسٹ کریں"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"آلات تلاش کئے جا رہے ہیں"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"غیر منسلک کریں"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"کاسٹ کرنا بند کریں"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"بند کریں"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"چلائیں"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"موقوف کریں"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"روکیں"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"پھیلائیں"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"سکیڑیں"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"البم آرٹ"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"والیوم سلائیڈر"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"کوئی میڈیا منتخب نہیں ہے"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"کوئی معلومات دستیاب نہیں"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"اسکرین کاسٹ ہو رہی ہے"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-uz/strings.xml b/mediarouter/src/main/res/values-uz/strings.xml
index bd7394b..2eadc9b 100644
--- a/mediarouter/src/main/res/values-uz/strings.xml
+++ b/mediarouter/src/main/res/values-uz/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Tizim"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Qurilmalar"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Translatsiya tugmasi"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Translatsiya tugmasi. Uzildi"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Translatsiya tugmasi. Ulanmoqda"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Translatsiya tugmasi. Ulandi"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Bunga translatsiya qilish:"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Qurilmalarni topish"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Uzish"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Translatsiyani to‘xtatish"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Yopish"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Ijro"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Pauza"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"To‘xtatish"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Yoyish"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Kichraytirish"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Albom muqovasi"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Tovush balandligi slayderi"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Hech narsa tanlanmagan"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Hech narsa topilmadi"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Ekran namoyish qilinmoqda"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Tizim"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Qurilmalar"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Translatsiya qilish tugmasi"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Translatsiya tugmasi. Uzildi"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Translatsiya tugmasi. Ulanmoqda"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Translatsiya tugmasi. Ulandi"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Bunga translatsiya qilish:"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Qurilmalarni topish"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Uzish"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Translatsiyani to‘xtatish"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Yopish"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Ijro"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Pauza"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"To‘xtatish"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Yoyish"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Yig‘ish"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Albom muqovasi"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Tovush balandligi slayderi"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Multimedia tanlamagan"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Ma’lumot yo‘q"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Ekran namoyish qilinmoqda"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-vi/strings.xml b/mediarouter/src/main/res/values-vi/strings.xml
index 82204b4..d0f7311 100644
--- a/mediarouter/src/main/res/values-vi/strings.xml
+++ b/mediarouter/src/main/res/values-vi/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Hệ thống"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Thiết bị"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Nút truyền"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Nút truyền. Đã ngắt kết nối"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Nút truyền. Đang kết nối"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Nút truyền. Đã kết nối"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Truyền tới"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Đang tìm thiết bị"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Ngắt kết nối"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Dừng truyền"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Đóng"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Phát"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Tạm dừng"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Dừng"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Mở rộng"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Thu gọn"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Ảnh bìa album"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Thanh trượt âm lượng"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Chưa chọn phương tiện nào"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Không có thông tin nào"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Đang truyền màn hình"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Hệ thống"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Thiết bị"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Nút truyền"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Nút truyền. Đã ngắt kết nối"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Nút truyền. Đang kết nối"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Nút truyền. Đã kết nối"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Truyền tới"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Đang tìm thiết bị"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Ngắt kết nối"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Dừng truyền"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Đóng"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Phát"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Tạm dừng"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Dừng"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Mở rộng"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Thu gọn"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Ảnh bìa album"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Thanh trượt âm lượng"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Không có phương tiện nào được chọn"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Không có thông tin nào"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Đang truyền màn hình"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-zh-rCN/strings.xml b/mediarouter/src/main/res/values-zh-rCN/strings.xml
index 92fe319..140c817 100644
--- a/mediarouter/src/main/res/values-zh-rCN/strings.xml
+++ b/mediarouter/src/main/res/values-zh-rCN/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"系统"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"设备"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"投射按钮"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"投射按钮。已断开连接"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"投射按钮。正在连接"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"投射按钮。已连接"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"投射到"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"正在查找设备"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"断开连接"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"停止投射"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"关闭"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"播放"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"暂停"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"停止"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"展开"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"收起"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"专辑封面"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"音量滑块"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"未选择任何媒体内容"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"没有任何相关信息"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"正在投射屏幕"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"系统"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"设备"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"投射按钮"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"投射按钮。已断开连接"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"投射按钮。正在连接"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"投射按钮。已连接"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"投射到"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"正在查找设备"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"断开连接"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"停止投射"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"关闭"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"播放"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"暂停"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"停止"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"展开"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"收起"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"专辑封面"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"音量滑块"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"未选择任何媒体内容"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"没有任何相关信息"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"正在投射屏幕"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-zh-rHK/strings.xml b/mediarouter/src/main/res/values-zh-rHK/strings.xml
index 2de9f04..9318093 100644
--- a/mediarouter/src/main/res/values-zh-rHK/strings.xml
+++ b/mediarouter/src/main/res/values-zh-rHK/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"系統"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"裝置"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"投放按鈕"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"投放按鈕。解除咗連線"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"投放按鈕。連緊線"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"投放按鈕。連咗線"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"投放至"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"正在尋找裝置"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"解除連接"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"停止投放"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"閂"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"播"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"暫停"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"停"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"展開"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"收合"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"專輯封面"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"音量滑桿"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"未選取任何媒體"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"沒有資料可以提供"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"正在投放畫面"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"系統"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"裝置"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"投放按鈕"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"投放按鈕。解除咗連線"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"投放按鈕。連緊線"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"投放按鈕。連咗線"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"投放至"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"正在尋找裝置"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"解除連線"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"停止投放"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"閂"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"播放"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"暫停"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"停"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"展開"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"收合"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"專輯封面"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"音量滑桿"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"未選取任何媒體"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"沒有資料可以提供"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"正在投放畫面"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-zh-rTW/strings.xml b/mediarouter/src/main/res/values-zh-rTW/strings.xml
index 08b92c6..bd2f9ad 100644
--- a/mediarouter/src/main/res/values-zh-rTW/strings.xml
+++ b/mediarouter/src/main/res/values-zh-rTW/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"系統"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"裝置"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"投放按鈕"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"投放按鈕;已中斷連線"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"投放按鈕;連線中"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"投放按鈕;已連線"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"投放到"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"正在尋找裝置"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"中斷連線"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"停止投放"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"關閉"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"播放"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"暫停"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"停止"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"展開"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"收合"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"專輯封面"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"音量滑桿"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"未選取任何媒體"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"沒有可用的資訊"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"正在投放畫面"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"系統"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"裝置"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"投放按鈕"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"投放按鈕;已中斷連線"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"投放按鈕;連線中"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"投放按鈕;已連線"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"投放到"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"正在尋找裝置"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"中斷連線"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"停止投放"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"關閉"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"播放"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"暫停"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"停止"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"展開"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"收合"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"專輯封面"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"音量滑桿"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"未選取任何媒體"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"沒有可用的資訊"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"正在投放畫面"</string>
 </resources>
diff --git a/mediarouter/src/main/res/values-zu/strings.xml b/mediarouter/src/main/res/values-zu/strings.xml
index cf767c0..e91293f 100644
--- a/mediarouter/src/main/res/values-zu/strings.xml
+++ b/mediarouter/src/main/res/values-zu/strings.xml
@@ -16,25 +16,25 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mr_system_route_name" msgid="3117964881088969586">"Isistimu"</string>
-    <string name="mr_user_route_category_name" msgid="8236416097133080726">"Amadivayisi"</string>
-    <string name="mr_button_content_description" msgid="1685185767093348095">"Inkinobho yokusakaza"</string>
-    <string name="mr_cast_button_disconnected" msgid="5501231066847739632">"Inkinobho yokusakaza. Kunqanyuliwe"</string>
-    <string name="mr_cast_button_connecting" msgid="8959304318293841992">"Inkinobho yokusakaza. Kuyaxhunywa"</string>
-    <string name="mr_cast_button_connected" msgid="1350095112462806159">"Inkinobho yokusakaza. Kuxhunyiwe"</string>
-    <string name="mr_chooser_title" msgid="7548226170787476564">"Sakaza ku-"</string>
-    <string name="mr_chooser_searching" msgid="5504553798429329689">"Ithola amadivayisi"</string>
-    <string name="mr_controller_disconnect" msgid="1370654436555555647">"Nqamula"</string>
-    <string name="mr_controller_stop_casting" msgid="7617024847862349259">"Misa ukusakaza"</string>
-    <string name="mr_controller_close_description" msgid="5468775621814500662">"Vala"</string>
-    <string name="mr_controller_play" msgid="4443315438268112801">"Dlala"</string>
-    <string name="mr_controller_pause" msgid="4701315813294065305">"Phumula"</string>
-    <string name="mr_controller_stop" msgid="5106056093749454009">"Misa"</string>
-    <string name="mr_controller_expand_group" msgid="2422682304043876468">"Nweba"</string>
-    <string name="mr_controller_collapse_group" msgid="5518911192681928413">"Goqa"</string>
-    <string name="mr_controller_album_art" msgid="5813284753012893250">"Ubuciko be-albhamu"</string>
-    <string name="mr_controller_volume_slider" msgid="691656961160498512">"Isilayida sevolumu"</string>
-    <string name="mr_controller_no_media_selected" msgid="4342878516155861006">"Ayikho imidiya ekhethiwe"</string>
-    <string name="mr_controller_no_info_available" msgid="7299368841849988218">"Alukho ulwazi olutholakalayo"</string>
-    <string name="mr_controller_casting_screen" msgid="5286734709674025661">"Isikrini sokusakaza"</string>
+    <string name="mr_system_route_name" msgid="6445173646164603280">"Isistimu"</string>
+    <string name="mr_user_route_category_name" msgid="8951247913519682277">"Amadivayisi"</string>
+    <string name="mr_button_content_description" msgid="6209940985205889239">"Inkinobho yokusakaza"</string>
+    <string name="mr_cast_button_disconnected" msgid="1214396433859225686">"Inkinobho yokusakaza. Kunqanyuliwe"</string>
+    <string name="mr_cast_button_connecting" msgid="7767160474954808770">"Inkinobho yokusakaza. Kuyaxhunywa"</string>
+    <string name="mr_cast_button_connected" msgid="7205934955575650355">"Inkinobho yokusakaza. Kuxhunyiwe"</string>
+    <string name="mr_chooser_title" msgid="1469819231928206099">"Sakaza ku-"</string>
+    <string name="mr_chooser_searching" msgid="7883700464756247478">"Ithola amadivayisi"</string>
+    <string name="mr_controller_disconnect" msgid="1224563715954797152">"Nqamula"</string>
+    <string name="mr_controller_stop_casting" msgid="6043110833085090960">"Misa ukusakaza"</string>
+    <string name="mr_controller_close_description" msgid="1404151965680505956">"Vala"</string>
+    <string name="mr_controller_play" msgid="2233159395781515552">"Dlala"</string>
+    <string name="mr_controller_pause" msgid="5465089322498973309">"Misa isikhashana"</string>
+    <string name="mr_controller_stop" msgid="6970507798830838731">"Misa"</string>
+    <string name="mr_controller_expand_group" msgid="6561849209271950311">"Nweba"</string>
+    <string name="mr_controller_collapse_group" msgid="5621264648958127139">"Goqa"</string>
+    <string name="mr_controller_album_art" msgid="8313236767081989488">"Ubuciko be-albhamu"</string>
+    <string name="mr_controller_volume_slider" msgid="390328956880221771">"Isilayida sevolumu"</string>
+    <string name="mr_controller_no_media_selected" msgid="5388112032574870059">"Ayikho imidiya ekhethiwe"</string>
+    <string name="mr_controller_no_info_available" msgid="942251150039480236">"Alukho ulwazi olutholakalayo"</string>
+    <string name="mr_controller_casting_screen" msgid="2406876321200529148">"Isikrini sokusakaza"</string>
 </resources>
diff --git a/paging/runtime/src/main/java/androidx/paging/AsyncPagedListDiffer.java b/paging/runtime/src/main/java/androidx/paging/AsyncPagedListDiffer.java
index 0033665..f30163d 100644
--- a/paging/runtime/src/main/java/androidx/paging/AsyncPagedListDiffer.java
+++ b/paging/runtime/src/main/java/androidx/paging/AsyncPagedListDiffer.java
@@ -150,7 +150,7 @@
     public AsyncPagedListDiffer(@NonNull RecyclerView.Adapter adapter,
             @NonNull DiffUtil.ItemCallback<T> diffCallback) {
         mUpdateCallback = new AdapterListUpdateCallback(adapter);
-        mConfig = new AsyncDifferConfig.Builder<>(diffCallback).build();
+        mConfig = new AsyncDifferConfig.Builder<T>(diffCallback).build();
     }
 
     @SuppressWarnings("WeakerAccess")
@@ -227,7 +227,6 @@
      *
      * @param pagedList The new PagedList.
      */
-    @SuppressWarnings("ReferenceEquality")
     public void submitList(final PagedList<T> pagedList) {
         if (pagedList != null) {
             if (mPagedList == null && mSnapshot == null) {
diff --git a/preference/res/values-af/strings.xml b/preference/res/values-af/strings.xml
index 0f325ec..17c2037 100644
--- a/preference/res/values-af/strings.xml
+++ b/preference/res/values-af/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"AAN"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"AF"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Gevorderd"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"AAN"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"AF"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Gevorderd"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-am/strings.xml b/preference/res/values-am/strings.xml
index c7de5d8..052425c 100644
--- a/preference/res/values-am/strings.xml
+++ b/preference/res/values-am/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"በርቷል"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ጠፍቷል"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"የላቀ"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>፣ <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"በርቷል"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ቅናሽ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"የላቀ"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>፣ <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ar/strings.xml b/preference/res/values-ar/strings.xml
index 90b2266..1e5515d 100644
--- a/preference/res/values-ar/strings.xml
+++ b/preference/res/values-ar/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"تفعيل"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"إيقاف"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"إعدادات متقدمة"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>، <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"تفعيل"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"إيقاف"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"إعدادات متقدمة"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>، <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-as/strings.xml b/preference/res/values-as/strings.xml
deleted file mode 100644
index 739db0d..0000000
--- a/preference/res/values-as/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"অন কৰক"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"অফ অৱস্থাত আছে"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"উন্নত"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
-</resources>
diff --git a/preference/res/values-az/strings.xml b/preference/res/values-az/strings.xml
index 1b208c8..978b862 100644
--- a/preference/res/values-az/strings.xml
+++ b/preference/res/values-az/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"AKTİV"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DEAKTİV"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Qabaqcıl"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"AKTİV"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DEAKTİV"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Qabaqcıl"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-b+sr+Latn/strings.xml b/preference/res/values-b+sr+Latn/strings.xml
index 6ab31a0..61c784ae 100644
--- a/preference/res/values-b+sr+Latn/strings.xml
+++ b/preference/res/values-b+sr+Latn/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"UKLJUČENO"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ISKLJUČENO"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Napredno"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"UKLJUČENO"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ISKLJUČENO"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Napredno"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-be/strings.xml b/preference/res/values-be/strings.xml
index 0e2bd91..8ebdeaf 100644
--- a/preference/res/values-be/strings.xml
+++ b/preference/res/values-be/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"УКЛ."</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ВЫКЛ."</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Пашыраныя налады"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"УКЛ."</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ВЫКЛ."</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Высокая"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-bg/strings.xml b/preference/res/values-bg/strings.xml
index 0323468..e2e9544 100644
--- a/preference/res/values-bg/strings.xml
+++ b/preference/res/values-bg/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ВКЛ."</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ИЗКЛ."</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Разширени"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ВКЛ."</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ИЗКЛ."</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Разширени"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-bn/strings.xml b/preference/res/values-bn/strings.xml
index 92cd74f..a17e22a 100644
--- a/preference/res/values-bn/strings.xml
+++ b/preference/res/values-bn/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"চালু"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"বন্ধ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"উন্নত"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"চালু"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"বন্ধ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"উন্নত"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-bs/strings.xml b/preference/res/values-bs/strings.xml
index 6ab31a0..61c784ae 100644
--- a/preference/res/values-bs/strings.xml
+++ b/preference/res/values-bs/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"UKLJUČENO"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ISKLJUČENO"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Napredno"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"UKLJUČENO"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ISKLJUČENO"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Napredno"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ca/strings.xml b/preference/res/values-ca/strings.xml
index 10f3d94..56e5c66 100644
--- a/preference/res/values-ca/strings.xml
+++ b/preference/res/values-ca/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ACTIVAT"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DESACTIVAT"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Opcions avançades"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ACTIVAT"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DESACTIVAT"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Opcions avançades"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-cs/strings.xml b/preference/res/values-cs/strings.xml
index 11a67f8..5865c0b 100644
--- a/preference/res/values-cs/strings.xml
+++ b/preference/res/values-cs/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ZAP"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"VYP"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Rozšířená nastavení"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ZAP"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"VYP"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Rozšířené"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-da/strings.xml b/preference/res/values-da/strings.xml
index 67cb27c..da2532f 100644
--- a/preference/res/values-da/strings.xml
+++ b/preference/res/values-da/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"TIL"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"FRA"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Avanceret"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"TIL"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"FRA"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avanceret"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-de/strings.xml b/preference/res/values-de/strings.xml
index 759818d..5b0be51 100644
--- a/preference/res/values-de/strings.xml
+++ b/preference/res/values-de/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"EIN"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"AUS"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Erweitert"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"AN"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"AUS"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Erweitert"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-el/strings.xml b/preference/res/values-el/strings.xml
index 645d0bf..59ba395 100644
--- a/preference/res/values-el/strings.xml
+++ b/preference/res/values-el/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ΕΝΕΡΓΗ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ΑΝΕΝΕΡΓΗ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Σύνθετες"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ΕΝΕΡΓΟΠΟΙΗΣΗ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ΑΠΕΝΕΡΓΟΠΟΙΗΣΗ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Σύνθετες"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-en-rAU/strings.xml b/preference/res/values-en-rAU/strings.xml
index c8d1681..dd3e15f 100644
--- a/preference/res/values-en-rAU/strings.xml
+++ b/preference/res/values-en-rAU/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ON"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"OFF"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Advanced"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ON"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"OFF"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Advanced"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-en-rCA/strings.xml b/preference/res/values-en-rCA/strings.xml
index c8d1681..dd3e15f 100644
--- a/preference/res/values-en-rCA/strings.xml
+++ b/preference/res/values-en-rCA/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ON"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"OFF"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Advanced"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ON"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"OFF"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Advanced"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-en-rGB/strings.xml b/preference/res/values-en-rGB/strings.xml
index c8d1681..dd3e15f 100644
--- a/preference/res/values-en-rGB/strings.xml
+++ b/preference/res/values-en-rGB/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ON"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"OFF"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Advanced"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ON"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"OFF"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Advanced"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-en-rIN/strings.xml b/preference/res/values-en-rIN/strings.xml
index c8d1681..dd3e15f 100644
--- a/preference/res/values-en-rIN/strings.xml
+++ b/preference/res/values-en-rIN/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ON"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"OFF"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Advanced"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ON"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"OFF"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Advanced"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-en-rXC/strings.xml b/preference/res/values-en-rXC/strings.xml
index 96219e7..3f4c7a0 100644
--- a/preference/res/values-en-rXC/strings.xml
+++ b/preference/res/values-en-rXC/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‏‏‏‎‎‎‏‏‏‎ON‎‏‎‎‏‎"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‏‎OFF‎‏‎‎‏‎"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‎‎Advanced‎‏‎‎‏‎"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="ADDED_ITEMS">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‎‎ON‎‏‎‎‏‎"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎OFF‎‏‎‎‏‎"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‏‏‎‎‎Advanced‎‏‎‎‏‎"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‎‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="ADDED_ITEMS">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
 </resources>
diff --git a/preference/res/values-es-rUS/strings.xml b/preference/res/values-es-rUS/strings.xml
index e7639c1..3911ab9 100644
--- a/preference/res/values-es-rUS/strings.xml
+++ b/preference/res/values-es-rUS/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ACTIVADA"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DESACTIVADA"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Opciones avanzadas"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ACTIVADO"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DESACTIVADO"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avanzado"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-es/strings.xml b/preference/res/values-es/strings.xml
index f40f3ea..3911ab9 100644
--- a/preference/res/values-es/strings.xml
+++ b/preference/res/values-es/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ACTIVADO"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DESACTIVADA"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Avanzada"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ACTIVADO"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DESACTIVADO"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avanzado"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-et/strings.xml b/preference/res/values-et/strings.xml
index a315280..9fa4f4f 100644
--- a/preference/res/values-et/strings.xml
+++ b/preference/res/values-et/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"SEES"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"VÄLJAS"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Täpsem"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"SEES"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"VÄLJAS"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Täpsemad"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-eu/strings.xml b/preference/res/values-eu/strings.xml
index 1a71b90..6718992 100644
--- a/preference/res/values-eu/strings.xml
+++ b/preference/res/values-eu/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"AKTIBATUTA"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DESAKTIBATUTA"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Hobespen aurreratuak"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"AKTIBATUTA"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DESAKTIBATUTA"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Aurreratua"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-fa/strings.xml b/preference/res/values-fa/strings.xml
index b4191aa..86e9f30 100644
--- a/preference/res/values-fa/strings.xml
+++ b/preference/res/values-fa/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"روشن"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"خاموش"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"پیشرفته"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>، <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"روشن"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"خاموش"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"پیشرفته"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>، <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-fi/strings.xml b/preference/res/values-fi/strings.xml
index cd82547..cec0857 100644
--- a/preference/res/values-fi/strings.xml
+++ b/preference/res/values-fi/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"KÄYTÖSSÄ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"POIS KÄYTÖSTÄ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Lisäasetukset"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"PÄÄLLÄ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"POIS PÄÄLTÄ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Lisätiedot"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-fr-rCA/strings.xml b/preference/res/values-fr-rCA/strings.xml
index 07af614..db4c2b5 100644
--- a/preference/res/values-fr-rCA/strings.xml
+++ b/preference/res/values-fr-rCA/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ACTIVÉ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DÉSACTIVÉ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Avancé"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ACTIVÉ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DÉSACTIVÉ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avancé"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-fr/strings.xml b/preference/res/values-fr/strings.xml
index e74b2a4..b5cca98 100644
--- a/preference/res/values-fr/strings.xml
+++ b/preference/res/values-fr/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ACTIVÉ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DÉSACTIVÉ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Préférences avancées"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ACTIVÉ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DÉSACTIVÉ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Options avancées"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-gl/strings.xml b/preference/res/values-gl/strings.xml
index 8091d9c..3911ab9 100644
--- a/preference/res/values-gl/strings.xml
+++ b/preference/res/values-gl/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ACTIVADO"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DESACTIVADO"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Configuración avanzada"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ACTIVADO"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DESACTIVADO"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avanzado"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-gu/strings.xml b/preference/res/values-gu/strings.xml
index a5c0287..468fd2c 100644
--- a/preference/res/values-gu/strings.xml
+++ b/preference/res/values-gu/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ચાલુ કરો"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"બંધ કરો"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"વિગતવાર"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ચાલુ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"બંધ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"વિગતવાર"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-hi/strings.xml b/preference/res/values-hi/strings.xml
index 3ac8ecc..dcfb766 100644
--- a/preference/res/values-hi/strings.xml
+++ b/preference/res/values-hi/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"चालू"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"बंद"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"बेहतर सेटिंग"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"चालू"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"बंद"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"बेहतर विकल्प"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-hr/strings.xml b/preference/res/values-hr/strings.xml
index 6ab31a0..61c784ae 100644
--- a/preference/res/values-hr/strings.xml
+++ b/preference/res/values-hr/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"UKLJUČENO"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ISKLJUČENO"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Napredno"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"UKLJUČENO"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ISKLJUČENO"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Napredno"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-hu/strings.xml b/preference/res/values-hu/strings.xml
index 0b65185..85f80aa 100644
--- a/preference/res/values-hu/strings.xml
+++ b/preference/res/values-hu/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"BE"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"KI"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Speciális"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"BE"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"KI"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Speciális"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-hy/strings.xml b/preference/res/values-hy/strings.xml
index c9d47a8..06f9d22 100644
--- a/preference/res/values-hy/strings.xml
+++ b/preference/res/values-hy/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ՄԻԱՑՎԱԾ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ԱՆՋԱՏԱԾ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Լրացուցիչ"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ՄԻԱՑՎԱԾ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ԱՆՋԱՏԱԾ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Լրացուցիչ"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-in/strings.xml b/preference/res/values-in/strings.xml
index d56dcd3..e17c251 100644
--- a/preference/res/values-in/strings.xml
+++ b/preference/res/values-in/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"AKTIF"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"NONAKTIF"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Lanjutan"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"AKTIF"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"NONAKTIF"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Lanjutan"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-is/strings.xml b/preference/res/values-is/strings.xml
index 6af367f..361d1c3 100644
--- a/preference/res/values-is/strings.xml
+++ b/preference/res/values-is/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"KVEIKT"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"SLÖKKT"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Ítarlegt"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"KVEIKT"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"SLÖKKT"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Ítarlegt"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-it/strings.xml b/preference/res/values-it/strings.xml
index 4fb3179..2514600 100644
--- a/preference/res/values-it/strings.xml
+++ b/preference/res/values-it/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ON"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"OFF"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Avanzate"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ON"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"OFF"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avanzate"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-iw/strings.xml b/preference/res/values-iw/strings.xml
index 8afe71e..6ca15e5 100644
--- a/preference/res/values-iw/strings.xml
+++ b/preference/res/values-iw/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"מופעל"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"כבוי"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"מתקדם"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"מופעל"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"כבוי"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"מתקדם"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ja/strings.xml b/preference/res/values-ja/strings.xml
index 30ebd124..2d599d3 100644
--- a/preference/res/values-ja/strings.xml
+++ b/preference/res/values-ja/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ON"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"OFF"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"詳細設定"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>、<xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ON"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"OFF"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"詳細設定"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>、<xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ka/strings.xml b/preference/res/values-ka/strings.xml
index 731ddd4..21b8246 100644
--- a/preference/res/values-ka/strings.xml
+++ b/preference/res/values-ka/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ჩართული"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"გამორთული"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"დამატებით"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ჩართული"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"გამორთული"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"დამატებით"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-kk/strings.xml b/preference/res/values-kk/strings.xml
index 2a5880c..ebbba78 100644
--- a/preference/res/values-kk/strings.xml
+++ b/preference/res/values-kk/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ҚОСУЛЫ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ӨШІРУЛІ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Қосымша"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ҚОСУЛЫ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ӨШІРУЛІ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Қосымша"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-km/strings.xml b/preference/res/values-km/strings.xml
index 4945df6..d7cb942 100644
--- a/preference/res/values-km/strings.xml
+++ b/preference/res/values-km/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"បើក"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"បិទ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"កម្រិតខ្ពស់"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"បើក"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"បិទ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"កម្រិតខ្ពស់"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-kn/strings.xml b/preference/res/values-kn/strings.xml
index a5a6200..9ce1917 100644
--- a/preference/res/values-kn/strings.xml
+++ b/preference/res/values-kn/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ಆನ್"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ಆಫ್"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"ಸುಧಾರಿತ"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ಆನ್"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ಆಫ್"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"ಸುಧಾರಿತ"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ko/strings.xml b/preference/res/values-ko/strings.xml
index 78d6449..ab1f380 100644
--- a/preference/res/values-ko/strings.xml
+++ b/preference/res/values-ko/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"사용"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"사용 안함"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"고급"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"사용"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"사용 안함"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"고급"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ky/strings.xml b/preference/res/values-ky/strings.xml
index 621effa..257c6d5 100644
--- a/preference/res/values-ky/strings.xml
+++ b/preference/res/values-ky/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"КҮЙҮК"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ӨЧҮК"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Өркүндөтүлгөн"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"КҮЙҮК"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ӨЧҮК"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Өркүндөтүлгөн"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-lo/strings.xml b/preference/res/values-lo/strings.xml
index 9a740a8..f4c1e2d 100644
--- a/preference/res/values-lo/strings.xml
+++ b/preference/res/values-lo/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ເປີດ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ປິດ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"ຂັ້ນສູງ"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ເປີດ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ປິດ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"ຂັ້ນສູງ"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-lt/strings.xml b/preference/res/values-lt/strings.xml
index ddfd0dc..ef1bfd6 100644
--- a/preference/res/values-lt/strings.xml
+++ b/preference/res/values-lt/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ĮJUNGTA"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"IŠJUNGTA"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Išplėstinė"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"Įjungta"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"Išjungta"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Išplėstinės"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-lv/strings.xml b/preference/res/values-lv/strings.xml
index 07c4dea..e4890b1 100644
--- a/preference/res/values-lv/strings.xml
+++ b/preference/res/values-lv/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"IESLĒGTS"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"IZSLĒGTS"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Papildu iestatījumi"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"IESLĒGTS"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"IZSLĒGTS"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Papildu"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-mk/strings.xml b/preference/res/values-mk/strings.xml
index fd4d5a1..f276876 100644
--- a/preference/res/values-mk/strings.xml
+++ b/preference/res/values-mk/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ВКЛУЧЕНО"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ИСКЛУЧЕНО"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Напредни"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ВКЛУЧЕНО"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ИСКЛУЧЕНО"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Напредно"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ml/strings.xml b/preference/res/values-ml/strings.xml
index 46d5e49..83d1125 100644
--- a/preference/res/values-ml/strings.xml
+++ b/preference/res/values-ml/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ഓൺ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ഓഫ്"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"വിപുലമായത്"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ഓൺ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ഓഫ്"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"വിപുലമായത്"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-mn/strings.xml b/preference/res/values-mn/strings.xml
index bf54850..2d20950 100644
--- a/preference/res/values-mn/strings.xml
+++ b/preference/res/values-mn/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ИДЭВХТЭЙ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ИДЭВХГҮЙ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Дэлгэрэнгүй"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"АСААЛТТАЙ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"УНТРААТАЙ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Нарийвчилсан"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-mr/strings.xml b/preference/res/values-mr/strings.xml
index 2cd0eec..1e492dd 100644
--- a/preference/res/values-mr/strings.xml
+++ b/preference/res/values-mr/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"चालू"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"बंद"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"प्रगत"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"चालू"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"बंद"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"प्रगत"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ms/strings.xml b/preference/res/values-ms/strings.xml
index b753aac..1601d8a 100644
--- a/preference/res/values-ms/strings.xml
+++ b/preference/res/values-ms/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"HIDUP"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"MATI"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Terperinci"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"HIDUP"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"MATI"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Lanjutan"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-my/strings.xml b/preference/res/values-my/strings.xml
index e1a96ec..77237bc 100644
--- a/preference/res/values-my/strings.xml
+++ b/preference/res/values-my/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ဖွင့်ရန်"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ပိတ်ရန်"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"အဆင့်မြင့်"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>၊ <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ဖွင့်ရန်"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ပိတ်ရန်"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"အဆင့်မြင့်"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>၊ <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-nb/strings.xml b/preference/res/values-nb/strings.xml
index 07e7b3a..d5c814b 100644
--- a/preference/res/values-nb/strings.xml
+++ b/preference/res/values-nb/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"PÅ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"AV"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Avansert"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"PÅ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"AV"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avansert"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ne/strings.xml b/preference/res/values-ne/strings.xml
index 28cdfe9..1da1f25 100644
--- a/preference/res/values-ne/strings.xml
+++ b/preference/res/values-ne/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"सक्रिय"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"निष्क्रिय पार्नुहोस्‌"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"उन्नत"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"सक्रिय छ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"निष्क्रिय छ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"उन्नत"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-nl/strings.xml b/preference/res/values-nl/strings.xml
index 5269cf0..dc84ab8 100644
--- a/preference/res/values-nl/strings.xml
+++ b/preference/res/values-nl/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"AAN"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"UIT"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Geavanceerd"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"AAN"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"UIT"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Geavanceerd"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-or/strings.xml b/preference/res/values-or/strings.xml
deleted file mode 100644
index 40ec596..0000000
--- a/preference/res/values-or/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ଅନ୍ ଅଛି"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ଅଫ୍ ଅଛି"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"ଅଧିକ ଉନ୍ନତ"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
-</resources>
diff --git a/preference/res/values-pa/strings.xml b/preference/res/values-pa/strings.xml
index 9d1a2f9..29471c3 100644
--- a/preference/res/values-pa/strings.xml
+++ b/preference/res/values-pa/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ਚਾਲੂ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ਬੰਦ"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"ਉੱਨਤ"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ਚਾਲੂ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ਬੰਦ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"ਉੱਨਤ"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-pl/strings.xml b/preference/res/values-pl/strings.xml
index d5d3bc1..ef7bbf8 100644
--- a/preference/res/values-pl/strings.xml
+++ b/preference/res/values-pl/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"WŁ."</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"WYŁ."</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Zaawansowane"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"WŁ."</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"WYŁ."</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Zaawansowane"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-pt-rBR/strings.xml b/preference/res/values-pt-rBR/strings.xml
index a77b7d4..433e8e3 100644
--- a/preference/res/values-pt-rBR/strings.xml
+++ b/preference/res/values-pt-rBR/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ATIVADO"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DESATIVADO"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Avançado"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ATIVADO"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DESATIVADO"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avançado"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-pt-rPT/strings.xml b/preference/res/values-pt-rPT/strings.xml
index 2c02859..4f296f6 100644
--- a/preference/res/values-pt-rPT/strings.xml
+++ b/preference/res/values-pt-rPT/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ATIVADO"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DESATIVADO"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Avançadas"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ATIVADA"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DESATIVADA"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avançadas"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-pt/strings.xml b/preference/res/values-pt/strings.xml
index a77b7d4..433e8e3 100644
--- a/preference/res/values-pt/strings.xml
+++ b/preference/res/values-pt/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ATIVADO"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DESATIVADO"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Avançado"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ATIVADO"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DESATIVADO"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avançado"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ro/strings.xml b/preference/res/values-ro/strings.xml
index 296bef2..1353a6f 100644
--- a/preference/res/values-ro/strings.xml
+++ b/preference/res/values-ro/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ACTIVAT"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"DEZACTIVAT"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Avansat"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ACTIVAT"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"DEZACTIVAT"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avansat"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ru/strings.xml b/preference/res/values-ru/strings.xml
index 854a395..8449700 100644
--- a/preference/res/values-ru/strings.xml
+++ b/preference/res/values-ru/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ВКЛ."</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ВЫКЛ."</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Дополнительно"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ВКЛ."</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ВЫКЛ."</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Дополнительно"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-si/strings.xml b/preference/res/values-si/strings.xml
index 11f85fe..27bf118 100644
--- a/preference/res/values-si/strings.xml
+++ b/preference/res/values-si/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ක්‍රියාත්මකයි"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ක්‍රියාවිරහිතයි"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"උසස්"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ක්‍රියාත්මකයි"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ක්‍රියාවිරහිතයි"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"උසස්"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-sk/strings.xml b/preference/res/values-sk/strings.xml
index 5d56e98..a087a8b 100644
--- a/preference/res/values-sk/strings.xml
+++ b/preference/res/values-sk/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ZAP."</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"VYP."</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Rozšírené"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ZAP."</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"VYP."</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Rozšírené"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-sl/strings.xml b/preference/res/values-sl/strings.xml
index c21b129..887c1b1 100644
--- a/preference/res/values-sl/strings.xml
+++ b/preference/res/values-sl/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"VKLOPLJENO"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"IZKLOPLJENO"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Dodatno"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"VKLOPLJENO"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"IZKLOPLJENO"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Dodatno"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-sq/strings.xml b/preference/res/values-sq/strings.xml
index 7ba659c..f2f5b77 100644
--- a/preference/res/values-sq/strings.xml
+++ b/preference/res/values-sq/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"AKTIV"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"JOAKTIV"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Të përparuara"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"AKTIV"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"JOAKTIV"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Të përparuara"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-sr/strings.xml b/preference/res/values-sr/strings.xml
index 3128648..322ace5 100644
--- a/preference/res/values-sr/strings.xml
+++ b/preference/res/values-sr/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"УКЉУЧЕНО"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ИСКЉУЧЕНО"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Напредно"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"УКЉУЧЕНО"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ИСКЉУЧЕНО"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Напредно"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-sv/strings.xml b/preference/res/values-sv/strings.xml
index 9257e88..c689ea1 100644
--- a/preference/res/values-sv/strings.xml
+++ b/preference/res/values-sv/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"PÅ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"AV"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Avancerat"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"PÅ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"AV"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Avancerat"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-sw/strings.xml b/preference/res/values-sw/strings.xml
index f3e72d5..9010663 100644
--- a/preference/res/values-sw/strings.xml
+++ b/preference/res/values-sw/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"IMEWASHWA"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"IMEZIMWA"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Mipangilio ya Kina"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"IMEWASHWA"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"IMEZIMWA"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Mipangilio ya Kina"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ta/strings.xml b/preference/res/values-ta/strings.xml
index d13e3ec..9fc536d 100644
--- a/preference/res/values-ta/strings.xml
+++ b/preference/res/values-ta/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ஆன்"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ஆஃப்"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"மேம்பட்டவை"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ஆன் செய்"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ஆஃப் செய்"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"மேம்பட்டது"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-te/strings.xml b/preference/res/values-te/strings.xml
index 30d0c45..7277c76 100644
--- a/preference/res/values-te/strings.xml
+++ b/preference/res/values-te/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"ఆన్ చేయండి"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ఆఫ్ చేయండి"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"అధునాతన"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"ఆన్"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ఆఫ్"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"అధునాతనం"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-th/strings.xml b/preference/res/values-th/strings.xml
index 18e3ba4..90a5433 100644
--- a/preference/res/values-th/strings.xml
+++ b/preference/res/values-th/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"เปิด"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ปิด"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"ขั้นสูง"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g> <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"เปิด"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ปิด"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"ขั้นสูง"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g> <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-tl/strings.xml b/preference/res/values-tl/strings.xml
index 1d9a85d..5b6885b 100644
--- a/preference/res/values-tl/strings.xml
+++ b/preference/res/values-tl/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"NAKA-ON"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"NAKA-OFF"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Advanced"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"NAKA-ON"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"NAKA-OFF"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Advanced"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-tr/strings.xml b/preference/res/values-tr/strings.xml
index 8363a5b..fa66179 100644
--- a/preference/res/values-tr/strings.xml
+++ b/preference/res/values-tr/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"AÇIK"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"KAPALI"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Gelişmiş"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"AÇIK"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"KAPALI"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Gelişmiş"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-uk/strings.xml b/preference/res/values-uk/strings.xml
index b8c60e0..47280c3 100644
--- a/preference/res/values-uk/strings.xml
+++ b/preference/res/values-uk/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"УВІМКНЕНО"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"ВИМКНЕНО"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Додатково"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"УВІМКНЕНО"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"ВИМКНЕНО"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Додатково"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-ur/strings.xml b/preference/res/values-ur/strings.xml
index 0e6560f..c304b12 100644
--- a/preference/res/values-ur/strings.xml
+++ b/preference/res/values-ur/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"آن"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"آف ہے"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"جدید ترین"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>، <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"آن"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"آف"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"جدید ترین"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>، <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-uz/strings.xml b/preference/res/values-uz/strings.xml
index 15f1021..6730b74 100644
--- a/preference/res/values-uz/strings.xml
+++ b/preference/res/values-uz/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"YONIQ"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"YOQILMAGAN"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Kengaytirilgan"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"YONIQ"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"O‘CHIQ"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Ekspert"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-vi/strings.xml b/preference/res/values-vi/strings.xml
index 3cdbad3..d8ea12b 100644
--- a/preference/res/values-vi/strings.xml
+++ b/preference/res/values-vi/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"BẬT"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"TẮT"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Nâng cao"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"BẬT"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"TẮT"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Nâng cao"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-zh-rCN/strings.xml b/preference/res/values-zh-rCN/strings.xml
index 368e7a3..3f91ed6 100644
--- a/preference/res/values-zh-rCN/strings.xml
+++ b/preference/res/values-zh-rCN/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"开启"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"关闭"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"高级"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>、<xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"开启"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"关闭"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"高级"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"当前显示了 <xliff:g id="CURRENT_ITEMS">%1$s</xliff:g> 项(已添加 <xliff:g id="ADDED_ITEMS">%2$s</xliff:g> 项)"</string>
 </resources>
diff --git a/preference/res/values-zh-rHK/strings.xml b/preference/res/values-zh-rHK/strings.xml
index ac8a0ed..fe64c50af 100644
--- a/preference/res/values-zh-rHK/strings.xml
+++ b/preference/res/values-zh-rHK/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"開啟"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"關閉"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"進階"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>,<xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"開啟"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"關閉"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"進階"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>,<xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-zh-rTW/strings.xml b/preference/res/values-zh-rTW/strings.xml
index ac8a0ed..fe64c50af 100644
--- a/preference/res/values-zh-rTW/strings.xml
+++ b/preference/res/values-zh-rTW/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"開啟"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"關閉"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"進階"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>,<xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"開啟"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"關閉"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"進階"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>,<xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/res/values-zu/strings.xml b/preference/res/values-zu/strings.xml
index 85b99bb..dab4cba 100644
--- a/preference/res/values-zu/strings.xml
+++ b/preference/res/values-zu/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="v7_preference_on" msgid="27351710992731591">"VULA"</string>
-    <string name="v7_preference_off" msgid="5138405918326871307">"VALA"</string>
-    <string name="expand_button_title" msgid="1234962710353108940">"Okuthuthukisiwe"</string>
-    <string name="summary_collapsed_preference_list" msgid="5190123168583152844">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
+    <string name="v7_preference_on" msgid="7922757586228621900">"VULA"</string>
+    <string name="v7_preference_off" msgid="2082379519172883894">"VALA"</string>
+    <string name="expand_button_title" msgid="3265458434114353660">"Okuthuthukisiwe"</string>
+    <string name="summary_collapsed_preference_list" msgid="5255557321652385027">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
 </resources>
diff --git a/preference/src/main/java/androidx/preference/PreferenceCategory.java b/preference/src/main/java/androidx/preference/PreferenceCategory.java
index d00d959..3585bd9 100644
--- a/preference/src/main/java/androidx/preference/PreferenceCategory.java
+++ b/preference/src/main/java/androidx/preference/PreferenceCategory.java
@@ -20,7 +20,6 @@
 import android.util.AttributeSet;
 
 import androidx.core.content.res.TypedArrayUtils;
-import androidx.core.os.BuildCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat;
 
@@ -67,30 +66,21 @@
     }
 
     @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        super.onBindViewHolder(holder);
-        if (BuildCompat.isAtLeastP()) {
-            holder.itemView.setAccessibilityHeading(true);
-        }
-    }
-
-    @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfoCompat info) {
         super.onInitializeAccessibilityNodeInfo(info);
-        if (!BuildCompat.isAtLeastP()) {
-            CollectionItemInfoCompat existingItemInfo = info.getCollectionItemInfo();
-            if (existingItemInfo == null) {
-                return;
-            }
 
-            final CollectionItemInfoCompat newItemInfo = CollectionItemInfoCompat.obtain(
-                    existingItemInfo.getRowIndex(),
-                    existingItemInfo.getRowSpan(),
-                    existingItemInfo.getColumnIndex(),
-                    existingItemInfo.getColumnSpan(),
-                    true /* heading */,
-                    existingItemInfo.isSelected());
-            info.setCollectionItemInfo(newItemInfo);
+        CollectionItemInfoCompat existingItemInfo = info.getCollectionItemInfo();
+        if (existingItemInfo == null) {
+            return;
         }
+
+        final CollectionItemInfoCompat newItemInfo = CollectionItemInfoCompat.obtain(
+                existingItemInfo.getRowIndex(),
+                existingItemInfo.getRowSpan(),
+                existingItemInfo.getColumnIndex(),
+                existingItemInfo.getColumnSpan(),
+                true /* heading */,
+                existingItemInfo.isSelected());
+        info.setCollectionItemInfo(newItemInfo);
     }
 }
diff --git a/samples/SupportCarDemos/src/main/AndroidManifest.xml b/samples/SupportCarDemos/src/main/AndroidManifest.xml
index ceb6aa7..8bba75f 100644
--- a/samples/SupportCarDemos/src/main/AndroidManifest.xml
+++ b/samples/SupportCarDemos/src/main/AndroidManifest.xml
@@ -140,17 +140,6 @@
             <meta-data android:name="android.support.PARENT_ACTIVITY"
                        android:value=".SupportCarDemoActivity" />
         </activity>
-
-        <activity android:name=".AppBarActivity"
-            android:label="App Bar"
-            android:parentActivityName=".SupportCarDemoActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.SAMPLE_CODE" />
-            </intent-filter>
-            <meta-data android:name="android.support.PARENT_ACTIVITY"
-                android:value=".SupportCarDemoActivity" />
-        </activity>
     </application>
 </manifest>
 
diff --git a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/AlphaJumpActivity.java b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/AlphaJumpActivity.java
index fcbe2a3..6801a6a 100644
--- a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/AlphaJumpActivity.java
+++ b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/AlphaJumpActivity.java
@@ -24,14 +24,14 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import java.util.Arrays;
+import java.util.Collection;
+
 import androidx.car.widget.AlphaJumpBucketer;
 import androidx.car.widget.IAlphaJumpAdapter;
 import androidx.car.widget.PagedListView;
 import androidx.recyclerview.widget.RecyclerView;
 
-import java.util.Arrays;
-import java.util.Collection;
-
 /**
  * An activity with a long list of cheeses, initially in a random order but you can use alpha jump
  * to quickly jump to your favourite cheese.
diff --git a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/AppBarActivity.java b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/AppBarActivity.java
deleted file mode 100644
index 3919c5a..0000000
--- a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/AppBarActivity.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.car;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.view.Menu;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
-import androidx.car.widget.ListItem;
-import androidx.car.widget.ListItemAdapter;
-import androidx.car.widget.ListItemProvider;
-import androidx.car.widget.PagedListView;
-import androidx.car.widget.TextListItem;
-
-/**
- * Demo activity for creating {@code App Bar} with {@link Toolbar}.
- */
-public class AppBarActivity extends AppCompatActivity {
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_app_bar);
-        Toolbar toolbar = findViewById(R.id.car_toolbar);
-        setSupportActionBar(toolbar);
-        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-        getSupportActionBar().setTitle("Title");
-        getSupportActionBar().setSubtitle("Subtitle");
-
-        setUpList();
-    }
-
-    private void setUpList() {
-        PagedListView list = findViewById(R.id.list);
-        list.setAdapter(new ListItemAdapter(this, new SampleProvider(this, 50)));
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.demo_menu, menu);
-        return super.onCreateOptionsMenu(menu);
-    }
-
-    private static class SampleProvider extends ListItemProvider {
-
-        private int mCount;
-        private Context mContext;
-
-        SampleProvider(Context context, int count) {
-            mContext = context;
-            mCount = count;
-        }
-
-        @Override
-        public ListItem get(int position) {
-            if (position < 0 || position >= mCount) {
-                throw new IndexOutOfBoundsException();
-            }
-            TextListItem item = new TextListItem(mContext);
-            item.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false);
-            item.setTitle("title");
-            return item;
-        }
-
-        @Override
-        public int size() {
-            return mCount;
-        }
-    }
-}
diff --git a/samples/SupportCarDemos/src/main/res/layout/activity_app_bar.xml b/samples/SupportCarDemos/src/main/res/layout/activity_app_bar.xml
deleted file mode 100644
index 74dcbc3..0000000
--- a/samples/SupportCarDemos/src/main/res/layout/activity_app_bar.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT 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:orientation="vertical">
-    <androidx.appcompat.widget.Toolbar
-        android:id="@+id/car_toolbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:background="@color/car_card" />
-
-    <androidx.car.widget.PagedListView
-        android:id="@+id/list"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        app:gutter="both" />
-</LinearLayout>
diff --git a/samples/SupportCarDemos/src/main/res/layout/list_dialog_activity.xml b/samples/SupportCarDemos/src/main/res/layout/list_dialog_activity.xml
index 1b67ddcb..790e25e 100644
--- a/samples/SupportCarDemos/src/main/res/layout/list_dialog_activity.xml
+++ b/samples/SupportCarDemos/src/main/res/layout/list_dialog_activity.xml
@@ -34,53 +34,53 @@
         android:checked="true"
         android:text="@string/list_dialog_checkbox_title" />
 
-    <com.google.android.material.textfield.TextInputLayout
+    <android.support.design.widget.TextInputLayout
         android:id="@+id/num_of_sections"
         android:layout_width="match_parent"
         android:layout_height="@dimen/car_single_line_list_item_height"
         android:hint="@string/list_dialog_num_of_sections_hint"
         app:hintTextAppearance="@style/TextAppearance.Car.Hint">
 
-        <com.google.android.material.textfield.TextInputEditText
+        <android.support.design.widget.TextInputEditText
             android:id="@+id/num_of_sections_edit"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:inputType="number"
             android:maxLines="1"
             android:textAppearance="@style/TextAppearance.Car.Body2"/>
-    </com.google.android.material.textfield.TextInputLayout>
+    </android.support.design.widget.TextInputLayout>
 
-    <com.google.android.material.textfield.TextInputLayout
+    <android.support.design.widget.TextInputLayout
         android:id="@+id/num_of_items"
         android:layout_width="match_parent"
         android:layout_height="@dimen/car_single_line_list_item_height"
         android:hint="@string/list_dialog_num_of_items_hint"
         app:hintTextAppearance="@style/TextAppearance.Car.Hint">
 
-        <com.google.android.material.textfield.TextInputEditText
+        <android.support.design.widget.TextInputEditText
             android:id="@+id/num_of_items_edit"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:inputType="number"
             android:maxLines="1"
             android:textAppearance="@style/TextAppearance.Car.Body2"/>
-    </com.google.android.material.textfield.TextInputLayout>
+    </android.support.design.widget.TextInputLayout>
 
-    <com.google.android.material.textfield.TextInputLayout
+    <android.support.design.widget.TextInputLayout
         android:id="@+id/initial_position"
         android:layout_width="match_parent"
         android:layout_height="@dimen/car_single_line_list_item_height"
         android:hint="@string/list_dialog_initial_position_hint"
         app:hintTextAppearance="@style/TextAppearance.Car.Hint">
 
-        <com.google.android.material.textfield.TextInputEditText
+        <android.support.design.widget.TextInputEditText
             android:id="@+id/initial_position_edit"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:inputType="number"
             android:maxLines="1"
             android:textAppearance="@style/TextAppearance.Car.Body2"/>
-    </com.google.android.material.textfield.TextInputLayout>
+    </android.support.design.widget.TextInputLayout>
 
     <Button
         android:id="@+id/create_dialog"
diff --git a/samples/SupportCarDemos/src/main/res/menu/demo_menu.xml b/samples/SupportCarDemos/src/main/res/menu/demo_menu.xml
deleted file mode 100644
index a1b256b..0000000
--- a/samples/SupportCarDemos/src/main/res/menu/demo_menu.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<menu xmlns:tools="http://schemas.android.com/tools"
-      xmlns:android="http://schemas.android.com/apk/res/android"
-      tools:ignore="AppCompatResource"
-      xmlns:app="http://schemas.android.com/apk/res-auto">
-
-    <item
-        android:id="@+id/action_icon"
-        android:icon="@drawable/pressed_icon"
-        android:title="Action1 with icon"
-        app:showAsAction="always|withText"/>
-
-    <item
-        android:id="@+id/action_overflow"
-        android:title="Action2"
-        app:showAsAction="always|withText"/>
-
-    <item
-            android:id="@+id/action_overflow2"
-            android:title="Action3"
-            app:showAsAction="never" />
-</menu>
\ No newline at end of file
diff --git a/samples/SupportContentDemos/build.gradle b/samples/SupportContentDemos/build.gradle
index 8d8a06c..d7b61e8 100644
--- a/samples/SupportContentDemos/build.gradle
+++ b/samples/SupportContentDemos/build.gradle
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (C) 2017 The Android Open Source Project
  *
@@ -15,19 +14,16 @@
  * limitations under the License.
  */
 
-import static androidx.build.dependencies.DependenciesKt.SUPPORT_DESIGN
-
 plugins {
     id("SupportAndroidTestAppPlugin")
 }
 
 dependencies {
-    implementation(SUPPORT_DESIGN, libs.exclude_for_material)
+    implementation("com.android.support:design:28.0.0-SNAPSHOT", { transitive = false })
     implementation(project(":transition"))
     implementation(project(":recyclerview"))
     implementation(project(":appcompat"))
     implementation(project(":contentpager"))
-    implementation(project(":cardview"))
 }
 
 android {
diff --git a/samples/SupportContentDemos/src/main/java/com/example/android/support/content/demos/ContentPagerDemoActivity.java b/samples/SupportContentDemos/src/main/java/com/example/android/support/content/demos/ContentPagerDemoActivity.java
index 119f3a1..8a661fc 100644
--- a/samples/SupportContentDemos/src/main/java/com/example/android/support/content/demos/ContentPagerDemoActivity.java
+++ b/samples/SupportContentDemos/src/main/java/com/example/android/support/content/demos/ContentPagerDemoActivity.java
@@ -19,6 +19,8 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.ViewGroup;
@@ -34,10 +36,6 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.google.android.material.snackbar.BaseTransientBottomBar;
-import com.google.android.material.snackbar.Snackbar;
-
 import java.util.Locale;
 
 /**
@@ -143,7 +141,7 @@
     private void msg(String msg) {
         Snackbar.make(
                 mRecycler,
-                msg, BaseTransientBottomBar.LENGTH_LONG)
+                msg, Snackbar.LENGTH_LONG)
                 .setAction("Action", null).show();
     }
 
diff --git a/samples/SupportDesignDemos/build.gradle b/samples/SupportDesignDemos/build.gradle
index 2bf34000..8721e2b 100644
--- a/samples/SupportDesignDemos/build.gradle
+++ b/samples/SupportDesignDemos/build.gradle
@@ -1,11 +1,18 @@
-import static androidx.build.dependencies.DependenciesKt.SUPPORT_DESIGN
-
 plugins {
     id("SupportAndroidTestAppPlugin")
 }
 
 dependencies {
-    implementation(SUPPORT_DESIGN, libs.exclude_for_material)
+    api "com.android.temp.support:design:28.0.0-alpha1", {
+        exclude group: 'androidx.annotation'
+        exclude group: 'androidx.core'
+        exclude group: 'androidx.legacy'
+        exclude group: 'androidx.fragment'
+        exclude group: 'androidx.transition'
+        exclude group: 'androidx.appcompat'
+        exclude group: 'androidx.recyclerview'
+        exclude group: 'androidx.cardview'
+    }
     implementation(project(":transition"))
     implementation(project(":recyclerview"))
     implementation(project(":appcompat"))
@@ -14,6 +21,8 @@
 
 android {
     defaultConfig {
+        minSdkVersion 14
         vectorDrawables.useSupportLibrary = true
     }
 }
+
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/AppBarLayoutUsageBase.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/AppBarLayoutUsageBase.java
index bcf244a..9607991 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/AppBarLayoutUsageBase.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/AppBarLayoutUsageBase.java
@@ -18,6 +18,9 @@
 
 import android.os.Bundle;
 import android.os.Handler;
+import android.support.design.widget.AppBarLayout;
+import android.support.design.widget.CollapsingToolbarLayout;
+import android.support.design.widget.TabLayout;
 import android.text.TextUtils;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -32,9 +35,6 @@
 import com.example.android.support.design.Cheeses;
 import com.example.android.support.design.R;
 import com.example.android.support.design.Shakespeare;
-import com.google.android.material.appbar.AppBarLayout;
-import com.google.android.material.appbar.CollapsingToolbarLayout;
-import com.google.android.material.tabs.TabLayout;
 
 import java.util.Random;
 
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomNavigationViewUsage.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomNavigationViewUsage.java
index 412f1f4..e4ae51f 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomNavigationViewUsage.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomNavigationViewUsage.java
@@ -18,6 +18,7 @@
 
 import android.content.res.ColorStateList;
 import android.os.Bundle;
+import android.support.design.widget.BottomNavigationView;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.Button;
@@ -27,7 +28,6 @@
 import androidx.appcompat.app.AppCompatActivity;
 
 import com.example.android.support.design.R;
-import com.google.android.material.bottomnavigation.BottomNavigationView;
 
 /**
  * This demonstrates idiomatic usage of the bottom navigation widget.
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetDynamicContent.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetDynamicContent.java
index 077bb1f..d96db57 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetDynamicContent.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetDynamicContent.java
@@ -17,6 +17,7 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.BottomSheetBehavior;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -30,7 +31,6 @@
 
 import com.example.android.support.design.Cheeses;
 import com.example.android.support.design.R;
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
 
 import java.util.ArrayList;
 import java.util.Random;
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetHideable.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetHideable.java
index 2988c14..1888c1b 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetHideable.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetHideable.java
@@ -17,6 +17,7 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.BottomSheetBehavior;
 import android.view.View;
 import android.widget.Button;
 import android.widget.TextView;
@@ -25,7 +26,6 @@
 import androidx.annotation.Nullable;
 
 import com.example.android.support.design.R;
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
 
 
 /**
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModal.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModal.java
index 69ab271..262f390 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModal.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModal.java
@@ -16,7 +16,7 @@
 
 package com.example.android.support.design.widget;
 
-import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+import android.support.design.widget.BottomSheetDialogFragment;
 
 /**
  * This demonstrates basic usage of {@link BottomSheetDialogFragment}.
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModalBase.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModalBase.java
index e3c31ae..7cef4a8 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModalBase.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModalBase.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.Bundle;
+import android.support.design.widget.BottomSheetDialogFragment;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -29,7 +30,6 @@
 
 import com.example.android.support.design.Cheeses;
 import com.example.android.support.design.R;
-import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
 
 abstract class BottomSheetModalBase extends AppCompatActivity {
 
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModalSkipCollapsed.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModalSkipCollapsed.java
index 729154a..509dd7c 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModalSkipCollapsed.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetModalSkipCollapsed.java
@@ -16,7 +16,7 @@
 
 package com.example.android.support.design.widget;
 
-import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+import android.support.design.widget.BottomSheetDialogFragment;
 
 /**
  * This demonstrates basic usage of {@link BottomSheetDialogFragment}.
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetPersistent.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetPersistent.java
index 2da32ab..5e02e60 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetPersistent.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetPersistent.java
@@ -16,8 +16,9 @@
 
 package com.example.android.support.design.widget;
 
+import android.support.design.widget.BottomSheetBehavior;
+
 import com.example.android.support.design.R;
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
 
 
 /**
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetUsageBase.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetUsageBase.java
index 4d873cf..62c76be 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetUsageBase.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetUsageBase.java
@@ -17,6 +17,7 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.BottomSheetBehavior;
 import android.text.TextUtils;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -26,7 +27,6 @@
 
 import com.example.android.support.design.R;
 import com.example.android.support.design.Shakespeare;
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
 
 /**
  * This demonstrates basic usage of {@link BottomSheetBehavior}.
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetWithFab.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetWithFab.java
index c197b93..b3a2855 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetWithFab.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetWithFab.java
@@ -18,6 +18,7 @@
 
 
 import android.os.Bundle;
+import android.support.design.widget.BottomSheetBehavior;
 import android.view.View;
 import android.widget.Button;
 
@@ -25,7 +26,6 @@
 import androidx.annotation.Nullable;
 
 import com.example.android.support.design.R;
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
 
 
 /**
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetWithFragment.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetWithFragment.java
index c7fb168..b095c37 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetWithFragment.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/BottomSheetWithFragment.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.Bundle;
+import android.support.design.widget.BottomSheetBehavior;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -30,7 +31,6 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.example.android.support.design.R;
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
 
 /**
  * This demonstrates basic usage of {@link BottomSheetBehavior} with Fragment.
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/CustomSnackbar.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/CustomSnackbar.java
index af62e4f8..bcc6303 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/CustomSnackbar.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/CustomSnackbar.java
@@ -15,13 +15,13 @@
  */
 package com.example.android.support.design.widget;
 
+import android.support.design.widget.BaseTransientBottomBar;
 import android.view.View;
 import android.widget.TextView;
 
 import androidx.coordinatorlayout.widget.CoordinatorLayout;
 
 import com.example.android.support.design.R;
-import com.google.android.material.snackbar.BaseTransientBottomBar;
 
 /**
  * Sample code for a custom snackbar that shows two separate text views and two images
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/CustomSnackbarUsage.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/CustomSnackbarUsage.java
index 1b0057c..bd0168e 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/CustomSnackbarUsage.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/CustomSnackbarUsage.java
@@ -17,6 +17,7 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.BaseTransientBottomBar;
 import android.view.LayoutInflater;
 import android.view.View;
 
@@ -24,7 +25,6 @@
 import androidx.coordinatorlayout.widget.CoordinatorLayout;
 
 import com.example.android.support.design.R;
-import com.google.android.material.snackbar.BaseTransientBottomBar;
 
 /**
  * This demonstrates custom usage of the snackbar
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewUsage.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewUsage.java
index c90d44f..7ed367a 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewUsage.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewUsage.java
@@ -17,6 +17,7 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.NavigationView;
 import android.util.TypedValue;
 import android.view.MenuItem;
 import android.view.View;
@@ -26,7 +27,6 @@
 import androidx.drawerlayout.widget.DrawerLayout;
 
 import com.example.android.support.design.R;
-import com.google.android.material.navigation.NavigationView;
 
 /**
  * This demonstrates basic usage of NavigationView
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewUsageBase.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewUsageBase.java
index 86848bb..5d452a9 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewUsageBase.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewUsageBase.java
@@ -17,6 +17,7 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.NavigationView;
 import android.view.MenuItem;
 import android.widget.TextView;
 import android.widget.Toast;
@@ -25,7 +26,6 @@
 import androidx.appcompat.app.AppCompatActivity;
 
 import com.example.android.support.design.R;
-import com.google.android.material.navigation.NavigationView;
 
 public abstract class NavigationViewUsageBase extends AppCompatActivity {
 
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewWithoutDrawer.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewWithoutDrawer.java
index 2a443398..81e9419 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewWithoutDrawer.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/NavigationViewWithoutDrawer.java
@@ -16,10 +16,10 @@
 
 package com.example.android.support.design.widget;
 
+import android.support.design.widget.NavigationView;
 import android.view.MenuItem;
 
 import com.example.android.support.design.R;
-import com.google.android.material.navigation.NavigationView;
 
 /**
  * This demonstrates basic usage of NavigationView
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/SnackbarUsage.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/SnackbarUsage.java
index 35d910d..c0475ab 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/SnackbarUsage.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/SnackbarUsage.java
@@ -17,6 +17,7 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.Snackbar;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Toast;
@@ -24,7 +25,6 @@
 import androidx.appcompat.app.AppCompatActivity;
 
 import com.example.android.support.design.R;
-import com.google.android.material.snackbar.Snackbar;
 
 /**
  * This demonstrates idiomatic usage of the snackbar
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutCustomItemsUsage.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutCustomItemsUsage.java
index 23f6eb9..299ea75 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutCustomItemsUsage.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutCustomItemsUsage.java
@@ -17,12 +17,12 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.TabLayout;
 
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.appcompat.widget.Toolbar;
 
 import com.example.android.support.design.R;
-import com.google.android.material.tabs.TabLayout;
 
 /**
  * This demonstrates usage of TabLayout with custom items
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutPreselectedUsage.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutPreselectedUsage.java
index ed90273..f0b04cd 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutPreselectedUsage.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutPreselectedUsage.java
@@ -17,6 +17,7 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.TabLayout;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
@@ -32,7 +33,6 @@
 
 import com.example.android.support.design.Cheeses;
 import com.example.android.support.design.R;
-import com.google.android.material.tabs.TabLayout;
 
 import java.util.ArrayList;
 
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutUsage.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutUsage.java
index 7f77086..3eb2c4f 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutUsage.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TabLayoutUsage.java
@@ -17,6 +17,7 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.TabLayout;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
@@ -32,7 +33,6 @@
 
 import com.example.android.support.design.Cheeses;
 import com.example.android.support.design.R;
-import com.google.android.material.tabs.TabLayout;
 
 import java.util.ArrayList;
 import java.util.Random;
diff --git a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TextInputLayoutUsage.java b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TextInputLayoutUsage.java
index fd054c9..92a7a66 100644
--- a/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TextInputLayoutUsage.java
+++ b/samples/SupportDesignDemos/src/main/java/com/example/android/support/design/widget/TextInputLayoutUsage.java
@@ -17,12 +17,12 @@
 package com.example.android.support.design.widget;
 
 import android.os.Bundle;
+import android.support.design.widget.TextInputLayout;
 import android.view.View;
 
 import androidx.appcompat.app.AppCompatActivity;
 
 import com.example.android.support.design.R;
-import com.google.android.material.textfield.TextInputLayout;
 
 /**
  * This demonstrates idiomatic usage of {@code TextInputLayout}
diff --git a/samples/SupportDesignDemos/src/main/res/layout/custom_snackbar_with_fab.xml b/samples/SupportDesignDemos/src/main/res/layout/custom_snackbar_with_fab.xml
index ad55e8a..9c51d39 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/custom_snackbar_with_fab.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/custom_snackbar_with_fab.xml
@@ -34,7 +34,7 @@
 
     </LinearLayout>
 
-    <com.google.android.material.floatingactionbutton.FloatingActionButton
+    <android.support.design.widget.FloatingActionButton
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             android:layout_gravity="bottom|end"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin.xml
index d6d9033..b3f1638 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin.xml
@@ -22,13 +22,13 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="192dp"
             android:layout_width="match_parent"
             android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 
-        <com.google.android.material.appbar.CollapsingToolbarLayout
+        <android.support.design.widget.CollapsingToolbarLayout
                 android:id="@+id/collapsing_app_bar"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
@@ -40,9 +40,9 @@
                     android:layout_width="match_parent"
                     app:layout_collapseMode="pin"/>
 
-        </com.google.android.material.appbar.CollapsingToolbarLayout>
+        </android.support.design.widget.CollapsingToolbarLayout>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_recyclerview"/>
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin_nested.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin_nested.xml
index d96dacf..09e83cf 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin_nested.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin_nested.xml
@@ -22,12 +22,12 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="192dp"
             android:layout_width="match_parent">
 
-        <com.google.android.material.appbar.CollapsingToolbarLayout
+        <android.support.design.widget.CollapsingToolbarLayout
                 android:id="@+id/collapsing_app_bar"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
@@ -50,9 +50,9 @@
 
             </FrameLayout>
 
-        </com.google.android.material.appbar.CollapsingToolbarLayout>
+        </android.support.design.widget.CollapsingToolbarLayout>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_recyclerview"/>
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin_with_fab.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin_with_fab.xml
index c90ed6b..2660cb5 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin_with_fab.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_pin_with_fab.xml
@@ -22,13 +22,13 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="192dp"
             android:layout_width="match_parent"
             android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 
-        <com.google.android.material.appbar.CollapsingToolbarLayout
+        <android.support.design.widget.CollapsingToolbarLayout
                 android:id="@+id/collapsing_app_bar"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
@@ -40,13 +40,13 @@
                     android:layout_width="match_parent"
                     app:layout_collapseMode="pin"/>
 
-        </com.google.android.material.appbar.CollapsingToolbarLayout>
+        </android.support.design.widget.CollapsingToolbarLayout>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_scrollview"/>
 
-    <com.google.android.material.floatingactionbutton.FloatingActionButton
+    <android.support.design.widget.FloatingActionButton
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             app:layout_anchor="@id/app_bar"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_scroll.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_scroll.xml
index 602bc25..9aa38af 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_scroll.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_scroll.xml
@@ -22,13 +22,13 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="192dp"
             android:layout_width="match_parent"
             android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 
-        <com.google.android.material.appbar.CollapsingToolbarLayout
+        <android.support.design.widget.CollapsingToolbarLayout
                 android:id="@+id/collapsing_app_bar"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
@@ -40,9 +40,9 @@
                     android:layout_width="match_parent"
                     app:layout_collapseMode="pin"/>
 
-        </com.google.android.material.appbar.CollapsingToolbarLayout>
+        </android.support.design.widget.CollapsingToolbarLayout>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_scrollview"/>
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_scroll_with_swiperefresh.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_scroll_with_swiperefresh.xml
index 5910227..36c4020e 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_scroll_with_swiperefresh.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_scroll_with_swiperefresh.xml
@@ -22,13 +22,13 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="192dp"
             android:layout_width="match_parent"
             android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 
-        <com.google.android.material.appbar.CollapsingToolbarLayout
+        <android.support.design.widget.CollapsingToolbarLayout
                 android:id="@+id/collapsing_app_bar"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
@@ -40,9 +40,9 @@
                     android:layout_width="match_parent"
                     app:layout_collapseMode="pin"/>
 
-        </com.google.android.material.appbar.CollapsingToolbarLayout>
+        </android.support.design.widget.CollapsingToolbarLayout>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_recyclerview_swiperefresh"/>
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_with_image.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_with_image.xml
index a671f91..fb801974 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_with_image.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_with_image.xml
@@ -22,13 +22,13 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="192dp"
             android:layout_width="match_parent"
             android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 
-        <com.google.android.material.appbar.CollapsingToolbarLayout
+        <android.support.design.widget.CollapsingToolbarLayout
                 android:id="@+id/collapsing_app_bar"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
@@ -49,9 +49,9 @@
                     android:layout_width="match_parent"
                     app:layout_collapseMode="pin"/>
 
-        </com.google.android.material.appbar.CollapsingToolbarLayout>
+        </android.support.design.widget.CollapsingToolbarLayout>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_scrollview"/>
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_with_image_insets.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_with_image_insets.xml
index 6d6ad13..a38bdf4 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_with_image_insets.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_collapse_with_image_insets.xml
@@ -23,14 +23,14 @@
         android:layout_height="match_parent"
         android:fitsSystemWindows="true">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
             android:fitsSystemWindows="true">
 
-        <com.google.android.material.appbar.CollapsingToolbarLayout
+        <android.support.design.widget.CollapsingToolbarLayout
                 android:id="@+id/collapsing_app_bar"
                 android:layout_width="match_parent"
                 android:layout_height="256dp"
@@ -52,9 +52,9 @@
                     android:layout_width="match_parent"
                     app:layout_collapseMode="pin"/>
 
-        </com.google.android.material.appbar.CollapsingToolbarLayout>
+        </android.support.design.widget.CollapsingToolbarLayout>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_scrollview"/>
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_parallax_overlap.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_parallax_overlap.xml
index 73c8391..86700aa 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_parallax_overlap.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_parallax_overlap.xml
@@ -22,13 +22,13 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="192dp"
             android:layout_width="match_parent"
             android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 
-        <com.google.android.material.appbar.CollapsingToolbarLayout
+        <android.support.design.widget.CollapsingToolbarLayout
                 android:id="@+id/collapsing_app_bar"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
@@ -49,9 +49,9 @@
                     android:layout_width="match_parent"
                     app:layout_collapseMode="pin"/>
 
-        </com.google.android.material.appbar.CollapsingToolbarLayout>
+        </android.support.design.widget.CollapsingToolbarLayout>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_scrollview_with_image" />
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_pinned.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_pinned.xml
index 0a5d9eb..e4682dd 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_pinned.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_pinned.xml
@@ -22,7 +22,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -34,13 +34,13 @@
                 android:layout_width="match_parent"
                 app:layout_scrollFlags="scroll|enterAlways"/>
 
-        <com.google.android.material.tabs.TabLayout
+        <android.support.design.widget.TabLayout
                 android:id="@+id/tabs"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 app:tabMode="scrollable"/>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_recyclerview"/>
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_pinned_with_swiperefres.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_pinned_with_swiperefres.xml
index ae14514..b66ba33 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_pinned_with_swiperefres.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_pinned_with_swiperefres.xml
@@ -22,7 +22,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -34,13 +34,13 @@
                 android:layout_width="match_parent"
                 app:layout_scrollFlags="scroll|enterAlways"/>
 
-        <com.google.android.material.tabs.TabLayout
+        <android.support.design.widget.TabLayout
                 android:id="@+id/tabs"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 app:tabMode="scrollable"/>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_recyclerview_swiperefresh" />
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_scroll.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_scroll.xml
index 6b1856c..186d8d6 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_scroll.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_scroll.xml
@@ -22,7 +22,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -34,14 +34,14 @@
                 android:layout_width="match_parent"
                 app:layout_scrollFlags="scroll|enterAlways"/>
 
-        <com.google.android.material.tabs.TabLayout
+        <android.support.design.widget.TabLayout
                 android:id="@+id/tabs"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 app:layout_scrollFlags="scroll|enterAlways"
                 app:tabMode="scrollable"/>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_scrollview"/>
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_scroll_snap.xml b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_scroll_snap.xml
index 0bdb1a5..2154762 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_scroll_snap.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_appbar_toolbar_scroll_tabs_scroll_snap.xml
@@ -22,7 +22,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <android.support.design.widget.AppBarLayout
             android:id="@+id/app_bar"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -34,14 +34,14 @@
                 android:layout_width="match_parent"
                 app:layout_scrollFlags="scroll|enterAlways|snap"/>
 
-        <com.google.android.material.tabs.TabLayout
+        <android.support.design.widget.TabLayout
                 android:id="@+id/tabs"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 app:layout_scrollFlags="scroll|enterAlways|snap"
                 app:tabMode="scrollable"/>
 
-    </com.google.android.material.appbar.AppBarLayout>
+    </android.support.design.widget.AppBarLayout>
 
     <include layout="@layout/include_appbar_scrollview"/>
 
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_bottom_navigation_view.xml b/samples/SupportDesignDemos/src/main/res/layout/design_bottom_navigation_view.xml
index a416573..b2a4d59 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_bottom_navigation_view.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_bottom_navigation_view.xml
@@ -66,7 +66,7 @@
                 android:layout_below="@+id/button_select_next"/>
         </RelativeLayout>
     </ScrollView>
-    <com.google.android.material.bottomnavigation.BottomNavigationView
+    <android.support.design.widget.BottomNavigationView
             android:id="@+id/bottom_navigation"
             android:layout_width="match_parent"
             android:layout_height="56dp"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_bottom_sheet_with_fab.xml b/samples/SupportDesignDemos/src/main/res/layout/design_bottom_sheet_with_fab.xml
index c0f2787..4776455 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_bottom_sheet_with_fab.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_bottom_sheet_with_fab.xml
@@ -61,7 +61,7 @@
 
     </LinearLayout>
 
-    <com.google.android.material.floatingactionbutton.FloatingActionButton
+    <android.support.design.widget.FloatingActionButton
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
         android:src="@drawable/ic_add"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_bottom_sheet_with_fragment.xml b/samples/SupportDesignDemos/src/main/res/layout/design_bottom_sheet_with_fragment.xml
index 5956de78..508e9e4 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_bottom_sheet_with_fragment.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_bottom_sheet_with_fragment.xml
@@ -43,7 +43,7 @@
 
     <fragment
             android:id="@+id/bottom_sheet"
-            class="com.example.com.google.android.material.bottomsheet.BottomSheetWithFragment$BottomSheetFragment"
+            class="com.example.android.support.design.widget.BottomSheetWithFragment$BottomSheetFragment"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             app:layout_behavior="@string/bottom_sheet_behavior"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_fab.xml b/samples/SupportDesignDemos/src/main/res/layout/design_fab.xml
index d9cd75a..c49ee07 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_fab.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_fab.xml
@@ -44,7 +44,7 @@
                 android:text="@string/fab_size_normal"
                 android:layout_margin="16dp"/>
 
-        <com.google.android.material.floatingactionbutton.FloatingActionButton
+        <android.support.design.widget.FloatingActionButton
                 android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:layout_margin="16dp"
@@ -58,7 +58,7 @@
                 android:textAppearance="@style/TextAppearance.AppCompat.Title"
                 android:text="@string/fab_size_mini" />
 
-        <com.google.android.material.floatingactionbutton.FloatingActionButton
+        <android.support.design.widget.FloatingActionButton
                 android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:layout_margin="16dp"
@@ -73,7 +73,7 @@
             android:textAppearance="@style/TextAppearance.AppCompat.Title"
             android:text="@string/fab_size_custom" />
 
-        <com.google.android.material.floatingactionbutton.FloatingActionButton
+        <android.support.design.widget.FloatingActionButton
             android:id="@+id/custom_fab"
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_navigation.xml b/samples/SupportDesignDemos/src/main/res/layout/design_navigation.xml
index 37a9329..2a3c605 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_navigation.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_navigation.xml
@@ -47,7 +47,7 @@
 
     </LinearLayout>
 
-    <com.google.android.material.navigation.NavigationView
+    <android.support.design.widget.NavigationView
             android:id="@+id/navigation"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_navigation_without_drawer.xml b/samples/SupportDesignDemos/src/main/res/layout/design_navigation_without_drawer.xml
index 7c4d044..548d339 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_navigation_without_drawer.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_navigation_without_drawer.xml
@@ -21,7 +21,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <com.google.android.material.navigation.NavigationView
+    <android.support.design.widget.NavigationView
             android:id="@+id/navigation"
             android:layout_width="0dp"
             android:layout_height="match_parent"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_snackbar_with_fab.xml b/samples/SupportDesignDemos/src/main/res/layout/design_snackbar_with_fab.xml
index aaadca5..45ae83e 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_snackbar_with_fab.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_snackbar_with_fab.xml
@@ -58,7 +58,7 @@
 
     </LinearLayout>
 
-    <com.google.android.material.floatingactionbutton.FloatingActionButton
+    <android.support.design.widget.FloatingActionButton
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             android:layout_gravity="bottom|end"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_tabs_custom.xml b/samples/SupportDesignDemos/src/main/res/layout/design_tabs_custom.xml
index f8a3b18..72a0782 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_tabs_custom.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_tabs_custom.xml
@@ -31,7 +31,7 @@
             app:contentInsetStart="72dp"
             app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
 
-    <com.google.android.material.tabs.TabLayout
+    <android.support.design.widget.TabLayout
             android:id="@+id/tabs"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_tabs_item.xml b/samples/SupportDesignDemos/src/main/res/layout/design_tabs_item.xml
index 6773b85..bcde5dc 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_tabs_item.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_tabs_item.xml
@@ -31,19 +31,19 @@
             app:contentInsetStart="72dp"
             app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
 
-    <com.google.android.material.tabs.TabLayout
+    <android.support.design.widget.TabLayout
             android:id="@+id/tabs"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:background="?attr/colorPrimary"
             android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 
-        <com.google.android.material.tabs.TabItem
+        <android.support.design.widget.TabItem
                 android:text="@string/tab_text"/>
 
-        <com.google.android.material.tabs.TabItem
+        <android.support.design.widget.TabItem
                 android:icon="@drawable/ic_android"/>
 
-    </com.google.android.material.tabs.TabLayout>
+    </android.support.design.widget.TabLayout>
 
 </LinearLayout>
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_tabs_viewpager.xml b/samples/SupportDesignDemos/src/main/res/layout/design_tabs_viewpager.xml
index 269dd2cd..c501136 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_tabs_viewpager.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_tabs_viewpager.xml
@@ -31,7 +31,7 @@
             app:contentInsetStart="72dp"
             app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
 
-    <com.google.android.material.tabs.TabLayout
+    <android.support.design.widget.TabLayout
             android:id="@+id/tabs"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_text_input.xml b/samples/SupportDesignDemos/src/main/res/layout/design_text_input.xml
index 2958f0d..fc9ff00 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_text_input.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_text_input.xml
@@ -25,19 +25,19 @@
         android:orientation="vertical"
         android:padding="16dp">
 
-        <com.google.android.material.textfield.TextInputLayout
+        <android.support.design.widget.TextInputLayout
             android:id="@+id/input_username"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             app:errorEnabled="true">
 
-            <com.google.android.material.textfield.TextInputEditText
+            <android.support.design.widget.TextInputEditText
                 android:id="@+id/edit_username"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:hint="@string/form_username" />
 
-        </com.google.android.material.textfield.TextInputLayout>
+        </android.support.design.widget.TextInputLayout>
 
         <LinearLayout
             android:layout_width="match_parent"
@@ -64,22 +64,22 @@
 
         </LinearLayout>
 
-        <com.google.android.material.textfield.TextInputLayout
+        <android.support.design.widget.TextInputLayout
             android:id="@+id/input_email"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="8dp"
             app:errorEnabled="true">
 
-            <com.google.android.material.textfield.TextInputEditText
+            <android.support.design.widget.TextInputEditText
                 android:id="@+id/edit_email"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:hint="@string/form_email" />
 
-        </com.google.android.material.textfield.TextInputLayout>
+        </android.support.design.widget.TextInputLayout>
 
-        <com.google.android.material.textfield.TextInputLayout
+        <android.support.design.widget.TextInputLayout
             android:id="@+id/input_description"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -93,9 +93,9 @@
                 android:layout_height="wrap_content"
                 android:hint="@string/form_description" />
 
-        </com.google.android.material.textfield.TextInputLayout>
+        </android.support.design.widget.TextInputLayout>
 
-        <com.google.android.material.textfield.TextInputLayout
+        <android.support.design.widget.TextInputLayout
             android:id="@+id/input_auto_complete"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -109,9 +109,9 @@
                 android:layout_height="wrap_content"
                 android:hint="@string/form_auto_complete" />
 
-        </com.google.android.material.textfield.TextInputLayout>
+        </android.support.design.widget.TextInputLayout>
 
-        <com.google.android.material.textfield.TextInputLayout
+        <android.support.design.widget.TextInputLayout
             android:id="@+id/input_password"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -125,7 +125,7 @@
                 android:hint="@string/form_password"
                 android:inputType="textPassword" />
 
-        </com.google.android.material.textfield.TextInputLayout>
+        </android.support.design.widget.TextInputLayout>
 
         <LinearLayout
             android:layout_width="match_parent"
diff --git a/samples/SupportMediaDemos/build.gradle b/samples/SupportMediaDemos/build.gradle
index fecf2a5..bf23177 100644
--- a/samples/SupportMediaDemos/build.gradle
+++ b/samples/SupportMediaDemos/build.gradle
@@ -25,7 +25,7 @@
 
 android {
     defaultConfig {
-        minSdkVersion = 19
-        targetSdkVersion = 26
+        minSdkVersion 19
+        targetSdkVersion 26
     }
 }
diff --git a/samples/SupportMediaDemos/src/main/AndroidManifest.xml b/samples/SupportMediaDemos/src/main/AndroidManifest.xml
index b686fcd..267eafd 100644
--- a/samples/SupportMediaDemos/src/main/AndroidManifest.xml
+++ b/samples/SupportMediaDemos/src/main/AndroidManifest.xml
@@ -15,17 +15,14 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
     package="com.example.androidx.media">
-
-    <uses-sdk tools:overrideLibrary="androidx.media.widget" />
-
     <application android:label="Video View Test">
 
         <!-- Video Selection Activity -->
         <activity android:name="VideoSelector"
-            android:theme="@style/Theme.AppCompat"
-            android:configChanges="orientation|screenSize">
+            android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+            android:configChanges="orientation|screenSize"
+            >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
@@ -34,8 +31,8 @@
 
         <!-- Video playback activity -->
         <activity android:name="VideoViewTest"
-            android:theme="@style/Theme.AppCompat"
-            android:configChanges="orientation|screenSize">
+            android:configChanges="orientation|screenSize"
+            >
             <intent-filter>
                 <action android:name="android.intent.action.VIEW"/>
             </intent-filter>
diff --git a/samples/SupportMediaDemos/src/main/java/com/example/androidx/media/VideoViewTest.java b/samples/SupportMediaDemos/src/main/java/com/example/androidx/media/VideoViewTest.java
index 2289769..d640303 100644
--- a/samples/SupportMediaDemos/src/main/java/com/example/androidx/media/VideoViewTest.java
+++ b/samples/SupportMediaDemos/src/main/java/com/example/androidx/media/VideoViewTest.java
@@ -29,7 +29,6 @@
 import android.support.v4.media.session.PlaybackStateCompat;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
@@ -37,7 +36,6 @@
 import android.view.WindowManager;
 import android.widget.Toast;
 
-import androidx.fragment.app.FragmentActivity;
 import androidx.media.widget.MediaControlView2;
 import androidx.media.widget.VideoView2;
 
@@ -45,7 +43,7 @@
  * Test application for VideoView2/MediaControlView2
  */
 @SuppressLint("NewApi")
-public class VideoViewTest extends FragmentActivity {
+public class VideoViewTest extends Activity {
     public static final String LOOPING_EXTRA_NAME =
             "com.example.androidx.media.VideoViewTest.IsLooping";
     public static final String USE_TEXTURE_VIEW_EXTRA_NAME =
@@ -73,7 +71,6 @@
         setContentView(R.layout.video_activity);
 
         mVideoView = findViewById(R.id.video_view);
-        mVideoView.setActivity(this);
 
         String errorString = null;
         Intent intent = getIntent();
@@ -85,11 +82,12 @@
             if (mUseTextureView) {
                 mVideoView.setViewType(VideoView2.VIEW_TYPE_TEXTUREVIEW);
             }
+
+            mVideoView.setFullScreenRequestListener(new FullScreenRequestListener());
             mVideoView.setVideoUri(contentUri);
 
             mMediaControlView = new MediaControlView2(this);
             mVideoView.setMediaControlView2(mMediaControlView, 2000);
-            mMediaControlView.setOnFullScreenListener(new FullScreenListener());
         }
         if (errorString != null) {
             showErrorDialog(errorString);
@@ -181,10 +179,9 @@
         }
     };
 
-    private class FullScreenListener
-            implements MediaControlView2.OnFullScreenListener {
+    private class FullScreenRequestListener implements VideoView2.OnFullScreenRequestListener {
         @Override
-        public void onFullScreen(View view, boolean fullScreen) {
+        public void onFullScreenRequest(View view, boolean fullScreen) {
             // TODO: Remove bottom controls after adding back button functionality.
             if (mPrevHeight == 0 && mPrevWidth == 0) {
                 ViewGroup.LayoutParams params = mVideoView.getLayoutParams();
@@ -226,7 +223,6 @@
     public static class MyVideoView extends VideoView2 {
         private float mDX;
         private float mDY;
-        private Activity mActivity;
 
         public MyVideoView(Context context) {
             super(context);
@@ -259,18 +255,6 @@
             }
             return super.onTouchEvent(ev);
         }
-
-        @Override
-        public boolean onKeyDown(int keyCode, KeyEvent event)  {
-            if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
-                mActivity.finish();
-            }
-            return true;
-        }
-
-        public void setActivity(Activity activity) {
-            mActivity = activity;
-        }
     }
 
     @Override
diff --git a/samples/SupportPreferenceDemos/build.gradle b/samples/SupportPreferenceDemos/build.gradle
index d37bfa2..6aa8343 100644
--- a/samples/SupportPreferenceDemos/build.gradle
+++ b/samples/SupportPreferenceDemos/build.gradle
@@ -8,4 +8,5 @@
     implementation(project(":preference"))
     implementation(project(":leanback"))
     implementation(project(":leanback-preference"))
+    implementation(project(":car"))
 }
diff --git a/samples/SupportPreferenceDemos/src/main/AndroidManifest.xml b/samples/SupportPreferenceDemos/src/main/AndroidManifest.xml
index 0e9aa9b..dc7f3dc 100644
--- a/samples/SupportPreferenceDemos/src/main/AndroidManifest.xml
+++ b/samples/SupportPreferenceDemos/src/main/AndroidManifest.xml
@@ -20,7 +20,7 @@
     package="com.example.android.supportpreference">
 
     <uses-sdk
-        tools:overrideLibrary="androidx.leanback.preference, androidx.leanback" />
+        tools:overrideLibrary="androidx.leanback.preference, androidx.leanback, androidx.car" />
 
     <uses-feature android:name="android.software.Leanback" android:required="false" />
 
@@ -68,5 +68,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".FragmentSupportPreferencesCar"
+            android:label="@string/fragment_support_preferences_car_demo"
+            android:theme="@style/SupportPreferenceCar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="com.example.android.supportpreference.SAMPLE_CODE"/>
+            </intent-filter>
+        </activity>
+
     </application>
-</manifest>
+</manifest>
\ No newline at end of file
diff --git a/samples/SupportPreferenceDemos/src/main/java/com/example/android/supportpreference/FragmentSupportPreferencesCar.java b/samples/SupportPreferenceDemos/src/main/java/com/example/android/supportpreference/FragmentSupportPreferencesCar.java
new file mode 100644
index 0000000..83cb384
--- /dev/null
+++ b/samples/SupportPreferenceDemos/src/main/java/com/example/android/supportpreference/FragmentSupportPreferencesCar.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.supportpreference;
+
+import android.os.Bundle;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+/**
+ * Demonstration of PreferenceFragment, showing a single fragment in an
+ * activity for the Car.
+ */
+public class FragmentSupportPreferencesCar extends AppCompatActivity
+        implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Display the fragment as the main content.
+        if (savedInstanceState == null) {
+            getSupportFragmentManager().beginTransaction().replace(android.R.id.content,
+                    new PrefsFragment()).commitNow();
+        }
+    }
+
+    @Override
+    public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) {
+        Fragment fragment = new PrefsFragment();
+        Bundle args = new Bundle();
+        args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, pref.getKey());
+        fragment.setArguments(args);
+        getSupportFragmentManager().beginTransaction()
+                .replace(android.R.id.content, fragment)
+                .commitNow();
+        return true;
+    }
+
+    /**
+     * Create a PrefsFragment from the xml file of preferences
+     */
+    public static class PrefsFragment extends PreferenceFragmentCompat {
+
+        @Override
+        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+            // Load the preferences from an XML resource
+            setPreferencesFromResource(R.xml.preferences, rootKey);
+        }
+    }
+}
+
diff --git a/samples/SupportPreferenceDemos/src/main/res/values/strings.xml b/samples/SupportPreferenceDemos/src/main/res/values/strings.xml
index e6effdf..a3a81b1 100644
--- a/samples/SupportPreferenceDemos/src/main/res/values/strings.xml
+++ b/samples/SupportPreferenceDemos/src/main/res/values/strings.xml
@@ -19,6 +19,7 @@
     <string name="fragment_support_preferences_demo">Support PreferenceFragment</string>
     <string name="fragment_support_preferences_compat_demo">Support PreferenceFragmentCompat</string>
     <string name="fragment_support_preferences_leanback_demo">Support LeanbackPreferenceFragment</string>
+    <string name="fragment_support_preferences_car_demo">Support Car PreferenceFragment</string>
 
     <string name="root_title">Demo Preferences</string>
 
diff --git a/samples/SupportPreferenceDemos/src/main/res/values/styles.xml b/samples/SupportPreferenceDemos/src/main/res/values/styles.xml
index 5194c9f..6b28378 100644
--- a/samples/SupportPreferenceDemos/src/main/res/values/styles.xml
+++ b/samples/SupportPreferenceDemos/src/main/res/values/styles.xml
@@ -31,4 +31,9 @@
         <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Leanback</item>
     </style>
 
+    <style name="SupportPreferenceCar" parent="Theme.Car.NoActionBar">
+        <item name="preferenceTheme">@style/PreferenceThemeOverlayCar</item>
+        <item name="android:windowBackground">@color/car_card</item>
+    </style>
+
 </resources>
diff --git a/samples/SupportPreferenceDemos/src/main/res/xml/preferences.xml b/samples/SupportPreferenceDemos/src/main/res/xml/preferences.xml
index 4d1dca7..2f49202 100644
--- a/samples/SupportPreferenceDemos/src/main/res/xml/preferences.xml
+++ b/samples/SupportPreferenceDemos/src/main/res/xml/preferences.xml
@@ -57,6 +57,13 @@
             android:entries="@array/entries_list_preference"
             android:entryValues="@array/entryvalues_list_preference" />
 
+        <SeekBarPreference
+            android:key="seekbar_preference"
+            android:title="Seekbar preference"
+            android:summary="This is a seekbar preference"
+            android:max="10"
+            android:defaultValue="5"/>
+
     </PreferenceCategory>
 
     <PreferenceCategory
diff --git a/samples/SupportSliceDemos/build.gradle b/samples/SupportSliceDemos/build.gradle
index bd68a95..8675869 100644
--- a/samples/SupportSliceDemos/build.gradle
+++ b/samples/SupportSliceDemos/build.gradle
@@ -24,6 +24,7 @@
     implementation(project(":slice-view"))
     implementation(project(":slice-builders"))
     implementation(project(":slice-core"))
+    implementation("com.android.support:design:28.0.0-SNAPSHOT", { transitive = false })
     implementation(project(":transition"))
     implementation(project(":recyclerview"))
     implementation(project(":appcompat"))
diff --git a/samples/SupportSliceDemos/src/main/AndroidManifest.xml b/samples/SupportSliceDemos/src/main/AndroidManifest.xml
index 4d43211..355a77a 100644
--- a/samples/SupportSliceDemos/src/main/AndroidManifest.xml
+++ b/samples/SupportSliceDemos/src/main/AndroidManifest.xml
@@ -48,7 +48,6 @@
 
         <provider android:authorities="com.example.androidx.slice.demos"
                   android:name=".SampleSliceProvider"
-                  android:exported="true"
                   android:grantUriPermissions="true">
             <intent-filter>
                 <action android:name="androidx.intent.SLICE_ACTION"/>
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
index afa5415..0beb745 100644
--- 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
@@ -65,27 +65,9 @@
     public static final String ACTION_TOAST_RANGE_VALUE =
             "com.example.androidx.slice.action.TOAST_RANGE_VALUE";
 
-    public static final String[] URI_PATHS = {
-            "message",
-            "wifi",
-            "note",
-            "ride",
-            "toggle",
-            "toggle2",
-            "toggletester",
-            "contact",
-            "contact2",
-            "gallery",
-            "gallery2",
-            "weather",
-            "reservation",
-            "loadlist",
-            "loadgrid",
-            "inputrange",
-            "range",
-            "subscription",
-            "singleitems",
-    };
+    public static final String[] URI_PATHS = {"message", "wifi", "note", "ride", "toggle",
+            "toggle2", "contact", "gallery", "weather", "reservation", "loadlist", "loadgrid",
+            "inputrange", "range", "contact2", "subscription"};
 
     /**
      * @return Uri with the provided path
@@ -134,16 +116,12 @@
                 return createCustomToggleSlice(sliceUri);
             case "/toggle2":
                 return createTwoCustomToggleSlices(sliceUri);
-            case "/toggletester":
-                return createdToggleTesterSlice(sliceUri);
             case "/contact":
                 return createContact(sliceUri);
             case "/contact2":
                 return createContact2(sliceUri);
             case "/gallery":
-                return createGallery(sliceUri, true /* showHeader */);
-            case "/gallery2":
-                return createGallery(sliceUri, false /* showHeader */);
+                return createGallery(sliceUri);
             case "/weather":
                 return createWeather(sliceUri);
             case "/reservation":
@@ -158,8 +136,6 @@
                 return createDownloadProgressRange(sliceUri);
             case "/subscription":
                 return createCatSlice(sliceUri, false /* customSeeMore */);
-            case "/singleitems":
-                return createSingleSlice(sliceUri);
         }
         throw new IllegalArgumentException("Unknown uri " + sliceUri);
     }
@@ -205,41 +181,58 @@
                 .build();
     }
 
-    private Slice createGallery(Uri sliceUri, boolean showHeader) {
+    private Slice createGallery(Uri sliceUri) {
         SliceAction primaryAction = new SliceAction(
                 getBroadcastIntent(ACTION_TOAST, "open photo album"),
                 IconCompat.createWithResource(getContext(), R.drawable.slices_1),
                 LARGE_IMAGE,
                 "Open photo album");
-        ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY)
-                .setAccentColor(0xff4285F4);
-        if (showHeader) {
-            lb.addRow(b -> b
-                    .setTitle("Family trip to Hawaii")
-                    .setSubtitle("Sep 30, 2017 - Oct 2, 2017")
-                    .setPrimaryAction(primaryAction))
-                    .addAction(new SliceAction(
-                            getBroadcastIntent(ACTION_TOAST, "cast photo album"),
-                            IconCompat.createWithResource(getContext(), R.drawable.ic_cast),
-                            "Cast photo album"))
-                    .addAction(new SliceAction(
-                            getBroadcastIntent(ACTION_TOAST, "share photo album"),
-                            IconCompat.createWithResource(getContext(), R.drawable.ic_share),
-                            "Share photo album"));
-        }
-        int[] galleryResId = new int[] {R.drawable.slices_1, R.drawable.slices_2,
-                R.drawable.slices_3, R.drawable.slices_4};
-        int imageCount = 7;
-        GridRowBuilder grb = new GridRowBuilder(lb);
-        for (int i = 0; i < imageCount; i++) {
-            IconCompat ic = IconCompat.createWithResource(getContext(),
-                    galleryResId[i % galleryResId.length]);
-            grb.addCell(cb -> cb.addImage(ic, LARGE_IMAGE));
-        }
-        grb.setPrimaryAction(primaryAction)
-                .setSeeMoreAction(getBroadcastIntent(ACTION_TOAST, "see your gallery"))
-                .setContentDescription("Images from your trip to Hawaii");
-        return lb.addGridRow(grb).build();
+        return new ListBuilder(getContext(), sliceUri, INFINITY)
+                .setColor(0xff4285F4)
+                .addRow(b -> b
+                        .setTitle("Family trip to Hawaii")
+                        .setSubtitle("Sep 30, 2017 - Oct 2, 2017")
+                        .setPrimaryAction(primaryAction))
+                .addAction(new SliceAction(
+                        getBroadcastIntent(ACTION_TOAST, "cast photo album"),
+                        IconCompat.createWithResource(getContext(), R.drawable.ic_cast),
+                        "Cast photo album"))
+                .addAction(new SliceAction(
+                        getBroadcastIntent(ACTION_TOAST, "share photo album"),
+                        IconCompat.createWithResource(getContext(), R.drawable.ic_share),
+                        "Share photo album"))
+                .addGridRow(b -> b
+                        .addCell(cb -> cb
+                                .addImage(IconCompat.createWithResource(getContext(),
+                                        R.drawable.slices_1),
+                                        LARGE_IMAGE))
+                        .addCell(cb -> cb
+                                .addImage(IconCompat.createWithResource(getContext(),
+                                        R.drawable.slices_2),
+                                        LARGE_IMAGE))
+                        .addCell(cb -> cb
+                                .addImage(IconCompat.createWithResource(getContext(),
+                                        R.drawable.slices_3),
+                                        LARGE_IMAGE))
+                        .addCell(cb -> cb
+                                .addImage(IconCompat.createWithResource(getContext(),
+                                        R.drawable.slices_4),
+                                        LARGE_IMAGE))
+                        .addCell(cb -> cb
+                                .addImage(IconCompat.createWithResource(getContext(),
+                                        R.drawable.slices_2),
+                                        LARGE_IMAGE))
+                        .addCell(cb -> cb
+                                .addImage(IconCompat.createWithResource(getContext(),
+                                        R.drawable.slices_3),
+                                        LARGE_IMAGE))
+                        .addCell(cb -> cb
+                                .addImage(IconCompat.createWithResource(getContext(),
+                                        R.drawable.slices_4),
+                                        LARGE_IMAGE))
+                        .setSeeMoreAction(getBroadcastIntent(ACTION_TOAST, "see your gallery"))
+                        .setContentDescription("Images from your trip to Hawaii"))
+                .build();
     }
 
     private Slice createCatSlice(Uri sliceUri, boolean customSeeMore) {
@@ -287,7 +280,7 @@
         ListBuilder b = new ListBuilder(getContext(), sliceUri, INFINITY);
         ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(b);
         GridRowBuilder gb = new GridRowBuilder(b);
-        return b.setAccentColor(0xff3949ab)
+        return b.setColor(0xff3949ab)
                 .addRow(rb
                         .setTitle("Mady Pitza")
                         .setSubtitle("Frequently contacted contact")
@@ -329,7 +322,7 @@
                 R.drawable.mady), SMALL_IMAGE, "Mady");
 
         return new ListBuilder(getContext(), sliceUri, INFINITY)
-                .setAccentColor(0xff3949ab)
+                .setColor(0xff3949ab)
                 .setHeader(b -> b
                         .setTitle("Mady Pitza")
                         .setSummary("Called " + lastCalledString)
@@ -384,7 +377,7 @@
     private Slice createNoteSlice(Uri sliceUri) {
         // TODO: Remote input.
         return new ListBuilder(getContext(), sliceUri, INFINITY)
-                .setAccentColor(0xfff4b400)
+                .setColor(0xfff4b400)
                 .addRow(b -> b.setTitle("Create new note"))
                 .addAction(new SliceAction(getBroadcastIntent(ACTION_TOAST, "create note"),
                         IconCompat.createWithResource(getContext(), R.drawable.ic_create),
@@ -400,7 +393,7 @@
 
     private Slice createReservationSlice(Uri sliceUri) {
         return new ListBuilder(getContext(), sliceUri, INFINITY)
-                .setAccentColor(0xffFF5252)
+                .setColor(0xffFF5252)
                 .setHeader(b -> b
                         .setTitle("Upcoming trip to Seattle")
                         .setSubtitle("Feb 1 - 19 | 2 guests"))
@@ -438,8 +431,8 @@
 
         SliceAction primaryAction = new SliceAction(getBroadcastIntent(ACTION_TOAST, "get ride"),
                 IconCompat.createWithResource(getContext(), R.drawable.ic_car), "Get Ride");
-        return new ListBuilder(getContext(), sliceUri, TimeUnit.SECONDS.toMillis(10))
-                .setAccentColor(0xff0F9D58)
+        return new ListBuilder(getContext(), sliceUri, -TimeUnit.MINUTES.toMillis(2))
+                .setColor(0xff0F9D58)
                 .setHeader(b -> b
                         .setTitle("Get ride")
                         .setSubtitle(headerSubtitle)
@@ -462,7 +455,7 @@
 
     private Slice createCustomToggleSlice(Uri sliceUri) {
         return new ListBuilder(getContext(), sliceUri, INFINITY)
-                .setAccentColor(0xffff4081)
+                .setColor(0xffff4081)
                 .addRow(b -> b
                         .setTitle("Custom toggle")
                         .setSubtitle("It can support two states")
@@ -475,7 +468,7 @@
 
     private Slice createTwoCustomToggleSlices(Uri sliceUri) {
         return new ListBuilder(getContext(), sliceUri, INFINITY)
-                .setAccentColor(0xffff4081)
+                .setColor(0xffff4081)
                 .addRow(b -> b
                         .setTitle("2 toggles")
                         .setSubtitle("each supports two states")
@@ -521,7 +514,7 @@
         String sliceCDString = wifiEnabled ? "Wifi connected to " + state
                 : "Wifi disconnected, 10 networks available";
         ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY)
-                .setAccentColor(0xff4285f4)
+                .setColor(0xff4285f4)
                 .setHeader(b -> b
                         .setTitle("Wi-fi")
                         .setSubtitle(state)
@@ -577,7 +570,7 @@
                 new SliceAction(getBroadcastIntent(ACTION_TOAST, "open star rating"),
                         icon, "Rate");
         return new ListBuilder(getContext(), sliceUri, INFINITY)
-                .setAccentColor(0xffff4081)
+                .setColor(0xffff4081)
                 .addInputRange(c -> c
                         .setTitle("Star rating")
                         .setSubtitle("Rate from 5 to 10 because it's weird")
@@ -597,7 +590,7 @@
                 new SliceAction(
                         getBroadcastIntent(ACTION_TOAST, "open download"), icon, "Download");
         return new ListBuilder(getContext(), sliceUri, INFINITY)
-                .setAccentColor(0xffff4081)
+                .setColor(0xffff4081)
                 .addRange(c -> c
                         .setTitle("Download progress")
                         .setSubtitle("Download is happening")
@@ -607,116 +600,6 @@
                 .build();
     }
 
-    private Slice createdToggleTesterSlice(Uri uri) {
-        IconCompat star = IconCompat.createWithResource(getContext(), R.drawable.toggle_star);
-        IconCompat icon = IconCompat.createWithResource(getContext(), R.drawable.ic_star_on);
-
-        SliceAction primaryAction = new SliceAction(
-                getBroadcastIntent(ACTION_TOAST, "primary action"), icon, "Primary action");
-        SliceAction toggleAction = new SliceAction(
-                getBroadcastIntent(ACTION_TOAST, "star note"), star, "Star note", false);
-        SliceAction toggleAction2 = new SliceAction(
-                getBroadcastIntent(ACTION_TOAST, "star note 2"), star, "Star note 2", true);
-        SliceAction toggleAction3 = new SliceAction(
-                getBroadcastIntent(ACTION_TOAST, "star note 3"), star, "Star note 3", false);
-
-        ListBuilder lb = new ListBuilder(getContext(), uri, INFINITY);
-
-        // Primary action toggle
-        ListBuilder.RowBuilder primaryToggle = new ListBuilder.RowBuilder(lb);
-        primaryToggle.setTitle("Primary action is a toggle")
-                .setPrimaryAction(toggleAction);
-
-        // End toggle + normal primary action
-        ListBuilder.RowBuilder endToggle = new ListBuilder.RowBuilder(lb);
-        endToggle.setTitle("Only end toggles")
-                .setSubtitle("Normal primary action")
-                .setPrimaryAction(primaryAction)
-                .addEndItem(toggleAction)
-                .addEndItem(toggleAction2);
-
-        // Start toggle + normal primary
-        ListBuilder.RowBuilder startToggle = new ListBuilder.RowBuilder(lb);
-        startToggle.setTitle("One start toggle")
-                .setTitleItem(toggleAction)
-                .setSubtitle("Normal primary action")
-                .setPrimaryAction(primaryAction);
-
-        // Start + end toggles + normal primary action
-        ListBuilder.RowBuilder someToggles = new ListBuilder.RowBuilder(lb);
-        someToggles.setTitleItem(toggleAction)
-                .setPrimaryAction(primaryAction)
-                .setTitle("Start & end toggles")
-                .setSubtitle("Normal primary action")
-                .addEndItem(toggleAction2)
-                .addEndItem(toggleAction3);
-
-        // Start toggle ONLY
-        ListBuilder.RowBuilder startToggleOnly = new ListBuilder.RowBuilder(lb);
-        startToggleOnly.setTitle("Start action is a toggle")
-                .setSubtitle("No other actions")
-                .setTitleItem(toggleAction);
-
-        // End toggle ONLY
-        ListBuilder.RowBuilder endToggleOnly = new ListBuilder.RowBuilder(lb);
-        endToggleOnly.setTitle("End action is a toggle")
-                .setSubtitle("No other actions")
-                .addEndItem(toggleAction);
-
-        // All toggles: end item should be ignored / replaced with primary action
-        ListBuilder.RowBuilder muchToggles = new ListBuilder.RowBuilder(lb);
-        muchToggles.setTitleItem(toggleAction)
-                .setTitle("All toggles")
-                .setSubtitle("Even the primary action")
-                .setPrimaryAction(toggleAction2)
-                .addEndItem(toggleAction3);
-
-        lb.addRow(primaryToggle);
-        lb.addRow(endToggleOnly);
-        lb.addRow(endToggle);
-        lb.addRow(startToggleOnly);
-        lb.addRow(startToggle);
-        lb.addRow(someToggles);
-        lb.addRow(muchToggles);
-        return lb.build();
-    }
-
-    private Slice createSingleSlice(Uri uri) {
-        IconCompat ic2 = IconCompat.createWithResource(getContext(), R.drawable.ic_create);
-        IconCompat image = IconCompat.createWithResource(getContext(), R.drawable.cat_3);
-        IconCompat toggle = IconCompat.createWithResource(getContext(), R.drawable.toggle_star);
-        SliceAction toggleAction = new SliceAction(
-                getBroadcastIntent(ACTION_TOAST, "toggle action"), toggle, "toggle", false);
-        SliceAction simpleAction = new SliceAction(
-                getBroadcastIntent(ACTION_TOAST, "icon action"), ic2, "icon");
-        ListBuilder lb = new ListBuilder(getContext(), uri, INFINITY);
-        return lb.addRow(new ListBuilder.RowBuilder(lb)
-                .setTitle("Single title"))
-                .addRow(new ListBuilder.RowBuilder(lb)
-                        .setSubtitle("Single subtitle"))
-                 //Time stamps
-                .addRow(new ListBuilder.RowBuilder(lb)
-                        .setTitleItem(System.currentTimeMillis()))
-                .addRow(new ListBuilder.RowBuilder(lb)
-                        .addEndItem(System.currentTimeMillis()))
-                // Toggle actions
-                .addRow(new ListBuilder.RowBuilder(lb)
-                        .setTitleItem(toggleAction))
-                .addRow(new ListBuilder.RowBuilder(lb)
-                        .addEndItem(toggleAction))
-                // Icon actions
-                .addRow(new ListBuilder.RowBuilder(lb)
-                        .setTitleItem(simpleAction))
-                .addRow(new ListBuilder.RowBuilder(lb)
-                        .addEndItem(simpleAction))
-                // Images
-                .addRow(new ListBuilder.RowBuilder(lb)
-                        .setTitleItem(image, SMALL_IMAGE))
-                .addRow(new ListBuilder.RowBuilder(lb)
-                        .addEndItem(image, SMALL_IMAGE))
-                .build();
-    }
-
     private Handler mHandler = new Handler();
     private SparseArray<String> mListSummaries = new SparseArray<>();
     private long mListLastUpdate;
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
index 7b9d3d6..4facfb3 100644
--- 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
@@ -16,14 +16,13 @@
 
 package com.example.androidx.slice.demos;
 
-import static androidx.slice.core.SliceHints.INFINITY;
-
 import static com.example.androidx.slice.demos.SampleSliceProvider.URI_PATHS;
 import static com.example.androidx.slice.demos.SampleSliceProvider.getUri;
 
 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;
@@ -49,7 +48,6 @@
 import androidx.lifecycle.LiveData;
 import androidx.slice.Slice;
 import androidx.slice.SliceItem;
-import androidx.slice.SliceMetadata;
 import androidx.slice.widget.EventInfo;
 import androidx.slice.widget.SliceLiveData;
 import androidx.slice.widget.SliceView;
@@ -68,7 +66,7 @@
 
     private static final String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
     private static final boolean TEST_INTENT = false;
-    private static final boolean TEST_THEMES = true;
+    private static final boolean TEST_THEMES = false;
     private static final boolean SCROLLING_ENABLED = true;
 
     private ArrayList<Uri> mSliceUris = new ArrayList<Uri>();
@@ -132,6 +130,7 @@
             mSearchView.setQuery(savedInstanceState.getString("SELECTED_QUERY"), true);
         }
 
+        grantPackage(getPackageName());
         // TODO: Listen for changes.
         updateAvailableSlices();
         if (TEST_INTENT) {
@@ -147,6 +146,7 @@
         mTypeMenu.add("Shortcut");
         mTypeMenu.add("Small");
         mTypeMenu.add("Large");
+        menu.add("Auth");
         super.onCreateOptionsMenu(menu);
         return true;
     }
@@ -154,6 +154,9 @@
     @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;
@@ -180,6 +183,21 @@
         outState.putString("SELECTED_QUERY", mSearchView.getQuery().toString());
     }
 
+    private void authAllSlices() {
+        List<ApplicationInfo> packages = getPackageManager().getInstalledApplications(0);
+        for (ApplicationInfo info : packages) {
+            grantPackage(info.packageName);
+        }
+    }
+
+    private void grantPackage(String packageName) {
+        for (int i = 0; i < URI_PATHS.length; i++) {
+            grantUriPermission(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()
@@ -221,17 +239,7 @@
             mContainer.addView(v);
             mSliceLiveData = SliceLiveData.fromUri(this, uri);
             v.setMode(mSelectedMode);
-            mSliceLiveData.observe(this, slice -> {
-                v.setSlice(slice);
-                SliceMetadata metadata = SliceMetadata.from(this, slice);
-                long expiry = metadata.getExpiry();
-                if (expiry != INFINITY) {
-                    // Shows the updated text after the TTL expires.
-                    v.postDelayed(() -> v.setSlice(slice),
-                            expiry - System.currentTimeMillis() + 15);
-                }
-            });
-            mSliceLiveData.observe(this, slice -> Log.d(TAG, "Slice: " + slice));
+            mSliceLiveData.observe(this, v);
         } else {
             Log.w(TAG, "Invalid uri, skipping slice: " + uri);
         }
diff --git a/samples/SupportSliceDemos/src/main/res/values/styles.xml b/samples/SupportSliceDemos/src/main/res/values/styles.xml
index fcc4b1f..d276a41 100644
--- a/samples/SupportSliceDemos/src/main/res/values/styles.xml
+++ b/samples/SupportSliceDemos/src/main/res/values/styles.xml
@@ -34,7 +34,21 @@
     <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
 
     <style name="CustomSliceView" parent="Widget.SliceView">
-        <item name="gridTopPadding">4dp</item>
-        <item name="gridBottomPadding">4dp</item>
+        <item name="tintColor">@color/tintColor</item>
+
+        <item name="titleColor">@color/textColor</item>
+        <item name="subtitleColor">@color/textColor</item>
+
+        <item name="headerTitleSize">@dimen/textSize</item>
+        <item name="headerSubtitleSize">@dimen/textSize</item>
+        <item name="titleSize">@dimen/textSize</item>
+        <item name="subtitleSize">@dimen/textSize</item>
+        <item name="gridTitleSize">@dimen/textSize</item>
+        <item name="gridSubtitleSize">@dimen/smallTextSize</item>
+
+        <item name="android:paddingLeft">8dp</item>
+        <item name="android:paddingTop">8dp</item>
+        <item name="android:paddingRight">8dp</item>
+        <item name="android:paddingBottom">8dp</item>
     </style>
 </resources>
diff --git a/slices/builders/api/current.txt b/slices/builders/api/current.txt
index f191aed..1041eb9 100644
--- a/slices/builders/api/current.txt
+++ b/slices/builders/api/current.txt
@@ -77,8 +77,7 @@
     method public deprecated androidx.slice.builders.ListBuilder addSeeMoreAction(android.app.PendingIntent);
     method public deprecated androidx.slice.builders.ListBuilder addSeeMoreRow(androidx.slice.builders.ListBuilder.RowBuilder);
     method public deprecated androidx.slice.builders.ListBuilder addSeeMoreRow(androidx.core.util.Consumer<androidx.slice.builders.ListBuilder.RowBuilder>);
-    method public androidx.slice.builders.ListBuilder setAccentColor(int);
-    method public deprecated androidx.slice.builders.ListBuilder setColor(int);
+    method public androidx.slice.builders.ListBuilder setColor(int);
     method public androidx.slice.builders.ListBuilder setHeader(androidx.slice.builders.ListBuilder.HeaderBuilder);
     method public androidx.slice.builders.ListBuilder setHeader(androidx.core.util.Consumer<androidx.slice.builders.ListBuilder.HeaderBuilder>);
     method public androidx.slice.builders.ListBuilder setKeywords(java.util.List<java.lang.String>);
diff --git a/slices/builders/build.gradle b/slices/builders/build.gradle
index 91c7599..ec85148 100644
--- a/slices/builders/build.gradle
+++ b/slices/builders/build.gradle
@@ -37,5 +37,4 @@
     description = "A set of builders to create templates using SliceProvider APIs"
     minSdkVersion = 19
     failOnUncheckedWarnings = false
-    failOnDeprecationWarnings = false
 }
diff --git a/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
index 76b9e08..1c81ebd 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
@@ -82,10 +82,9 @@
  * <ul>
  *     <li>{@link androidx.slice.widget.SliceView#MODE_SHORTCUT} - The primary {@link SliceAction}
  *     of the slice is used your primary action should contain an image and title representative
- *     of your slice. If providing a tintable icon, use {@link #setAccentColor(int)} to specify the
- *     color. If a header has been specified for the list, the primary action associated with it
- *     will be used, otherwise it will be the primary action associated with the first row of the
- *     list.
+ *     of your slice. If providing a tintable icon, use {@link #setColor(int)} to specify the color.
+ *     If a header has been specified for the list, the primary action associated with it will be
+ *     used, otherwise it will be the primary action associated with the first row of the list.
  *     </li>
  *     <li>{@link androidx.slice.widget.SliceView#MODE_SMALL} - Only a single row of content is
  *     displayed in small format. If a header has been specified it will be displayed. If no header
@@ -311,15 +310,6 @@
     }
 
     /**
-     * @deprecated TO BE REMOVED; use {@link #setAccentColor(int)} instead.
-     */
-    @Deprecated
-    @NonNull
-    public ListBuilder setColor(@ColorInt int color) {
-        return setAccentColor(color);
-    }
-
-    /**
      * Sets the color to use on tintable items within the list builder.
      * Things that might be tinted are:
      * <ul>
@@ -332,7 +322,7 @@
      * </ul>
      */
     @NonNull
-    public ListBuilder setAccentColor(@ColorInt int color) {
+    public ListBuilder setColor(@ColorInt int color) {
         mImpl.setColor(color);
         return this;
     }
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java
index 16471ed..714b570 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java
@@ -18,9 +18,11 @@
 
 import static android.app.slice.Slice.HINT_HORIZONTAL;
 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_PARTIAL;
 import static android.app.slice.Slice.HINT_SEE_MORE;
+import static android.app.slice.Slice.HINT_SHORTCUT;
 import static android.app.slice.Slice.HINT_TITLE;
 import static android.app.slice.Slice.SUBTYPE_CONTENT_DESCRIPTION;
 
@@ -57,12 +59,23 @@
     /**
      */
     @Override
-    public void apply(Slice.Builder builder) {
-        builder.addHints(HINT_HORIZONTAL);
+    @NonNull
+    public Slice build() {
+        Slice.Builder sb = new Slice.Builder(getBuilder())
+                .addHints(HINT_HORIZONTAL, HINT_LIST_ITEM);
+        sb.addSubSlice(getBuilder().addHints(HINT_HORIZONTAL, HINT_LIST_ITEM).build());
         if (mPrimaryAction != null) {
-            Slice.Builder actionBuilder = new Slice.Builder(getBuilder()).addHints(HINT_TITLE);
-            builder.addSubSlice(mPrimaryAction.buildSlice(actionBuilder));
+            Slice.Builder actionBuilder = new Slice.Builder(getBuilder())
+                    .addHints(HINT_SHORTCUT, HINT_TITLE);
+            sb.addSubSlice(mPrimaryAction.buildSlice(actionBuilder));
         }
+        return sb.build();
+    }
+
+    /**
+     */
+    @Override
+    public void apply(Slice.Builder builder) {
     }
 
     /**
@@ -83,7 +96,7 @@
      */
     @Override
     public void addCell(TemplateBuilderImpl builder) {
-        builder.apply(getBuilder());
+        getBuilder().addSubSlice(builder.getBuilder().addHints(HINT_LIST_ITEM).build());
     }
 
 
@@ -92,7 +105,7 @@
     @Override
     public void setSeeMoreCell(@NonNull TemplateBuilderImpl builder) {
         builder.getBuilder().addHints(HINT_SEE_MORE);
-        builder.apply(getBuilder());
+        getBuilder().addSubSlice(builder.build());
     }
 
     /**
@@ -171,8 +184,8 @@
         @Override
         public void addTitleText(@Nullable CharSequence text, boolean isLoading) {
             @Slice.SliceHint String[] hints = isLoading
-                    ? new String[] {HINT_PARTIAL, HINT_TITLE}
-                    : new String[] {HINT_TITLE};
+                    ? new String[] {HINT_PARTIAL, HINT_LARGE}
+                    : new String[] {HINT_LARGE};
             getBuilder().addText(text, null, hints);
         }
 
@@ -223,12 +236,20 @@
         @RestrictTo(LIBRARY)
         @Override
         public void apply(Slice.Builder b) {
-            getBuilder().addHints(HINT_HORIZONTAL);
+        }
+
+        /**
+         */
+        @Override
+        @NonNull
+        public Slice build() {
             if (mContentIntent != null) {
-                b.addAction(mContentIntent, getBuilder().build(), null);
-            } else {
-                b.addSubSlice(getBuilder().build());
+                return new Slice.Builder(getBuilder())
+                        .addHints(HINT_HORIZONTAL)
+                        .addAction(mContentIntent, getBuilder().build(), null)
+                        .build();
             }
+            return getBuilder().addHints(HINT_HORIZONTAL).build();
         }
     }
 }
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
index 8b16abe..c771b62 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
@@ -76,7 +76,7 @@
      */
     @Override
     public void apply(Slice.Builder builder) {
-        builder.addLong(System.currentTimeMillis(), SUBTYPE_MILLIS, HINT_LAST_UPDATED);
+        builder.addTimestamp(System.currentTimeMillis(), SUBTYPE_MILLIS, HINT_LAST_UPDATED);
         if (mSliceHeader != null) {
             builder.addSubSlice(mSliceHeader);
         }
@@ -95,7 +95,6 @@
     @NonNull
     @Override
     public void addRow(@NonNull TemplateBuilderImpl builder) {
-        builder.getBuilder().addHints(HINT_LIST_ITEM);
         getBuilder().addSubSlice(builder.build());
     }
 
@@ -104,7 +103,6 @@
     @NonNull
     @Override
     public void addGridRow(@NonNull TemplateBuilderImpl builder) {
-        builder.getBuilder().addHints(HINT_LIST_ITEM);
         getBuilder().addSubSlice(builder.build());
     }
 
@@ -560,6 +558,7 @@
                         getBuilder()).addHints(HINT_TITLE, HINT_SHORTCUT);
                 b.addSubSlice(mPrimaryAction.buildSlice(sb), null);
             }
+            b.addHints(HINT_LIST_ITEM);
         }
     }
 
diff --git a/slices/core/api/current.txt b/slices/core/api/current.txt
index c6077bf..09a69fd 100644
--- a/slices/core/api/current.txt
+++ b/slices/core/api/current.txt
@@ -26,7 +26,6 @@
   }
 
   public abstract class SliceProvider extends android.content.ContentProvider implements androidx.core.app.CoreComponentFactory.CompatWrapped {
-    ctor public SliceProvider(java.lang.String...);
     ctor public SliceProvider();
     method public final int bulkInsert(android.net.Uri, android.content.ContentValues[]);
     method public final android.net.Uri canonicalize(android.net.Uri);
diff --git a/slices/core/src/androidTest/java/androidx/slice/SliceTest.java b/slices/core/src/androidTest/java/androidx/slice/SliceTest.java
index e092c97..041c8fe 100644
--- a/slices/core/src/androidTest/java/androidx/slice/SliceTest.java
+++ b/slices/core/src/androidTest/java/androidx/slice/SliceTest.java
@@ -23,9 +23,9 @@
 import static android.app.slice.SliceItem.FORMAT_ACTION;
 import static android.app.slice.SliceItem.FORMAT_IMAGE;
 import static android.app.slice.SliceItem.FORMAT_INT;
-import static android.app.slice.SliceItem.FORMAT_LONG;
 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.app.slice.SliceProvider.SLICE_TYPE;
 
 import static org.junit.Assert.assertEquals;
@@ -184,7 +184,7 @@
         assertEquals(1, s.getItems().size());
 
         SliceItem item = s.getItems().get(0);
-        assertEquals(FORMAT_LONG, item.getFormat());
+        assertEquals(FORMAT_TIMESTAMP, item.getFormat());
         assertEquals(43, item.getTimestamp());
     }
 
diff --git a/slices/core/src/androidTest/java/androidx/slice/compat/CompatPermissionManagerTest.java b/slices/core/src/androidTest/java/androidx/slice/compat/CompatPermissionManagerTest.java
deleted file mode 100644
index 552df8c..0000000
--- a/slices/core/src/androidTest/java/androidx/slice/compat/CompatPermissionManagerTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.slice.compat;
-
-import static androidx.core.content.PermissionChecker.PERMISSION_DENIED;
-import static androidx.core.content.PermissionChecker.PERMISSION_GRANTED;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.os.Process;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class CompatPermissionManagerTest {
-
-    private final Context mContext = InstrumentationRegistry.getContext();
-
-    @Test
-    public void testAutoGrant() {
-        final Uri uri = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority("my.authority")
-                .path("my_path")
-                .build();
-        final String testPermission = "android.permission.SOME_PERMISSION";
-
-        final int grantedPid = Process.myPid();
-        final int grantedUid = Process.myUid();
-
-        final int nonGrantedPid = grantedPid + 1;
-        final int nonGrantedUid = grantedUid + 1;
-
-        Context permContext = new ContextWrapper(mContext) {
-            @Override
-            public int checkPermission(String permission, int pid, int uid) {
-                if (testPermission.equals(permission)) {
-                    if (grantedUid == uid) {
-                        return PackageManager.PERMISSION_GRANTED;
-                    } else if (nonGrantedUid == uid) {
-                        return PackageManager.PERMISSION_DENIED;
-                    }
-                }
-                return super.checkPermission(permission, pid, uid);
-            }
-
-            @Override
-            public PackageManager getPackageManager() {
-                PackageManager pm = spy(super.getPackageManager());
-                when(pm.getPackagesForUid(grantedUid)).thenReturn(new String[] { "grant_pkg"});
-                when(pm.getPackagesForUid(nonGrantedUid)).thenReturn(new String[] { "other_pkg"});
-                return pm;
-            }
-        };
-        CompatPermissionManager manager = spy(new CompatPermissionManager(permContext, "nothing", 0,
-                new String[] {testPermission}));
-
-        assertEquals(PERMISSION_DENIED, manager.checkSlicePermission(uri,
-                nonGrantedPid, nonGrantedUid));
-
-        assertEquals(PERMISSION_GRANTED, manager.checkSlicePermission(uri, grantedPid, grantedUid));
-        verify(manager).grantSlicePermission(eq(uri), eq("grant_pkg"));
-
-    }
-
-}
diff --git a/slices/core/src/androidTest/java/androidx/slice/compat/SliceProviderCompatTest.java b/slices/core/src/androidTest/java/androidx/slice/compat/SliceProviderCompatTest.java
deleted file mode 100644
index cc4ba49..0000000
--- a/slices/core/src/androidTest/java/androidx/slice/compat/SliceProviderCompatTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.slice.compat;
-
-import static androidx.core.content.PermissionChecker.PERMISSION_DENIED;
-import static androidx.core.content.PermissionChecker.PERMISSION_GRANTED;
-import static androidx.slice.compat.SliceProviderCompat.EXTRA_BIND_URI;
-import static androidx.slice.compat.SliceProviderCompat.EXTRA_SLICE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import androidx.slice.Slice;
-import androidx.slice.SliceProvider;
-import androidx.slice.SliceSpec;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Collections;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class SliceProviderCompatTest {
-
-    private final Context mContext = InstrumentationRegistry.getContext();
-
-    @Test
-    public void testBindWithPermission() {
-        Uri uri = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority("my.authority")
-                .path("my_path")
-                .build();
-        Slice s = new Slice.Builder(uri)
-                .addText("", null)
-                .build();
-
-        SliceProvider provider = spy(new SliceProviderImpl());
-        CompatPermissionManager permissions = mock(CompatPermissionManager.class);
-        when(permissions.checkSlicePermission(any(Uri.class), anyInt(), anyInt()))
-                .thenReturn(PERMISSION_GRANTED);
-
-        when(provider.onBindSlice(eq(uri))).thenReturn(s);
-        SliceProviderCompat compat = new SliceProviderCompat(provider, permissions,
-                mContext) {
-            @Override
-            public String getCallingPackage() {
-                return mContext.getPackageName();
-            }
-        };
-
-        Bundle b = new Bundle();
-        b.putParcelable(EXTRA_BIND_URI, uri);
-        SliceProviderCompat.addSpecs(b, Collections.<SliceSpec>emptySet());
-
-        Bundle result = compat.call(SliceProviderCompat.METHOD_SLICE, null, b);
-        assertEquals(s.toString(), new Slice(result.getBundle(EXTRA_SLICE)).toString());
-    }
-
-    @Test
-    public void testBindWithoutPermission() {
-        Uri uri = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority("my.authority")
-                .path("my_path")
-                .build();
-        Slice s = new Slice.Builder(uri)
-                .addText("", null)
-                .build();
-
-        SliceProvider provider = spy(new SliceProviderImpl());
-        CompatPermissionManager permissions = mock(CompatPermissionManager.class);
-        when(permissions.checkSlicePermission(any(Uri.class), anyInt(), anyInt()))
-                .thenReturn(PERMISSION_DENIED);
-
-        when(provider.onBindSlice(eq(uri))).thenReturn(s);
-        SliceProviderCompat compat = new SliceProviderCompat(provider, permissions,
-                mContext) {
-            @Override
-            public String getCallingPackage() {
-                return mContext.getPackageName();
-            }
-        };
-
-        Bundle b = new Bundle();
-        b.putParcelable(EXTRA_BIND_URI, uri);
-        SliceProviderCompat.addSpecs(b, Collections.<SliceSpec>emptySet());
-
-        Bundle result = compat.call(SliceProviderCompat.METHOD_SLICE, null, b);
-        assertNotEquals(s.toString(), new Slice(result.getBundle(EXTRA_SLICE)).toString());
-    }
-
-    public static class SliceProviderImpl extends SliceProvider {
-
-        @Override
-        public boolean onCreateSliceProvider() {
-            return true;
-        }
-
-        @Override
-        public Slice onBindSlice(Uri sliceUri) {
-            return null;
-        }
-    }
-}
diff --git a/slices/core/src/main/java/androidx/slice/Slice.java b/slices/core/src/main/java/androidx/slice/Slice.java
index aa077cb..d18ef23 100644
--- a/slices/core/src/main/java/androidx/slice/Slice.java
+++ b/slices/core/src/main/java/androidx/slice/Slice.java
@@ -35,6 +35,7 @@
 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 static androidx.slice.SliceConvert.unwrap;
 import static androidx.slice.core.SliceHints.HINT_KEYWORDS;
@@ -387,7 +388,7 @@
         }
 
         /**
-         * Add a long to the slice being constructed
+         * Add a timestamp to the slice being constructed
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
          */
@@ -398,16 +399,6 @@
         }
 
         /**
-         * Add a long to the slice being constructed
-         * @param subType Optional template-specific type information
-         * @see {@link SliceItem#getSubType()}
-         */
-        public Slice.Builder addLong(long time, @Nullable String subType,
-                @SliceHint List<String> hints) {
-            return addLong(time, 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()}
@@ -416,7 +407,7 @@
         @Deprecated
         public Slice.Builder addTimestamp(long time, @Nullable String subType,
                 @SliceHint String... hints) {
-            mItems.add(new SliceItem(time, FORMAT_LONG, subType, hints));
+            mItems.add(new SliceItem(time, FORMAT_TIMESTAMP, subType, hints));
             return this;
         }
 
@@ -464,37 +455,20 @@
     public String toString(String indent) {
         StringBuilder sb = new StringBuilder();
         sb.append(indent);
-        sb.append("slice ");
-        addHints(sb, mHints);
-        sb.append("{\n");
-        String nextIndent = indent + "  ";
+        sb.append("slice: ");
+        sb.append("\n");
+        indent += "   ";
         for (int i = 0; i < mItems.length; i++) {
             SliceItem item = mItems[i];
-            sb.append(item.toString(nextIndent));
+            sb.append(item.toString(indent));
+            if (!FORMAT_SLICE.equals(item.getFormat())) {
+                sb.append("\n");
+            }
         }
-        sb.append(indent);
-        sb.append("}");
         return sb.toString();
     }
 
     /**
-     * @hide
-     */
-    @RestrictTo(Scope.LIBRARY)
-    public static void addHints(StringBuilder sb, String[] hints) {
-        if (hints == null || hints.length == 0) return;
-
-        sb.append("(");
-        int end = hints.length - 1;
-        for (int i = 0; i < end; i++) {
-            sb.append(hints[i]);
-            sb.append(", ");
-        }
-        sb.append(hints[end]);
-        sb.append(") ");
-    }
-
-    /**
      * Turns a slice Uri into slice content.
      *
      * @hide
@@ -519,6 +493,6 @@
     private static Slice callBindSlice(Context context, Uri uri,
             Set<SliceSpec> supportedSpecs) {
         return SliceConvert.wrap(context.getSystemService(SliceManager.class)
-                .bindSlice(uri, unwrap(supportedSpecs)));
+                .bindSlice(uri, new ArrayList<>(unwrap(supportedSpecs))));
     }
 }
diff --git a/slices/core/src/main/java/androidx/slice/SliceConvert.java b/slices/core/src/main/java/androidx/slice/SliceConvert.java
index fea5b4c..73ff368 100644
--- a/slices/core/src/main/java/androidx/slice/SliceConvert.java
+++ b/slices/core/src/main/java/androidx/slice/SliceConvert.java
@@ -19,16 +19,17 @@
 import static android.app.slice.SliceItem.FORMAT_ACTION;
 import static android.app.slice.SliceItem.FORMAT_IMAGE;
 import static android.app.slice.SliceItem.FORMAT_INT;
-import static android.app.slice.SliceItem.FORMAT_LONG;
 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 androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.collection.ArraySet;
 import androidx.core.graphics.drawable.IconCompat;
 
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -42,8 +43,9 @@
      */
     public static android.app.slice.Slice unwrap(androidx.slice.Slice slice) {
         android.app.slice.Slice.Builder builder = new android.app.slice.Slice.Builder(
-                slice.getUri(), unwrap(slice.getSpec()));
+                slice.getUri());
         builder.addHints(slice.getHints());
+        builder.setSpec(unwrap(slice.getSpec()));
         for (androidx.slice.SliceItem item : slice.getItems()) {
             switch (item.getFormat()) {
                 case FORMAT_SLICE:
@@ -65,8 +67,8 @@
                 case FORMAT_INT:
                     builder.addInt(item.getInt(), item.getSubType(), item.getHints());
                     break;
-                case FORMAT_LONG:
-                    builder.addLong(item.getLong(), item.getSubType(), item.getHints());
+                case FORMAT_TIMESTAMP:
+                    builder.addTimestamp(item.getTimestamp(), item.getSubType(), item.getHints());
                     break;
             }
         }
@@ -117,8 +119,8 @@
                 case FORMAT_INT:
                     builder.addInt(item.getInt(), item.getSubType(), item.getHints());
                     break;
-                case FORMAT_LONG:
-                    builder.addLong(item.getLong(), item.getSubType(), item.getHints());
+                case FORMAT_TIMESTAMP:
+                    builder.addTimestamp(item.getTimestamp(), item.getSubType(), item.getHints());
                     break;
             }
         }
@@ -135,7 +137,7 @@
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     public static Set<androidx.slice.SliceSpec> wrap(
-            Set<android.app.slice.SliceSpec> supportedSpecs) {
+            List<android.app.slice.SliceSpec> supportedSpecs) {
         Set<androidx.slice.SliceSpec> ret = new ArraySet<>();
         for (android.app.slice.SliceSpec spec : supportedSpecs) {
             ret.add(wrap(spec));
diff --git a/slices/core/src/main/java/androidx/slice/SliceItem.java b/slices/core/src/main/java/androidx/slice/SliceItem.java
index f6ae848..004e51d 100644
--- a/slices/core/src/main/java/androidx/slice/SliceItem.java
+++ b/slices/core/src/main/java/androidx/slice/SliceItem.java
@@ -23,8 +23,7 @@
 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 androidx.slice.Slice.addHints;
+import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
 
 import android.app.PendingIntent;
 import android.app.RemoteInput;
@@ -58,7 +57,7 @@
  * <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_INT}</li>
- * <li>{@link android.app.slice.SliceItem#FORMAT_LONG}</li>
+ * <li>{@link android.app.slice.SliceItem#FORMAT_TIMESTAMP}</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
@@ -77,7 +76,7 @@
      */
     @RestrictTo(Scope.LIBRARY)
     @StringDef({FORMAT_SLICE, FORMAT_TEXT, FORMAT_IMAGE, FORMAT_ACTION, FORMAT_INT,
-            FORMAT_LONG, FORMAT_REMOTE_INPUT, FORMAT_LONG})
+            FORMAT_TIMESTAMP, FORMAT_REMOTE_INPUT, FORMAT_LONG})
     public @interface SliceType {
     }
 
@@ -163,7 +162,7 @@
      * <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_INT}</li>
-     * <li>{@link android.app.slice.SliceItem#FORMAT_LONG}</li>
+     * <li>{@link android.app.slice.SliceItem#FORMAT_TIMESTAMP}</li>
      * <li>{@link android.app.slice.SliceItem#FORMAT_REMOTE_INPUT}</li>
      * @see #getSubType() ()
      */
@@ -346,7 +345,7 @@
             case FORMAT_INT:
                 dest.putInt(OBJ, (Integer) mObj);
                 break;
-            case FORMAT_LONG:
+            case FORMAT_TIMESTAMP:
                 dest.putLong(OBJ, (Long) mObj);
                 break;
         }
@@ -368,7 +367,7 @@
                         new Slice(in.getBundle(OBJ_2)));
             case FORMAT_INT:
                 return in.getInt(OBJ);
-            case FORMAT_LONG:
+            case FORMAT_TIMESTAMP:
                 return in.getLong(OBJ);
         }
         throw new RuntimeException("Unsupported type " + type);
@@ -390,8 +389,8 @@
                 return "Action";
             case FORMAT_INT:
                 return "Int";
-            case FORMAT_LONG:
-                return "Long";
+            case FORMAT_TIMESTAMP:
+                return "Timestamp";
             case FORMAT_REMOTE_INPUT:
                 return "RemoteInput";
         }
@@ -413,35 +412,36 @@
     @RestrictTo(Scope.LIBRARY)
     public String toString(String indent) {
         StringBuilder sb = new StringBuilder();
+        if (!FORMAT_SLICE.equals(getFormat())) {
+            sb.append(indent);
+            sb.append(getFormat());
+            sb.append(": ");
+        }
         switch (getFormat()) {
             case FORMAT_SLICE:
                 sb.append(getSlice().toString(indent));
                 break;
             case FORMAT_ACTION:
-                sb.append(indent).append(getAction()).append(",\n");
+                sb.append(getAction());
+                sb.append("\n");
                 sb.append(getSlice().toString(indent));
                 break;
             case FORMAT_TEXT:
-                sb.append(indent).append('"').append(getText()).append('"');
+                sb.append(getText());
                 break;
             case FORMAT_IMAGE:
-                sb.append(indent).append(getIcon());
+                sb.append(getIcon());
                 break;
             case FORMAT_INT:
-                sb.append(indent).append(getInt());
+                sb.append(getInt());
                 break;
-            case FORMAT_LONG:
-                sb.append(indent).append(getLong());
+            case FORMAT_TIMESTAMP:
+                sb.append(getTimestamp());
                 break;
             default:
-                sb.append(indent).append(SliceItem.typeToString(getFormat()));
+                sb.append(SliceItem.typeToString(getFormat()));
                 break;
         }
-        if (!FORMAT_SLICE.equals(getFormat())) {
-            sb.append(' ');
-            addHints(sb, mHints);
-        }
-        sb.append(",\n");
         return sb.toString();
     }
 }
diff --git a/slices/core/src/main/java/androidx/slice/SliceProvider.java b/slices/core/src/main/java/androidx/slice/SliceProvider.java
index 9c604eb..7ec9232 100644
--- a/slices/core/src/main/java/androidx/slice/SliceProvider.java
+++ b/slices/core/src/main/java/androidx/slice/SliceProvider.java
@@ -20,9 +20,20 @@
 import static android.app.slice.SliceProvider.SLICE_TYPE;
 
 import static androidx.slice.compat.SliceProviderCompat.EXTRA_BIND_URI;
+import static androidx.slice.compat.SliceProviderCompat.EXTRA_INTENT;
 import static androidx.slice.compat.SliceProviderCompat.EXTRA_PKG;
 import static androidx.slice.compat.SliceProviderCompat.EXTRA_PROVIDER_PKG;
-import static androidx.slice.compat.SliceProviderCompat.PERMS_PREFIX;
+import static androidx.slice.compat.SliceProviderCompat.EXTRA_SLICE;
+import static androidx.slice.compat.SliceProviderCompat.EXTRA_SLICE_DESCENDANTS;
+import static androidx.slice.compat.SliceProviderCompat.METHOD_GET_DESCENDANTS;
+import static androidx.slice.compat.SliceProviderCompat.METHOD_GET_PINNED_SPECS;
+import static androidx.slice.compat.SliceProviderCompat.METHOD_MAP_INTENT;
+import static androidx.slice.compat.SliceProviderCompat.METHOD_MAP_ONLY_INTENT;
+import static androidx.slice.compat.SliceProviderCompat.METHOD_PIN;
+import static androidx.slice.compat.SliceProviderCompat.METHOD_SLICE;
+import static androidx.slice.compat.SliceProviderCompat.METHOD_UNPIN;
+import static androidx.slice.compat.SliceProviderCompat.addSpecs;
+import static androidx.slice.compat.SliceProviderCompat.getSpecs;
 import static androidx.slice.core.SliceHints.HINT_PERMISSION_REQUEST;
 
 import android.app.PendingIntent;
@@ -37,23 +48,26 @@
 import android.database.ContentObserver;
 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.Process;
+import android.os.StrictMode;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
-import androidx.annotation.VisibleForTesting;
 import androidx.core.app.CoreComponentFactory;
 import androidx.core.os.BuildCompat;
-import androidx.slice.compat.CompatPermissionManager;
-import androidx.slice.compat.SliceProviderCompat;
+import androidx.slice.compat.CompatPinnedList;
 import androidx.slice.compat.SliceProviderWrapperContainer;
 import androidx.slice.core.R;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Set;
@@ -104,31 +118,14 @@
 
     private static final String TAG = "SliceProvider";
 
+    private static final String DATA_PREFIX = "slice_data_";
+    private static final long SLICE_BIND_ANR = 2000;
+
     private static final boolean DEBUG = false;
-    private final String[] mAutoGrantPermissions;
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private CompatPinnedList mPinnedList;
 
-    private SliceProviderCompat mCompat;
-
-
-    /**
-     * A version of constructing a SliceProvider that allows autogranting slice permissions
-     * to apps that hold specific platform permissions.
-     * <p>
-     * When an app tries to bind a slice from this provider that it does not have access to,
-     * This provider will check if the caller holds permissions to any of the autoGrantPermissions
-     * specified, if they do they will be granted persisted uri access to all slices of this
-     * provider.
-     *
-     * @param autoGrantPermissions List of permissions that holders are auto-granted access
-     *                             to slices.
-     */
-    public SliceProvider(@NonNull String... autoGrantPermissions) {
-        mAutoGrantPermissions = autoGrantPermissions;
-    }
-
-    public SliceProvider() {
-        mAutoGrantPermissions = new String[0];
-    }
+    private String mCallback;
 
     /**
      * Implement this to initialize your slice provider on startup.
@@ -150,33 +147,18 @@
     @Override
     public Object getWrapper() {
         if (BuildCompat.isAtLeastP()) {
-            return new SliceProviderWrapperContainer.SliceProviderWrapper(this,
-                    mAutoGrantPermissions);
+            return new SliceProviderWrapperContainer.SliceProviderWrapper(this);
         }
         return null;
     }
 
     @Override
     public final boolean onCreate() {
-        if (!BuildCompat.isAtLeastP()) {
-            mCompat = new SliceProviderCompat(this,
-                    onCreatePermissionManager(mAutoGrantPermissions), getContext());
-        }
+        mPinnedList = new CompatPinnedList(getContext(),
+                DATA_PREFIX + getClass().getName());
         return onCreateSliceProvider();
     }
 
-    /**
-     * @hide
-     * @param autoGrantPermissions
-     */
-    @VisibleForTesting
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    protected CompatPermissionManager onCreatePermissionManager(
-            String[] autoGrantPermissions) {
-        return new CompatPermissionManager(getContext(), PERMS_PREFIX + getClass().getName(),
-                Process.myUid(), autoGrantPermissions);
-    }
-
     @Override
     public final String getType(Uri uri) {
         if (DEBUG) Log.d(TAG, "getFormat " + uri);
@@ -185,7 +167,115 @@
 
     @Override
     public Bundle call(String method, String arg, Bundle extras) {
-        return mCompat != null ? mCompat.call(method, arg, extras) : null;
+        if (method.equals(METHOD_SLICE)) {
+            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
+            if (Binder.getCallingUid() != Process.myUid()) {
+                getContext().enforceUriPermission(uri, Binder.getCallingPid(),
+                        Binder.getCallingUid(),
+                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+                        "Slice binding requires write access to the uri");
+            }
+            Set<SliceSpec> specs = getSpecs(extras);
+
+            Slice s = handleBindSlice(uri, specs, getCallingPackage());
+            Bundle b = new Bundle();
+            b.putParcelable(EXTRA_SLICE, s.toBundle());
+            return b;
+        } else if (method.equals(METHOD_MAP_INTENT)) {
+            Intent intent = extras.getParcelable(EXTRA_INTENT);
+            Uri uri = onMapIntentToUri(intent);
+            Bundle b = new Bundle();
+            if (uri != null) {
+                Set<SliceSpec> specs = getSpecs(extras);
+                Slice s = handleBindSlice(uri, specs, getCallingPackage());
+                b.putParcelable(EXTRA_SLICE, s.toBundle());
+            } else {
+                b.putParcelable(EXTRA_SLICE, null);
+            }
+            return b;
+        } else if (method.equals(METHOD_MAP_ONLY_INTENT)) {
+            Intent intent = extras.getParcelable(EXTRA_INTENT);
+            Uri uri = onMapIntentToUri(intent);
+            Bundle b = new Bundle();
+            b.putParcelable(EXTRA_SLICE, uri);
+            return b;
+        } else if (method.equals(METHOD_PIN)) {
+            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
+            Set<SliceSpec> specs = getSpecs(extras);
+            String pkg = extras.getString(EXTRA_PKG);
+            if (mPinnedList.addPin(uri, pkg, specs)) {
+                handleSlicePinned(uri);
+            }
+            return null;
+        } else if (method.equals(METHOD_UNPIN)) {
+            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
+            String pkg = extras.getString(EXTRA_PKG);
+            if (mPinnedList.removePin(uri, pkg)) {
+                handleSliceUnpinned(uri);
+            }
+            return null;
+        } else if (method.equals(METHOD_GET_PINNED_SPECS)) {
+            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
+            Bundle b = new Bundle();
+            addSpecs(b, mPinnedList.getSpecs(uri));
+            return b;
+        } else if (method.equals(METHOD_GET_DESCENDANTS)) {
+            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
+            Bundle b = new Bundle();
+            b.putParcelableArrayList(EXTRA_SLICE_DESCENDANTS,
+                    new ArrayList<>(handleGetDescendants(uri)));
+            return b;
+        }
+        return super.call(method, arg, extras);
+    }
+
+    private Collection<Uri> handleGetDescendants(Uri uri) {
+        mCallback = "onGetSliceDescendants";
+        mHandler.postDelayed(mAnr, SLICE_BIND_ANR);
+        try {
+            return onGetSliceDescendants(uri);
+        } finally {
+            mHandler.removeCallbacks(mAnr);
+        }
+    }
+
+    private void handleSlicePinned(final Uri sliceUri) {
+        mCallback = "onSlicePinned";
+        mHandler.postDelayed(mAnr, SLICE_BIND_ANR);
+        try {
+            onSlicePinned(sliceUri);
+        } finally {
+            mHandler.removeCallbacks(mAnr);
+        }
+    }
+
+    private void handleSliceUnpinned(final Uri sliceUri) {
+        mCallback = "onSliceUnpinned";
+        mHandler.postDelayed(mAnr, SLICE_BIND_ANR);
+        try {
+            onSliceUnpinned(sliceUri);
+        } finally {
+            mHandler.removeCallbacks(mAnr);
+        }
+    }
+
+    private Slice handleBindSlice(final Uri sliceUri, final Set<SliceSpec> specs,
+            final String callingPkg) {
+        // This can be removed once Slice#bindSlice is removed and everyone is using
+        // SliceManager#bindSlice.
+        String pkg = callingPkg != null ? callingPkg
+                : getContext().getPackageManager().getNameForUid(Binder.getCallingUid());
+        if (Binder.getCallingUid() != Process.myUid()) {
+            try {
+                getContext().enforceUriPermission(sliceUri,
+                        Binder.getCallingPid(), Binder.getCallingUid(),
+                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+                        "Slice binding requires write access to Uri");
+            } catch (SecurityException e) {
+                return createPermissionSlice(getContext(), sliceUri, pkg);
+            }
+        }
+        return onBindSliceStrict(sliceUri, specs);
     }
 
     /**
@@ -247,6 +337,35 @@
         }
     }
 
+    private Slice onBindSliceStrict(Uri sliceUri, Set<SliceSpec> specs) {
+        StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
+        mCallback = "onBindSlice";
+        mHandler.postDelayed(mAnr, SLICE_BIND_ANR);
+        try {
+            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+                    .detectAll()
+                    .penaltyDeath()
+                    .build());
+            SliceProvider.setSpecs(specs);
+            try {
+                return onBindSlice(sliceUri);
+            } finally {
+                SliceProvider.setSpecs(null);
+                mHandler.removeCallbacks(mAnr);
+            }
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+    }
+
+    private final Runnable mAnr = new Runnable() {
+        @Override
+        public void run() {
+            Process.sendSignal(Process.myPid(), Process.SIGNAL_QUIT);
+            Log.wtf(TAG, "Timed out while handling slice callback " + mCallback);
+        }
+    };
+
     /**
      * Implemented to create a slice.
      * <p>
diff --git a/slices/core/src/main/java/androidx/slice/compat/CompatPermissionManager.java b/slices/core/src/main/java/androidx/slice/compat/CompatPermissionManager.java
deleted file mode 100644
index 8321a05..0000000
--- a/slices/core/src/main/java/androidx/slice/compat/CompatPermissionManager.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.slice.compat;
-
-import static androidx.core.content.PermissionChecker.PERMISSION_DENIED;
-import static androidx.core.content.PermissionChecker.PERMISSION_GRANTED;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.net.Uri;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.RestrictTo;
-import androidx.collection.ArraySet;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * @hide
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-public class CompatPermissionManager {
-
-    private static final String TAG = "CompatPermissionManager";
-    public static final String ALL_SUFFIX = "_all";
-
-    private final Context mContext;
-    private final String mPrefsName;
-    private final int mMyUid;
-    private final String[] mAutoGrantPermissions;
-
-    public CompatPermissionManager(Context context, String prefsName, int myUid,
-            String[] autoGrantPermissions) {
-        mContext = context;
-        mPrefsName = prefsName;
-        mMyUid = myUid;
-        mAutoGrantPermissions = autoGrantPermissions;
-    }
-
-    private SharedPreferences getPrefs() {
-        return mContext.getSharedPreferences(mPrefsName, Context.MODE_PRIVATE);
-    }
-
-    public int checkSlicePermission(Uri uri, int pid, int uid) {
-        if (uid == mMyUid) {
-            return PERMISSION_GRANTED;
-        }
-        String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
-        for (String pkg : pkgs) {
-            if (checkSlicePermission(uri, pkg) == PERMISSION_GRANTED) {
-                return PERMISSION_GRANTED;
-            }
-        }
-        for (String autoGrantPermission : mAutoGrantPermissions) {
-            if (mContext.checkPermission(autoGrantPermission, pid, uid) == PERMISSION_GRANTED) {
-                for (String pkg : pkgs) {
-                    grantSlicePermission(uri, pkg);
-                }
-                return PERMISSION_GRANTED;
-            }
-        }
-        // Fall back to allowing uri permissions through.
-        return mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-    }
-
-    private int checkSlicePermission(Uri uri, String pkg) {
-        PermissionState state = getPermissionState(pkg, uri.getAuthority());
-        return state.hasAccess(uri.getPathSegments()) ? PERMISSION_GRANTED : PERMISSION_DENIED;
-    }
-
-    public void grantSlicePermission(Uri uri, String toPkg) {
-        PermissionState state = getPermissionState(toPkg, uri.getAuthority());
-        if (state.addPath(uri.getPathSegments())) {
-            persist(state);
-        }
-    }
-
-    public void revokeSlicePermission(Uri uri, String toPkg) {
-        PermissionState state = getPermissionState(toPkg, uri.getAuthority());
-        if (state.removePath(uri.getPathSegments())) {
-            persist(state);
-        }
-    }
-
-    private synchronized void persist(PermissionState state) {
-        if (!getPrefs().edit()
-                .putStringSet(state.getKey(), state.toPersistable())
-                .putBoolean(state.getKey() + ALL_SUFFIX, state.hasAllPermissions())
-                .commit()) {
-            Log.e(TAG, "Unable to persist permissions");
-        }
-    }
-
-    private PermissionState getPermissionState(String pkg, String authority) {
-        String key = pkg + "_" + authority;
-        Set<String> grant = getPrefs().getStringSet(key, Collections.<String>emptySet());
-        boolean hasAllPermissions = getPrefs().getBoolean(key + ALL_SUFFIX, false);
-        return new PermissionState(grant, key, hasAllPermissions);
-    }
-
-    public static class PermissionState {
-
-        private final ArraySet<String[]> mPaths = new ArraySet<>();
-        private final String mKey;
-
-        PermissionState(Set<String> grant, String key, boolean hasAllPermissions) {
-            if (hasAllPermissions) {
-                mPaths.add(new String[0]);
-            } else {
-                for (String g : grant) {
-                    mPaths.add(decodeSegments(g));
-                }
-            }
-            mKey = key;
-        }
-
-        public boolean hasAllPermissions() {
-            return hasAccess(Collections.<String>emptyList());
-        }
-
-        public String getKey() {
-            return mKey;
-        }
-
-        public Set<String> toPersistable() {
-            ArraySet<String> ret = new ArraySet<>();
-            for (String[] path : mPaths) {
-                ret.add(encodeSegments(path));
-            }
-            return ret;
-        }
-
-        public boolean hasAccess(List<String> path) {
-            String[] inPath = path.toArray(new String[path.size()]);
-            for (String[] p : mPaths) {
-                if (isPathPrefixMatch(p, inPath)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        boolean addPath(List<String> path) {
-            String[] pathSegs = path.toArray(new String[path.size()]);
-            for (int i = mPaths.size() - 1; i >= 0; i--) {
-                String[] existing = mPaths.valueAt(i);
-                if (isPathPrefixMatch(existing, pathSegs)) {
-                    // Nothing to add here.
-                    return false;
-                }
-                if (isPathPrefixMatch(pathSegs, existing)) {
-                    mPaths.removeAt(i);
-                }
-            }
-            mPaths.add(pathSegs);
-            return true;
-        }
-
-        boolean removePath(List<String> path) {
-            boolean changed = false;
-            String[] pathSegs = path.toArray(new String[path.size()]);
-            for (int i = mPaths.size() - 1; i >= 0; i--) {
-                String[] existing = mPaths.valueAt(i);
-                if (isPathPrefixMatch(pathSegs, existing)) {
-                    changed = true;
-                    mPaths.removeAt(i);
-                }
-            }
-            return changed;
-        }
-
-        private boolean isPathPrefixMatch(String[] prefix, String[] path) {
-            final int prefixSize = prefix.length;
-            if (path.length < prefixSize) return false;
-
-            for (int i = 0; i < prefixSize; i++) {
-                if (!Objects.equals(path[i], prefix[i])) {
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        private String encodeSegments(String[] s) {
-            String[] out = new String[s.length];
-            for (int i = 0; i < s.length; i++) {
-                out[i] = Uri.encode(s[i]);
-            }
-            return TextUtils.join("/", out);
-        }
-
-        private String[] decodeSegments(String s) {
-            String[] sets = s.split("/", -1);
-            for (int i = 0; i < sets.length; i++) {
-                sets[i] = Uri.decode(sets[i]);
-            }
-            return sets;
-        }
-    }
-}
diff --git a/slices/core/src/main/java/androidx/slice/compat/CompatPinnedList.java b/slices/core/src/main/java/androidx/slice/compat/CompatPinnedList.java
index da602f5..56b8122 100644
--- a/slices/core/src/main/java/androidx/slice/compat/CompatPinnedList.java
+++ b/slices/core/src/main/java/androidx/slice/compat/CompatPinnedList.java
@@ -28,8 +28,6 @@
 import androidx.core.util.ObjectsCompat;
 import androidx.slice.SliceSpec;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Set;
 
 /**
@@ -72,22 +70,6 @@
         return prefs;
     }
 
-    /**
-     * Get pinned specs
-     */
-    public List<Uri> getPinnedSlices() {
-        List<Uri> pinned = new ArrayList<>();
-        for (String key : getPrefs().getAll().keySet()) {
-            if (key.startsWith(PIN_PREFIX)) {
-                Uri uri = Uri.parse(key.substring(PIN_PREFIX.length()));
-                if (!getPins(uri).isEmpty()) {
-                    pinned.add(uri);
-                }
-            }
-        }
-        return pinned;
-    }
-
     private Set<String> getPins(Uri uri) {
         return getPrefs().getStringSet(PIN_PREFIX + uri.toString(), new ArraySet<String>());
     }
@@ -103,8 +85,8 @@
         if (TextUtils.isEmpty(specNamesStr) || TextUtils.isEmpty(specRevsStr)) {
             return new ArraySet<>();
         }
-        String[] specNames = specNamesStr.split(",", -1);
-        String[] specRevs = specRevsStr.split(",", -1);
+        String[] specNames = specNamesStr.split(",");
+        String[] specRevs = specRevsStr.split(",");
         if (specNames.length != specRevs.length) {
             return new ArraySet<>();
         }
diff --git a/slices/core/src/main/java/androidx/slice/compat/SlicePermissionActivity.java b/slices/core/src/main/java/androidx/slice/compat/SlicePermissionActivity.java
index 5fa33ae..f3270f8 100644
--- a/slices/core/src/main/java/androidx/slice/compat/SlicePermissionActivity.java
+++ b/slices/core/src/main/java/androidx/slice/compat/SlicePermissionActivity.java
@@ -20,20 +20,16 @@
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.content.DialogInterface.OnDismissListener;
-import android.content.pm.ApplicationInfo;
+import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.Uri;
 import android.os.Bundle;
-import android.text.Html;
-import android.text.TextPaint;
-import android.text.TextUtils;
 import android.util.Log;
 import android.widget.TextView;
 
 import androidx.annotation.RestrictTo;
 import androidx.appcompat.app.AlertDialog;
-import androidx.core.text.BidiFormatter;
 import androidx.slice.core.R;
 
 /**
@@ -44,8 +40,6 @@
 public class SlicePermissionActivity extends Activity implements OnClickListener,
         OnDismissListener {
 
-    private static final float MAX_LABEL_SIZE_PX = 500f;
-
     private static final String TAG = "SlicePermissionActivity";
 
     private Uri mUri;
@@ -62,12 +56,8 @@
 
         try {
             PackageManager pm = getPackageManager();
-            CharSequence app1 = BidiFormatter.getInstance().unicodeWrap(
-                    loadSafeLabel(pm, pm.getApplicationInfo(mCallingPkg, 0))
-                    .toString());
-            CharSequence app2 = BidiFormatter.getInstance().unicodeWrap(
-                    loadSafeLabel(pm, pm.getApplicationInfo(mProviderPkg, 0))
-                    .toString());
+            CharSequence app1 = pm.getApplicationInfo(mCallingPkg, 0).loadLabel(pm);
+            CharSequence app2 = pm.getApplicationInfo(mProviderPkg, 0).loadLabel(pm);
             AlertDialog dialog = new AlertDialog.Builder(this)
                     .setTitle(getString(R.string.abc_slice_permission_title, app1, app2))
                     .setView(R.layout.abc_slice_permission_request)
@@ -85,50 +75,14 @@
         }
     }
 
-    // Based on loadSafeLabel in PackageitemInfo
-    private CharSequence loadSafeLabel(PackageManager pm, ApplicationInfo appInfo) {
-        // loadLabel() always returns non-null
-        String label = appInfo.loadLabel(pm).toString();
-        // strip HTML tags to avoid <br> and other tags overwriting original message
-        String labelStr = Html.fromHtml(label).toString();
-
-        // If the label contains new line characters it may push the UI
-        // down to hide a part of it. Labels shouldn't have new line
-        // characters, so just truncate at the first time one is seen.
-        final int labelLength = labelStr.length();
-        int offset = 0;
-        while (offset < labelLength) {
-            final int codePoint = labelStr.codePointAt(offset);
-            final int type = Character.getType(codePoint);
-            if (type == Character.LINE_SEPARATOR
-                    || type == Character.CONTROL
-                    || type == Character.PARAGRAPH_SEPARATOR) {
-                labelStr = labelStr.substring(0, offset);
-                break;
-            }
-            // replace all non-break space to " " in order to be trimmed
-            if (type == Character.SPACE_SEPARATOR) {
-                labelStr = labelStr.substring(0, offset) + " " + labelStr.substring(offset
-                        + Character.charCount(codePoint));
-            }
-            offset += Character.charCount(codePoint);
-        }
-
-        labelStr = labelStr.trim();
-        if (labelStr.isEmpty()) {
-            return appInfo.packageName;
-        }
-        TextPaint paint = new TextPaint();
-        paint.setTextSize(42);
-
-        return TextUtils.ellipsize(labelStr, paint, MAX_LABEL_SIZE_PX, TextUtils.TruncateAt.END);
-    }
-
     @Override
     public void onClick(DialogInterface dialog, int which) {
         if (which == DialogInterface.BUTTON_POSITIVE) {
-            SliceProviderCompat.grantSlicePermission(this, getPackageName(), mCallingPkg,
-                    mUri.buildUpon().path("").build());
+            grantUriPermission(mCallingPkg, mUri.buildUpon().path("").build(),
+                    Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                            | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
+            getContentResolver().notifyChange(mUri, null);
         }
         finish();
     }
diff --git a/slices/core/src/main/java/androidx/slice/compat/SliceProviderCompat.java b/slices/core/src/main/java/androidx/slice/compat/SliceProviderCompat.java
index 22e832e..61bc65e 100644
--- a/slices/core/src/main/java/androidx/slice/compat/SliceProviderCompat.java
+++ b/slices/core/src/main/java/androidx/slice/compat/SliceProviderCompat.java
@@ -15,30 +15,19 @@
  */
 package androidx.slice.compat;
 
-import static android.app.slice.SliceManager.CATEGORY_SLICE;
-import static android.app.slice.SliceManager.SLICE_METADATA_KEY;
 import static android.app.slice.SliceProvider.SLICE_TYPE;
 
-import static androidx.core.content.PermissionChecker.PERMISSION_DENIED;
-import static androidx.core.content.PermissionChecker.PERMISSION_GRANTED;
-
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
-import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
-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.util.Log;
 
 import androidx.annotation.NonNull;
@@ -47,8 +36,8 @@
 import androidx.collection.ArraySet;
 import androidx.core.util.Preconditions;
 import androidx.slice.Slice;
-import androidx.slice.SliceProvider;
 import androidx.slice.SliceSpec;
+import androidx.slice.core.SliceHints;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -61,13 +50,9 @@
  */
 @RestrictTo(Scope.LIBRARY)
 public class SliceProviderCompat {
-    public static final String PERMS_PREFIX = "slice_perms_";
     private static final String TAG = "SliceProviderCompat";
-    private static final String DATA_PREFIX = "slice_data_";
-    private static final String ALL_FILES = DATA_PREFIX + "all_slice_files";
 
-    private static final long SLICE_BIND_ANR = 2000;
-
+    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 METHOD_PIN = "pin_slice";
@@ -75,11 +60,7 @@
     public static final String METHOD_GET_PINNED_SPECS = "get_specs";
     public static final String METHOD_MAP_ONLY_INTENT = "map_only";
     public static final String METHOD_GET_DESCENDANTS = "get_descendants";
-    public static final String METHOD_CHECK_PERMISSION = "check_perms";
-    public static final String METHOD_GRANT_PERMISSION = "grant_perms";
-    public static final String METHOD_REVOKE_PERMISSION = "revoke_perms";
 
-    public static final String EXTRA_BIND_URI = "slice_uri";
     public static final String EXTRA_INTENT = "slice_intent";
     public static final String EXTRA_SLICE = "slice";
     public static final String EXTRA_SUPPORTED_SPECS = "specs";
@@ -87,213 +68,22 @@
     public static final String EXTRA_PKG = "pkg";
     public static final String EXTRA_PROVIDER_PKG = "provider_pkg";
     public static final String EXTRA_SLICE_DESCENDANTS = "slice_descendants";
-    public static final String EXTRA_UID = "uid";
-    public static final String EXTRA_PID = "pid";
-    public static final String EXTRA_RESULT = "result";
-
-    private final Handler mHandler = new Handler(Looper.getMainLooper());
-    private final Context mContext;
-
-    private String mCallback;
-    private final SliceProvider mProvider;
-    private CompatPinnedList mPinnedList;
-    private CompatPermissionManager mPermissionManager;
-
-    public SliceProviderCompat(SliceProvider provider, CompatPermissionManager permissionManager,
-            Context context) {
-        mProvider = provider;
-        mContext = context;
-        String prefsFile = DATA_PREFIX + getClass().getName();
-        SharedPreferences allFiles = mContext.getSharedPreferences(ALL_FILES, 0);
-        Set<String> files = allFiles.getStringSet(ALL_FILES, Collections.<String>emptySet());
-        if (!files.contains(prefsFile)) {
-            // Make sure this is editable.
-            files = new ArraySet<>(files);
-            files.add(prefsFile);
-            allFiles.edit()
-                    .putStringSet(ALL_FILES, files)
-                    .commit();
-        }
-        mPinnedList = new CompatPinnedList(mContext, prefsFile);
-        mPermissionManager = permissionManager;
-    }
-
-    private Context getContext() {
-        return mContext;
-    }
-
-    public String getCallingPackage() {
-        return mProvider.getCallingPackage();
-    }
-
-    /**
-     * Called by SliceProvider when compat is needed.
-     */
-    public Bundle call(String method, String arg, Bundle extras) {
-        if (method.equals(METHOD_SLICE)) {
-            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
-            Set<SliceSpec> specs = getSpecs(extras);
-
-            Slice s = handleBindSlice(uri, specs, getCallingPackage());
-            Bundle b = new Bundle();
-            b.putParcelable(EXTRA_SLICE, s != null ? s.toBundle() : null);
-            return b;
-        } else if (method.equals(METHOD_MAP_INTENT)) {
-            Intent intent = extras.getParcelable(EXTRA_INTENT);
-            Uri uri = mProvider.onMapIntentToUri(intent);
-            Bundle b = new Bundle();
-            if (uri != null) {
-                Set<SliceSpec> specs = getSpecs(extras);
-                Slice s = handleBindSlice(uri, specs, getCallingPackage());
-                b.putParcelable(EXTRA_SLICE, s != null ? s.toBundle() : null);
-            } else {
-                b.putParcelable(EXTRA_SLICE, null);
-            }
-            return b;
-        } else if (method.equals(METHOD_MAP_ONLY_INTENT)) {
-            Intent intent = extras.getParcelable(EXTRA_INTENT);
-            Uri uri = mProvider.onMapIntentToUri(intent);
-            Bundle b = new Bundle();
-            b.putParcelable(EXTRA_SLICE, uri);
-            return b;
-        } else if (method.equals(METHOD_PIN)) {
-            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
-            Set<SliceSpec> specs = getSpecs(extras);
-            String pkg = extras.getString(EXTRA_PKG);
-            if (mPinnedList.addPin(uri, pkg, specs)) {
-                handleSlicePinned(uri);
-            }
-            return null;
-        } else if (method.equals(METHOD_UNPIN)) {
-            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
-            String pkg = extras.getString(EXTRA_PKG);
-            if (mPinnedList.removePin(uri, pkg)) {
-                handleSliceUnpinned(uri);
-            }
-            return null;
-        } else if (method.equals(METHOD_GET_PINNED_SPECS)) {
-            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
-            Bundle b = new Bundle();
-            addSpecs(b, mPinnedList.getSpecs(uri));
-            return b;
-        } else if (method.equals(METHOD_GET_DESCENDANTS)) {
-            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
-            Bundle b = new Bundle();
-            b.putParcelableArrayList(EXTRA_SLICE_DESCENDANTS,
-                    new ArrayList<>(handleGetDescendants(uri)));
-            return b;
-        } else if (method.equals(METHOD_CHECK_PERMISSION)) {
-            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
-            String pkg = extras.getString(EXTRA_PKG);
-            int pid = extras.getInt(EXTRA_PID);
-            int uid = extras.getInt(EXTRA_UID);
-            Bundle b = new Bundle();
-            b.putInt(EXTRA_RESULT, mPermissionManager.checkSlicePermission(uri, pid, uid));
-            return b;
-        } else if (method.equals(METHOD_GRANT_PERMISSION)) {
-            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
-            String toPkg = extras.getString(EXTRA_PKG);
-            if (Binder.getCallingUid() != Process.myUid()) {
-                throw new SecurityException("Only the owning process can manage slice permissions");
-            }
-            mPermissionManager.grantSlicePermission(uri, toPkg);
-        } else if (method.equals(METHOD_REVOKE_PERMISSION)) {
-            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
-            String toPkg = extras.getString(EXTRA_PKG);
-            if (Binder.getCallingUid() != Process.myUid()) {
-                throw new SecurityException("Only the owning process can manage slice permissions");
-            }
-            mPermissionManager.revokeSlicePermission(uri, toPkg);
-        }
-        return null;
-    }
-
-    private Collection<Uri> handleGetDescendants(Uri uri) {
-        mCallback = "onGetSliceDescendants";
-        mHandler.postDelayed(mAnr, SLICE_BIND_ANR);
-        try {
-            return mProvider.onGetSliceDescendants(uri);
-        } finally {
-            mHandler.removeCallbacks(mAnr);
-        }
-    }
-
-    private void handleSlicePinned(final Uri sliceUri) {
-        mCallback = "onSlicePinned";
-        mHandler.postDelayed(mAnr, SLICE_BIND_ANR);
-        try {
-            mProvider.onSlicePinned(sliceUri);
-        } finally {
-            mHandler.removeCallbacks(mAnr);
-        }
-    }
-
-    private void handleSliceUnpinned(final Uri sliceUri) {
-        mCallback = "onSliceUnpinned";
-        mHandler.postDelayed(mAnr, SLICE_BIND_ANR);
-        try {
-            mProvider.onSliceUnpinned(sliceUri);
-        } finally {
-            mHandler.removeCallbacks(mAnr);
-        }
-    }
-
-    private Slice handleBindSlice(final Uri sliceUri, final Set<SliceSpec> specs,
-            final String callingPkg) {
-        // This can be removed once Slice#bindSlice is removed and everyone is using
-        // SliceManager#bindSlice.
-        String pkg = callingPkg != null ? callingPkg
-                : getContext().getPackageManager().getNameForUid(Binder.getCallingUid());
-        if (mPermissionManager.checkSlicePermission(sliceUri, Binder.getCallingPid(),
-                Binder.getCallingUid()) != PERMISSION_GRANTED) {
-            return mProvider.createPermissionSlice(getContext(), sliceUri, pkg);
-        }
-        return onBindSliceStrict(sliceUri, specs);
-    }
-
-    private Slice onBindSliceStrict(Uri sliceUri, Set<SliceSpec> specs) {
-        StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
-        mCallback = "onBindSlice";
-        mHandler.postDelayed(mAnr, SLICE_BIND_ANR);
-        try {
-            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
-                    .detectAll()
-                    .penaltyDeath()
-                    .build());
-            SliceProvider.setSpecs(specs);
-            try {
-                return mProvider.onBindSlice(sliceUri);
-            } finally {
-                SliceProvider.setSpecs(null);
-                mHandler.removeCallbacks(mAnr);
-            }
-        } finally {
-            StrictMode.setThreadPolicy(oldPolicy);
-        }
-    }
-
-    private final Runnable mAnr = new Runnable() {
-        @Override
-        public void run() {
-            Process.sendSignal(Process.myPid(), Process.SIGNAL_QUIT);
-            Log.wtf(TAG, "Timed out while handling slice callback " + mCallback);
-        }
-    };
 
     /**
      * Compat version of {@link Slice#bindSlice}.
      */
     public static Slice bindSlice(Context context, Uri uri,
             Set<SliceSpec> supportedSpecs) {
-        ProviderHolder holder = acquireClient(context.getContentResolver(), uri);
-        if (holder.mProvider == null) {
+        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);
             addSpecs(extras, supportedSpecs);
-            final Bundle res = holder.mProvider.call(METHOD_SLICE, null, extras);
+            final Bundle res = provider.call(METHOD_SLICE, null, extras);
             if (res == null) {
                 return null;
             }
@@ -303,9 +93,15 @@
             }
             return new Slice((Bundle) bundle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to bind slice", e);
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return null;
         } finally {
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                provider.close();
+            } else {
+                provider.release();
+            }
         }
     }
 
@@ -341,10 +137,6 @@
      */
     public static Slice bindSlice(Context context, Intent intent,
             Set<SliceSpec> supportedSpecs) {
-        Preconditions.checkNotNull(intent, "intent");
-        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null
-                || intent.getData() != null,
-                String.format("Slice intent must be explicit %s", intent));
         ContentResolver resolver = context.getContentResolver();
 
         // Check if the intent has data for the slice uri on it and use that
@@ -353,37 +145,23 @@
             return bindSlice(context, intentData, supportedSpecs);
         }
         // Otherwise ask the app
-        Intent queryIntent = new Intent(intent);
-        if (!queryIntent.hasCategory(CATEGORY_SLICE)) {
-            queryIntent.addCategory(CATEGORY_SLICE);
-        }
         List<ResolveInfo> providers =
-                context.getPackageManager().queryIntentContentProviders(queryIntent, 0);
-        if (providers == null || providers.isEmpty()) {
-            // There are no providers, see if this activity has a direct link.
-            ResolveInfo resolve = context.getPackageManager().resolveActivity(intent,
-                    PackageManager.GET_META_DATA);
-            if (resolve != null && resolve.activityInfo != null
-                    && resolve.activityInfo.metaData != null
-                    && resolve.activityInfo.metaData.containsKey(SLICE_METADATA_KEY)) {
-                return bindSlice(context, Uri.parse(
-                        resolve.activityInfo.metaData.getString(SLICE_METADATA_KEY)),
-                        supportedSpecs);
-            }
-            return null;
+                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();
-        ProviderHolder holder = acquireClient(resolver, uri);
-        if (holder.mProvider == null) {
+        ContentProviderClient provider = resolver.acquireContentProviderClient(uri);
+        if (provider == null) {
             throw new IllegalArgumentException("Unknown URI " + uri);
         }
         try {
             Bundle extras = new Bundle();
             extras.putParcelable(EXTRA_INTENT, intent);
             addSpecs(extras, supportedSpecs);
-            final Bundle res = holder.mProvider.call(METHOD_MAP_INTENT, null, extras);
+            final Bundle res = provider.call(METHOD_MAP_INTENT, null, extras);
             if (res == null) {
                 return null;
             }
@@ -393,8 +171,11 @@
             }
             return new Slice((Bundle) bundle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to bind slice", e);
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return null;
+        } finally {
+            provider.close();
         }
     }
 
@@ -403,8 +184,9 @@
      */
     public static void pinSlice(Context context, Uri uri,
             Set<SliceSpec> supportedSpecs) {
-        ProviderHolder holder = acquireClient(context.getContentResolver(), uri);
-        if (holder.mProvider == null) {
+        ContentProviderClient provider = context.getContentResolver()
+                .acquireContentProviderClient(uri);
+        if (provider == null) {
             throw new IllegalArgumentException("Unknown URI " + uri);
         }
         try {
@@ -412,9 +194,12 @@
             extras.putParcelable(EXTRA_BIND_URI, uri);
             extras.putString(EXTRA_PKG, context.getPackageName());
             addSpecs(extras, supportedSpecs);
-            holder.mProvider.call(METHOD_PIN, null, extras);
+            provider.call(METHOD_PIN, null, extras);
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to pin slice", e);
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+        } finally {
+            provider.close();
         }
     }
 
@@ -423,8 +208,9 @@
      */
     public static void unpinSlice(Context context, Uri uri,
             Set<SliceSpec> supportedSpecs) {
-        ProviderHolder holder = acquireClient(context.getContentResolver(), uri);
-        if (holder.mProvider == null) {
+        ContentProviderClient provider = context.getContentResolver()
+                .acquireContentProviderClient(uri);
+        if (provider == null) {
             throw new IllegalArgumentException("Unknown URI " + uri);
         }
         try {
@@ -432,9 +218,12 @@
             extras.putParcelable(EXTRA_BIND_URI, uri);
             extras.putString(EXTRA_PKG, context.getPackageName());
             addSpecs(extras, supportedSpecs);
-            holder.mProvider.call(METHOD_UNPIN, null, extras);
+            provider.call(METHOD_UNPIN, null, extras);
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to unpin slice", e);
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+        } finally {
+            provider.close();
         }
     }
 
@@ -442,21 +231,26 @@
      * Compat version of {@link android.app.slice.SliceManager#getPinnedSpecs(Uri)}.
      */
     public static Set<SliceSpec> getPinnedSpecs(Context context, Uri uri) {
-        ProviderHolder holder = acquireClient(context.getContentResolver(), uri);
-        if (holder.mProvider == null) {
+        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 = holder.mProvider.call(METHOD_GET_PINNED_SPECS, null, extras);
-            if (res != null) {
-                return getSpecs(res);
+            final Bundle res = provider.call(METHOD_GET_PINNED_SPECS, null, extras);
+            if (res == null) {
+                return null;
             }
+            return getSpecs(res);
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to get pinned specs", e);
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+            return null;
+        } finally {
+            provider.close();
         }
-        return null;
     }
 
     /**
@@ -464,8 +258,7 @@
      */
     public static Uri mapIntentToUri(Context context, Intent intent) {
         Preconditions.checkNotNull(intent, "intent");
-        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null
-                || intent.getData() != null,
+        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null,
                 String.format("Slice intent must be explicit %s", intent));
         ContentResolver resolver = context.getContentResolver();
 
@@ -475,41 +268,39 @@
             return intentData;
         }
         // Otherwise ask the app
-        Intent queryIntent = new Intent(intent);
-        if (!queryIntent.hasCategory(CATEGORY_SLICE)) {
-            queryIntent.addCategory(CATEGORY_SLICE);
-        }
         List<ResolveInfo> providers =
-                context.getPackageManager().queryIntentContentProviders(queryIntent, 0);
+                context.getPackageManager().queryIntentContentProviders(intent, 0);
         if (providers == null || providers.isEmpty()) {
             // There are no providers, see if this activity has a direct link.
             ResolveInfo resolve = context.getPackageManager().resolveActivity(intent,
                     PackageManager.GET_META_DATA);
             if (resolve != null && resolve.activityInfo != null
                     && resolve.activityInfo.metaData != null
-                    && resolve.activityInfo.metaData.containsKey(SLICE_METADATA_KEY)) {
+                    && resolve.activityInfo.metaData.containsKey(SliceHints.SLICE_METADATA_KEY)) {
                 return Uri.parse(
-                        resolve.activityInfo.metaData.getString(SLICE_METADATA_KEY));
+                        resolve.activityInfo.metaData.getString(SliceHints.SLICE_METADATA_KEY));
             }
             return null;
         }
         String authority = providers.get(0).providerInfo.authority;
         Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
                 .authority(authority).build();
-        try (ProviderHolder holder = acquireClient(resolver, uri)) {
-            if (holder.mProvider == null) {
+        try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) {
+            if (provider == null) {
                 throw new IllegalArgumentException("Unknown URI " + uri);
             }
             Bundle extras = new Bundle();
             extras.putParcelable(EXTRA_INTENT, intent);
-            final Bundle res = holder.mProvider.call(METHOD_MAP_ONLY_INTENT, null, extras);
-            if (res != null) {
-                return res.getParcelable(EXTRA_SLICE);
+            final Bundle res = provider.call(METHOD_MAP_ONLY_INTENT, null, extras);
+            if (res == null) {
+                return null;
             }
+            return res.getParcelable(EXTRA_SLICE);
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to map slice", e);
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+            return null;
         }
-        return null;
     }
 
     /**
@@ -517,114 +308,17 @@
      */
     public static @NonNull Collection<Uri> getSliceDescendants(Context context, @NonNull Uri uri) {
         ContentResolver resolver = context.getContentResolver();
-        try (ProviderHolder holder = acquireClient(resolver, uri)) {
+        try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) {
             Bundle extras = new Bundle();
             extras.putParcelable(EXTRA_BIND_URI, uri);
-            final Bundle res = holder.mProvider.call(METHOD_GET_DESCENDANTS, null, extras);
-            if (res != null) {
-                return res.getParcelableArrayList(EXTRA_SLICE_DESCENDANTS);
-            }
+            final Bundle res = provider.call(METHOD_GET_DESCENDANTS, null, extras);
+            return res.getParcelableArrayList(EXTRA_SLICE_DESCENDANTS);
         } catch (RemoteException e) {
             Log.e(TAG, "Unable to get slice descendants", e);
         }
         return Collections.emptyList();
     }
 
-    /**
-     * Compat version of {@link android.app.slice.SliceManager#checkSlicePermission}.
-     */
-    public static int checkSlicePermission(Context context, String packageName, Uri uri, int pid,
-            int uid) {
-        ContentResolver resolver = context.getContentResolver();
-        try (ProviderHolder holder = acquireClient(resolver, uri)) {
-            Bundle extras = new Bundle();
-            extras.putParcelable(EXTRA_BIND_URI, uri);
-            extras.putString(EXTRA_PKG, packageName);
-            extras.putInt(EXTRA_PID, pid);
-            extras.putInt(EXTRA_UID, uid);
-
-            final Bundle res = holder.mProvider.call(METHOD_CHECK_PERMISSION, null, extras);
-            if (res != null) {
-                return res.getInt(EXTRA_RESULT);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Unable to check slice permission", e);
-        }
-        return PERMISSION_DENIED;
-    }
-
-    /**
-     * Compat version of {@link android.app.slice.SliceManager#grantSlicePermission}.
-     */
-    public static void grantSlicePermission(Context context, String packageName, String toPackage,
-            Uri uri) {
-        ContentResolver resolver = context.getContentResolver();
-        try (ProviderHolder holder = acquireClient(resolver, uri)) {
-            Bundle extras = new Bundle();
-            extras.putParcelable(EXTRA_BIND_URI, uri);
-            extras.putString(EXTRA_PROVIDER_PKG, packageName);
-            extras.putString(EXTRA_PKG, toPackage);
-
-            holder.mProvider.call(METHOD_GRANT_PERMISSION, null, extras);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Unable to get slice descendants", e);
-        }
-    }
-
-    /**
-     * Compat version of {@link android.app.slice.SliceManager#revokeSlicePermission}.
-     */
-    public static void revokeSlicePermission(Context context, String packageName, String toPackage,
-            Uri uri) {
-        ContentResolver resolver = context.getContentResolver();
-        try (ProviderHolder holder = acquireClient(resolver, uri)) {
-            Bundle extras = new Bundle();
-            extras.putParcelable(EXTRA_BIND_URI, uri);
-            extras.putString(EXTRA_PROVIDER_PKG, packageName);
-            extras.putString(EXTRA_PKG, toPackage);
-
-            holder.mProvider.call(METHOD_REVOKE_PERMISSION, null, extras);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Unable to get slice descendants", e);
-        }
-    }
-
-    /**
-     * Compat version of {@link android.app.slice.SliceManager#getPinnedSlices}.
-     */
-    public static List<Uri> getPinnedSlices(Context context) {
-        ArrayList<Uri> pinnedSlices = new ArrayList<>();
-        SharedPreferences prefs = context.getSharedPreferences(ALL_FILES, 0);
-        Set<String> prefSet = prefs.getStringSet(ALL_FILES, Collections.<String>emptySet());
-        for (String pref : prefSet) {
-            pinnedSlices.addAll(new CompatPinnedList(context, pref).getPinnedSlices());
-        }
-        return pinnedSlices;
-    }
-
-    private static ProviderHolder acquireClient(ContentResolver resolver, Uri uri) {
-        ContentProviderClient provider = resolver.acquireContentProviderClient(uri);
-        if (provider == null) {
-            throw new IllegalArgumentException("No provider found for " + uri);
-        }
-        return new ProviderHolder(provider);
-    }
-
-    private static class ProviderHolder implements AutoCloseable {
-        private final ContentProviderClient mProvider;
-
-        ProviderHolder(ContentProviderClient provider) {
-            this.mProvider = provider;
-        }
-
-        @Override
-        public void close() {
-            if (mProvider == null) return;
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                mProvider.close();
-            } else {
-                mProvider.release();
-            }
-        }
+    private SliceProviderCompat() {
     }
 }
diff --git a/slices/core/src/main/java/androidx/slice/compat/SliceProviderWrapperContainer.java b/slices/core/src/main/java/androidx/slice/compat/SliceProviderWrapperContainer.java
index c04c2fd..8641530 100644
--- a/slices/core/src/main/java/androidx/slice/compat/SliceProviderWrapperContainer.java
+++ b/slices/core/src/main/java/androidx/slice/compat/SliceProviderWrapperContainer.java
@@ -29,10 +29,11 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
+import androidx.collection.ArraySet;
 import androidx.slice.SliceConvert;
 
 import java.util.Collection;
-import java.util.Set;
+import java.util.List;
 
 /**
  * @hide
@@ -47,9 +48,7 @@
 
         private androidx.slice.SliceProvider mSliceProvider;
 
-        public SliceProviderWrapper(androidx.slice.SliceProvider provider,
-                String[] autoGrantPermissions) {
-            super(autoGrantPermissions);
+        public SliceProviderWrapper(androidx.slice.SliceProvider provider) {
             mSliceProvider = provider;
         }
 
@@ -65,8 +64,8 @@
         }
 
         @Override
-        public Slice onBindSlice(Uri sliceUri, Set<SliceSpec> supportedVersions) {
-            androidx.slice.SliceProvider.setSpecs(wrap(supportedVersions));
+        public Slice onBindSlice(Uri sliceUri, List<SliceSpec> supportedVersions) {
+            androidx.slice.SliceProvider.setSpecs(new ArraySet<>(wrap(supportedVersions)));
             try {
                 return SliceConvert.unwrap(mSliceProvider.onBindSlice(sliceUri));
             } finally {
diff --git a/slices/core/src/main/res/values-as/strings.xml b/slices/core/src/main/res/values-as/strings.xml
deleted file mode 100644
index 95722b9..0000000
--- a/slices/core/src/main/res/values-as/strings.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-~ Copyright 2018 The Android Open Source Project
-~
-~ Licensed under the Apache License, Version 2.0 (the "License");
-~ you may not use this file except in compliance with the License.
-~ You may obtain a copy of the License at
-~
-~      http://www.apache.org/licenses/LICENSE-2.0
-~
-~ Unless required by applicable law or agreed to in writing, software
-~ distributed under the License is distributed on an "AS IS" BASIS,
-~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-~ See the License for the specific language governing permissions and
-~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="abc_slices_permission_request" msgid="3604847235923472451">"<xliff:g id="APP_0">%1$s</xliff:g>এ <xliff:g id="APP_2">%2$s</xliff:g>ৰ অংশ দেখুওৱাব খুজিছে"</string>
-    <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g>ক <xliff:g id="APP_2">%2$s</xliff:g>ৰ অংশ দেখুওৱাবলৈ অনুমতি দিবনে?"</string>
-    <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ই <xliff:g id="APP">%1$s</xliff:g>ৰ তথ্য পঢ়িব পাৰে"</string>
-    <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ই <xliff:g id="APP">%1$s</xliff:g>ৰ ভিতৰত কাৰ্য কৰিব পাৰে"</string>
-    <string name="abc_slice_permission_checkbox" msgid="5696872682700058611">"<xliff:g id="APP">%1$s</xliff:g>ক যিকোনো এপৰ অংশ দেখুওৱাবলৈ অনুমতি দিয়ক"</string>
-    <string name="abc_slice_permission_allow" msgid="5024599872061409708">"অনুমতি দিয়ক"</string>
-    <string name="abc_slice_permission_deny" msgid="3819478292430407705">"অস্বীকাৰ কৰক"</string>
-</resources>
diff --git a/slices/core/src/main/res/values-be/strings.xml b/slices/core/src/main/res/values-be/strings.xml
index 5fadc3f..c9fc9a8 100644
--- a/slices/core/src/main/res/values-be/strings.xml
+++ b/slices/core/src/main/res/values-be/strings.xml
@@ -17,11 +17,11 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="abc_slices_permission_request" msgid="3604847235923472451">"Праграма <xliff:g id="APP_0">%1$s</xliff:g> запытвае дазвол на паказ фрагментаў праграмы <xliff:g id="APP_2">%2$s</xliff:g>"</string>
-    <string name="abc_slice_permission_title" msgid="4175332421259324948">"Дазволіць праграме <xliff:g id="APP_0">%1$s</xliff:g> паказваць фрагменты праграмы <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+    <string name="abc_slices_permission_request" msgid="3604847235923472451">"Праграма <xliff:g id="APP_0">%1$s</xliff:g> запытвае дазвол на паказ зрэзаў праграмы <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+    <string name="abc_slice_permission_title" msgid="4175332421259324948">"Дазволіць праграме <xliff:g id="APP_0">%1$s</xliff:g> паказваць зрэзы праграмы <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Можа счытваць інфармацыю з праграмы <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Можа выконваць дзеянні ў праграме <xliff:g id="APP">%1$s</xliff:g>"</string>
-    <string name="abc_slice_permission_checkbox" msgid="5696872682700058611">"Дазволіць праграме <xliff:g id="APP">%1$s</xliff:g> паказваць фрагменты іншых праграм"</string>
+    <string name="abc_slice_permission_checkbox" msgid="5696872682700058611">"Дазволіць праграме <xliff:g id="APP">%1$s</xliff:g> паказваць зрэзы іншых праграм"</string>
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Дазволіць"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Адмовіць"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ja/strings.xml b/slices/core/src/main/res/values-ja/strings.xml
index 315326f..a04df0b 100644
--- a/slices/core/src/main/res/values-ja/strings.xml
+++ b/slices/core/src/main/res/values-ja/strings.xml
@@ -19,7 +19,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slices_permission_request" msgid="3604847235923472451">"<xliff:g id="APP_0">%1$s</xliff:g> が <xliff:g id="APP_2">%2$s</xliff:g> のスライスの表示をリクエストしています"</string>
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_2">%2$s</xliff:g> のスライスの表示を <xliff:g id="APP_0">%1$s</xliff:g> に許可しますか?"</string>
-    <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- <xliff:g id="APP">%1$s</xliff:g> からの情報を読み取ることができます"</string>
+    <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- <xliff:g id="APP">%1$s</xliff:g> からの情報を読み取ることがあります"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- <xliff:g id="APP">%1$s</xliff:g> 内部で操作することがあります"</string>
     <string name="abc_slice_permission_checkbox" msgid="5696872682700058611">"すべてのアプリのスライスを表示することを <xliff:g id="APP">%1$s</xliff:g> に許可する"</string>
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"許可"</string>
diff --git a/slices/core/src/main/res/values-or/strings.xml b/slices/core/src/main/res/values-or/strings.xml
deleted file mode 100644
index f6b9443..0000000
--- a/slices/core/src/main/res/values-or/strings.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-~ Copyright 2018 The Android Open Source Project
-~
-~ Licensed under the Apache License, Version 2.0 (the "License");
-~ you may not use this file except in compliance with the License.
-~ You may obtain a copy of the License at
-~
-~      http://www.apache.org/licenses/LICENSE-2.0
-~
-~ Unless required by applicable law or agreed to in writing, software
-~ distributed under the License is distributed on an "AS IS" BASIS,
-~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-~ See the License for the specific language governing permissions and
-~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="abc_slices_permission_request" msgid="3604847235923472451">"<xliff:g id="APP_0">%1$s</xliff:g>, <xliff:g id="APP_2">%2$s</xliff:g> ସ୍ଲାଇସ୍‌କୁ ଦେଖାଇବା ପାଇଁ ଚାହେଁ"</string>
-    <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_2">%2$s</xliff:g> ସ୍ଲାଇସ୍‌କୁ ଦେଖାଇବା ପାଇଁ <xliff:g id="APP_0">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
-    <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ଏହା <xliff:g id="APP">%1$s</xliff:g>ରୁ ସୂଚନାକୁ ପଢ଼ିପାରିବ"</string>
-    <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ଏହା <xliff:g id="APP">%1$s</xliff:g> ଭିତରେ କାମ କରିପାରିବ"</string>
-    <string name="abc_slice_permission_checkbox" msgid="5696872682700058611">"ଯେକୌଣସି ଆପ୍‌ରେ ସ୍ଲାଇସ୍‌କୁ ଦେଖାଇବା ପାଇଁ <xliff:g id="APP">%1$s</xliff:g>କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
-    <string name="abc_slice_permission_allow" msgid="5024599872061409708">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
-    <string name="abc_slice_permission_deny" msgid="3819478292430407705">"ଅସ୍ଵୀକାର କରନ୍ତୁ"</string>
-</resources>
diff --git a/slices/view/api/current.txt b/slices/view/api/current.txt
index 7be0368..5a37826 100644
--- a/slices/view/api/current.txt
+++ b/slices/view/api/current.txt
@@ -5,8 +5,6 @@
     method public abstract androidx.slice.Slice bindSlice(android.content.Intent);
     method public abstract int checkSlicePermission(android.net.Uri, int, int);
     method public static androidx.slice.SliceManager getInstance(android.content.Context);
-    method public abstract java.util.List<android.net.Uri> getPinnedSlices();
-    method public abstract java.util.Set<androidx.slice.SliceSpec> getPinnedSpecs(android.net.Uri);
     method public abstract java.util.Collection<android.net.Uri> getSliceDescendants(android.net.Uri);
     method public abstract void grantSlicePermission(java.lang.String, android.net.Uri);
     method public abstract android.net.Uri mapIntentToUri(android.content.Intent);
@@ -26,7 +24,6 @@
     method public static androidx.slice.SliceMetadata from(android.content.Context, androidx.slice.Slice);
     method public long getExpiry();
     method public int getHeaderType();
-    method public android.app.PendingIntent getInputRangeAction();
     method public long getLastUpdatedTime();
     method public int getLoadingState();
     method public androidx.slice.core.SliceAction getPrimaryAction();
@@ -120,13 +117,12 @@
     method public java.util.List<androidx.slice.SliceItem> getSliceActions();
     method public void onChanged(androidx.slice.Slice);
     method public void onClick(android.view.View);
-    method public void setAccentColor(int);
     method public void setMode(int);
     method public void setOnSliceActionListener(androidx.slice.widget.SliceView.OnSliceActionListener);
     method public void setScrollable(boolean);
     method public void setSlice(androidx.slice.Slice);
     method public void setSliceActions(java.util.List<androidx.slice.SliceItem>);
-    method public deprecated void setTint(int);
+    method public void setTint(int);
     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/src/androidTest/AndroidManifest.xml b/slices/view/src/androidTest/AndroidManifest.xml
index 7c90f90..78f3ad8 100644
--- a/slices/view/src/androidTest/AndroidManifest.xml
+++ b/slices/view/src/androidTest/AndroidManifest.xml
@@ -27,7 +27,6 @@
                   android:exported="true">
             <intent-filter>
                 <action android:name="androidx.slice.action.TEST" />
-                <category android:name="android.app.slice.category.SLICE" />
             </intent-filter>
         </provider>
 
diff --git a/slices/view/src/androidTest/java/androidx/slice/SliceManagerTest.java b/slices/view/src/androidTest/java/androidx/slice/SliceManagerTest.java
index e0e8f51..5564f72 100644
--- a/slices/view/src/androidTest/java/androidx/slice/SliceManagerTest.java
+++ b/slices/view/src/androidTest/java/androidx/slice/SliceManagerTest.java
@@ -16,10 +16,7 @@
 
 package androidx.slice;
 
-import static androidx.slice.compat.SliceProviderCompat.PERMS_PREFIX;
-
 import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
@@ -39,8 +36,8 @@
 
 import androidx.annotation.NonNull;
 import androidx.core.os.BuildCompat;
-import androidx.slice.compat.CompatPermissionManager;
 import androidx.slice.render.SliceRenderActivity;
+import androidx.slice.widget.SliceLiveData;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -48,7 +45,6 @@
 
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
 import java.util.concurrent.Executor;
 
 @RunWith(AndroidJUnit4.class)
@@ -93,28 +89,6 @@
     }
 
     @Test
-    public void testPinList() {
-        Uri uri = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(mContext.getPackageName())
-                .build();
-        Uri longerUri = uri.buildUpon().appendPath("something").build();
-        try {
-            mManager.pinSlice(uri);
-            mManager.pinSlice(longerUri);
-            verify(mSliceProvider, timeout(2000)).onSlicePinned(eq(longerUri));
-
-            List<Uri> uris = mManager.getPinnedSlices();
-            assertEquals(2, uris.size());
-            assertTrue(uris.contains(uri));
-            assertTrue(uris.contains(longerUri));
-        } finally {
-            mManager.unpinSlice(uri);
-            mManager.unpinSlice(longerUri);
-        }
-    }
-
-    @Test
     public void testCallback() {
         if (BuildCompat.isAtLeastP()) {
             return;
@@ -150,8 +124,7 @@
         mManager.pinSlice(uri);
         verify(mSliceProvider).onSlicePinned(eq(uri));
 
-        // Disabled while we update APIs.
-        //assertEquals(SliceLiveData.SUPPORTED_SPECS, mManager.getPinnedSpecs(uri));
+        assertEquals(SliceLiveData.SUPPORTED_SPECS, mManager.getPinnedSpecs(uri));
     }
 
     @Test
@@ -172,8 +145,8 @@
         when(mSliceProvider.onMapIntentToUri(eq(intent))).thenReturn(expected);
         Uri uri = mManager.mapIntentToUri(intent);
 
-        verify(mSliceProvider).onMapIntentToUri(eq(intent));
         assertEquals(expected, uri);
+        verify(mSliceProvider).onMapIntentToUri(eq(intent));
     }
 
     @Test
@@ -239,12 +212,6 @@
             }
         }
 
-        protected CompatPermissionManager onCreatePermissionManager(
-                String[] autoGrantPermissions) {
-            return new CompatPermissionManager(getContext(), PERMS_PREFIX + getClass().getName(),
-                    -1 /* Different uid to run permissions */, autoGrantPermissions);
-        }
-
         @Override
         public Collection<Uri> onGetSliceDescendants(Uri uri) {
             if (sSliceProviderReceiver != null) {
diff --git a/slices/view/src/androidTest/java/androidx/slice/SliceMetadataTest.java b/slices/view/src/androidTest/java/androidx/slice/SliceMetadataTest.java
index 78c8cf6..650114e 100644
--- a/slices/view/src/androidTest/java/androidx/slice/SliceMetadataTest.java
+++ b/slices/view/src/androidTest/java/androidx/slice/SliceMetadataTest.java
@@ -16,6 +16,7 @@
 
 package androidx.slice;
 
+import static android.app.slice.Slice.HINT_PARTIAL;
 import static android.app.slice.Slice.HINT_TITLE;
 
 import static androidx.slice.SliceMetadata.LOADED_ALL;
@@ -23,7 +24,6 @@
 import static androidx.slice.SliceMetadata.LOADED_PARTIAL;
 import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
 import static androidx.slice.core.SliceHints.HINT_KEYWORDS;
-import static androidx.slice.core.SliceHints.INFINITY;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
@@ -36,6 +36,7 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
@@ -91,7 +92,7 @@
         PendingIntent pi = getIntent("");
         Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
         new Canvas(b).drawColor(0xffff0000);
-        IconCompat icon = IconCompat.createWithBitmap(b);
+        IconCompat icon = IconCompat.createFromIcon(Icon.createWithBitmap(b));
 
         SliceAction action1 = new SliceAction(pi, icon, "action1");
         SliceAction action2 = new SliceAction(pi, icon, "action2");
@@ -122,7 +123,7 @@
         PendingIntent pi = getIntent("");
         Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
         new Canvas(b).drawColor(0xffff0000);
-        IconCompat icon = IconCompat.createWithBitmap(b);
+        IconCompat icon = IconCompat.createFromIcon(Icon.createWithBitmap(b));
 
         SliceAction primaryAction = new SliceAction(pi, icon, "action");
 
@@ -145,7 +146,7 @@
         PendingIntent pi = getIntent("");
         Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
         new Canvas(b).drawColor(0xffff0000);
-        IconCompat icon = IconCompat.createWithBitmap(b);
+        IconCompat icon = IconCompat.createFromIcon(Icon.createWithBitmap(b));
 
         SliceAction primaryAction = new SliceAction(pi, icon, "action");
         SliceAction endAction = new SliceAction(pi, "toogle action", false);
@@ -168,7 +169,7 @@
         PendingIntent pi = getIntent("");
         Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
         new Canvas(b).drawColor(0xffff0000);
-        IconCompat icon = IconCompat.createWithBitmap(b);
+        IconCompat icon = IconCompat.createFromIcon(Icon.createWithBitmap(b));
 
         SliceAction primaryAction = new SliceAction(pi, icon, "action");
         SliceAction sliceAction = new SliceAction(pi, "another action", true);
@@ -191,7 +192,7 @@
         PendingIntent pi = getIntent("");
         Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
         new Canvas(b).drawColor(0xffff0000);
-        IconCompat icon = IconCompat.createWithBitmap(b);
+        IconCompat icon = IconCompat.createFromIcon(Icon.createWithBitmap(b));
 
         SliceAction endAction1 = new SliceAction(pi, icon, "action");
         SliceAction endAction2 = new SliceAction(pi, "toogle action", false);
@@ -262,7 +263,7 @@
                 .setTitle("another title")
                 .setValue(5)
                 .setMax(10)
-                .setInputAction(pi));
+                .setAction(pi));
 
         Slice sliderSlice = lb.build();
         SliceMetadata sliderInfo = SliceMetadata.from(mContext, sliderSlice);
@@ -304,22 +305,22 @@
         Uri uri = Uri.parse("content://pkg/slice");
         Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
         new Canvas(b).drawColor(0xffff0000);
-        IconCompat icon = IconCompat.createWithBitmap(b);
+        Icon icon = Icon.createWithBitmap(b);
 
         ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
         GridRowBuilder grb = new GridRowBuilder(lb);
         grb.addCell(new GridRowBuilder.CellBuilder(grb)
                 .addText("some text")
                 .addText("more text")
-                .addImage(icon, ICON_IMAGE));
+                .addImage(IconCompat.createFromIcon(icon), ICON_IMAGE));
         grb.addCell(new GridRowBuilder.CellBuilder(grb)
                 .addText("some text")
                 .addText("more text")
-                .addImage(icon, ICON_IMAGE));
+                .addImage(IconCompat.createFromIcon(icon), ICON_IMAGE));
         grb.addCell(new GridRowBuilder.CellBuilder(grb)
                 .addText("some text")
                 .addText("more text")
-                .addImage(icon, ICON_IMAGE));
+                .addImage(IconCompat.createFromIcon(icon), ICON_IMAGE));
         lb.addGridRow(grb);
 
         Slice gridSlice = lb.build();
@@ -406,7 +407,7 @@
         PendingIntent pi = getIntent("");
         Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
         new Canvas(b).drawColor(0xffff0000);
-        IconCompat icon = IconCompat.createWithBitmap(b);
+        IconCompat icon = IconCompat.createFromIcon(Icon.createWithBitmap(b));
 
         SliceAction toggleAction = new SliceAction(pi, icon, "toggle", false /* isChecked */);
         SliceAction toggleAction2 = new SliceAction(pi, icon, "toggle2", true /* isChecked */);
@@ -467,31 +468,6 @@
     }
 
     @Test
-    public void testGetInputRangeAction() {
-        Uri uri = Uri.parse("content://pkg/slice");
-        PendingIntent expectedIntent = getIntent("rangeintent");
-
-        Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
-        new Canvas(b).drawColor(0xffff0000);
-        IconCompat icon = IconCompat.createWithBitmap(b);
-        SliceAction primaryAction = new SliceAction(getIntent(""), icon, "action");
-
-        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
-        lb.addInputRange(new ListBuilder.InputRangeBuilder(lb)
-                .setTitle("another title")
-                .setValue(7)
-                .setMin(5)
-                .setMax(10)
-                .setPrimaryAction(primaryAction)
-                .setInputAction(expectedIntent));
-        Slice sliderSlice = lb.build();
-
-        SliceMetadata sliderInfo = SliceMetadata.from(mContext, sliderSlice);
-        assertEquals(expectedIntent, sliderInfo.getInputRangeAction());
-        assertEquivalent(primaryAction, sliderInfo.getPrimaryAction());
-    }
-
-    @Test
     public void testGetRangeForProgress() {
         Uri uri = Uri.parse("content://pkg/slice");
 
@@ -551,23 +527,17 @@
     @Test
     public void testGetLoadingState() {
         Uri uri = Uri.parse("content://pkg/slice");
-        Slice s1 = new ListBuilder(mContext, uri, INFINITY).build();
+        Slice s1 = new Slice.Builder(uri).build();
         SliceMetadata SliceMetadata1 = SliceMetadata.from(mContext, s1);
         int actualState1 = SliceMetadata1.getLoadingState();
         assertEquals(LOADED_NONE, actualState1);
 
-        ListBuilder lb = new ListBuilder(mContext, uri, INFINITY);
-        Slice s2 = lb.addRow(new ListBuilder.RowBuilder(lb)
-                .setTitle(null, true /* isLoading */))
-                .build();
+        Slice s2 = new Slice.Builder(uri).addText(null, null, HINT_PARTIAL).build();
         SliceMetadata SliceMetadata2 = SliceMetadata.from(mContext, s2);
         int actualState2 = SliceMetadata2.getLoadingState();
         assertEquals(LOADED_PARTIAL, actualState2);
 
-        ListBuilder lb2 = new ListBuilder(mContext, uri, INFINITY);
-        Slice s3 = lb2.addRow(new ListBuilder.RowBuilder(lb2)
-                .setTitle("Title", false /* isLoading */))
-                .build();
+        Slice s3 = new Slice.Builder(uri).addText("Text", null).build();
         SliceMetadata SliceMetadata3 = SliceMetadata.from(mContext, s3);
         int actualState3 = SliceMetadata3.getLoadingState();
         assertEquals(LOADED_ALL, actualState3);
@@ -580,9 +550,9 @@
         long ttl = TimeUnit.DAYS.toMillis(1);
         Slice ttlSlice = new Slice.Builder(uri)
                 .addText("Some text", null)
-                .addLong(timestamp, null)
-                .addLong(timestamp, null, SliceHints.HINT_LAST_UPDATED)
-                .addLong(ttl, null, SliceHints.HINT_TTL)
+                .addTimestamp(timestamp, null)
+                .addTimestamp(timestamp, null, SliceHints.HINT_LAST_UPDATED)
+                .addTimestamp(ttl, null, SliceHints.HINT_TTL)
                 .build();
 
         SliceMetadata si1 = SliceMetadata.from(mContext, ttlSlice);
@@ -591,7 +561,7 @@
 
         Slice noTtlSlice = new Slice.Builder(uri)
                 .addText("Some text", null)
-                .addLong(timestamp, null).build();
+                .addTimestamp(timestamp, null).build();
         SliceMetadata si2 = SliceMetadata.from(mContext, noTtlSlice);
         long retrievedTtl2 = si2.getExpiry();
         assertEquals(0, retrievedTtl2);
@@ -604,9 +574,9 @@
         long ttl = TimeUnit.DAYS.toMillis(1);
         Slice ttlSlice = new Slice.Builder(uri)
                 .addText("Some text", null)
-                .addLong(timestamp - 20, null)
-                .addLong(timestamp, null, SliceHints.HINT_LAST_UPDATED)
-                .addLong(ttl, null, SliceHints.HINT_TTL)
+                .addTimestamp(timestamp - 20, null)
+                .addTimestamp(timestamp, null, SliceHints.HINT_LAST_UPDATED)
+                .addTimestamp(ttl, null, SliceHints.HINT_TTL)
                 .build();
 
         SliceMetadata si1 = SliceMetadata.from(mContext, ttlSlice);
@@ -615,7 +585,7 @@
 
         Slice noTtlSlice = new Slice.Builder(uri)
                 .addText("Some text", null)
-                .addLong(timestamp, null).build();
+                .addTimestamp(timestamp, null).build();
 
         SliceMetadata si2 = SliceMetadata.from(mContext, noTtlSlice);
         long retrievedLastUpdated2 = si2.getLastUpdatedTime();
diff --git a/slices/view/src/androidTest/java/androidx/slice/SlicePermissionTest.java b/slices/view/src/androidTest/java/androidx/slice/SlicePermissionTest.java
deleted file mode 100644
index ffb65e0..0000000
--- a/slices/view/src/androidTest/java/androidx/slice/SlicePermissionTest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.slice;
-
-import static androidx.core.content.PermissionChecker.PERMISSION_DENIED;
-import static androidx.core.content.PermissionChecker.PERMISSION_GRANTED;
-
-import static org.junit.Assert.assertEquals;
-
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.net.Uri;
-import android.os.Process;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class SlicePermissionTest {
-
-    private static final Uri BASE_URI = Uri.parse("content://androidx.slice.view.test/");
-    private final Context mContext = InstrumentationRegistry.getContext();
-    private String mTestPkg;
-    private int mTestUid;
-    private int mTestPid;
-    private SliceManager mSliceManager;
-
-    @Before
-    public void setup() throws NameNotFoundException {
-        mSliceManager = SliceManager.getInstance(mContext);
-        mTestPkg = mContext.getPackageName();
-        mTestUid = mContext.getPackageManager().getPackageUid(mTestPkg, 0);
-        mTestPid = Process.myPid();
-    }
-
-    @After
-    public void tearDown() {
-        mSliceManager.revokeSlicePermission(mTestPkg, BASE_URI);
-    }
-
-    @Test
-    public void testGrant() {
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-
-        mSliceManager.grantSlicePermission(mTestPkg, BASE_URI);
-
-        assertEquals(PERMISSION_GRANTED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-    }
-
-    @Test
-    public void testGrantParent() {
-        Uri uri = BASE_URI.buildUpon()
-                .appendPath("something")
-                .build();
-
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(uri, mTestPid, mTestUid));
-
-        mSliceManager.grantSlicePermission(mTestPkg, BASE_URI);
-
-        assertEquals(PERMISSION_GRANTED,
-                mSliceManager.checkSlicePermission(uri, mTestPid, mTestUid));
-    }
-
-    @Test
-    public void testGrantParentExpands() {
-        Uri uri = BASE_URI.buildUpon()
-                .appendPath("something")
-                .build();
-
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(uri, mTestPid, mTestUid));
-
-        mSliceManager.grantSlicePermission(mTestPkg, uri);
-
-        // Only sub-path granted.
-        assertEquals(PERMISSION_GRANTED,
-                mSliceManager.checkSlicePermission(uri, mTestPid, mTestUid));
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-
-        mSliceManager.grantSlicePermission(mTestPkg, BASE_URI);
-
-        // Now all granted.
-        assertEquals(PERMISSION_GRANTED,
-                mSliceManager.checkSlicePermission(uri, mTestPid, mTestUid));
-        assertEquals(PERMISSION_GRANTED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-    }
-
-    @Test
-    public void testGrantChild() {
-        Uri uri = BASE_URI.buildUpon()
-                .appendPath("something")
-                .build();
-
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-
-        mSliceManager.grantSlicePermission(mTestPkg, uri);
-
-        // Still no permission because only a child was granted
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-    }
-
-    @Test
-    public void testRevoke() {
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-
-        mSliceManager.grantSlicePermission(mTestPkg, BASE_URI);
-
-        assertEquals(PERMISSION_GRANTED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-
-        mSliceManager.revokeSlicePermission(mTestPkg, BASE_URI);
-
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-    }
-
-    @Test
-    public void testRevokeParent() {
-        Uri uri = BASE_URI.buildUpon()
-                .appendPath("something")
-                .build();
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(uri, mTestPid, mTestUid));
-
-        mSliceManager.grantSlicePermission(mTestPkg, uri);
-
-        assertEquals(PERMISSION_GRANTED,
-                mSliceManager.checkSlicePermission(uri, mTestPid, mTestUid));
-
-        mSliceManager.revokeSlicePermission(mTestPkg, BASE_URI);
-
-        // Revoked because parent was revoked
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(uri, mTestPid, mTestUid));
-    }
-
-    @Test
-    public void testRevokeChild() {
-        Uri uri = BASE_URI.buildUpon()
-                .appendPath("something")
-                .build();
-        assertEquals(PERMISSION_DENIED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-
-        mSliceManager.grantSlicePermission(mTestPkg, BASE_URI);
-
-        assertEquals(PERMISSION_GRANTED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-
-        mSliceManager.revokeSlicePermission(mTestPkg, uri);
-
-        // Not revoked because child was revoked.
-        assertEquals(PERMISSION_GRANTED,
-                mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
-    }
-
-}
diff --git a/slices/view/src/androidTest/java/androidx/slice/render/RenderTest.java b/slices/view/src/androidTest/java/androidx/slice/render/RenderTest.java
index 4c3b6fc..deb1f90 100644
--- a/slices/view/src/androidTest/java/androidx/slice/render/RenderTest.java
+++ b/slices/view/src/androidTest/java/androidx/slice/render/RenderTest.java
@@ -16,15 +16,12 @@
 
 package androidx.slice.render;
 
-import static android.os.Build.VERSION.SDK_INT;
-
 import static androidx.slice.render.SliceRenderer.SCREENSHOT_DIR;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.os.Build;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -32,11 +29,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -47,7 +39,7 @@
     private final Context mContext = InstrumentationRegistry.getContext();
 
     @Test
-    public void testRender() throws Exception {
+    public void testRender() throws InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
         BroadcastReceiver receiver = new BroadcastReceiver() {
             @Override
@@ -61,53 +53,8 @@
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
 
         latch.await(30000, TimeUnit.MILLISECONDS);
-        String path = new File(mContext.getFilesDir(), SCREENSHOT_DIR).getAbsolutePath();
-        if (SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(
-                    "mv " + path + " " + "/sdcard/");
-        } else {
-            deleteDir(new File("/sdcard/" + SCREENSHOT_DIR));
-            copyDirectory(new File(path), new File("/sdcard/" + SCREENSHOT_DIR));
-        }
-    }
-
-
-    public static void copyDirectory(File sourceLocation, File targetLocation) throws Exception {
-        if (sourceLocation.isDirectory()) {
-            if (!targetLocation.exists()) {
-                targetLocation.mkdirs();
-            }
-
-            String[] children = sourceLocation.list();
-            for (int i = 0; i < children.length; i++) {
-                copyDirectory(new File(sourceLocation, children[i]), new File(
-                        targetLocation, children[i]));
-            }
-        } else {
-            copyFile(sourceLocation, targetLocation);
-        }
-    }
-
-    public static void copyFile(File sourceLocation, File targetLocation) throws Exception {
-        InputStream in = new FileInputStream(sourceLocation);
-        OutputStream out = new FileOutputStream(targetLocation);
-
-        byte[] buf = new byte[1024];
-        int len;
-        while ((len = in.read(buf)) > 0) {
-            out.write(buf, 0, len);
-        }
-        in.close();
-        out.close();
-    }
-
-    static void deleteDir(File file) {
-        File[] contents = file.listFiles();
-        if (contents != null) {
-            for (File f : contents) {
-                deleteDir(f);
-            }
-        }
-        file.delete();
+        String path = mContext.getDataDir().toString() + "/" + SCREENSHOT_DIR;
+        InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(
+                "mv " + path + " " + "/sdcard/");
     }
 }
diff --git a/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java b/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
index 5f08f3f..2312b36 100644
--- a/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
+++ b/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
@@ -57,27 +57,9 @@
             "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",
-            "wifi2",
-            "note",
-            "ride",
-            "ride-ttl",
-            "toggle",
-            "toggle2",
-            "contact",
-            "gallery",
-            "subscription",
-            "subscription2",
-            "weather",
-            "reservation",
-            "inputrange",
-            "inputrange2",
-            "range",
-            "permission",
-            "empty",
-    };
+    public static final String[] URI_PATHS = {"message", "wifi", "wifi2", "note", "ride",
+            "ride-ttl", "toggle", "toggle2", "contact", "gallery", "subscription", "subscription2",
+            "weather", "reservation", "inputrange", "range", "permission"};
 
     private final Context mContext;
 
@@ -133,14 +115,10 @@
                 return createReservationSlice(sliceUri);
             case "/inputrange":
                 return createStarRatingInputRange(sliceUri);
-            case "/inputrange2":
-                return createBasicInputRange(sliceUri);
             case "/range":
                 return createDownloadProgressRange(sliceUri);
             case "/permission":
                 return createPermissionSlice(sliceUri);
-            case "/empty":
-                return new ListBuilder(getContext(), sliceUri, INFINITY).build();
         }
         throw new IllegalArgumentException("Unknown uri " + sliceUri);
     }
@@ -258,7 +236,7 @@
                 "See contact info"), IconCompat.createWithResource(getContext(),
                 R.drawable.mady), SMALL_IMAGE, "Mady");
         GridRowBuilder gb = new GridRowBuilder(b);
-        return b.setAccentColor(0xff3949ab)
+        return b.setColor(0xff3949ab)
                 .addRow(rb
                         .setTitle("Mady Pitza")
                         .setSubtitle("Frequently contacted contact")
@@ -314,7 +292,7 @@
     private Slice createNoteSlice(Uri sliceUri) {
         // TODO: Remote input.
         ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY);
-        return lb.setAccentColor(0xfff4b400)
+        return lb.setColor(0xfff4b400)
                 .addRow(new ListBuilder.RowBuilder(lb)
                         .setTitle("Create new note")
                         .setSubtitle("with this note taking app")
@@ -344,11 +322,11 @@
                 ? -TimeUnit.MINUTES.toMillis(2) // negative for testing
                 : INFINITY;
         ListBuilder lb = new ListBuilder(getContext(), sliceUri, ttl);
-        return lb.setAccentColor(0xff0F9D58)
+        return lb.setColor(0xff0F9D58)
                 .setHeader(new ListBuilder.HeaderBuilder(lb)
                         .setTitle("Get ride")
                         .setSubtitle(headerSubtitle)
-                        .setSummary("Ride to work in 12 min | Ride home in 1 hour 45 min")
+                        .setSummarySubtitle("Ride to work in 12 min | Ride home in 1 hour 45 min")
                         .setPrimaryAction(primaryAction))
                 .addRow(new ListBuilder.RowBuilder(lb)
                         .setTitle("Work")
@@ -367,7 +345,7 @@
 
     private Slice createCustomToggleSlice(Uri sliceUri) {
         ListBuilder b = new ListBuilder(getContext(), sliceUri, -TimeUnit.HOURS.toMillis(1));
-        return b.setAccentColor(0xffff4081)
+        return b.setColor(0xffff4081)
                 .addRow(new ListBuilder.RowBuilder(b)
                         .setTitle("Custom toggle")
                         .addEndItem(
@@ -380,7 +358,7 @@
 
     private Slice createTwoCustomToggleSlices(Uri sliceUri) {
         ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY);
-        return lb.setAccentColor(0xffff4081)
+        return lb.setColor(0xffff4081)
                 .addRow(new ListBuilder.RowBuilder(lb)
                         .setTitle("2 toggles")
                         .setSubtitle("each supports two states")
@@ -420,7 +398,7 @@
         ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY);
         SliceAction primaryAction = new SliceAction(getIntent(Settings.ACTION_WIFI_SETTINGS),
                 IconCompat.createWithResource(getContext(), R.drawable.ic_wifi), "Wi-fi Settings");
-        lb.setAccentColor(0xff4285f4);
+        lb.setColor(0xff4285f4);
         lb.addRow(new ListBuilder.RowBuilder(lb)
                 .setTitle("Wi-fi")
                 .setTitleItem(IconCompat.createWithResource(getContext(), R.drawable.ic_wifi),
@@ -481,7 +459,7 @@
                 .addCell(new GridRowBuilder.CellBuilder(gb2)
                         .addTitleText("Check Out")
                         .addText("11:00 AM, Feb 19"));
-        return lb.setAccentColor(0xffFF5252)
+        return lb.setColor(0xffFF5252)
                 .setHeader(new ListBuilder.HeaderBuilder(lb)
                         .setTitle("Upcoming trip to Seattle")
                         .setSubtitle("Feb 1 - 19 | 2 guests"))
@@ -497,30 +475,13 @@
                 .build();
     }
 
-    private Slice createBasicInputRange(Uri sliceUri) {
-        IconCompat icon = IconCompat.createWithResource(getContext(), R.drawable.ic_star_on);
-        SliceAction primaryAction =
-                new SliceAction(getBroadcastIntent(ACTION_TOAST, "open star rating"),
-                        icon, "Rate");
-        ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY);
-        return lb.setAccentColor(0xff4285f4)
-                .addInputRange(new ListBuilder.InputRangeBuilder(lb)
-                        .setTitle("Alarm volume")
-                        .setSubtitle("Adjust your volume")
-                        .setInputAction(getBroadcastIntent(ACTION_TOAST, "volume changed"))
-                        .setValue(80)
-                        .setPrimaryAction(primaryAction)
-                        .setContentDescription("Slider for alarm volume"))
-                .build();
-    }
-
     private Slice createStarRatingInputRange(Uri sliceUri) {
         IconCompat icon = IconCompat.createWithResource(getContext(), R.drawable.ic_star_on);
         SliceAction primaryAction =
                 new SliceAction(getBroadcastIntent(ACTION_TOAST, "open star rating"), icon,
                         "Rate");
         ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY);
-        return lb.setAccentColor(0xffff4081)
+        return lb.setColor(0xffff4081)
                 .addInputRange(new ListBuilder.InputRangeBuilder(lb)
                         .setTitle("Star rating")
                         .setSubtitle("Pick a rating from 0 to 5")
@@ -541,7 +502,7 @@
                         getBroadcastIntent(ACTION_TOAST, "open download"), icon,
                         "Download");
         ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY);
-        return lb.setAccentColor(0xffff4081)
+        return lb.setColor(0xffff4081)
                 .addRange(new ListBuilder.RangeBuilder(lb)
                         .setTitle("Download progress")
                         .setSubtitle("Download is happening")
diff --git a/slices/view/src/androidTest/java/androidx/slice/render/SliceRenderer.java b/slices/view/src/androidTest/java/androidx/slice/render/SliceRenderer.java
index ec5e55a..0734edf 100644
--- a/slices/view/src/androidTest/java/androidx/slice/render/SliceRenderer.java
+++ b/slices/view/src/androidTest/java/androidx/slice/render/SliceRenderer.java
@@ -116,7 +116,7 @@
 
     private File getScreenshotDirectory() {
         if (sScreenshotDirectory == null) {
-            File storage = mContext.getFilesDir();
+            File storage = mContext.getDataDir();
             sScreenshotDirectory = new File(storage, SCREENSHOT_DIR);
             if (!sScreenshotDirectory.exists()) {
                 if (!sScreenshotDirectory.mkdirs()) {
@@ -188,12 +188,12 @@
                             .setActionMode(SliceUtils.SerializeOptions.MODE_CONVERT));
 
             byte[] bytes = outputStream.toByteArray();
-            Log.d(TAG, "Serialized: " + new String(bytes));
             ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
             return SliceUtils.parseSlice(mContext, inputStream, "UTF-8",
                     new SliceUtils.SliceActionListener() {
                         @Override
-                        public void onSliceAction(Uri actionUri) { }
+                        public void onSliceAction(Uri actionUri) {
+                        }
                     });
         } catch (Exception e) {
             throw new RuntimeException(e);
diff --git a/slices/view/src/main/java/androidx/slice/SliceManager.java b/slices/view/src/main/java/androidx/slice/SliceManager.java
index 83febcc..63c56e8 100644
--- a/slices/view/src/main/java/androidx/slice/SliceManager.java
+++ b/slices/view/src/main/java/androidx/slice/SliceManager.java
@@ -28,7 +28,6 @@
 import androidx.core.os.BuildCompat;
 
 import java.util.Collection;
-import java.util.List;
 import java.util.Set;
 import java.util.concurrent.Executor;
 
@@ -126,8 +125,10 @@
      * <p>
      * This is the set of specs supported for a specific pinned slice. It will take
      * into account all clients and returns only specs supported by all.
+     * @hide
      * @see SliceSpec
      */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public abstract @NonNull Set<SliceSpec> getPinnedSpecs(@NonNull Uri uri);
 
     /**
@@ -140,8 +141,9 @@
     public abstract @Nullable Slice bindSlice(@NonNull Uri uri);
 
     /**
-     * Turns a slice intent into slice content. Is a shortcut to perform the action
-     * of both {@link #mapIntentToUri(Intent)} and {@link #bindSlice(Uri)} at once.
+     * Turns a slice intent into slice content. Expects an explicit intent. If there is no
+     * {@link android.content.ContentProvider} associated with the given intent this will throw
+     * {@link IllegalArgumentException}.
      *
      * @param intent The intent associated with a slice.
      * @return The Slice provided by the app or null if none is given.
@@ -152,23 +154,12 @@
     public abstract @Nullable Slice bindSlice(@NonNull Intent intent);
 
     /**
-     * Turns a slice intent into a slice uri. Expects an explicit intent.
-     * <p>
-     * This goes through a several stage resolution process to determine if any slice
-     * can represent this intent.
-     * <ol>
-     *  <li> If the intent contains data that {@link android.content.ContentResolver#getType} is
-     *  {@link android.app.slice.SliceProvider#SLICE_TYPE} then the data will be returned.</li>
-     *  <li>If the intent explicitly points at an activity, and that activity has
-     *  meta-data for key {@link android.app.slice.SliceManager#SLICE_METADATA_KEY},
-     *  then the Uri specified there will be returned.</li>
-     *  <li>Lastly, if the intent with {@link android.app.slice.SliceManager#CATEGORY_SLICE} added
-     *  resolves to a provider, then the provider will be asked to
-     *  {@link SliceProvider#onMapIntentToUri} and that result will be returned.</li>
-     *  <li>If no slice is found, then {@code null} is returned.</li>
-     * </ol>
+     * Turns a slice intent into a slice uri. Expects an explicit intent. If there is no
+     * {@link android.content.ContentProvider} associated with the given intent this will throw
+     * {@link IllegalArgumentException}.
+     *
      * @param intent The intent associated with a slice.
-     * @return The Slice Uri provided by the app or null if none exists.
+     * @return The Slice Uri provided by the app or null if none is given.
      * @see Slice
      * @see SliceProvider#onMapIntentToUri(Intent)
      * @see Intent
@@ -232,12 +223,6 @@
     public abstract @NonNull Collection<Uri> getSliceDescendants(@NonNull Uri uri);
 
     /**
-     * Get the list of currently pinned slices for this app.
-     * @see SliceProvider#onSlicePinned
-     */
-    public abstract @NonNull List<Uri> getPinnedSlices();
-
-    /**
      * Class that listens to changes in {@link Slice}s.
      */
     public interface SliceCallback {
diff --git a/slices/view/src/main/java/androidx/slice/SliceManagerBase.java b/slices/view/src/main/java/androidx/slice/SliceManagerBase.java
index 5192dad..fb9fccd 100644
--- a/slices/view/src/main/java/androidx/slice/SliceManagerBase.java
+++ b/slices/view/src/main/java/androidx/slice/SliceManagerBase.java
@@ -19,9 +19,11 @@
 import static androidx.slice.widget.SliceLiveData.SUPPORTED_SPECS;
 
 import android.content.Context;
+import android.content.Intent;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.util.ArrayMap;
@@ -29,6 +31,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
+import androidx.core.content.PermissionChecker;
 
 import java.util.concurrent.Executor;
 
@@ -68,6 +71,31 @@
         if (impl != null) impl.stopListening();
     }
 
+    @Override
+    @PermissionChecker.PermissionResult
+    public int checkSlicePermission(@NonNull Uri uri, int pid, int uid) {
+        // TODO: Switch off Uri permissions.
+        return mContext.checkUriPermission(uri, pid, uid,
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+    }
+
+    @Override
+    public void grantSlicePermission(@NonNull String toPackage, @NonNull Uri uri) {
+        // TODO: Switch off Uri permissions.
+        mContext.grantUriPermission(toPackage, uri,
+                Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+                        | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                        | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
+    }
+
+    @Override
+    public void revokeSlicePermission(@NonNull String toPackage, @NonNull Uri uri) {
+        // TODO: Switch off Uri permissions.
+        if (Build.VERSION.SDK_INT >= 26) {
+            mContext.revokeUriPermission(toPackage, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        }
+    }
+
 
     private SliceListenerImpl getListener(Uri uri, SliceCallback callback,
             SliceListenerImpl listener) {
diff --git a/slices/view/src/main/java/androidx/slice/SliceManagerCompat.java b/slices/view/src/main/java/androidx/slice/SliceManagerCompat.java
index 0018c13..1badbb4 100644
--- a/slices/view/src/main/java/androidx/slice/SliceManagerCompat.java
+++ b/slices/view/src/main/java/androidx/slice/SliceManagerCompat.java
@@ -29,7 +29,6 @@
 import androidx.slice.widget.SliceLiveData;
 
 import java.util.Collection;
-import java.util.List;
 import java.util.Set;
 
 
@@ -77,30 +76,7 @@
     }
 
     @Override
-    public int checkSlicePermission(Uri uri, int pid, int uid) {
-        return SliceProviderCompat.checkSlicePermission(mContext, mContext.getPackageName(), uri,
-                pid, uid);
-    }
-
-    @Override
-    public void grantSlicePermission(String toPackage, Uri uri) {
-        SliceProviderCompat.grantSlicePermission(mContext, mContext.getPackageName(), toPackage,
-                uri);
-    }
-
-    @Override
-    public void revokeSlicePermission(String toPackage, Uri uri) {
-        SliceProviderCompat.revokeSlicePermission(mContext, mContext.getPackageName(), toPackage,
-                uri);
-    }
-
-    @Override
     public Collection<Uri> getSliceDescendants(Uri uri) {
         return SliceProviderCompat.getSliceDescendants(mContext, uri);
     }
-
-    @Override
-    public List<Uri> getPinnedSlices() {
-        return SliceProviderCompat.getPinnedSlices(mContext);
-    }
 }
diff --git a/slices/view/src/main/java/androidx/slice/SliceManagerWrapper.java b/slices/view/src/main/java/androidx/slice/SliceManagerWrapper.java
index ec49fe2..e0c0342 100644
--- a/slices/view/src/main/java/androidx/slice/SliceManagerWrapper.java
+++ b/slices/view/src/main/java/androidx/slice/SliceManagerWrapper.java
@@ -28,10 +28,9 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
-import androidx.core.content.PermissionChecker;
 
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
@@ -43,7 +42,7 @@
 class SliceManagerWrapper extends SliceManagerBase {
 
     private final android.app.slice.SliceManager mManager;
-    private final Set<SliceSpec> mSpecs;
+    private final List<SliceSpec> mSpecs;
 
     SliceManagerWrapper(Context context) {
         this(context, context.getSystemService(android.app.slice.SliceManager.class));
@@ -52,7 +51,7 @@
     SliceManagerWrapper(Context context, android.app.slice.SliceManager manager) {
         super(context);
         mManager = manager;
-        mSpecs = unwrap(SUPPORTED_SPECS);
+        mSpecs = new ArrayList<>(unwrap(SUPPORTED_SPECS));
     }
 
     @Override
@@ -67,9 +66,7 @@
 
     @Override
     public @NonNull Set<androidx.slice.SliceSpec> getPinnedSpecs(@NonNull Uri uri) {
-        // Disabled while we update APIs.
-        //return SliceConvert.wrap(mManager.getPinnedSpecs(uri));
-        return Collections.EMPTY_SET;
+        return SliceConvert.wrap(mManager.getPinnedSpecs(uri));
     }
 
     @Nullable
@@ -89,30 +86,9 @@
         return mManager.getSliceDescendants(uri);
     }
 
-    @Override
-    @PermissionChecker.PermissionResult
-    public int checkSlicePermission(@NonNull Uri uri, int pid, int uid) {
-        return mManager.checkSlicePermission(uri, pid, uid);
-    }
-
-    @Override
-    public void grantSlicePermission(@NonNull String toPackage, @NonNull Uri uri) {
-        mManager.grantSlicePermission(toPackage, uri);
-    }
-
-    @Override
-    public void revokeSlicePermission(@NonNull String toPackage, @NonNull Uri uri) {
-        mManager.revokeSlicePermission(toPackage, uri);
-    }
-
     @Nullable
     @Override
     public Uri mapIntentToUri(@NonNull Intent intent) {
         return mManager.mapIntentToUri(intent);
     }
-
-    @Override
-    public List<Uri> getPinnedSlices() {
-        return mManager.getPinnedSlices();
-    }
 }
diff --git a/slices/view/src/main/java/androidx/slice/SliceMetadata.java b/slices/view/src/main/java/androidx/slice/SliceMetadata.java
index d7c9097..8a4ee03 100644
--- a/slices/view/src/main/java/androidx/slice/SliceMetadata.java
+++ b/slices/view/src/main/java/androidx/slice/SliceMetadata.java
@@ -23,9 +23,9 @@
 import static android.app.slice.Slice.SUBTYPE_MAX;
 import static android.app.slice.Slice.SUBTYPE_VALUE;
 import static android.app.slice.SliceItem.FORMAT_INT;
-import static android.app.slice.SliceItem.FORMAT_LONG;
 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.slice.core.SliceHints.HINT_KEYWORDS;
 import static androidx.slice.core.SliceHints.HINT_LAST_UPDATED;
@@ -35,7 +35,6 @@
 import static androidx.slice.widget.EventInfo.ROW_TYPE_PROGRESS;
 import static androidx.slice.widget.EventInfo.ROW_TYPE_SLIDER;
 
-import android.app.PendingIntent;
 import android.content.Context;
 import android.text.TextUtils;
 
@@ -119,17 +118,17 @@
     private SliceMetadata(@NonNull Context context, @NonNull Slice slice) {
         mSlice = slice;
         mContext = context;
-        SliceItem ttlItem = SliceQuery.find(slice, FORMAT_LONG, HINT_TTL, null);
+        SliceItem ttlItem = SliceQuery.find(slice, FORMAT_TIMESTAMP, HINT_TTL, null);
         if (ttlItem != null) {
             mExpiry = ttlItem.getTimestamp();
         }
-        SliceItem updatedItem = SliceQuery.find(slice, FORMAT_LONG, HINT_LAST_UPDATED, null);
+        SliceItem updatedItem = SliceQuery.find(slice, FORMAT_TIMESTAMP, HINT_LAST_UPDATED, null);
         if (updatedItem != null) {
             mLastUpdated = updatedItem.getTimestamp();
         }
         mSliceActions = getSliceActions(mSlice);
 
-        mListContent = new ListContent(context, slice, null, 0, 0);
+        mListContent = new ListContent(context, slice);
         mHeaderItem = mListContent.getHeaderItem();
         mTemplateType = mListContent.getHeaderTemplateType();
 
@@ -198,23 +197,6 @@
     }
 
     /**
-     * Gets the input range action associated for this slice, if it exists.
-     *
-     * @return the {@link android.app.PendingIntent} for the input range.
-     */
-    @Nullable
-    public PendingIntent getInputRangeAction() {
-        if (mTemplateType == ROW_TYPE_SLIDER) {
-            RowContent rc = new RowContent(mContext, mHeaderItem, true /* isHeader */);
-            SliceItem range = rc.getRange();
-            if (range != null) {
-                return range.getAction();
-            }
-        }
-        return null;
-    }
-
-    /**
      * Gets the range information associated with a progress bar or input range associated with this
      * slice, if it exists.
      *
@@ -288,7 +270,7 @@
     public int getLoadingState() {
         // Check loading state
         boolean hasHintPartial = SliceQuery.find(mSlice, null, HINT_PARTIAL, null) != null;
-        if (!mListContent.isValid()) {
+        if (mSlice.getItems().size() == 0) {
             // Empty slice
             return LOADED_NONE;
         } else if (hasHintPartial) {
diff --git a/slices/view/src/main/java/androidx/slice/SliceXml.java b/slices/view/src/main/java/androidx/slice/SliceXml.java
index 43b4c9b..673bfca 100644
--- a/slices/view/src/main/java/androidx/slice/SliceXml.java
+++ b/slices/view/src/main/java/androidx/slice/SliceXml.java
@@ -30,7 +30,6 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
-import android.os.Build;
 import android.text.Html;
 import android.text.Spanned;
 import android.text.TextUtils;
@@ -182,10 +181,6 @@
                         break;
                     case android.app.slice.SliceItem.FORMAT_TEXT:
                         v = parser.getText();
-                        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
-                            // 19-21 don't allow special characters in XML, so we base64 encode it.
-                            v = new String(Base64.decode(v, Base64.NO_WRAP));
-                        }
                         b.addText(Html.fromHtml(v), subtype, hints);
                         break;
                     case android.app.slice.SliceItem.FORMAT_LONG:
@@ -305,19 +300,9 @@
                 break;
             case android.app.slice.SliceItem.FORMAT_TEXT:
                 if (item.getText() instanceof Spanned) {
-                    String text = Html.toHtml((Spanned) item.getText());
-                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
-                        // 19-21 don't allow special characters in XML, so we base64 encode it.
-                        text = Base64.encodeToString(text.getBytes(), Base64.NO_WRAP);
-                    }
-                    serializer.text(text);
+                    serializer.text(Html.toHtml((Spanned) item.getText()));
                 } else {
-                    String text = String.valueOf(item.getText());
-                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
-                        // 19-21 don't allow special characters in XML, so we base64 encode it.
-                        text = Base64.encodeToString(text.getBytes(), Base64.NO_WRAP);
-                    }
-                    serializer.text(text);
+                    serializer.text(String.valueOf(item.getText()));
                 }
                 break;
             case android.app.slice.SliceItem.FORMAT_LONG:
diff --git a/slices/view/src/main/java/androidx/slice/widget/GridContent.java b/slices/view/src/main/java/androidx/slice/widget/GridContent.java
index c194fef..69d5c44 100644
--- a/slices/view/src/main/java/androidx/slice/widget/GridContent.java
+++ b/slices/view/src/main/java/androidx/slice/widget/GridContent.java
@@ -17,6 +17,7 @@
 package androidx.slice.widget;
 
 import static android.app.slice.Slice.HINT_ACTIONS;
+import static android.app.slice.Slice.HINT_LIST_ITEM;
 import static android.app.slice.Slice.HINT_SEE_MORE;
 import static android.app.slice.Slice.HINT_SHORTCUT;
 import static android.app.slice.Slice.HINT_TITLE;
@@ -25,9 +26,9 @@
 import static android.app.slice.SliceItem.FORMAT_ACTION;
 import static android.app.slice.SliceItem.FORMAT_IMAGE;
 import static android.app.slice.SliceItem.FORMAT_INT;
-import static android.app.slice.SliceItem.FORMAT_LONG;
 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.slice.core.SliceHints.HINT_KEYWORDS;
 import static androidx.slice.core.SliceHints.HINT_LAST_UPDATED;
@@ -101,11 +102,7 @@
                 new String[] {HINT_ACTIONS} /* nonHints */);
         mAllImages = true;
         if (FORMAT_SLICE.equals(gridItem.getFormat())) {
-            List<SliceItem> items = gridItem.getSlice().getItems();
-            if (items.size() == 1 && FORMAT_SLICE.equals(items.get(0).getFormat())) {
-                // TODO: this can be removed at release
-                items = items.get(0).getSlice().getItems();
-            }
+            List<SliceItem> items = gridItem.getSlice().getItems().get(0).getSlice().getItems();
             items = filterAndProcessItems(items);
             // Check if it it's only one item that is a slice
             if (items.size() == 1 && items.get(0).getFormat().equals(FORMAT_SLICE)) {
@@ -200,14 +197,11 @@
         List<SliceItem> filteredItems = new ArrayList<>();
         for (int i = 0; i < items.size(); i++) {
             SliceItem item = items.get(i);
-            // TODO: This see more can be removed at release
-            boolean containsSeeMore = SliceQuery.find(item, null, HINT_SEE_MORE, null) != null;
-            boolean isNonCellContent = containsSeeMore
-                    || item.hasAnyHints(HINT_SHORTCUT, HINT_SEE_MORE, HINT_KEYWORDS, HINT_TTL,
-                            HINT_LAST_UPDATED);
+            boolean isNonCellContent = item.hasAnyHints(HINT_SHORTCUT, HINT_SEE_MORE,
+                    HINT_KEYWORDS, HINT_TTL, HINT_LAST_UPDATED);
             if (SUBTYPE_CONTENT_DESCRIPTION.equals(item.getSubType())) {
                 mContentDescr = item;
-            } else if (!isNonCellContent) {
+            } else if (item.hasHint(HINT_LIST_ITEM) && !isNonCellContent) {
                 filteredItems.add(item);
             }
         }
@@ -230,8 +224,6 @@
 
     /**
      * @return the height to display a grid row at when it is used as a small template.
-     * Does not include padding that might be added by slice view attributes,
-     * see {@link ListContent#getListHeight(Context, List)}.
      */
     public int getSmallHeight() {
         return getHeight(true /* isSmall */);
@@ -239,8 +231,6 @@
 
     /**
      * @return the height the content in this template requires to be displayed.
-     * Does not include padding that might be added by slice view attributes,
-     * see {@link ListContent#getListHeight(Context, List)}.
      */
     public int getActualHeight() {
         return getHeight(false /* isSmall */);
@@ -305,7 +295,7 @@
                     if (SUBTYPE_CONTENT_DESCRIPTION.equals(item.getSubType())) {
                         mContentDescr = item;
                     } else if (mTextCount < 2 && (FORMAT_TEXT.equals(itemFormat)
-                            || FORMAT_LONG.equals(itemFormat))) {
+                            || FORMAT_TIMESTAMP.equals(itemFormat))) {
                         mTextCount++;
                         mCellItems.add(item);
                     } else if (imageCount < 1 && FORMAT_IMAGE.equals(item.getFormat())) {
@@ -350,7 +340,7 @@
                     || cellItem.hasAnyHints(HINT_KEYWORDS, HINT_TTL, HINT_LAST_UPDATED);
             return !isNonCellContent
                     && (FORMAT_TEXT.equals(format)
-                    || FORMAT_LONG.equals(format)
+                    || FORMAT_TIMESTAMP.equals(format)
                     || FORMAT_IMAGE.equals(format));
         }
 
diff --git a/slices/view/src/main/java/androidx/slice/widget/GridRowView.java b/slices/view/src/main/java/androidx/slice/widget/GridRowView.java
index 78df091..4b8078c 100644
--- a/slices/view/src/main/java/androidx/slice/widget/GridRowView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/GridRowView.java
@@ -21,9 +21,9 @@
 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_LONG;
 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;
 
@@ -48,6 +48,7 @@
 
 import androidx.annotation.ColorInt;
 import androidx.annotation.RestrictTo;
+import androidx.slice.Slice;
 import androidx.slice.SliceItem;
 import androidx.slice.core.SliceQuery;
 import androidx.slice.view.R;
@@ -78,12 +79,9 @@
     private static final int MAX_CELL_IMAGES = 1;
 
     private int mRowIndex;
-    private int mRowCount;
-
     private int mSmallImageSize;
     private int mIconSize;
     private int mGutter;
-    private int mTextPadding;
 
     private GridContent mGridContent;
     private LinearLayout mViewContainer;
@@ -102,43 +100,17 @@
         mIconSize = res.getDimensionPixelSize(R.dimen.abc_slice_icon_size);
         mSmallImageSize = res.getDimensionPixelSize(R.dimen.abc_slice_small_image_size);
         mGutter = res.getDimensionPixelSize(R.dimen.abc_slice_grid_gutter);
-        mTextPadding = res.getDimensionPixelSize(R.dimen.abc_slice_grid_text_padding);
     }
 
     @Override
     public int getSmallHeight() {
         // GridRow is small if its the first element in a list without a header presented in small
-        if (mGridContent == null) {
-            return 0;
-        }
-        return mGridContent.getSmallHeight() + getExtraTopPadding() + getExtraBottomPadding();
+        return mGridContent != null ? mGridContent.getSmallHeight() : 0;
     }
 
     @Override
     public int getActualHeight() {
-        if (mGridContent == null) {
-            return 0;
-        }
-        return mGridContent.getActualHeight() + getExtraTopPadding() + getExtraBottomPadding();
-    }
-
-    private int getExtraTopPadding() {
-        if (mGridContent != null && mGridContent.isAllImages()) {
-            // Might need to add padding if in first or last position
-            if (mRowIndex == 0) {
-                return mGridTopPadding;
-            }
-        }
-        return 0;
-    }
-
-    private int getExtraBottomPadding() {
-        if (mGridContent != null && mGridContent.isAllImages()) {
-            if (mRowIndex == mRowCount - 1 || getMode() == MODE_SMALL) {
-                return mGridBottomPadding;
-            }
-        }
-        return 0;
+        return mGridContent != null ? mGridContent.getActualHeight() : 0;
     }
 
     @Override
@@ -160,19 +132,22 @@
         }
     }
 
+    @Override
+    public void setSlice(Slice slice) {
+        // Nothing to do
+    }
+
     /**
      * This is called when GridView is being used as a component in a larger template.
      */
     @Override
-    public void setSliceItem(SliceItem slice, boolean isHeader, int rowIndex,
-            int rowCount, SliceView.OnSliceActionListener observer) {
+    public void setSliceItem(SliceItem slice, boolean isHeader, int index,
+            SliceView.OnSliceActionListener observer) {
         resetView();
         setSliceActionListener(observer);
-        mRowIndex = rowIndex;
-        mRowCount = rowCount;
+        mRowIndex = index;
         mGridContent = new GridContent(getContext(), slice);
         populateViews(mGridContent);
-        mViewContainer.setPadding(0, getExtraTopPadding(), 0, getExtraBottomPadding());
     }
 
     private void populateViews(GridContent gc) {
@@ -229,11 +204,6 @@
             seeMoreView = (LinearLayout) inflater.inflate(
                     R.layout.abc_slice_grid_see_more, mViewContainer, false);
             extraText = seeMoreView.findViewById(R.id.text_see_more_count);
-
-            // Update text appearance
-            TextView moreText = seeMoreView.findViewById(R.id.text_see_more);
-            moreText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mGridTitleSize);
-            moreText.setTextColor(mTitleColor);
         }
         mViewContainer.addView(seeMoreView, new LinearLayout.LayoutParams(0, MATCH_PARENT, 1));
         extraText.setText(getResources().getString(R.string.abc_slice_more_content, numExtra));
@@ -279,29 +249,25 @@
             Iterator<SliceItem> iterator = textItems.iterator();
             while (textItems.size() > 1) {
                 SliceItem item = iterator.next();
-                if (!item.hasAnyHints(HINT_TITLE, HINT_LARGE)) {
+                if (!item.hasHint(HINT_TITLE)) {
                     iterator.remove();
                 }
             }
         }
-        SliceItem prevItem = null;
         for (int i = 0; i < cellItems.size(); i++) {
             SliceItem item = cellItems.get(i);
             final String itemFormat = item.getFormat();
-            int padding = determinePadding(prevItem);
             if (textCount < maxCellText && (FORMAT_TEXT.equals(itemFormat)
-                    || FORMAT_LONG.equals(itemFormat))) {
+                    || FORMAT_TIMESTAMP.equals(itemFormat))) {
                 if (textItems != null && !textItems.contains(item)) {
                     continue;
                 }
-                if (addItem(item, mTintColor, cellContainer, padding)) {
-                    prevItem = item;
+                if (addItem(item, mTintColor, cellContainer, singleItem)) {
                     textCount++;
                     added = true;
                 }
             } else if (imageCount < MAX_CELL_IMAGES && FORMAT_IMAGE.equals(item.getFormat())) {
-                if (addItem(item, mTintColor, cellContainer, 0)) {
-                    prevItem = item;
+                if (addItem(item, mTintColor, cellContainer, singleItem)) {
                     imageCount++;
                     added = true;
                 }
@@ -334,28 +300,22 @@
 
     /**
      * Adds simple items to a container. Simple items include icons, text, and timestamps.
-     *
-     * @param item item to add to the container.
-     * @param container the container to add to.
-     * @param padding the padding to apply to the item.
-     *
      * @return Whether an item was added.
      */
-    private boolean addItem(SliceItem item, int color, ViewGroup container, int padding) {
+    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_LONG.equals(format)) {
+        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);
-            tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, title ? mGridTitleSize : mGridSubtitleSize);
+            tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, title ? mTitleSize : mSubtitleSize);
             tv.setTextColor(title ? mTitleColor : mSubtitleColor);
-            CharSequence text = FORMAT_LONG.equals(format)
+            CharSequence text = FORMAT_TIMESTAMP.equals(format)
                     ? SliceViewUtil.getRelativeTimeString(item.getTimestamp())
                     : item.getText();
             tv.setText(text);
             container.addView(tv);
-            tv.setPadding(0, padding, 0, 0);
             addedView = tv;
         } else if (FORMAT_IMAGE.equals(format)) {
             ImageView iv = new ImageView(getContext());
@@ -379,19 +339,6 @@
         return addedView != null;
     }
 
-    private int determinePadding(SliceItem prevItem) {
-        if (prevItem == null) {
-            // No need for top padding
-            return 0;
-        } else if (FORMAT_IMAGE.equals(prevItem.getFormat())) {
-            return mTextPadding;
-        } else if (FORMAT_TEXT.equals(prevItem.getFormat())
-                || FORMAT_LONG.equals(prevItem.getFormat())) {
-            return mVerticalGridTextPadding;
-        }
-        return 0;
-    }
-
     private void makeClickable(View layout, boolean isClickable) {
         layout.setOnClickListener(isClickable ? this : null);
         layout.setBackground(isClickable
diff --git a/slices/view/src/main/java/androidx/slice/widget/LargeSliceAdapter.java b/slices/view/src/main/java/androidx/slice/widget/LargeSliceAdapter.java
index 81059d4..9e077ab 100644
--- a/slices/view/src/main/java/androidx/slice/widget/LargeSliceAdapter.java
+++ b/slices/view/src/main/java/androidx/slice/widget/LargeSliceAdapter.java
@@ -17,7 +17,6 @@
 package androidx.slice.widget;
 
 import static android.app.slice.Slice.HINT_HORIZONTAL;
-import static android.app.slice.Slice.HINT_SUMMARY;
 import static android.app.slice.Slice.SUBTYPE_MESSAGE;
 import static android.app.slice.Slice.SUBTYPE_SOURCE;
 import static android.app.slice.SliceItem.FORMAT_INT;
@@ -104,14 +103,14 @@
     /**
      * Set the {@link SliceItem}'s to be displayed in the adapter and the accent color.
      */
-    public void setSliceItems(List<SliceItem> slices, int color, int mode) {
+    public void setSliceItems(List<SliceItem> slices, int color) {
         if (slices == null) {
             mSlices.clear();
         } else {
             mIdGen.resetUsage();
             mSlices = new ArrayList<>(slices.size());
             for (SliceItem s : slices) {
-                mSlices.add(new SliceWrapper(s, mIdGen, mode));
+                mSlices.add(new SliceWrapper(s, mIdGen));
             }
         }
         mColor = color;
@@ -192,6 +191,8 @@
                         null);
                 break;
         }
+        int mode = mParent != null ? mParent.getMode() : MODE_LARGE;
+        ((SliceChildView) v).setMode(mode);
         return v;
     }
 
@@ -200,10 +201,10 @@
         private final int mType;
         private final long mId;
 
-        public SliceWrapper(SliceItem item, IdGenerator idGen, int mode) {
+        public SliceWrapper(SliceItem item, IdGenerator idGen) {
             mItem = item;
             mType = getFormat(item);
-            mId = idGen.getId(item, mode);
+            mId = idGen.getId(item);
         }
 
         public static int getFormat(SliceItem item) {
@@ -247,16 +248,14 @@
             mSliceChildView.setOnTouchListener(this);
 
             final boolean isHeader = position == HEADER_INDEX;
-            int mode = mParent != null ? mParent.getMode() : MODE_LARGE;
-            mSliceChildView.setMode(mode);
             mSliceChildView.setTint(mColor);
             mSliceChildView.setStyle(mAttrs, mDefStyleAttr, mDefStyleRes);
-            mSliceChildView.setSliceItem(item, isHeader, position, getItemCount(), mSliceObserver);
-            mSliceChildView.setSliceActions(isHeader ? mSliceActions : null);
-            mSliceChildView.setLastUpdated(isHeader ? mLastUpdated : -1);
-            mSliceChildView.setShowLastUpdated(isHeader && mShowLastUpdated);
-            if (mSliceChildView instanceof RowView) {
+            mSliceChildView.setSliceItem(item, isHeader, position, mSliceObserver);
+            if (isHeader && mSliceChildView instanceof RowView) {
                 ((RowView) mSliceChildView).setSingleItem(getItemCount() == 1);
+                mSliceChildView.setSliceActions(mSliceActions);
+                mSliceChildView.setLastUpdated(mLastUpdated);
+                mSliceChildView.setShowLastUpdated(mShowLastUpdated);
             }
             int[] info = new int[2];
             info[0] = ListContent.getRowType(mContext, item, isHeader, mSliceActions);
@@ -286,12 +285,8 @@
         private final ArrayMap<String, Long> mCurrentIds = new ArrayMap<>();
         private final ArrayMap<String, Integer> mUsedIds = new ArrayMap<>();
 
-        public long getId(SliceItem item, int mode) {
+        public long getId(SliceItem item) {
             String str = genString(item);
-            SliceItem summary = SliceQuery.find(item, null, HINT_SUMMARY, null);
-            if (summary != null) {
-                str += mode; // mode matters
-            }
             if (!mCurrentIds.containsKey(str)) {
                 mCurrentIds.put(str, mNextLong++);
             }
diff --git a/slices/view/src/main/java/androidx/slice/widget/LargeTemplateView.java b/slices/view/src/main/java/androidx/slice/widget/LargeTemplateView.java
index 0cba347..6632097 100644
--- a/slices/view/src/main/java/androidx/slice/widget/LargeTemplateView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/LargeTemplateView.java
@@ -16,7 +16,7 @@
 
 package androidx.slice.widget;
 
-import static androidx.slice.widget.SliceView.MODE_SMALL;
+import static android.app.slice.Slice.HINT_HORIZONTAL;
 
 import android.content.Context;
 import android.os.Build;
@@ -28,6 +28,7 @@
 import androidx.annotation.RestrictTo;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
+import androidx.slice.Slice;
 import androidx.slice.SliceItem;
 
 import java.util.ArrayList;
@@ -44,6 +45,7 @@
     private final View mForeground;
     private final LargeSliceAdapter mAdapter;
     private final RecyclerView mRecyclerView;
+    private Slice mSlice;
     private boolean mIsScrollable;
     private ListContent mListContent;
     private List<SliceItem> mDisplayedItems = new ArrayList<>();
@@ -129,8 +131,13 @@
             return 0;
         }
         SliceItem headerItem = mListContent.getHeaderItem();
-        return mListContent.getHeight(getContext(), headerItem, true /* isHeader */,
-                0 /* rowIndex */, 1 /* rowCount */, MODE_SMALL);
+        if (headerItem.hasHint(HINT_HORIZONTAL)) {
+            GridContent gc = new GridContent(getContext(), headerItem);
+            return gc.getSmallHeight();
+        } else {
+            RowContent rc = new RowContent(getContext(), headerItem, mListContent.hasHeader());
+            return rc.getSmallHeight();
+        }
     }
 
     @Override
@@ -153,8 +160,8 @@
     }
 
     @Override
-    public void setSliceContent(ListContent sliceContent) {
-        mListContent = sliceContent;
+    public void setSlice(Slice slice) {
+        mSlice = slice;
         populate();
     }
 
@@ -177,10 +184,11 @@
     }
 
     private void populate() {
-        if (mListContent == null) {
+        if (mSlice == null) {
             resetView();
             return;
         }
+        mListContent = new ListContent(getContext(), mSlice);
         updateDisplayedItems(getMeasuredHeight());
     }
 
@@ -208,21 +216,21 @@
         } else {
             mDisplayedItems = mListContent.getRowItems();
         }
-        mDisplayedItemsHeight = mListContent.getListHeight(getContext(), mDisplayedItems);
-        int mode = getMode();
-        if (mode == SliceView.MODE_LARGE) {
-            mAdapter.setSliceItems(mDisplayedItems, mTintColor, mode);
-        } else if (mode == MODE_SMALL) {
+        mDisplayedItemsHeight = ListContent.getListHeight(getContext(), mDisplayedItems);
+        if (getMode() == SliceView.MODE_LARGE) {
+            mAdapter.setSliceItems(mDisplayedItems, mTintColor);
+        } else if (getMode() == SliceView.MODE_SMALL) {
             mAdapter.setSliceItems(
-                    Collections.singletonList(mDisplayedItems.get(0)), mTintColor, mode);
+                    Collections.singletonList(mDisplayedItems.get(0)), mTintColor);
         }
     }
 
     @Override
     public void resetView() {
+        mSlice = null;
         mDisplayedItemsHeight = 0;
         mDisplayedItems.clear();
-        mAdapter.setSliceItems(null, -1, getMode());
+        mAdapter.setSliceItems(null, -1);
         mListContent = null;
     }
 }
diff --git a/slices/view/src/main/java/androidx/slice/widget/ListContent.java b/slices/view/src/main/java/androidx/slice/widget/ListContent.java
index 8f3cdf2..1dca6cb 100644
--- a/slices/view/src/main/java/androidx/slice/widget/ListContent.java
+++ b/slices/view/src/main/java/androidx/slice/widget/ListContent.java
@@ -30,12 +30,8 @@
 import static androidx.slice.core.SliceHints.HINT_KEYWORDS;
 import static androidx.slice.core.SliceHints.HINT_LAST_UPDATED;
 import static androidx.slice.core.SliceHints.HINT_TTL;
-import static androidx.slice.widget.SliceView.MODE_LARGE;
-import static androidx.slice.widget.SliceView.MODE_SMALL;
 
 import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -46,7 +42,6 @@
 import androidx.slice.core.SliceAction;
 import androidx.slice.core.SliceActionImpl;
 import androidx.slice.core.SliceQuery;
-import androidx.slice.view.R;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -58,7 +53,6 @@
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public class ListContent {
 
-    private Slice mSlice;
     private SliceItem mHeaderItem;
     private SliceItem mColorItem;
     private SliceItem mSeeMoreItem;
@@ -66,54 +60,8 @@
     private List<SliceItem> mSliceActions;
     private Context mContext;
 
-    private int mHeaderTitleSize;
-    private int mHeaderSubtitleSize;
-    private int mVerticalHeaderTextPadding;
-    private int mTitleSize;
-    private int mSubtitleSize;
-    private int mVerticalTextPadding;
-    private int mGridTitleSize;
-    private int mGridSubtitleSize;
-    private int mVerticalGridTextPadding;
-    private int mGridTopPadding;
-    private int mGridBottomPadding;
-
-    public ListContent(Context context, Slice slice, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        mSlice = slice;
+    public ListContent(Context context, Slice slice) {
         mContext = context;
-
-        // TODO: duplicated code from SliceChildView; could do something better
-        // Some of this information will impact the size calculations for slice content.
-        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SliceView,
-                defStyleAttr, defStyleRes);
-        try {
-            mHeaderTitleSize = (int) a.getDimension(
-                    R.styleable.SliceView_headerTitleSize, 0);
-            mHeaderSubtitleSize = (int) a.getDimension(
-                    R.styleable.SliceView_headerSubtitleSize, 0);
-            mVerticalHeaderTextPadding = (int) a.getDimension(
-                    R.styleable.SliceView_headerTextVerticalPadding, 0);
-
-            mTitleSize = (int) a.getDimension(R.styleable.SliceView_titleSize, 0);
-            mSubtitleSize = (int) a.getDimension(
-                    R.styleable.SliceView_subtitleSize, 0);
-            mVerticalTextPadding = (int) a.getDimension(
-                    R.styleable.SliceView_textVerticalPadding, 0);
-
-            mGridTitleSize = (int) a.getDimension(R.styleable.SliceView_gridTitleSize, 0);
-            mGridSubtitleSize = (int) a.getDimension(
-                    R.styleable.SliceView_gridSubtitleSize, 0);
-            int defaultVerticalGridPadding = context.getResources().getDimensionPixelSize(
-                    R.dimen.abc_slice_grid_text_inner_padding);
-            mVerticalGridTextPadding = (int) a.getDimension(
-                    R.styleable.SliceView_gridTextVerticalPadding, defaultVerticalGridPadding);
-            mGridTopPadding = (int) a.getDimension(R.styleable.SliceView_gridTopPadding, 0);
-            mGridBottomPadding = (int) a.getDimension(R.styleable.SliceView_gridTopPadding, 0);
-        } finally {
-            a.recycle();
-        }
-
         populate(slice);
     }
 
@@ -159,7 +107,7 @@
      *
      * @return the total height of all the rows contained in the provided list.
      */
-    public int getListHeight(Context context, List<SliceItem> listItems) {
+    public static int getListHeight(Context context, List<SliceItem> listItems) {
         if (listItems == null) {
             return 0;
         }
@@ -171,12 +119,10 @@
             hasRealHeader = !maybeHeader.hasAnyHints(HINT_LIST_ITEM, HINT_HORIZONTAL);
         }
         if (listItems.size() == 1 && !maybeHeader.hasHint(HINT_HORIZONTAL)) {
-            return getHeight(context, maybeHeader, true /* isHeader */, 0, 1, MODE_LARGE);
+            return getHeight(context, maybeHeader, true);
         }
-        int rowCount = listItems.size();
         for (int i = 0; i < listItems.size(); i++) {
-            height += getHeight(context, listItems.get(i), i == 0 && hasRealHeader /* isHeader */,
-                    i, rowCount, MODE_LARGE);
+            height += getHeight(context, listItems.get(i), i == 0 && hasRealHeader /* isHeader */);
         }
         return height;
     }
@@ -203,10 +149,8 @@
             RowContent rc = new RowContent(mContext, mSeeMoreItem, false /* isHeader */);
             visibleHeight += rc.getActualHeight();
         }
-        int rowCount = mRowItems.size();
-        for (int i = 0; i < rowCount; i++) {
-            int itemHeight = getHeight(mContext, mRowItems.get(i), i == 0 /* isHeader */,
-                    i, rowCount, MODE_LARGE);
+        for (int i = 0; i < mRowItems.size(); i++) {
+            int itemHeight = getHeight(mContext, mRowItems.get(i), i == 0 /* isHeader */);
             if ((height == -1 && i > idealItemCount)
                     || (height > 0 && visibleHeight + itemHeight > height)) {
                 break;
@@ -226,20 +170,13 @@
         return visibleItems;
     }
 
-    /**
-     * Determines the height of the provided {@link SliceItem}.
-     */
-    public int getHeight(Context context, SliceItem item, boolean isHeader, int index,
-            int count, int mode) {
+    private static int getHeight(Context context, SliceItem item, boolean isHeader) {
         if (item.hasHint(HINT_HORIZONTAL)) {
             GridContent gc = new GridContent(context, item);
-            int topPadding = gc.isAllImages() && index == 0 ? mGridTopPadding : 0;
-            int bottomPadding = gc.isAllImages() && index == count - 1 ? mGridBottomPadding : 0;
-            int height = mode == MODE_SMALL ? gc.getSmallHeight() : gc.getActualHeight();
-            return height + topPadding + bottomPadding;
+            return gc.getActualHeight();
         } else {
             RowContent rc = new RowContent(context, item, isHeader);
-            return mode == MODE_SMALL ? rc.getSmallHeight() : rc.getActualHeight();
+            return rc.getActualHeight();
         }
     }
 
@@ -251,11 +188,6 @@
     }
 
     @Nullable
-    public Slice getSlice() {
-        return mSlice;
-    }
-
-    @Nullable
     public SliceItem getColorItem() {
         return mColorItem;
     }
@@ -359,7 +291,7 @@
     private static SliceItem findHeaderItem(@NonNull Slice slice) {
         // See if header is specified
         String[] nonHints = new String[] {HINT_LIST_ITEM, HINT_SHORTCUT, HINT_ACTIONS,
-                HINT_KEYWORDS, HINT_TTL, HINT_LAST_UPDATED, HINT_HORIZONTAL};
+                HINT_KEYWORDS, HINT_TTL, HINT_LAST_UPDATED};
         SliceItem header = SliceQuery.find(slice, FORMAT_SLICE, null, nonHints);
         if (header != null && isValidHeader(header)) {
             return header;
@@ -370,7 +302,7 @@
     @Nullable
     private static SliceItem getSeeMoreItem(@NonNull Slice slice) {
         SliceItem item = SliceQuery.find(slice, null, HINT_SEE_MORE, null);
-        if (item != null) {
+        if (item != null && item.hasHint(HINT_SEE_MORE)) {
             if (FORMAT_SLICE.equals(item.getFormat())) {
                 List<SliceItem> items = item.getSlice().getItems();
                 if (items.size() == 1 && FORMAT_ACTION.equals(items.get(0).getFormat())) {
diff --git a/slices/view/src/main/java/androidx/slice/widget/MessageView.java b/slices/view/src/main/java/androidx/slice/widget/MessageView.java
index c597ed4..6035d0a 100644
--- a/slices/view/src/main/java/androidx/slice/widget/MessageView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/MessageView.java
@@ -30,6 +30,7 @@
 import android.widget.TextView;
 
 import androidx.annotation.RestrictTo;
+import androidx.slice.Slice;
 import androidx.slice.SliceItem;
 import androidx.slice.core.SliceQuery;
 
@@ -56,6 +57,11 @@
     }
 
     @Override
+    public void setSlice(Slice slice) {
+        // Do nothing it's always a list item
+    }
+
+    @Override
     public void resetView() {
         // TODO
     }
@@ -69,7 +75,7 @@
 
     @Override
     public void setSliceItem(SliceItem slice, boolean isHeader, int index,
-            int rowCount, SliceView.OnSliceActionListener observer) {
+            SliceView.OnSliceActionListener observer) {
         setSliceActionListener(observer);
         mRowIndex = index;
         SliceItem source = SliceQuery.findSubtype(slice, FORMAT_IMAGE, SUBTYPE_SOURCE);
diff --git a/slices/view/src/main/java/androidx/slice/widget/RowContent.java b/slices/view/src/main/java/androidx/slice/widget/RowContent.java
index 5ef06e9..bc3826f 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowContent.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowContent.java
@@ -16,7 +16,7 @@
 
 package androidx.slice.widget;
 
-import static android.app.slice.Slice.HINT_HORIZONTAL;
+import static android.app.slice.Slice.HINT_ACTIONS;
 import static android.app.slice.Slice.HINT_PARTIAL;
 import static android.app.slice.Slice.HINT_SEE_MORE;
 import static android.app.slice.Slice.HINT_SHORTCUT;
@@ -27,10 +27,10 @@
 import static android.app.slice.SliceItem.FORMAT_ACTION;
 import static android.app.slice.SliceItem.FORMAT_IMAGE;
 import static android.app.slice.SliceItem.FORMAT_INT;
-import static android.app.slice.SliceItem.FORMAT_LONG;
 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 static androidx.slice.core.SliceHints.HINT_KEYWORDS;
 import static androidx.slice.core.SliceHints.HINT_LAST_UPDATED;
@@ -95,7 +95,15 @@
             Log.w(TAG, "Provided SliceItem is invalid for RowContent");
             return false;
         }
-        determineStartAndPrimaryAction(rowSlice);
+        // Find primary action first (otherwise filtered out of valid row items)
+        String[] hints = new String[] {HINT_SHORTCUT, HINT_TITLE};
+        mPrimaryAction = SliceQuery.find(rowSlice, FORMAT_SLICE, hints,
+                new String[] { HINT_ACTIONS, HINT_KEYWORDS} /* nonHints */);
+
+        if (mPrimaryAction == null && FORMAT_ACTION.equals(rowSlice.getFormat())
+                && rowSlice.getSlice().getItems().size() == 1) {
+            mPrimaryAction = rowSlice;
+        }
 
         mContentDescr = SliceQuery.findSubtype(rowSlice, FORMAT_TEXT, SUBTYPE_CONTENT_DESCRIPTION);
 
@@ -104,7 +112,7 @@
         // If we've only got one item that's a slice / action use those items instead
         if (rowItems.size() == 1 && (FORMAT_ACTION.equals(rowItems.get(0).getFormat())
                 || FORMAT_SLICE.equals(rowItems.get(0).getFormat()))
-                && !rowItems.get(0).hasAnyHints(HINT_SHORTCUT, HINT_TITLE)) {
+                && !rowItems.get(0).hasHint(HINT_SHORTCUT)) {
             if (isValidRow(rowItems.get(0))) {
                 rowSlice = rowItems.get(0);
                 rowItems = filterInvalidItems(rowSlice);
@@ -114,12 +122,14 @@
             mRange = rowSlice;
         }
         if (rowItems.size() > 0) {
-            // Remove the things we already know about
-            if (mStartItem != null) {
-                rowItems.remove(mStartItem);
-            }
-            if (mPrimaryAction != null) {
-                rowItems.remove(mPrimaryAction);
+            // Start item
+            SliceItem firstItem = rowItems.get(0);
+            if (FORMAT_SLICE.equals(firstItem.getFormat())) {
+                SliceItem unwrappedItem = firstItem.getSlice().getItems().get(0);
+                if (isStartType(unwrappedItem)) {
+                    mStartItem = unwrappedItem;
+                    rowItems.remove(0);
+                }
             }
 
             // Text + end items
@@ -147,11 +157,11 @@
             }
             // Special rules for end items: only one timestamp
             boolean hasTimestamp = mStartItem != null
-                    && FORMAT_LONG.equals(mStartItem.getFormat());
+                    && FORMAT_TIMESTAMP.equals(mStartItem.getFormat());
             for (int i = 0; i < endItems.size(); i++) {
                 final SliceItem item = endItems.get(i);
                 boolean isAction = SliceQuery.find(item, FORMAT_ACTION) != null;
-                if (FORMAT_LONG.equals(item.getFormat())) {
+                if (FORMAT_TIMESTAMP.equals(item.getFormat())) {
                     if (!hasTimestamp) {
                         hasTimestamp = true;
                         mEndItems.add(item);
@@ -176,37 +186,6 @@
     }
 
     /**
-     * Sets the {@link #getPrimaryAction()} and {@link #getStartItem()} for this row.
-     */
-    private void determineStartAndPrimaryAction(@NonNull SliceItem rowSlice) {
-        List<SliceItem> possibleStartItems = SliceQuery.findAll(rowSlice, null, HINT_TITLE, null);
-        if (possibleStartItems.size() > 0) {
-            // The start item will be at position 0 if it exists
-            String format = possibleStartItems.get(0).getFormat();
-            if ((FORMAT_ACTION.equals(format)
-                    && SliceQuery.find(possibleStartItems.get(0), FORMAT_IMAGE) != null)
-                    || FORMAT_SLICE.equals(format)
-                    || FORMAT_LONG.equals(format)
-                    || FORMAT_IMAGE.equals(format)) {
-                mStartItem = possibleStartItems.get(0);
-            }
-        }
-
-        String[] hints = new String[] {HINT_SHORTCUT, HINT_TITLE};
-        List<SliceItem> possiblePrimaries = SliceQuery.findAll(rowSlice, FORMAT_SLICE, hints, null);
-        if (possiblePrimaries.isEmpty() && FORMAT_ACTION.equals(rowSlice.getFormat())
-                && rowSlice.getSlice().getItems().size() == 1) {
-            mPrimaryAction = rowSlice;
-        } else if (mStartItem != null && possiblePrimaries.size() > 1
-                && possiblePrimaries.get(0) == mStartItem) {
-            // Next item is the primary action
-            mPrimaryAction = possiblePrimaries.get(1);
-        } else if (possiblePrimaries.size() > 0) {
-            mPrimaryAction = possiblePrimaries.get(0);
-        }
-    }
-
-    /**
      * @return the {@link SliceItem} used to populate this row.
      */
     @NonNull
@@ -223,22 +202,6 @@
     }
 
     /**
-     * @return the {@link SliceItem} for the icon to use for the input range thumb drawable.
-     */
-    @Nullable
-    public SliceItem getInputRangeThumb() {
-        if (mRange != null) {
-            List<SliceItem> items = mRange.getSlice().getItems();
-            for (int i = 0; i < items.size(); i++) {
-                if (FORMAT_IMAGE.equals(items.get(i).getFormat())) {
-                    return items.get(i);
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
      * @return the {@link SliceItem} used for the main intent for this row; can be null.
      */
     @Nullable
@@ -358,7 +321,6 @@
      */
     public boolean isValid() {
         return mStartItem != null
-                || mPrimaryAction != null
                 || mTitleItem != null
                 || mSubtitleItem != null
                 || mEndItems.size() > 0
@@ -376,17 +338,17 @@
         // Must be slice or action
         if (FORMAT_SLICE.equals(rowSlice.getFormat())
                 || FORMAT_ACTION.equals(rowSlice.getFormat())) {
-            List<SliceItem> rowItems = rowSlice.getSlice().getItems();
-            // Special case: default see more just has an action but no other items
-            if (rowSlice.hasHint(HINT_SEE_MORE) && rowItems.isEmpty()) {
-                return true;
-            }
             // Must have at least one legitimate child
+            List<SliceItem> rowItems = rowSlice.getSlice().getItems();
             for (int i = 0; i < rowItems.size(); i++) {
                 if (isValidRowContent(rowSlice, rowItems.get(i))) {
                     return true;
                 }
             }
+            // Special case: default see more just has an action but no other items
+            if (rowSlice.hasHint(HINT_SEE_MORE) && rowItems.isEmpty()) {
+                return true;
+            }
         }
         return false;
     }
@@ -406,20 +368,39 @@
     }
 
     /**
-     * @return whether this item is valid content to visibly appear in a row.
+     * @return whether this item is valid content to display in a row.
      */
     private static boolean isValidRowContent(SliceItem slice, SliceItem item) {
-        if (item.hasAnyHints(HINT_KEYWORDS, HINT_TTL, HINT_LAST_UPDATED, HINT_HORIZONTAL)
-                || SUBTYPE_CONTENT_DESCRIPTION.equals(item.getSubType())) {
+        if (item.hasAnyHints(HINT_KEYWORDS, HINT_TTL, HINT_LAST_UPDATED)) {
             return false;
         }
+        if (FORMAT_SLICE.equals(item.getFormat()) && !item.hasHint(HINT_SHORTCUT)) {
+            // Unpack contents of slice
+            item = item.getSlice().getItems().get(0);
+        }
         final String itemFormat = item.getFormat();
-        return FORMAT_IMAGE.equals(itemFormat)
-                || FORMAT_TEXT.equals(itemFormat)
-                || FORMAT_LONG.equals(itemFormat)
-                || FORMAT_ACTION.equals(itemFormat)
+        return (FORMAT_TEXT.equals(itemFormat)
+                && !SUBTYPE_CONTENT_DESCRIPTION.equals(item.getSubType()))
+                || FORMAT_IMAGE.equals(itemFormat)
+                || FORMAT_TIMESTAMP.equals(itemFormat)
                 || FORMAT_REMOTE_INPUT.equals(itemFormat)
-                || FORMAT_SLICE.equals(itemFormat)
+                || (FORMAT_SLICE.equals(itemFormat) && item.hasHint(HINT_TITLE)
+                && !item.hasHint(HINT_SHORTCUT))
+                || (FORMAT_SLICE.equals(itemFormat) && item.hasHint(HINT_SHORTCUT)
+                && !item.hasHint(HINT_TITLE))
+                || FORMAT_ACTION.equals(itemFormat)
                 || (FORMAT_INT.equals(itemFormat) && SUBTYPE_RANGE.equals(slice.getSubType()));
     }
+
+    /**
+     * @return Whether this item is appropriate to be considered a "start" item, i.e. go in the
+     *         front slot of a row.
+     */
+    private static boolean isStartType(SliceItem item) {
+        final String type = item.getFormat();
+        return (FORMAT_ACTION.equals(type) && (SliceQuery.find(item, FORMAT_IMAGE) != null))
+                    || FORMAT_IMAGE.equals(type)
+                    || (FORMAT_TIMESTAMP.equals(type)
+                && !item.hasAnyHints(HINT_TTL, HINT_LAST_UPDATED));
+    }
 }
diff --git a/slices/view/src/main/java/androidx/slice/widget/RowView.java b/slices/view/src/main/java/androidx/slice/widget/RowView.java
index d9cf7d7..2479d70 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowView.java
@@ -21,12 +21,13 @@
 import static android.app.slice.Slice.HINT_PARTIAL;
 import static android.app.slice.Slice.HINT_SHORTCUT;
 import static android.app.slice.Slice.SUBTYPE_MAX;
+import static android.app.slice.Slice.SUBTYPE_TOGGLE;
 import static android.app.slice.Slice.SUBTYPE_VALUE;
 import static android.app.slice.SliceItem.FORMAT_ACTION;
 import static android.app.slice.SliceItem.FORMAT_IMAGE;
 import static android.app.slice.SliceItem.FORMAT_INT;
-import static android.app.slice.SliceItem.FORMAT_LONG;
 import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
 
 import static androidx.slice.core.SliceHints.ICON_IMAGE;
 import static androidx.slice.core.SliceHints.SMALL_IMAGE;
@@ -45,7 +46,6 @@
 import android.text.SpannableString;
 import android.text.TextUtils;
 import android.text.style.StyleSpan;
-import android.util.ArrayMap;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
@@ -62,11 +62,13 @@
 import androidx.annotation.RestrictTo;
 import androidx.core.graphics.drawable.DrawableCompat;
 import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
 import androidx.slice.SliceItem;
 import androidx.slice.core.SliceActionImpl;
 import androidx.slice.core.SliceQuery;
 import androidx.slice.view.R;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -90,7 +92,7 @@
     private TextView mSecondaryText;
     private TextView mLastUpdatedText;
     private View mDivider;
-    private ArrayMap<SliceActionImpl, SliceActionView> mToggles = new ArrayMap<>();
+    private ArrayList<SliceActionView> mToggles = new ArrayList<>();
     private LinearLayout mEndContainer;
     private ProgressBar mRangeBar;
     private View mSeeMoreView;
@@ -215,12 +217,17 @@
         }
     }
 
+    @Override
+    public void setSlice(Slice slice) {
+        // Nothing to do
+    }
+
     /**
      * This is called when RowView is being used as a component in a large template.
      */
     @Override
     public void setSliceItem(SliceItem slice, boolean isHeader, int index,
-            int rowCount, SliceView.OnSliceActionListener observer) {
+            SliceView.OnSliceActionListener observer) {
         setSliceActionListener(observer);
         mRowIndex = index;
         mIsHeader = ListContent.isValidHeader(slice);
@@ -239,9 +246,9 @@
         if (contentDescr != null) {
             mContent.setContentDescription(contentDescr);
         }
+        boolean showStart = false;
         final SliceItem startItem = mRowContent.getStartItem();
-        boolean showStart = startItem != null && mRowIndex > 0;
-        if (showStart) {
+        if (startItem != null) {
             showStart = addItem(startItem, mTintColor, true /* isStart */);
         }
         mStartContainer.setVisibility(showStart ? View.VISIBLE : View.GONE);
@@ -262,12 +269,11 @@
         addSubtitle(subtitleItem);
 
         SliceItem primaryAction = mRowContent.getPrimaryAction();
-        if (primaryAction != null && primaryAction != startItem) {
+        if (primaryAction != null) {
             mRowAction = new SliceActionImpl(primaryAction);
             if (mRowAction.isToggle()) {
                 // If primary action is a toggle, add it and we're done
                 addAction(mRowAction, mTintColor, mEndContainer, false /* isStart */);
-                // TODO: if start item is tappable, touch feedback should exclude it
                 setViewClickable(mRootView, true);
                 return;
             }
@@ -284,10 +290,16 @@
 
         // If we're here we can can show end items; check for top level actions first
         List<SliceItem> endItems = mRowContent.getEndItems();
-        if (mHeaderActions != null && mHeaderActions.size() > 0) {
+        if (mIsHeader && mHeaderActions != null && mHeaderActions.size() > 0) {
             // Use these if we have them instead
             endItems = mHeaderActions;
         }
+        boolean hasRowAction = mRowAction != null;
+        if (endItems.isEmpty()) {
+            if (hasRowAction) setViewClickable(mRootView, true);
+            return;
+        }
+
         // If we're here we might be able to show end items
         int itemCount = 0;
         boolean firstItemIsADefaultToggle = false;
@@ -296,7 +308,7 @@
             final SliceItem endItem = endItems.get(i);
             if (itemCount < MAX_END_ITEMS) {
                 if (addItem(endItem, mTintColor, false /* isStart */)) {
-                    if (SliceQuery.find(endItem, FORMAT_ACTION) != null) {
+                    if (FORMAT_ACTION.equals(endItem.getFormat())) {
                         hasEndItemAction = true;
                     }
                     itemCount++;
@@ -309,21 +321,19 @@
         }
 
         // If there is a row action and the first end item is a default toggle, show the divider.
-        mDivider.setVisibility(mRowAction != null && firstItemIsADefaultToggle
+        mDivider.setVisibility(hasRowAction && firstItemIsADefaultToggle
                 ? View.VISIBLE : View.GONE);
-        boolean hasStartAction = startItem != null
-                && SliceQuery.find(startItem, FORMAT_ACTION) != null;
-
-        if (mRowAction != null) {
-            // If there are outside actions make only the content bit clickable
-            // TODO: if start item is an image touch feedback should include it
-            setViewClickable((hasEndItemAction || hasStartAction) ? mContent : mRootView, true);
-        } else if (hasEndItemAction != hasStartAction && (itemCount == 1 || hasStartAction)) {
-            // Single action; make whole row clickable for it
-            if (!mToggles.isEmpty()) {
-                mRowAction = mToggles.keySet().iterator().next();
+        if (hasRowAction) {
+            if (itemCount > 0 && hasEndItemAction) {
+                setViewClickable(mContent, true);
             } else {
-                mRowAction = new SliceActionImpl(hasEndItemAction ? endItems.get(0) : startItem);
+                setViewClickable(mRootView, true);
+            }
+        } else if (mRowContent.endItemsContainAction() && itemCount == 1) {
+            // If the only end item is an action, make the whole row clickable.
+            SliceItem unwrappedActionItem = endItems.get(0).getSlice().getItems().get(0);
+            if (!SUBTYPE_TOGGLE.equals(unwrappedActionItem.getSubType())) {
+                mRowAction = new SliceActionImpl(endItems.get(0));
             }
             setViewClickable(mRootView, true);
         }
@@ -331,7 +341,7 @@
 
     private void addSubtitle(final SliceItem subtitleItem) {
         CharSequence subtitleTimeString = null;
-        if (mShowLastUpdated && mLastUpdated != -1) {
+        if (mShowLastUpdated) {
             subtitleTimeString = getResources().getString(R.string.abc_slice_updated,
                     SliceViewUtil.getRelativeTimeString(mLastUpdated));
         }
@@ -344,8 +354,6 @@
                     ? mHeaderSubtitleSize
                     : mSubtitleSize);
             mSecondaryText.setTextColor(mSubtitleColor);
-            int verticalPadding = mIsHeader ? mVerticalHeaderTextPadding : mVerticalTextPadding;
-            mSecondaryText.setPadding(0, verticalPadding, 0, 0);
         }
         if (subtitleTimeString != null) {
             if (!TextUtils.isEmpty(subtitle)) {
@@ -390,7 +398,7 @@
         addView(progressBar);
         mRangeBar = progressBar;
         if (isSeekBar) {
-            SliceItem thumb = mRowContent.getInputRangeThumb();
+            SliceItem thumb = SliceQuery.find(range, FORMAT_IMAGE);
             SeekBar seekBar = (SeekBar) mRangeBar;
             if (thumb != null) {
                 seekBar.setThumb(thumb.getIcon().loadDrawable(getContext()));
@@ -437,8 +445,9 @@
             info.setPosition(EventInfo.POSITION_START, 0, 1);
         }
         sav.setAction(actionContent, info, mObserver, color);
+
         if (isToggle) {
-            mToggles.put(actionContent, sav);
+            mToggles.add(sav);
         }
     }
 
@@ -451,8 +460,7 @@
         int imageMode = 0;
         SliceItem timeStamp = null;
         ViewGroup container = isStart ? mStartContainer : mEndContainer;
-        if (FORMAT_SLICE.equals(sliceItem.getFormat())
-                || FORMAT_ACTION.equals(sliceItem.getFormat())) {
+        if (FORMAT_SLICE.equals(sliceItem.getFormat())) {
             if (sliceItem.hasHint(HINT_SHORTCUT)) {
                 addAction(new SliceActionImpl(sliceItem), color, container, isStart);
                 return true;
@@ -464,7 +472,7 @@
         if (FORMAT_IMAGE.equals(sliceItem.getFormat())) {
             icon = sliceItem.getIcon();
             imageMode = sliceItem.hasHint(HINT_NO_TINT) ? SMALL_IMAGE : ICON_IMAGE;
-        } else if (FORMAT_LONG.equals(sliceItem.getFormat())) {
+        } else if (FORMAT_TIMESTAMP.equals(sliceItem.getFormat())) {
             timeStamp = sliceItem;
         }
         View addedView = null;
@@ -521,25 +529,21 @@
 
     @Override
     public void onClick(View view) {
-        if (mRowAction != null && mRowAction.getActionItem() != null) {
-            // Check if it's a row click for a toggle, in this case need to update the UI
-            if (mRowAction.isToggle() && !(view instanceof SliceActionView)) {
-                SliceActionView sav = mToggles.get(mRowAction);
-                if (sav != null) {
-                    sav.toggle();
+        if (mRowAction != null && mRowAction.getActionItem() != null && !mRowAction.isToggle()) {
+            // Check for a row action
+            try {
+                mRowAction.getActionItem().fireAction(null, null);
+                if (mObserver != null) {
+                    EventInfo info = new EventInfo(getMode(), EventInfo.ACTION_TYPE_CONTENT,
+                            EventInfo.ROW_TYPE_LIST, mRowIndex);
+                    mObserver.onSliceAction(info, mRowAction.getSliceItem());
                 }
-            } else {
-                try {
-                    mRowAction.getActionItem().fireAction(null, null);
-                    if (mObserver != null) {
-                        EventInfo info = new EventInfo(getMode(), EventInfo.ACTION_TYPE_CONTENT,
-                                EventInfo.ROW_TYPE_LIST, mRowIndex);
-                        mObserver.onSliceAction(info, mRowAction.getSliceItem());
-                    }
-                } catch (CanceledException e) {
-                    Log.e(TAG, "PendingIntent for slice cannot be sent", e);
-                }
+            } catch (CanceledException e) {
+                Log.e(TAG, "PendingIntent for slice cannot be sent", e);
             }
+        } else if (mToggles.size() == 1) {
+            // If there is only one toggle and no row action, just toggle it.
+            mToggles.get(0).toggle();
         }
     }
 
@@ -553,18 +557,16 @@
 
     @Override
     public void resetView() {
-        mRootView.setVisibility(VISIBLE);
+        mRootView.setVisibility(View.VISIBLE);
         setViewClickable(mRootView, false);
         setViewClickable(mContent, false);
         mStartContainer.removeAllViews();
         mEndContainer.removeAllViews();
         mPrimaryText.setText(null);
         mSecondaryText.setText(null);
-        mLastUpdatedText.setText(null);
-        mLastUpdatedText.setVisibility(GONE);
         mToggles.clear();
         mRowAction = null;
-        mDivider.setVisibility(GONE);
+        mDivider.setVisibility(View.GONE);
         if (mRangeBar != null) {
             removeView(mRangeBar);
         }
diff --git a/slices/view/src/main/java/androidx/slice/widget/ShortcutView.java b/slices/view/src/main/java/androidx/slice/widget/ShortcutView.java
index 2f97c64..37ef17b 100644
--- a/slices/view/src/main/java/androidx/slice/widget/ShortcutView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/ShortcutView.java
@@ -26,6 +26,7 @@
 import static android.app.slice.SliceItem.FORMAT_SLICE;
 import static android.app.slice.SliceItem.FORMAT_TEXT;
 
+import android.annotation.SuppressLint;
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
 import android.content.Context;
@@ -42,7 +43,6 @@
 import android.widget.ImageView;
 
 import androidx.annotation.RestrictTo;
-import androidx.core.graphics.drawable.DrawableCompat;
 import androidx.slice.Slice;
 import androidx.slice.SliceItem;
 import androidx.slice.core.SliceQuery;
@@ -56,7 +56,7 @@
 
     private static final String TAG = "ShortcutView";
 
-    private ListContent mListContent;
+    private Slice mSlice;
     private Uri mUri;
     private SliceItem mActionItem;
     private SliceItem mLabel;
@@ -72,23 +72,21 @@
         mLargeIconSize = res.getDimensionPixelSize(R.dimen.abc_slice_shortcut_size);
     }
 
+    @SuppressLint("NewApi") // mIcon can only be non-null on API 23+
     @Override
-    public void setSliceContent(ListContent sliceContent) {
+    public void setSlice(Slice slice) {
         resetView();
-        mListContent = sliceContent;
-        if (mListContent == null) {
-            return;
-        }
-        determineShortcutItems(getContext());
-        SliceItem colorItem = mListContent.getColorItem();
+        mSlice = slice;
+        determineShortcutItems(getContext(), slice);
+        SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
         if (colorItem == null) {
-            colorItem = SliceQuery.findSubtype(sliceContent.getSlice(), FORMAT_INT, SUBTYPE_COLOR);
+            colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
         }
         final int color = colorItem != null
                 ? colorItem.getInt()
                 : SliceViewUtil.getColorAccent(getContext());
-        Drawable circle = DrawableCompat.wrap(new ShapeDrawable(new OvalShape()));
-        DrawableCompat.setTint(circle, color);
+        ShapeDrawable circle = new ShapeDrawable(new OvalShape());
+        circle.setTint(color);
         ImageView iv = new ImageView(getContext());
         if (mIcon != null && !mIcon.hasHint(HINT_NO_TINT)) {
             // Only set the background if we're tintable
@@ -100,7 +98,7 @@
             final int iconSize = isImage ? mLargeIconSize : mSmallIconSize;
             SliceViewUtil.createCircledIcon(getContext(), iconSize, mIcon.getIcon(),
                     isImage, this /* parent */);
-            mUri = sliceContent.getSlice().getUri();
+            mUri = slice.getUri();
             setClickable(true);
         } else {
             setClickable(false);
@@ -114,9 +112,6 @@
 
     @Override
     public boolean performClick() {
-        if (mListContent == null) {
-            return false;
-        }
         if (!callOnClick()) {
             try {
                 if (mActionItem != null) {
@@ -132,8 +127,8 @@
                             EventInfo.ROW_TYPE_SHORTCUT, 0 /* rowIndex */);
                     SliceItem interactedItem = mActionItem != null
                             ? mActionItem
-                            : new SliceItem(mListContent.getSlice(), FORMAT_SLICE,
-                                    null /* subtype */, mListContent.getSlice().getHints());
+                            : new SliceItem(mSlice, FORMAT_SLICE, null /* subtype */,
+                                    mSlice.getHints());
                     mObserver.onSliceAction(ei, interactedItem);
                 }
             } catch (CanceledException e) {
@@ -146,12 +141,9 @@
     /**
      * Looks at the slice and determines which items are best to use to compose the shortcut.
      */
-    private void determineShortcutItems(Context context) {
-        if (mListContent == null) {
-            return;
-        }
-        SliceItem primaryAction = mListContent.getPrimaryAction();
-        Slice slice = mListContent.getSlice();
+    private void determineShortcutItems(Context context, Slice slice) {
+        ListContent lc = new ListContent(context, slice);
+        SliceItem primaryAction = lc.getPrimaryAction();
 
         if (primaryAction != null) {
             // Preferred case: slice has a primary action
@@ -203,7 +195,7 @@
                 if (mActionItem == null) {
                     mActionItem = new SliceItem(PendingIntent.getActivity(context, 0,
                             pm.getLaunchIntentForPackage(appInfo.packageName), 0),
-                            new Slice.Builder(slice.getUri()).build(), FORMAT_ACTION,
+                            new Slice.Builder(slice.getUri()).build(), FORMAT_SLICE,
                             null /* subtype */, null);
                 }
             }
@@ -212,7 +204,7 @@
 
     @Override
     public void resetView() {
-        mListContent = null;
+        mSlice = null;
         mUri = null;
         mActionItem = null;
         mLabel = null;
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceChildView.java b/slices/view/src/main/java/androidx/slice/widget/SliceChildView.java
index fcd71bb..2400e738c 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceChildView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceChildView.java
@@ -19,11 +19,13 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.view.View;
 import android.widget.FrameLayout;
 
 import androidx.annotation.ColorInt;
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
+import androidx.slice.Slice;
 import androidx.slice.SliceItem;
 import androidx.slice.view.R;
 
@@ -43,15 +45,10 @@
     protected int mSubtitleColor;
     protected int mHeaderTitleSize;
     protected int mHeaderSubtitleSize;
-    protected int mVerticalHeaderTextPadding;
     protected int mTitleSize;
     protected int mSubtitleSize;
-    protected int mVerticalTextPadding;
     protected int mGridTitleSize;
     protected int mGridSubtitleSize;
-    protected int mVerticalGridTextPadding;
-    protected int mGridTopPadding;
-    protected int mGridBottomPadding;
     protected boolean mShowLastUpdated;
     protected long mLastUpdated = -1;
 
@@ -63,46 +60,6 @@
         this(context);
     }
 
-    /**
-     * Called when the view should be reset.
-     */
-    public abstract void resetView();
-
-    /**
-     * Sets the content to display in this slice.
-     */
-    public void setSliceContent(ListContent content) {
-        // Do nothing
-    }
-
-    /**
-     * Called when the slice being displayed in this view is an element of a larger list.
-     */
-    public void setSliceItem(SliceItem slice, boolean isHeader, int rowIndex,
-            int rowCount, SliceView.OnSliceActionListener observer) {
-        // Do nothing
-    }
-
-    /**
-     * Sets the slice actions for this view.
-     */
-    public void setSliceActions(List<SliceItem> actions) {
-        // Do nothing
-    }
-
-    /**
-     * @return the height of the view when displayed in {@link SliceView#MODE_SMALL}.
-     */
-    public int getSmallHeight() {
-        return 0;
-    }
-
-    /**
-     * @return the height of the view when displayed in {@link SliceView#MODE_LARGE}.
-     */
-    public int getActualHeight() {
-        return 0;
-    }
 
     /**
      * Set the mode of the slice being presented.
@@ -120,6 +77,37 @@
     }
 
     /**
+     * @return the height of this view when displayed in {@link SliceView#MODE_SMALL}.
+     */
+    public int getSmallHeight() {
+        return 0;
+    }
+
+    /**
+     * @return the height of this view if it displayed all of its contents.
+     */
+    public int getActualHeight() {
+        return 0;
+    }
+
+    /**
+     * @param slice the slice to show in this view.
+     */
+    public abstract void setSlice(Slice slice);
+
+    /**
+     * Called when the view should be reset.
+     */
+    public abstract void resetView();
+
+    /**
+     * @return the view.
+     */
+    public View getView() {
+        return this;
+    }
+
+    /**
      * Sets a custom color to use for tinting elements like icons for this view.
      */
     public void setTint(@ColorInt int tintColor) {
@@ -158,31 +146,33 @@
             mTintColor = themeColor != -1 ? themeColor : mTintColor;
             mTitleColor = a.getColor(R.styleable.SliceView_titleColor, 0);
             mSubtitleColor = a.getColor(R.styleable.SliceView_subtitleColor, 0);
-
             mHeaderTitleSize = (int) a.getDimension(
                     R.styleable.SliceView_headerTitleSize, 0);
             mHeaderSubtitleSize = (int) a.getDimension(
                     R.styleable.SliceView_headerSubtitleSize, 0);
-            mVerticalHeaderTextPadding = (int) a.getDimension(
-                    R.styleable.SliceView_headerTextVerticalPadding, 0);
-
             mTitleSize = (int) a.getDimension(R.styleable.SliceView_titleSize, 0);
             mSubtitleSize = (int) a.getDimension(
                     R.styleable.SliceView_subtitleSize, 0);
-            mVerticalTextPadding = (int) a.getDimension(
-                    R.styleable.SliceView_textVerticalPadding, 0);
-
             mGridTitleSize = (int) a.getDimension(R.styleable.SliceView_gridTitleSize, 0);
             mGridSubtitleSize = (int) a.getDimension(
                     R.styleable.SliceView_gridSubtitleSize, 0);
-            int defaultVerticalGridPadding = getContext().getResources().getDimensionPixelSize(
-                    R.dimen.abc_slice_grid_text_inner_padding);
-            mVerticalGridTextPadding = (int) a.getDimension(
-                    R.styleable.SliceView_gridTextVerticalPadding, defaultVerticalGridPadding);
-            mGridTopPadding = (int) a.getDimension(R.styleable.SliceView_gridTopPadding, 0);
-            mGridBottomPadding = (int) a.getDimension(R.styleable.SliceView_gridTopPadding, 0);
         } finally {
             a.recycle();
         }
     }
+
+    /**
+     * Called when the slice being displayed in this view is an element of a larger list.
+     */
+    public void setSliceItem(SliceItem slice, boolean isHeader, int rowIndex,
+            SliceView.OnSliceActionListener observer) {
+        // Do nothing
+    }
+
+    /**
+     * Sets the slice actions for this view.
+     */
+    public void setSliceActions(List<SliceItem> actions) {
+        // Do nothing
+    }
 }
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceView.java b/slices/view/src/main/java/androidx/slice/widget/SliceView.java
index 7ba9eeb51..855bded 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceView.java
@@ -32,7 +32,6 @@
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 
-import androidx.annotation.ColorInt;
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -313,7 +312,7 @@
     private int getHeightForMode() {
         int mode = getMode();
         if (mode == MODE_SHORTCUT) {
-            return mListContent != null && mListContent.isValid() ? mShortcutSize : 0;
+            return mShortcutSize;
         }
         return mode == MODE_LARGE
                 ? mCurrentView.getActualHeight()
@@ -376,7 +375,7 @@
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        View v = mCurrentView;
+        View v = mCurrentView.getView();
         final int left = getPaddingLeft();
         final int top = getPaddingTop();
         v.layout(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
@@ -485,23 +484,15 @@
     }
 
     /**
-     * @deprecated TO BE REMOVED; use {@link #setAccentColor(int)} instead.
-     */
-    @Deprecated
-    public void setTint(int tintColor) {
-        setAccentColor(tintColor);
-    }
-
-    /**
      * Contents of a slice such as icons, text, and controls (e.g. toggle) can be tinted. Normally
      * a color for tinting will be provided by the slice. Using this method will override
-     * the slice-provided color information and instead tint elements with the color set here.
+     * this color information and instead tint elements with the provided color.
      *
-     * @param accentColor the color to use for tinting contents of this view.
+     * @param tintColor the color to use for tinting contents of this view.
      */
-    public void setAccentColor(@ColorInt int accentColor) {
-        mThemeTintColor = accentColor;
-        mCurrentView.setTint(accentColor);
+    public void setTint(int tintColor) {
+        mThemeTintColor = tintColor;
+        mCurrentView.setTint(tintColor);
     }
 
     /**
@@ -549,14 +540,11 @@
     private void reinflate() {
         if (mCurrentSlice == null) {
             mCurrentView.resetView();
-            updateActions();
             return;
         }
-        mListContent = new ListContent(getContext(), mCurrentSlice, mAttrs, mDefStyleAttr,
-                mDefStyleRes);
+        mListContent = new ListContent(getContext(), mCurrentSlice);
         if (!mListContent.isValid()) {
             mCurrentView.resetView();
-            updateActions();
             return;
         }
 
@@ -591,7 +579,7 @@
         mCurrentView.setShowLastUpdated(mShowLastUpdated && expired);
 
         // Set the slice
-        mCurrentView.setSliceContent(mListContent);
+        mCurrentView.setSlice(mCurrentSlice);
         updateActions();
     }
 
diff --git a/slices/view/src/main/res-public/values/public_attrs.xml b/slices/view/src/main/res-public/values/public_attrs.xml
index a535a6d..ad909ea 100644
--- a/slices/view/src/main/res-public/values/public_attrs.xml
+++ b/slices/view/src/main/res-public/values/public_attrs.xml
@@ -22,14 +22,9 @@
     <public type="attr" name="tintColor" />
     <public type="attr" name="headerTitleSize" />
     <public type="attr" name="headerSubtitleSize" />
-    <public type="attr" name="headerTextVerticalPadding" />
     <public type="attr" name="titleSize" />
     <public type="attr" name="subtitleSize" />
-    <public type="attr" name="textVerticalPadding" />
     <public type="attr" name="gridTitleSize" />
     <public type="attr" name="gridSubtitleSize" />
-    <public type="attr" name="gridTextVerticalPadding" />
-    <public type="attr" name="gridTopPadding" />
-    <public type="attr" name="gridBottomPadding" />
     <public type="attr" name="sliceViewStyle" />
-</resources>
+</resources>
\ No newline at end of file
diff --git a/slices/view/src/main/res/layout/abc_slice_grid_see_more.xml b/slices/view/src/main/res/layout/abc_slice_grid_see_more.xml
index 0a2e746..17c1c0f 100644
--- a/slices/view/src/main/res/layout/abc_slice_grid_see_more.xml
+++ b/slices/view/src/main/res/layout/abc_slice_grid_see_more.xml
@@ -33,6 +33,5 @@
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:gravity="center_horizontal"
-              android:paddingTop="@dimen/abc_slice_grid_text_padding"
               android:text="@string/abc_slice_more"/>
 </LinearLayout>
\ 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
index c6ff594..0870465 100644
--- a/slices/view/src/main/res/layout/abc_slice_secondary_text.xml
+++ b/slices/view/src/main/res/layout/abc_slice_secondary_text.xml
@@ -15,11 +15,14 @@
   ~ 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"
         android:maxLines="1"
-        android:singleLine="true"
         android:ellipsize="end"/>
diff --git a/slices/view/src/main/res/layout/abc_slice_title.xml b/slices/view/src/main/res/layout/abc_slice_title.xml
index eac5e8c..70a1400 100644
--- a/slices/view/src/main/res/layout/abc_slice_title.xml
+++ b/slices/view/src/main/res/layout/abc_slice_title.xml
@@ -18,9 +18,11 @@
 
 <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"
         android:maxLines="1"
-        android:singleLine="true"
         android:ellipsize="end"/>
diff --git a/slices/view/src/main/res/values-af/strings.xml b/slices/view/src/main/res/values-af/strings.xml
index cfe8138..ea5ab25 100644
--- a/slices/view/src/main/res/values-af/strings.xml
+++ b/slices/view/src/main/res/values-af/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Meer"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Wys meer"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Opgedateer om <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min. gelede</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min. gelede</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> jaar gelede</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> jaar gelede</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> dae gelede</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> dag gelede</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Kon nie koppel nie"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-am/strings.xml b/slices/view/src/main/res/values-am/strings.xml
index da542e1..ea5ab25 100644
--- a/slices/view/src/main/res/values-am/strings.xml
+++ b/slices/view/src/main/res/values-am/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"ተጨማሪ"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"ተጨማሪ አሳይ"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"የተዘመነው <xliff:g id="TIME">%1$s</xliff:g> ላይ"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ደቂቃ በፊት</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ደቂቃ በፊት</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ዓመት በፊት</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ዓመት በፊት</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ቀናት በፊት</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ቀናት በፊት</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"መገናኘት አልተቻለም"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ar/strings.xml b/slices/view/src/main/res/values-ar/strings.xml
index 1e9ca94..21aa8a4c 100644
--- a/slices/view/src/main/res/values-ar/strings.xml
+++ b/slices/view/src/main/res/values-ar/strings.xml
@@ -18,32 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"بالإضافة إلى <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"المزيد"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"عرض المزيد"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"وقت التحديث الأخير: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="zero">قبل <xliff:g id="ID_2">%d</xliff:g> دقيقة</item>
-      <item quantity="two">قبل دقيقتين (<xliff:g id="ID_2">%d</xliff:g>)</item>
-      <item quantity="few">قبل <xliff:g id="ID_2">%d</xliff:g> دقائق</item>
-      <item quantity="many">قبل <xliff:g id="ID_2">%d</xliff:g> دقيقة</item>
-      <item quantity="other">قبل <xliff:g id="ID_2">%d</xliff:g> دقيقة</item>
-      <item quantity="one">قبل <xliff:g id="ID_1">%d</xliff:g> دقيقة</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="zero">قبل <xliff:g id="ID_2">%d</xliff:g> سنة</item>
-      <item quantity="two">قبل سنتين (<xliff:g id="ID_2">%d</xliff:g>)</item>
-      <item quantity="few">قبل <xliff:g id="ID_2">%d</xliff:g> سنوات</item>
-      <item quantity="many">قبل <xliff:g id="ID_2">%d</xliff:g> سنة</item>
-      <item quantity="other">قبل <xliff:g id="ID_2">%d</xliff:g> سنة</item>
-      <item quantity="one">قبل <xliff:g id="ID_1">%d</xliff:g> سنة</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="zero">قبل <xliff:g id="ID_2">%d</xliff:g> يوم</item>
-      <item quantity="two">قبل يومين (<xliff:g id="ID_2">%d</xliff:g>)</item>
-      <item quantity="few">قبل <xliff:g id="ID_2">%d</xliff:g> أيام</item>
-      <item quantity="many">قبل <xliff:g id="ID_2">%d</xliff:g> يومًا</item>
-      <item quantity="other">قبل <xliff:g id="ID_2">%d</xliff:g> يوم</item>
-      <item quantity="one">قبل <xliff:g id="ID_1">%d</xliff:g> يوم</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"تعذّر الاتصال."</string>
 </resources>
diff --git a/slices/view/src/main/res/values-as/strings.xml b/slices/view/src/main/res/values-as/strings.xml
deleted file mode 100644
index dbc598f..0000000
--- a/slices/view/src/main/res/values-as/strings.xml
+++ /dev/null
@@ -1,37 +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.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"অধিক"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"অধিক দেখুৱাওক"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> আপডেট কৰা হৈছিল"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> মিনিট আগেয়ে</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> মিনিট আগেয়ে</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> বছৰ আগেয়ে</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> বছৰ আগেয়ে</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> দিন আগেয়ে</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g>দিন আগেয়ে</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"সংযোগ কৰিব পৰা নগ\'ল"</string>
-</resources>
diff --git a/slices/view/src/main/res/values-az/strings.xml b/slices/view/src/main/res/values-az/strings.xml
index 837f08c..ea5ab25 100644
--- a/slices/view/src/main/res/values-az/strings.xml
+++ b/slices/view/src/main/res/values-az/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Digər"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Digərinə baxın"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> tarixində yenilənib"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> dəq əvvəl</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> dəq əvvəl</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> il əvvəl</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> il əvvəl</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> gün əvvəl</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> gün əvvəl</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Qoşulmaq mümkün olmadı"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-b+sr+Latn/strings.xml b/slices/view/src/main/res/values-b+sr+Latn/strings.xml
index 8deb17c..ffd9b9b 100644
--- a/slices/view/src/main/res/values-b+sr+Latn/strings.xml
+++ b/slices/view/src/main/res/values-b+sr+Latn/strings.xml
@@ -18,23 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"i još <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Još"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Prikaži više"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Ažurirano <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">pre <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="few">pre <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="other">pre <xliff:g id="ID_2">%d</xliff:g> min</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">pre <xliff:g id="ID_2">%d</xliff:g> god</item>
-      <item quantity="few">pre <xliff:g id="ID_2">%d</xliff:g> god</item>
-      <item quantity="other">pre <xliff:g id="ID_2">%d</xliff:g> god</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">pre <xliff:g id="ID_2">%d</xliff:g> dan</item>
-      <item quantity="few">pre <xliff:g id="ID_2">%d</xliff:g> dana</item>
-      <item quantity="other">pre <xliff:g id="ID_2">%d</xliff:g> dana</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Povezivanje nije uspelo"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-be/strings.xml b/slices/view/src/main/res/values-be/strings.xml
index b03f283..df8e965 100644
--- a/slices/view/src/main/res/values-be/strings.xml
+++ b/slices/view/src/main/res/values-be/strings.xml
@@ -18,26 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"Яшчэ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Яшчэ"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Яшчэ"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Абноўлена <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> хвіліну таму</item>
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> хвіліны таму</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> хвілін таму</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> хвіліны таму</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> год таму</item>
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> гады таму</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> гадоў таму</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> года таму</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> дзень таму</item>
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> дні таму</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> дзён таму</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> дня таму</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Не атрымалася падключыцца"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-bg/strings.xml b/slices/view/src/main/res/values-bg/strings.xml
index b019a46b..ea5ab25 100644
--- a/slices/view/src/main/res/values-bg/strings.xml
+++ b/slices/view/src/main/res/values-bg/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Още"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Показване на още"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Актуализирано <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">Преди <xliff:g id="ID_2">%d</xliff:g> мин</item>
-      <item quantity="one">Преди <xliff:g id="ID_1">%d</xliff:g> мин</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">Преди <xliff:g id="ID_2">%d</xliff:g> год</item>
-      <item quantity="one">Преди <xliff:g id="ID_1">%d</xliff:g> год</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">Преди <xliff:g id="ID_2">%d</xliff:g> дни</item>
-      <item quantity="one">Преди <xliff:g id="ID_1">%d</xliff:g> ден</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Не можа да се установи връзка"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-bn/strings.xml b/slices/view/src/main/res/values-bn/strings.xml
index bc5c45b..8737d8c 100644
--- a/slices/view/src/main/res/values-bn/strings.xml
+++ b/slices/view/src/main/res/values-bn/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>টি"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"আরও"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"আরও দেখুন"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> আপডেট করা হয়েছে"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> মিনিট আগে</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> মিনিট আগে</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> বছর আগে</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> বছর আগে</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> দিন আগে</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> দিন আগে</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"কানেক্ট করা যায়নি"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-bs/strings.xml b/slices/view/src/main/res/values-bs/strings.xml
index cb84c18..ea5ab25 100644
--- a/slices/view/src/main/res/values-bs/strings.xml
+++ b/slices/view/src/main/res/values-bs/strings.xml
@@ -18,23 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Više"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Prikaži više"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Ažurirano <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">Prije <xliff:g id="ID_2">%d</xliff:g> min.</item>
-      <item quantity="few">Prije <xliff:g id="ID_2">%d</xliff:g> min.</item>
-      <item quantity="other">Prije <xliff:g id="ID_2">%d</xliff:g> min.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">Prije <xliff:g id="ID_2">%d</xliff:g> god.</item>
-      <item quantity="few">Prije <xliff:g id="ID_2">%d</xliff:g> god.</item>
-      <item quantity="other">Prije <xliff:g id="ID_2">%d</xliff:g> god.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">Prije <xliff:g id="ID_2">%d</xliff:g> dan</item>
-      <item quantity="few">Prije <xliff:g id="ID_2">%d</xliff:g> dana</item>
-      <item quantity="other">Prije <xliff:g id="ID_2">%d</xliff:g> dana</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Povezivanje nije uspjelo"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ca/strings.xml b/slices/view/src/main/res/values-ca/strings.xml
index cc5dde0..8ae6f78c 100644
--- a/slices/view/src/main/res/values-ca/strings.xml
+++ b/slices/view/src/main/res/values-ca/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> més"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Més"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Mostra\'n més"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"S\'ha actualitzat <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">Fa <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="one">Fa <xliff:g id="ID_1">%d</xliff:g> min</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">Fa <xliff:g id="ID_2">%d</xliff:g> anys</item>
-      <item quantity="one">Fa <xliff:g id="ID_1">%d</xliff:g> any</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">Fa <xliff:g id="ID_2">%d</xliff:g> dies</item>
-      <item quantity="one">Fa <xliff:g id="ID_1">%d</xliff:g> dia</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"No s\'ha pogut connectar"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-cs/strings.xml b/slices/view/src/main/res/values-cs/strings.xml
index c4c1fce..1d39c0f 100644
--- a/slices/view/src/main/res/values-cs/strings.xml
+++ b/slices/view/src/main/res/values-cs/strings.xml
@@ -18,26 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"a ještě <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Více"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Zobrazit více"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Aktualizováno <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="few">před <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="many">před <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="other">před <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="one">před <xliff:g id="ID_1">%d</xliff:g> min</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="few">před <xliff:g id="ID_2">%d</xliff:g> lety</item>
-      <item quantity="many">před <xliff:g id="ID_2">%d</xliff:g> roku</item>
-      <item quantity="other">před <xliff:g id="ID_2">%d</xliff:g> lety</item>
-      <item quantity="one">před <xliff:g id="ID_1">%d</xliff:g> rokem</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="few">před <xliff:g id="ID_2">%d</xliff:g> dny</item>
-      <item quantity="many">před <xliff:g id="ID_2">%d</xliff:g> dne</item>
-      <item quantity="other">před <xliff:g id="ID_2">%d</xliff:g> dny</item>
-      <item quantity="one">před <xliff:g id="ID_1">%d</xliff:g> dnem</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Nelze se připojit"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-da/strings.xml b/slices/view/src/main/res/values-da/strings.xml
index c7c2850..40de41d 100644
--- a/slices/view/src/main/res/values-da/strings.xml
+++ b/slices/view/src/main/res/values-da/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> mere"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Mere"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Se mere"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Opdateret <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">for <xliff:g id="ID_2">%d</xliff:g> min. siden</item>
-      <item quantity="other">for <xliff:g id="ID_2">%d</xliff:g> min. siden</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">for <xliff:g id="ID_2">%d</xliff:g> år siden</item>
-      <item quantity="other">for <xliff:g id="ID_2">%d</xliff:g> år siden</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">for <xliff:g id="ID_2">%d</xliff:g> dag siden</item>
-      <item quantity="other">for <xliff:g id="ID_2">%d</xliff:g> dage siden</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Der kunne ikke oprettes forbindelse"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-de/strings.xml b/slices/view/src/main/res/values-de/strings.xml
index 25dff37..9d9bede 100644
--- a/slices/view/src/main/res/values-de/strings.xml
+++ b/slices/view/src/main/res/values-de/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Mehr"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Mehr anzeigen"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Aktualisiert: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">vor <xliff:g id="ID_2">%d</xliff:g> Min.</item>
-      <item quantity="one">vor <xliff:g id="ID_1">%d</xliff:g> Min.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">vor <xliff:g id="ID_2">%d</xliff:g> Jahren</item>
-      <item quantity="one">vor <xliff:g id="ID_1">%d</xliff:g> Jahr</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">vor <xliff:g id="ID_2">%d</xliff:g> Tagen</item>
-      <item quantity="one">vor <xliff:g id="ID_1">%d</xliff:g> Tag</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Verbindung nicht möglich"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-el/strings.xml b/slices/view/src/main/res/values-el/strings.xml
index 31092af..ea5ab25 100644
--- a/slices/view/src/main/res/values-el/strings.xml
+++ b/slices/view/src/main/res/values-el/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Περισσότ."</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Εμφάνιση περισσότερων"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Ενημερώθηκε <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> λεπ. πριν</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> λεπ. πριν</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> χρ. πριν</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> χρ. πριν</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ημ. πριν</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ημ. πριν</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Αδυναμία σύνδεσης"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-en-rAU/strings.xml b/slices/view/src/main/res/values-en-rAU/strings.xml
index 8fa5b45..ea5ab25 100644
--- a/slices/view/src/main/res/values-en-rAU/strings.xml
+++ b/slices/view/src/main/res/values-en-rAU/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"More"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Show more"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Updated <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min ago</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> yr ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> yr ago</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> days ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> day ago</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Couldn\'t connect"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-en-rCA/strings.xml b/slices/view/src/main/res/values-en-rCA/strings.xml
index 8fa5b45..ea5ab25 100644
--- a/slices/view/src/main/res/values-en-rCA/strings.xml
+++ b/slices/view/src/main/res/values-en-rCA/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"More"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Show more"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Updated <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min ago</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> yr ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> yr ago</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> days ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> day ago</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Couldn\'t connect"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-en-rGB/strings.xml b/slices/view/src/main/res/values-en-rGB/strings.xml
index 8fa5b45..ea5ab25 100644
--- a/slices/view/src/main/res/values-en-rGB/strings.xml
+++ b/slices/view/src/main/res/values-en-rGB/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"More"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Show more"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Updated <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min ago</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> yr ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> yr ago</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> days ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> day ago</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Couldn\'t connect"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-en-rIN/strings.xml b/slices/view/src/main/res/values-en-rIN/strings.xml
index 8fa5b45..ea5ab25 100644
--- a/slices/view/src/main/res/values-en-rIN/strings.xml
+++ b/slices/view/src/main/res/values-en-rIN/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"More"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Show more"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Updated <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min ago</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> yr ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> yr ago</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> days ago</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> day ago</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Couldn\'t connect"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-en-rXC/strings.xml b/slices/view/src/main/res/values-en-rXC/strings.xml
index b24c1e6..b793412 100644
--- a/slices/view/src/main/res/values-en-rXC/strings.xml
+++ b/slices/view/src/main/res/values-en-rXC/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎+ ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%1$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎More‎‏‎‎‏‎"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‎Show more‎‏‎‎‏‎"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‎‎‎‎Updated ‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="ID_2">%d</xliff:g>‎‏‎‎‏‏‏‎ min ago‎‏‎‎‏‎</item>
-      <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="ID_1">%d</xliff:g>‎‏‎‎‏‏‏‎ min ago‎‏‎‎‏‎</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="ID_2">%d</xliff:g>‎‏‎‎‏‏‏‎ yr ago‎‏‎‎‏‎</item>
-      <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="ID_1">%d</xliff:g>‎‏‎‎‏‏‏‎ yr ago‎‏‎‎‏‎</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="ID_2">%d</xliff:g>‎‏‎‎‏‏‏‎ days ago‎‏‎‎‏‎</item>
-      <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="ID_1">%d</xliff:g>‎‏‎‎‏‏‏‎ day ago‎‏‎‎‏‎</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎Couldn\'t connect‎‏‎‎‏‎"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-es-rUS/strings.xml b/slices/view/src/main/res/values-es-rUS/strings.xml
index 3125104..a445505 100644
--- a/slices/view/src/main/res/values-es-rUS/strings.xml
+++ b/slices/view/src/main/res/values-es-rUS/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> más"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Más"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Mostrar más"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Última actualización: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">Hace <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="one">Hace <xliff:g id="ID_1">%d</xliff:g> min</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">Hace <xliff:g id="ID_2">%d</xliff:g> años</item>
-      <item quantity="one">Hace <xliff:g id="ID_1">%d</xliff:g> año</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">Hace <xliff:g id="ID_2">%d</xliff:g> días</item>
-      <item quantity="one">Hace <xliff:g id="ID_1">%d</xliff:g> día</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"No se pudo establecer conexión"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-es/strings.xml b/slices/view/src/main/res/values-es/strings.xml
index f6e42fc..dcdd33e 100644
--- a/slices/view/src/main/res/values-es/strings.xml
+++ b/slices/view/src/main/res/values-es/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> más"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Más"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Ver más"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Última actualización: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">hace <xliff:g id="ID_2">%d</xliff:g> minutos</item>
-      <item quantity="one">hace <xliff:g id="ID_1">%d</xliff:g> minuto</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">hace <xliff:g id="ID_2">%d</xliff:g> años</item>
-      <item quantity="one">hace <xliff:g id="ID_1">%d</xliff:g> año</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">hace <xliff:g id="ID_2">%d</xliff:g> días</item>
-      <item quantity="one">hace <xliff:g id="ID_1">%d</xliff:g> día</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"No se ha podido establecer la conexión"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-et/strings.xml b/slices/view/src/main/res/values-et/strings.xml
index 7e053e92..a1675ff 100644
--- a/slices/view/src/main/res/values-et/strings.xml
+++ b/slices/view/src/main/res/values-et/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"ja veel <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Rohkem"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Kuva rohkem"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Värskendatud kell <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min tagasi</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min tagasi</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> a tagasi</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> a tagasi</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> päeva tagasi</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> päev tagasi</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Ühendamine ebaõnnestus"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-eu/strings.xml b/slices/view/src/main/res/values-eu/strings.xml
index 5e0642c..1c79d4a 100644
--- a/slices/view/src/main/res/values-eu/strings.xml
+++ b/slices/view/src/main/res/values-eu/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"Beste <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Gehiago"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Erakutsi gehiago"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Azken eguneratzea: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">Duela <xliff:g id="ID_2">%d</xliff:g> minutu</item>
-      <item quantity="one">Duela <xliff:g id="ID_1">%d</xliff:g> minutu</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">Duela <xliff:g id="ID_2">%d</xliff:g> urte</item>
-      <item quantity="one">Duela <xliff:g id="ID_1">%d</xliff:g> urte</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">Duela <xliff:g id="ID_2">%d</xliff:g> egun</item>
-      <item quantity="one">Duela <xliff:g id="ID_1">%d</xliff:g> egun</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Ezin izan da konektatu"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-fa/strings.xml b/slices/view/src/main/res/values-fa/strings.xml
index 7832e8a..2b2abd2 100644
--- a/slices/view/src/main/res/values-fa/strings.xml
+++ b/slices/view/src/main/res/values-fa/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"‎+ <xliff:g id="NUMBER">%1$d</xliff:g>‎"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"بیشتر"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"بیشتر ببینید"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"زمان به‌روزرسانی <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> دقیقه قبل</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> دقیقه قبل</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> سال قبل</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> سال قبل</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> روز قبل</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> روز قبل</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"متصل نشد"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-fi/strings.xml b/slices/view/src/main/res/values-fi/strings.xml
index dbbe0cd..ea5ab25 100644
--- a/slices/view/src/main/res/values-fi/strings.xml
+++ b/slices/view/src/main/res/values-fi/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Lisää"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Näytä lisää"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Päivitetty <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min sitten</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min sitten</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> vuotta sitten</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> vuosi sitten</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> päivää sitten</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> päivä sitten</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Ei yhteyttä"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-fr-rCA/strings.xml b/slices/view/src/main/res/values-fr-rCA/strings.xml
index 63c7fcd..ea5ab25 100644
--- a/slices/view/src/main/res/values-fr-rCA/strings.xml
+++ b/slices/view/src/main/res/values-fr-rCA/strings.xml
@@ -17,21 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Plus"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Plus"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Mise à jour : <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">Il y a <xliff:g id="ID_2">%d</xliff:g> minute</item>
-      <item quantity="other">Il y a <xliff:g id="ID_2">%d</xliff:g> minutes</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">Il y a <xliff:g id="ID_2">%d</xliff:g> an</item>
-      <item quantity="other">Il y a <xliff:g id="ID_2">%d</xliff:g> ans</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">Il y a <xliff:g id="ID_2">%d</xliff:g> jour</item>
-      <item quantity="other">Il y a <xliff:g id="ID_2">%d</xliff:g> jours</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Impossible de se connecter"</string>
+    <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-fr/strings.xml b/slices/view/src/main/res/values-fr/strings.xml
index 47ff242..73685ce 100644
--- a/slices/view/src/main/res/values-fr/strings.xml
+++ b/slices/view/src/main/res/values-fr/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> autres"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Plus"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Afficher plus"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Dernière mise à jour : <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">Il y a <xliff:g id="ID_2">%d</xliff:g> minute</item>
-      <item quantity="other">Il y a <xliff:g id="ID_2">%d</xliff:g> minutes</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">Il y a <xliff:g id="ID_2">%d</xliff:g> an</item>
-      <item quantity="other">Il y a <xliff:g id="ID_2">%d</xliff:g> ans</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">Il y a <xliff:g id="ID_2">%d</xliff:g> jour</item>
-      <item quantity="other">Il y a <xliff:g id="ID_2">%d</xliff:g> jours</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Impossible de se connecter"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-gl/strings.xml b/slices/view/src/main/res/values-gl/strings.xml
index fb3d1c2..573eae9 100644
--- a/slices/view/src/main/res/values-gl/strings.xml
+++ b/slices/view/src/main/res/values-gl/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> máis"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Máis"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Amosar máis"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Contido actualizado (<xliff:g id="TIME">%1$s</xliff:g>)"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">hai <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="one">hai <xliff:g id="ID_1">%d</xliff:g> min</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">hai <xliff:g id="ID_2">%d</xliff:g> anos</item>
-      <item quantity="one">hai <xliff:g id="ID_1">%d</xliff:g> ano</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">hai <xliff:g id="ID_2">%d</xliff:g> días</item>
-      <item quantity="one">hai <xliff:g id="ID_1">%d</xliff:g> día</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Non se puido establecer conexión"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-gu/strings.xml b/slices/view/src/main/res/values-gu/strings.xml
index 4951f8c..ea5ab25 100644
--- a/slices/view/src/main/res/values-gu/strings.xml
+++ b/slices/view/src/main/res/values-gu/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"વધુ"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"વધુ બતાવો"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> અપડેટ થયું"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> મિનિટ પહેલાં</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> મિનિટ પહેલાં</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> વર્ષ પહેલાં</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> વર્ષ પહેલાં</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> દિવસ પહેલાં</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> દિવસ પહેલાં</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"કનેક્ટ કરી શકાયું નથી"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-hi/strings.xml b/slices/view/src/main/res/values-hi/strings.xml
index 79a64bb..ea5ab25 100644
--- a/slices/view/src/main/res/values-hi/strings.xml
+++ b/slices/view/src/main/res/values-hi/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"ज़्यादा देखें"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"ज़्यादा देखें"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> बजे अपडेट किया गया"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> मिनट पहले</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> मिनट पहले</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> साल पहले</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> साल पहले</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> दिन पहले</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> दिन पहले</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"कनेक्‍ट नहीं हो पाया"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-hr/strings.xml b/slices/view/src/main/res/values-hr/strings.xml
index f44b06c..7ecedf6 100644
--- a/slices/view/src/main/res/values-hr/strings.xml
+++ b/slices/view/src/main/res/values-hr/strings.xml
@@ -18,23 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"još <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Više"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Prikaži više"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Ažurirano <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">Prije <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="few">Prije <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="other">Prije <xliff:g id="ID_2">%d</xliff:g> min</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">Prije <xliff:g id="ID_2">%d</xliff:g> godinu</item>
-      <item quantity="few">Prije <xliff:g id="ID_2">%d</xliff:g> godine</item>
-      <item quantity="other">Prije <xliff:g id="ID_2">%d</xliff:g> godina</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">Prije <xliff:g id="ID_2">%d</xliff:g> dan</item>
-      <item quantity="few">Prije <xliff:g id="ID_2">%d</xliff:g> dana</item>
-      <item quantity="other">Prije <xliff:g id="ID_2">%d</xliff:g> dana</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Povezivanje nije moguće"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-hu/strings.xml b/slices/view/src/main/res/values-hu/strings.xml
index cf5ebdc..ea5ab25 100644
--- a/slices/view/src/main/res/values-hu/strings.xml
+++ b/slices/view/src/main/res/values-hu/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Több"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Több megjelenítése"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Frissítve: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> perce</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> perce</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> éve</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> éve</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> napja</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> napja</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Nem sikerült kapcsolódni"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-hy/strings.xml b/slices/view/src/main/res/values-hy/strings.xml
index fcf96af..ea5ab25 100644
--- a/slices/view/src/main/res/values-hy/strings.xml
+++ b/slices/view/src/main/res/values-hy/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Ավելին"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Ցուցադրել ավելի շատ"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Թարմացվել է <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> րոպե առաջ</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> րոպե առաջ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> տարի առաջ</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> տարի առաջ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> օր առաջ</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> օր առաջ</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Չհաջողվեց միանալ"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-in/strings.xml b/slices/view/src/main/res/values-in/strings.xml
index 5641ebb..ea5ab25 100644
--- a/slices/view/src/main/res/values-in/strings.xml
+++ b/slices/view/src/main/res/values-in/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Lainnya"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Tampilkan lainnya"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Diupdate <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> menit lalu</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> menit lalu</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> tahun lalu</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> tahun lalu</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> hari lalu</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> hari lalu</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Tidak dapat terhubung"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-is/strings.xml b/slices/view/src/main/res/values-is/strings.xml
index 855a858..ea5ab25 100644
--- a/slices/view/src/main/res/values-is/strings.xml
+++ b/slices/view/src/main/res/values-is/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Meira"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Sýna meira"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Uppfært <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">Fyrir <xliff:g id="ID_2">%d</xliff:g> mín.</item>
-      <item quantity="other">Fyrir <xliff:g id="ID_2">%d</xliff:g> mín.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">Fyrir <xliff:g id="ID_2">%d</xliff:g> ári</item>
-      <item quantity="other">Fyrir <xliff:g id="ID_2">%d</xliff:g> árum</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">Fyrir <xliff:g id="ID_2">%d</xliff:g> degi</item>
-      <item quantity="other">Fyrir <xliff:g id="ID_2">%d</xliff:g> dögum</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Tenging mistókst"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-it/strings.xml b/slices/view/src/main/res/values-it/strings.xml
index d2f7a39..ea5ab25 100644
--- a/slices/view/src/main/res/values-it/strings.xml
+++ b/slices/view/src/main/res/values-it/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Altro"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Mostra altro"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Aggiornamento: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min fa</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min fa</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> anni fa</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> anno fa</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> gg fa</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> g fa</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Impossibile collegarsi"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-iw/strings.xml b/slices/view/src/main/res/values-iw/strings.xml
index db052e3..ea5ab25 100644
--- a/slices/view/src/main/res/values-iw/strings.xml
+++ b/slices/view/src/main/res/values-iw/strings.xml
@@ -18,26 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"עוד"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"הצג יותר"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"עודכן ב-<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="two">לפני <xliff:g id="ID_2">%d</xliff:g> דק’</item>
-      <item quantity="many">לפני <xliff:g id="ID_2">%d</xliff:g> דק’</item>
-      <item quantity="other">לפני <xliff:g id="ID_2">%d</xliff:g> דק’</item>
-      <item quantity="one">לפני <xliff:g id="ID_1">%d</xliff:g> דק’</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="two">לפני <xliff:g id="ID_2">%d</xliff:g> שנים</item>
-      <item quantity="many">לפני <xliff:g id="ID_2">%d</xliff:g> שנים</item>
-      <item quantity="other">לפני <xliff:g id="ID_2">%d</xliff:g> שנים</item>
-      <item quantity="one">לפני שנה (<xliff:g id="ID_1">%d</xliff:g>)</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="two">לפני <xliff:g id="ID_2">%d</xliff:g> ימים</item>
-      <item quantity="many">לפני <xliff:g id="ID_2">%d</xliff:g> ימים</item>
-      <item quantity="other">לפני <xliff:g id="ID_2">%d</xliff:g> ימים</item>
-      <item quantity="one">לפני יום אחד (<xliff:g id="ID_1">%d</xliff:g>)</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"לא ניתן היה להתחבר"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ja/strings.xml b/slices/view/src/main/res/values-ja/strings.xml
index 4d21cdf..ed51803 100644
--- a/slices/view/src/main/res/values-ja/strings.xml
+++ b/slices/view/src/main/res/values-ja/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"他 <xliff:g id="NUMBER">%1$d</xliff:g> 件"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"もっと見る"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"もっと見る"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"更新時刻: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 分前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 分前</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 年前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 年前</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 日前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 日前</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"接続できませんでした"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ka/strings.xml b/slices/view/src/main/res/values-ka/strings.xml
index 9b8558c..ea5ab25 100644
--- a/slices/view/src/main/res/values-ka/strings.xml
+++ b/slices/view/src/main/res/values-ka/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"მეტი"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"მეტის ჩვენება"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"განახლების დრო: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> წუთის წინ</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> წუთის წინ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> წლის წინ</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> წლის წინ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> დღის წინ</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> დღის წინ</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"დაკავშირება ვერ მოხერხდა"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-kk/strings.xml b/slices/view/src/main/res/values-kk/strings.xml
index 72b0303..ea5ab25 100644
--- a/slices/view/src/main/res/values-kk/strings.xml
+++ b/slices/view/src/main/res/values-kk/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Тағы"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Толығырақ көрсету"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Жаңартылған уақыты: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> минут бұрын</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> минут бұрын</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> жыл бұрын</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> жыл бұрын</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> күн бұрын</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> күн бұрын</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Байланыс орнатылмады"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-km/strings.xml b/slices/view/src/main/res/values-km/strings.xml
index 1e78acb..ea5ab25 100644
--- a/slices/view/src/main/res/values-km/strings.xml
+++ b/slices/view/src/main/res/values-km/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"ច្រើន​ទៀត"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"បង្ហាញ​ច្រើនទៀត"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"បាន​ធ្វើ​បច្ចុប្បន្នភាព​កាលពី <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> នាទី​មុន</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> នាទី​មុន</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ឆ្នាំ​មុន</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ឆ្នាំ​មុន</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ថ្ងៃ​មុន</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ថ្ងៃ​មុន</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"មិន​អាចភ្ជាប់​បានទេ"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-kn/strings.xml b/slices/view/src/main/res/values-kn/strings.xml
index ed7dcd6..ea5ab25 100644
--- a/slices/view/src/main/res/values-kn/strings.xml
+++ b/slices/view/src/main/res/values-kn/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"ಇನ್ನಷ್ಟು"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"ಹೆಚ್ಚು ತೋರಿಸಿ"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> ಅನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಲಾಗಿದೆ"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ನಿಮಿಷದ ಹಿಂದೆ</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ನಿಮಿಷದ ಹಿಂದೆ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ವರ್ಷದ ಹಿಂದೆ</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ವರ್ಷದ ಹಿಂದೆ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ದಿನಗಳ ಹಿಂದೆ</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ದಿನಗಳ ಹಿಂದೆ</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ko/strings.xml b/slices/view/src/main/res/values-ko/strings.xml
index 4dab983..2dc0279 100644
--- a/slices/view/src/main/res/values-ko/strings.xml
+++ b/slices/view/src/main/res/values-ko/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g>개 더보기"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"더보기"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"더보기"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g>에 업데이트됨"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g>분 전</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g>분 전</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g>년 전</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g>년 전</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g>일 전</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g>일 전</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"연결할 수 없음"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ky/strings.xml b/slices/view/src/main/res/values-ky/strings.xml
index 63c7d13..ea5ab25 100644
--- a/slices/view/src/main/res/values-ky/strings.xml
+++ b/slices/view/src/main/res/values-ky/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Дагы"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Дагы көрсөтүү"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> жаңыртылды"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> мүн. мурун</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> мүн. мурун</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> жыл мурун</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> жыл мурун</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> күн мурун</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> күн мурун</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Туташпай койду"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-lo/strings.xml b/slices/view/src/main/res/values-lo/strings.xml
index 89c4291..ea5ab25 100644
--- a/slices/view/src/main/res/values-lo/strings.xml
+++ b/slices/view/src/main/res/values-lo/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"ເພີ່ມເຕີມ"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"ສະແດງເພີ່ມເຕີມ"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"ອັບເດດເມື່ອ <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ນທ ກ່ອນ</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ນທ ກ່ອນ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ປີກ່ອນ</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ປີກ່ອນ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ມື້ກ່ອນ</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ມື້ກ່ອນ</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"ບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-lt/strings.xml b/slices/view/src/main/res/values-lt/strings.xml
index e4094b4..bb6bcb3 100644
--- a/slices/view/src/main/res/values-lt/strings.xml
+++ b/slices/view/src/main/res/values-lt/strings.xml
@@ -18,26 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"Dar <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Daugiau"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Rodyti daugiau"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Atnaujinta <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">Prieš <xliff:g id="ID_2">%d</xliff:g> min.</item>
-      <item quantity="few">Prieš <xliff:g id="ID_2">%d</xliff:g> min.</item>
-      <item quantity="many">Prieš <xliff:g id="ID_2">%d</xliff:g> min.</item>
-      <item quantity="other">Prieš <xliff:g id="ID_2">%d</xliff:g> min.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">Prieš <xliff:g id="ID_2">%d</xliff:g> m.</item>
-      <item quantity="few">Prieš <xliff:g id="ID_2">%d</xliff:g> m.</item>
-      <item quantity="many">Prieš <xliff:g id="ID_2">%d</xliff:g> m.</item>
-      <item quantity="other">Prieš <xliff:g id="ID_2">%d</xliff:g> m.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">Prieš <xliff:g id="ID_2">%d</xliff:g> d.</item>
-      <item quantity="few">Prieš <xliff:g id="ID_2">%d</xliff:g> d.</item>
-      <item quantity="many">Prieš <xliff:g id="ID_2">%d</xliff:g> d.</item>
-      <item quantity="other">Prieš <xliff:g id="ID_2">%d</xliff:g> d.</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Prisijungti nepavyko"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-lv/strings.xml b/slices/view/src/main/res/values-lv/strings.xml
index 45be57c..79ccb99 100644
--- a/slices/view/src/main/res/values-lv/strings.xml
+++ b/slices/view/src/main/res/values-lv/strings.xml
@@ -18,23 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"Vēl <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Vēl"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Rādīt vairāk"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Atjaunināts <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="zero">Pirms <xliff:g id="ID_2">%d</xliff:g> minūtēm</item>
-      <item quantity="one">Pirms <xliff:g id="ID_2">%d</xliff:g> minūtes</item>
-      <item quantity="other">Pirms <xliff:g id="ID_2">%d</xliff:g> minūtēm</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="zero">Pirms <xliff:g id="ID_2">%d</xliff:g> gadiem</item>
-      <item quantity="one">Pirms <xliff:g id="ID_2">%d</xliff:g> gada</item>
-      <item quantity="other">Pirms <xliff:g id="ID_2">%d</xliff:g> gadiem</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="zero">Pirms <xliff:g id="ID_2">%d</xliff:g> dienām</item>
-      <item quantity="one">Pirms <xliff:g id="ID_2">%d</xliff:g> dienas</item>
-      <item quantity="other">Pirms <xliff:g id="ID_2">%d</xliff:g> dienām</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Nevarēja izveidot savienojumu"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-mk/strings.xml b/slices/view/src/main/res/values-mk/strings.xml
index ff88cd7..ea5ab25 100644
--- a/slices/view/src/main/res/values-mk/strings.xml
+++ b/slices/view/src/main/res/values-mk/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Повеќе"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Прикажи повеќе"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Ажурирано <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">Пред <xliff:g id="ID_2">%d</xliff:g> мин.</item>
-      <item quantity="other">Пред <xliff:g id="ID_2">%d</xliff:g> мин.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">Пред <xliff:g id="ID_2">%d</xliff:g> год.</item>
-      <item quantity="other">Пред <xliff:g id="ID_2">%d</xliff:g> год.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">Пред <xliff:g id="ID_2">%d</xliff:g> ден</item>
-      <item quantity="other">Пред <xliff:g id="ID_2">%d</xliff:g> дена</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Не може да се поврзе"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ml/strings.xml b/slices/view/src/main/res/values-ml/strings.xml
index b67ae80..ea5ab25 100644
--- a/slices/view/src/main/res/values-ml/strings.xml
+++ b/slices/view/src/main/res/values-ml/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"കൂടുതൽ"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"കൂടുതൽ കാണിക്കുക"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> അപ്‌ഡേറ്റ് ചെയ്‌തു"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> മിനിറ്റ് മുൻപ്</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> മിനിറ്റ് മുൻപ്</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> വർഷം മുൻപ്</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> വർഷം മുൻപ്</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ദിവസം മുൻപ്</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ദിവസം മുൻപ്</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"കണക്റ്റ് ചെയ്യാനായില്ല"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-mn/strings.xml b/slices/view/src/main/res/values-mn/strings.xml
index 52a5d1a..ea5ab25 100644
--- a/slices/view/src/main/res/values-mn/strings.xml
+++ b/slices/view/src/main/res/values-mn/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Бусад"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Дэлгэрэнгүй үзэх"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> шинэчилсэн"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> минутын өмнө</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> минутын өмнө</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> жилийн өмнө</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> жилийн өмнө</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> өдрийн өмнө</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> өдрийн өмнө</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Холбогдож чадсангүй"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-mr/strings.xml b/slices/view/src/main/res/values-mr/strings.xml
index 80aa0a7..ea5ab25 100644
--- a/slices/view/src/main/res/values-mr/strings.xml
+++ b/slices/view/src/main/res/values-mr/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"आणखी"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"आणखी दाखवा"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> ला अपडेट केले"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> मिनिटापूर्वी</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> मिनिटांपूर्वी</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> वर्षापूर्वी</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> वर्षांपूर्वी</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> दिवसापूर्वी</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> दिवसांपूर्वी</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"कनेक्ट करता आले नाही"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ms/strings.xml b/slices/view/src/main/res/values-ms/strings.xml
index 576b8df..ea5ab25 100644
--- a/slices/view/src/main/res/values-ms/strings.xml
+++ b/slices/view/src/main/res/values-ms/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Lagi"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Tunjukkan lagi"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Dikemas kini pada <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min yang lalu</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min yang lalu</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> thn yang lalu</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> thn yang lalu</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> hari yang lalu</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> hari yang lalu</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Tidak dapat menyambung"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-my/strings.xml b/slices/view/src/main/res/values-my/strings.xml
index 4a3e3d4..ea5ab25 100644
--- a/slices/view/src/main/res/values-my/strings.xml
+++ b/slices/view/src/main/res/values-my/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"နောက်ထပ်"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"နောက်ထပ် ပြပါ"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> က အပ်ဒိတ်လုပ်ထားသည်"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">ပြီးခဲ့သော<xliff:g id="ID_2">%d</xliff:g>မိနစ်</item>
-      <item quantity="one">ပြီးခဲ့သော<xliff:g id="ID_1">%d</xliff:g>မိနစ်</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">ပြီးခဲ့သော <xliff:g id="ID_2">%d</xliff:g>နှစ်</item>
-      <item quantity="one">ပြီးခဲ့သော <xliff:g id="ID_1">%d</xliff:g>နှစ်</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">ပြီးခဲ့သော <xliff:g id="ID_2">%d</xliff:g> ရက်</item>
-      <item quantity="one">ပြီးခဲ့သော <xliff:g id="ID_1">%d</xliff:g> ရက်</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"ချိတ်ဆက်၍ မရပါ"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-nb/strings.xml b/slices/view/src/main/res/values-nb/strings.xml
index 3fad9c4..ea5ab25 100644
--- a/slices/view/src/main/res/values-nb/strings.xml
+++ b/slices/view/src/main/res/values-nb/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Mer"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Vis mer"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Oppdatert <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">For <xliff:g id="ID_2">%d</xliff:g> min. siden</item>
-      <item quantity="one">For <xliff:g id="ID_1">%d</xliff:g> min. siden</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">For <xliff:g id="ID_2">%d</xliff:g> år siden</item>
-      <item quantity="one">For <xliff:g id="ID_1">%d</xliff:g> år siden</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">For <xliff:g id="ID_2">%d</xliff:g> dager siden</item>
-      <item quantity="one">For <xliff:g id="ID_1">%d</xliff:g> dag siden</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Kunne ikke koble til"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ne/strings.xml b/slices/view/src/main/res/values-ne/strings.xml
index beb8b311..ea5ab25 100644
--- a/slices/view/src/main/res/values-ne/strings.xml
+++ b/slices/view/src/main/res/values-ne/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"थप"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"थप देखाउनुहोस्"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"अद्यावधिक गरिएको समय: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> मिनेटअघि</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> मिनेटअघि</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> वर्षअघि</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> वर्षअघि</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> दिनअघि</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> दिनअघि</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"जडान गर्न सकिएन"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-nl/strings.xml b/slices/view/src/main/res/values-nl/strings.xml
index b5d2edc..ea5ab25 100644
--- a/slices/view/src/main/res/values-nl/strings.xml
+++ b/slices/view/src/main/res/values-nl/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Meer"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Meer weergeven"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Geüpdatet: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min geleden</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min geleden</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> jaar geleden</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> jaar geleden</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> dagen geleden</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> dag geleden</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Kan geen verbinding maken"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-or/strings.xml b/slices/view/src/main/res/values-or/strings.xml
deleted file mode 100644
index 6bf6019..0000000
--- a/slices/view/src/main/res/values-or/strings.xml
+++ /dev/null
@@ -1,37 +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.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"ଅଧିକ"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"ଅଧିକ ଦେଖାନ୍ତୁ"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g>ରେ ଅପଡେଟ୍ ହୋଇଥିଲା"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ମିନିଟ୍ ପୂର୍ବେ</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ମିନିଟ୍ ପୂର୍ବେ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ବର୍ଷ ପୂର୍ବେ</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ବର୍ଷ ପୂର୍ବେ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ଦିନ ପୂର୍ବେ</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ଦିନ ପୂର୍ବେ</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"କନେକ୍ଟ ହେଲାନାହିଁ"</string>
-</resources>
diff --git a/slices/view/src/main/res/values-pa/strings.xml b/slices/view/src/main/res/values-pa/strings.xml
index e588aac..ea5ab25 100644
--- a/slices/view/src/main/res/values-pa/strings.xml
+++ b/slices/view/src/main/res/values-pa/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"ਹੋਰ"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"ਹੋਰ ਦਿਖਾਓ"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> ਅੱਪਡੇਟ ਕੀਤੀ ਗਈ"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ਮਿੰਟ ਪਹਿਲਾਂ</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ਮਿੰਟ ਪਹਿਲਾਂ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ਸਾਲ ਪਹਿਲਾਂ</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ਸਾਲ ਪਹਿਲਾਂ</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ਦਿਨ ਪਹਿਲਾਂ</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ਦਿਨ ਪਹਿਲਾਂ</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-pl/strings.xml b/slices/view/src/main/res/values-pl/strings.xml
index c5300ca..9d9bede 100644
--- a/slices/view/src/main/res/values-pl/strings.xml
+++ b/slices/view/src/main/res/values-pl/strings.xml
@@ -18,26 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Więcej"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Pokaż więcej"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Aktualizacja: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> min temu</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> min temu</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min temu</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min temu</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> lata temu</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> lat temu</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> roku temu</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> rok temu</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> dni temu</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> dni temu</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> dnia temu</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> dzień temu</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Nie udało się połączyć"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-pt-rBR/strings.xml b/slices/view/src/main/res/values-pt-rBR/strings.xml
index 79cc7b7..629ba48 100644
--- a/slices/view/src/main/res/values-pt-rBR/strings.xml
+++ b/slices/view/src/main/res/values-pt-rBR/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"Mais <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Mais"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Mostrar mais"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Atualizado às <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> min atrás</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min atrás</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ano atrás</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> anos atrás</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> dia atrás</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> dias atrás</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Não foi possível conectar"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-pt-rPT/strings.xml b/slices/view/src/main/res/values-pt-rPT/strings.xml
index b81ec60..ea5ab25 100644
--- a/slices/view/src/main/res/values-pt-rPT/strings.xml
+++ b/slices/view/src/main/res/values-pt-rPT/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Mais"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Mostrar mais"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Atualizado: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> minutos.</item>
-      <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> minuto.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> anos.</item>
-      <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> ano.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> dias.</item>
-      <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> dia.</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Não foi possível ligar."</string>
 </resources>
diff --git a/slices/view/src/main/res/values-pt/strings.xml b/slices/view/src/main/res/values-pt/strings.xml
index 79cc7b7..629ba48 100644
--- a/slices/view/src/main/res/values-pt/strings.xml
+++ b/slices/view/src/main/res/values-pt/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"Mais <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Mais"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Mostrar mais"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Atualizado às <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> min atrás</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min atrás</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> ano atrás</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> anos atrás</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> dia atrás</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> dias atrás</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Não foi possível conectar"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ro/strings.xml b/slices/view/src/main/res/values-ro/strings.xml
index 9ff89d0..ea5ab25 100644
--- a/slices/view/src/main/res/values-ro/strings.xml
+++ b/slices/view/src/main/res/values-ro/strings.xml
@@ -18,23 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Mai mult"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Vedeți mai multe"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Actualizat la <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="few">acum <xliff:g id="ID_2">%d</xliff:g> min.</item>
-      <item quantity="other">acum <xliff:g id="ID_2">%d</xliff:g> de min.</item>
-      <item quantity="one">acum <xliff:g id="ID_1">%d</xliff:g> min.</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="few">acum <xliff:g id="ID_2">%d</xliff:g> ani</item>
-      <item quantity="other">acum <xliff:g id="ID_2">%d</xliff:g> de ani</item>
-      <item quantity="one">acum <xliff:g id="ID_1">%d</xliff:g> an</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="few">acum <xliff:g id="ID_2">%d</xliff:g> zile</item>
-      <item quantity="other">acum <xliff:g id="ID_2">%d</xliff:g> de zile</item>
-      <item quantity="one">acum <xliff:g id="ID_1">%d</xliff:g> zi</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Nu s-a putut conecta"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ru/strings.xml b/slices/view/src/main/res/values-ru/strings.xml
index 85953aa..9d9bede 100644
--- a/slices/view/src/main/res/values-ru/strings.xml
+++ b/slices/view/src/main/res/values-ru/strings.xml
@@ -18,26 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Ещё"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Ещё"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Обновлено <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> мин. назад</item>
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> мин. назад</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> мин. назад</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> мин. назад</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> г. назад</item>
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> г. назад</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> лет назад</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> г. назад</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> дн. назад</item>
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> дн. назад</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> дн. назад</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> дн. назад</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Ошибка подключения"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-si/strings.xml b/slices/view/src/main/res/values-si/strings.xml
index cfd7685..ea5ab25 100644
--- a/slices/view/src/main/res/values-si/strings.xml
+++ b/slices/view/src/main/res/values-si/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"තව"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"තව පෙන්වන්න"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> යාවත්කාලීන කරන ලදී"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">මිනි <xliff:g id="ID_2">%d</xliff:g>කට පෙර</item>
-      <item quantity="other">මිනි <xliff:g id="ID_2">%d</xliff:g>කට පෙර</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">වසර <xliff:g id="ID_2">%d</xliff:g>කට පෙර</item>
-      <item quantity="other">වසර <xliff:g id="ID_2">%d</xliff:g>කට පෙර</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">දින <xliff:g id="ID_2">%d</xliff:g>කට පෙර</item>
-      <item quantity="other">දින <xliff:g id="ID_2">%d</xliff:g>කට පෙර</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"සම්බන්ධ වීමට නොහැකි විය"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-sk/strings.xml b/slices/view/src/main/res/values-sk/strings.xml
index 76bed58..ea5ab25 100644
--- a/slices/view/src/main/res/values-sk/strings.xml
+++ b/slices/view/src/main/res/values-sk/strings.xml
@@ -18,26 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Viac"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Zobraziť viac"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Aktualizované <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="few">pred <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="many">pred <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="other">pred <xliff:g id="ID_2">%d</xliff:g> min</item>
-      <item quantity="one">pred <xliff:g id="ID_1">%d</xliff:g> min</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="few">pred <xliff:g id="ID_2">%d</xliff:g> rokmi</item>
-      <item quantity="many">pred <xliff:g id="ID_2">%d</xliff:g> roka</item>
-      <item quantity="other">pred <xliff:g id="ID_2">%d</xliff:g> rokmi</item>
-      <item quantity="one">pred <xliff:g id="ID_1">%d</xliff:g> rokom</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="few">pred <xliff:g id="ID_2">%d</xliff:g> dňami</item>
-      <item quantity="many">pred <xliff:g id="ID_2">%d</xliff:g> dňa</item>
-      <item quantity="other">pred <xliff:g id="ID_2">%d</xliff:g> dňami</item>
-      <item quantity="one">pred <xliff:g id="ID_1">%d</xliff:g> dňom</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Nepodarilo sa pripojiť"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-sl/strings.xml b/slices/view/src/main/res/values-sl/strings.xml
index 0389500..59bf101 100644
--- a/slices/view/src/main/res/values-sl/strings.xml
+++ b/slices/view/src/main/res/values-sl/strings.xml
@@ -18,26 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"in še <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Več"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Pokaži več"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Posodobljeno: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">pred <xliff:g id="ID_2">%d</xliff:g> minuto</item>
-      <item quantity="two">pred <xliff:g id="ID_2">%d</xliff:g> minutama</item>
-      <item quantity="few">pred <xliff:g id="ID_2">%d</xliff:g> minutami</item>
-      <item quantity="other">pred <xliff:g id="ID_2">%d</xliff:g> minutami</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">pred <xliff:g id="ID_2">%d</xliff:g> letom</item>
-      <item quantity="two">pred <xliff:g id="ID_2">%d</xliff:g> letoma</item>
-      <item quantity="few">pred <xliff:g id="ID_2">%d</xliff:g> leti</item>
-      <item quantity="other">pred <xliff:g id="ID_2">%d</xliff:g> leti</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">pred <xliff:g id="ID_2">%d</xliff:g> dnem</item>
-      <item quantity="two">pred <xliff:g id="ID_2">%d</xliff:g> dnevoma</item>
-      <item quantity="few">pred <xliff:g id="ID_2">%d</xliff:g> dnevi</item>
-      <item quantity="other">pred <xliff:g id="ID_2">%d</xliff:g> dnevi</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Povezava ni mogoča"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-sq/strings.xml b/slices/view/src/main/res/values-sq/strings.xml
index 0359c86..ea5ab25 100644
--- a/slices/view/src/main/res/values-sq/strings.xml
+++ b/slices/view/src/main/res/values-sq/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Më shumë"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Shfaq më shumë"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Përditësuar <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> minuta më parë</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> minutë më parë</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> vite më parë</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> vit më parë</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ditë më parë</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ditë më parë</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Nuk mund të lidhej"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-sr/strings.xml b/slices/view/src/main/res/values-sr/strings.xml
index 718f3d7..a66220a 100644
--- a/slices/view/src/main/res/values-sr/strings.xml
+++ b/slices/view/src/main/res/values-sr/strings.xml
@@ -18,23 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"и још <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Још"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Прикажи више"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Ажурирано <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one">пре <xliff:g id="ID_2">%d</xliff:g> мин</item>
-      <item quantity="few">пре <xliff:g id="ID_2">%d</xliff:g> мин</item>
-      <item quantity="other">пре <xliff:g id="ID_2">%d</xliff:g> мин</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one">пре <xliff:g id="ID_2">%d</xliff:g> год</item>
-      <item quantity="few">пре <xliff:g id="ID_2">%d</xliff:g> год</item>
-      <item quantity="other">пре <xliff:g id="ID_2">%d</xliff:g> год</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one">пре <xliff:g id="ID_2">%d</xliff:g> дан</item>
-      <item quantity="few">пре <xliff:g id="ID_2">%d</xliff:g> дана</item>
-      <item quantity="other">пре <xliff:g id="ID_2">%d</xliff:g> дана</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Повезивање није успело"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-sv/strings.xml b/slices/view/src/main/res/values-sv/strings.xml
index 90caa1a..cbcec4f 100644
--- a/slices/view/src/main/res/values-sv/strings.xml
+++ b/slices/view/src/main/res/values-sv/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> till"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Mer"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Visa mer"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Uppdaterades <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> minuter sedan</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> minut sedan</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> år sedan</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> år sedan</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> dagar sedan</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> dag sedan</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Det gick inte att ansluta"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-sw/strings.xml b/slices/view/src/main/res/values-sw/strings.xml
index 609c51f..ea5ab25 100644
--- a/slices/view/src/main/res/values-sw/strings.xml
+++ b/slices/view/src/main/res/values-sw/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Mengine"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Onyesha mengine"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Ilisasishwa <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other">Dakika <xliff:g id="ID_2">%d</xliff:g> zilizopita</item>
-      <item quantity="one">Dakika <xliff:g id="ID_1">%d</xliff:g> iliyopita</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other">Miaka <xliff:g id="ID_2">%d</xliff:g> iliyopita</item>
-      <item quantity="one">Mwaka <xliff:g id="ID_1">%d</xliff:g> uliopita</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other">Siku <xliff:g id="ID_2">%d</xliff:g> zilizopita</item>
-      <item quantity="one">Siku <xliff:g id="ID_1">%d</xliff:g> iliyopita</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Imeshindwa kuunganisha"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ta/strings.xml b/slices/view/src/main/res/values-ta/strings.xml
index 778218e..ea5ab25 100644
--- a/slices/view/src/main/res/values-ta/strings.xml
+++ b/slices/view/src/main/res/values-ta/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"மேலும்"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"மேலும் காட்டு"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"புதுப்பித்தது: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> நிமி. முன்</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> நிமி. முன்</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ஆண்டிற்கு முன்</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ஆண்டிற்கு முன்</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> நாளுக்கு முன்</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> நாளுக்கு முன்</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"இணைக்க முடியவில்லை"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-te/strings.xml b/slices/view/src/main/res/values-te/strings.xml
index 82137b8..ea5ab25 100644
--- a/slices/view/src/main/res/values-te/strings.xml
+++ b/slices/view/src/main/res/values-te/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"మరింత"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"మరింత చూపు"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"అప్‌డేట్ చేసిన సమయం <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> నిమి క్రితం</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> నిమి క్రితం</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> సం క్రితం</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> సం క్రితం</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> రోజుల క్రితం</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> రోజు క్రితం</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"కనెక్ట్ చేయడం సాధ్యపడలేదు"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-th/strings.xml b/slices/view/src/main/res/values-th/strings.xml
index 3ae19da..ea5ab25 100644
--- a/slices/view/src/main/res/values-th/strings.xml
+++ b/slices/view/src/main/res/values-th/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"เพิ่มเติม"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"แสดงเพิ่ม"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"อัปเดตเมื่อ <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> นาทีที่แล้ว</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> นาทีที่แล้ว</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ปีที่แล้ว</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ปีที่แล้ว</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> วันที่แล้ว</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> วันที่แล้ว</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"เชื่อมต่อไม่ได้"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-tl/strings.xml b/slices/view/src/main/res/values-tl/strings.xml
index 2e76a1a..ea5ab25 100644
--- a/slices/view/src/main/res/values-tl/strings.xml
+++ b/slices/view/src/main/res/values-tl/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Higit pa"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Magpakita pa"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Na-update noong <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> min ang nakalipas</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> na min ang nakalipas</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> taon ang nakalipas</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> na taon ang nakalipas</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> araw ang nakalipas</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> na araw ang nakalipas</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Hindi makakonekta"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-tr/strings.xml b/slices/view/src/main/res/values-tr/strings.xml
index 84da5fb..ea5ab25 100644
--- a/slices/view/src/main/res/values-tr/strings.xml
+++ b/slices/view/src/main/res/values-tr/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Diğer"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Daha fazla göster"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Güncellenme zamanı: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> dk. önce</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> dk. önce</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> yıl önce</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> yıl önce</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> gün önce</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> gün önce</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Bağlanılamadı"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-uk/strings.xml b/slices/view/src/main/res/values-uk/strings.xml
index 0706d80..ea5ab25 100644
--- a/slices/view/src/main/res/values-uk/strings.xml
+++ b/slices/view/src/main/res/values-uk/strings.xml
@@ -18,26 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Більше"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Показати більше"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Оновлено: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> хвилину тому</item>
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> хвилини тому</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> хвилин тому</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> хвилини тому</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> рік тому</item>
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> роки тому</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> років тому</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> року тому</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> день тому</item>
-      <item quantity="few"><xliff:g id="ID_2">%d</xliff:g> дні тому</item>
-      <item quantity="many"><xliff:g id="ID_2">%d</xliff:g> днів тому</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> дня тому</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Не вдалося під’єднатися"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-ur/strings.xml b/slices/view/src/main/res/values-ur/strings.xml
index 1fff81c4..ce427c0 100644
--- a/slices/view/src/main/res/values-ur/strings.xml
+++ b/slices/view/src/main/res/values-ur/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"‎‎‎‎‎+ <xliff:g id="NUMBER">%1$d</xliff:g>‎‎"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"مزید"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"مزید دکھائیں"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> اپ ڈیٹ کیا گیا"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> منٹ پہلے</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> منٹ پہلے</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> سال پہلے</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> سال پہلے</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> دن پہلے</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> دن پہلے</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"منسلک نہیں ہو سکا"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-uz/strings.xml b/slices/view/src/main/res/values-uz/strings.xml
index 0a973cd..ea5ab25 100644
--- a/slices/view/src/main/res/values-uz/strings.xml
+++ b/slices/view/src/main/res/values-uz/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Yana"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Yana"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Yangilandi: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> daqiqa oldin</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> daqiqa oldin</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> yil oldin</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> yil oldin</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> kun oldin</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> kun oldin</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Ulanib bo‘lmadi"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-vi/strings.xml b/slices/view/src/main/res/values-vi/strings.xml
index 1e71db6..ea5ab25 100644
--- a/slices/view/src/main/res/values-vi/strings.xml
+++ b/slices/view/src/main/res/values-vi/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Thêm"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Hiển thị thêm"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Đã cập nhật lúc <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> phút trước</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> phút trước</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> năm trước</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> năm trước</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> ngày trước</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> ngày trước</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Không thể kết nối"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-zh-rCN/strings.xml b/slices/view/src/main/res/values-zh-rCN/strings.xml
index c018343..ea5ab25 100644
--- a/slices/view/src/main/res/values-zh-rCN/strings.xml
+++ b/slices/view/src/main/res/values-zh-rCN/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"更多"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"显示更多"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"更新时间:<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 分钟前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 分钟前</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 年前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 年前</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 天前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 天前</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"无法连接"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-zh-rHK/strings.xml b/slices/view/src/main/res/values-zh-rHK/strings.xml
index d1ac276..ea5ab25 100644
--- a/slices/view/src/main/res/values-zh-rHK/strings.xml
+++ b/slices/view/src/main/res/values-zh-rHK/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"更多"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"顯示更多"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"更新時間:<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 分鐘前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 分鐘前</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 年前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 年前</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 天前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 天前</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"無法連線"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-zh-rTW/strings.xml b/slices/view/src/main/res/values-zh-rTW/strings.xml
index d1ac276..ea5ab25 100644
--- a/slices/view/src/main/res/values-zh-rTW/strings.xml
+++ b/slices/view/src/main/res/values-zh-rTW/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"更多"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"顯示更多"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"更新時間:<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 分鐘前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 分鐘前</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 年前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 年前</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> 天前</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> 天前</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"無法連線"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-zu/strings.xml b/slices/view/src/main/res/values-zu/strings.xml
index 966bb1b..ea5ab25 100644
--- a/slices/view/src/main/res/values-zu/strings.xml
+++ b/slices/view/src/main/res/values-zu/strings.xml
@@ -18,20 +18,4 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="abc_slice_more" msgid="1983560225998630901">"Okuningi"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"Bonisa okuningi"</string>
-    <string name="abc_slice_updated" msgid="8155085405396453848">"Kubuyekezwe ngo-<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> iminithi eledlule</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> iminithi eledlule</item>
-    </plurals>
-    <plurals name="abc_slice_duration_years" formatted="false" msgid="6212691832333991589">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> unyaka owedlule</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> unyaka owedlule</item>
-    </plurals>
-    <plurals name="abc_slice_duration_days" formatted="false" msgid="6241698511167107334">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> izinsuku ezedlule</item>
-      <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> izinsuku ezedlule</item>
-    </plurals>
-    <string name="abc_slice_error" msgid="4188371422904147368">"Ayikwazanga ukuxhuma"</string>
 </resources>
diff --git a/slices/view/src/main/res/values/attrs.xml b/slices/view/src/main/res/values/attrs.xml
index b73c5a5..f3e621b 100644
--- a/slices/view/src/main/res/values/attrs.xml
+++ b/slices/view/src/main/res/values/attrs.xml
@@ -30,33 +30,17 @@
         <attr name="headerTitleSize" format="dimension" />
         <!-- Text size to use for subtitle text in the header of the slice. -->
         <attr name="headerSubtitleSize" format="dimension"/>
-        <!-- Vertical padding to use between header title text and header subtitle text. -->
-        <attr name="headerTextVerticalPadding" format="dimension" />
-
         <!-- Text size to use for title text in a non-header row of the slice. -->
         <attr name="titleSize" format="dimension" />
         <!-- Text size to use for subtitle text in a non-header row of the slice. -->
         <attr name="subtitleSize" format="dimension" />
-        <!-- Vertical padding to use between title text and subtitle text. -->
-        <attr name="textVerticalPadding" format="dimension" />
-
         <!-- Text size to use for title text in a grid row of the slice. -->
         <attr name="gridTitleSize" format="dimension" />
         <!-- Text size to use for the subtitle text in a grid row of the slice. -->
         <attr name="gridSubtitleSize" format="dimension" />
-        <!-- Vertical padding to use between title text and subtitle text in a grid cell. -->
-        <attr name="gridTextVerticalPadding" format="dimension" />
-        <!-- A grid row with all images goes right to the edge of the view if it's the first or
-         last row of a slice. Use this to specify padding to apply to the top of the grid row in
-         this situation. -->
-        <attr name="gridTopPadding" format="dimension" />
-        <!-- A grid row with all images goes right to the edge of the view if it's the first or
-         last row of a slice. Use this to specify padding to apply to the bottom of the grid row in
-         this situation. -->
-        <attr name="gridBottomPadding" format="dimension" />
     </declare-styleable>
 
     <!-- To apply a style for all slices shown within an activity or app you
          may set this in your app theme pointing to your custom SliceView style.-->
-    <attr name="sliceViewStyle" format="reference" />
+    <attr name="sliceViewStyle" format="reference"/>
 </resources>
\ No newline at end of file
diff --git a/slices/view/src/main/res/values/dimens.xml b/slices/view/src/main/res/values/dimens.xml
index 2894fcc..f3313bf 100644
--- a/slices/view/src/main/res/values/dimens.xml
+++ b/slices/view/src/main/res/values/dimens.xml
@@ -58,10 +58,6 @@
     <dimen name="abc_slice_grid_small_image_text_height">120dp</dimen>
     <!-- Gutter between cells in a grid row-->
     <dimen name="abc_slice_grid_gutter">4dp</dimen>
-    <!-- Space between image and text items in grid row -->
-    <dimen name="abc_slice_grid_text_padding">10dp</dimen>
-    <!-- Space between text and text items in grid row -->
-    <dimen name="abc_slice_grid_text_inner_padding">2dp</dimen>
 
     <!-- Big picture -->
     <!-- Min height of row showing a single large image -->
diff --git a/swiperefreshlayout/api/current.txt b/swiperefreshlayout/api/current.txt
index 49e8991..018d30e 100644
--- a/swiperefreshlayout/api/current.txt
+++ b/swiperefreshlayout/api/current.txt
@@ -58,9 +58,7 @@
     method public void setProgressViewOffset(boolean, int, int);
     method public void setRefreshing(boolean);
     method public void setSize(int);
-    method public void setSlingshotDistance(int);
     field public static final int DEFAULT = 1; // 0x1
-    field public static final int DEFAULT_SLINGSHOT_DISTANCE = -1; // 0xffffffff
     field public static final int LARGE = 0; // 0x0
     field protected int mFrom;
     field protected int mOriginalOffsetTop;
diff --git a/swiperefreshlayout/src/main/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayout.java b/swiperefreshlayout/src/main/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayout.java
index 5df8cdd..cd99498 100644
--- a/swiperefreshlayout/src/main/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayout.java
+++ b/swiperefreshlayout/src/main/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayout.java
@@ -36,7 +36,6 @@
 import androidx.annotation.ColorRes;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.Px;
 import androidx.annotation.VisibleForTesting;
 import androidx.core.content.ContextCompat;
 import androidx.core.view.NestedScrollingChild;
@@ -74,8 +73,6 @@
     // Maps to ProgressBar default style
     public static final int DEFAULT = CircularProgressDrawable.DEFAULT;
 
-    public static final int DEFAULT_SLINGSHOT_DISTANCE = -1;
-
     @VisibleForTesting
     static final int CIRCLE_DIAMETER = 40;
     @VisibleForTesting
@@ -152,8 +149,6 @@
 
     int mSpinnerOffsetEnd;
 
-    int mCustomSlingshotDistance;
-
     CircularProgressDrawable mProgress;
 
     private Animation mScaleAnimation;
@@ -299,18 +294,6 @@
     }
 
     /**
-     * Sets a custom slingshot distance.
-     *
-     * @param slingshotDistance The distance in pixels that the refresh indicator can be pulled
-     *                          beyond its resting position. Use
-     *                          {@link #DEFAULT_SLINGSHOT_DISTANCE} to reset to the default value.
-     *
-     */
-    public void setSlingshotDistance(@Px int slingshotDistance) {
-        mCustomSlingshotDistance = slingshotDistance;
-    }
-
-    /**
      * One of DEFAULT, or LARGE.
      */
     public void setSize(int size) {
@@ -919,11 +902,8 @@
         float dragPercent = Math.min(1f, Math.abs(originalDragPercent));
         float adjustedPercent = (float) Math.max(dragPercent - .4, 0) * 5 / 3;
         float extraOS = Math.abs(overscrollTop) - mTotalDragDistance;
-        float slingshotDist = mCustomSlingshotDistance > 0
-                ? mCustomSlingshotDistance
-                : (mUsingCustomStart
-                        ? mSpinnerOffsetEnd - mOriginalOffsetTop
-                        : mSpinnerOffsetEnd);
+        float slingshotDist = mUsingCustomStart ? mSpinnerOffsetEnd - mOriginalOffsetTop
+                : mSpinnerOffsetEnd;
         float tensionSlingshotPercent = Math.max(0, Math.min(extraOS, slingshotDist * 2)
                 / slingshotDist);
         float tensionPercent = (float) ((tensionSlingshotPercent / 4) - Math.pow(
diff --git a/transition/src/main/java/androidx/transition/TransitionManager.java b/transition/src/main/java/androidx/transition/TransitionManager.java
index 579f4b9..517d2e3 100644
--- a/transition/src/main/java/androidx/transition/TransitionManager.java
+++ b/transition/src/main/java/androidx/transition/TransitionManager.java
@@ -193,16 +193,12 @@
     static ArrayMap<ViewGroup, ArrayList<Transition>> getRunningTransitions() {
         WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>> runningTransitions =
                 sRunningTransitions.get();
-        if (runningTransitions != null) {
-            ArrayMap<ViewGroup, ArrayList<Transition>> transitions = runningTransitions.get();
-            if (transitions != null) {
-                return transitions;
-            }
+        if (runningTransitions == null || runningTransitions.get() == null) {
+            ArrayMap<ViewGroup, ArrayList<Transition>> transitions = new ArrayMap<>();
+            runningTransitions = new WeakReference<>(transitions);
+            sRunningTransitions.set(runningTransitions);
         }
-        ArrayMap<ViewGroup, ArrayList<Transition>> transitions = new ArrayMap<>();
-        runningTransitions = new WeakReference<>(transitions);
-        sRunningTransitions.set(runningTransitions);
-        return transitions;
+        return runningTransitions.get();
     }
 
     private static void sceneChangeRunTransition(final ViewGroup sceneRoot,
diff --git a/tv-provider/src/main/java/androidx/tvprovider/media/tv/TvContractUtils.java b/tv-provider/src/main/java/androidx/tvprovider/media/tv/TvContractUtils.java
index 99383c0..3483d0f 100644
--- a/tv-provider/src/main/java/androidx/tvprovider/media/tv/TvContractUtils.java
+++ b/tv-provider/src/main/java/androidx/tvprovider/media/tv/TvContractUtils.java
@@ -50,7 +50,7 @@
         if (TextUtils.isEmpty(commaSeparatedRatings)) {
             return EMPTY;
         }
-        String[] ratings = commaSeparatedRatings.split("\\s*,\\s*", -1);
+        String[] ratings = commaSeparatedRatings.split("\\s*,\\s*");
         List<TvContentRating> contentRatings = new ArrayList<>(ratings.length);
         for (String rating : ratings) {
             try {
diff --git a/v7/appcompat/res/values-af/strings.xml b/v7/appcompat/res/values-af/strings.xml
index b7dd9bc..15ed3b2 100644
--- a/v7/appcompat/res/values-af/strings.xml
+++ b/v7/appcompat/res/values-af/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"AAN"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"AF"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Soek"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Kieslys+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Simbool+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funksie+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"spasiebalk"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-am/strings.xml b/v7/appcompat/res/values-am/strings.xml
index 485ffad..42bbc06 100644
--- a/v7/appcompat/res/values-am/strings.xml
+++ b/v7/appcompat/res/values-am/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"በርቷል"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ጠፍቷል"</string>
     <string name="search_menu_title" msgid="146198913615257606">"ፈልግ"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"ምናሌ+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"ሰርዝ"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ar/strings.xml b/v7/appcompat/res/values-ar/strings.xml
index a7683ce..3278162 100644
--- a/v7/appcompat/res/values-ar/strings.xml
+++ b/v7/appcompat/res/values-ar/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"تشغيل"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"إيقاف"</string>
     <string name="search_menu_title" msgid="146198913615257606">"البحث"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"القائمة+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-as/strings.xml b/v7/appcompat/res/values-as/strings.xml
index a3574d7..1f90618 100644
--- a/v7/appcompat/res/values-as/strings.xml
+++ b/v7/appcompat/res/values-as/strings.xml
@@ -29,19 +29,13 @@
     <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>
+    <!-- no translation found for abc_shareactionprovider_share_with_application (3300176832234831527) -->
+    <skip />
     <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>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"মেনু+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"মেটা+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"CTRL+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"শ্বিফ্ট+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"ফাংশ্বন+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"স্পেচ"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"এণ্টাৰ"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"মচক"</string>
+    <!-- no translation found for abc_capital_on (3405795526292276155) -->
+    <skip />
+    <!-- no translation found for abc_capital_off (121134116657445385) -->
+    <skip />
+    <!-- no translation found for search_menu_title (146198913615257606) -->
+    <skip />
 </resources>
diff --git a/v7/appcompat/res/values-az/strings.xml b/v7/appcompat/res/values-az/strings.xml
index aae3b94..29e00dd 100644
--- a/v7/appcompat/res/values-az/strings.xml
+++ b/v7/appcompat/res/values-az/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"AKTİV"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DEAKTİV"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Axtarış"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menyu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funksiya+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"kosmos"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"daxil olun"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"silin"</string>
 </resources>
diff --git a/v7/appcompat/res/values-b+sr+Latn/strings.xml b/v7/appcompat/res/values-b+sr+Latn/strings.xml
index 734525b..c3462f6 100644
--- a/v7/appcompat/res/values-b+sr+Latn/strings.xml
+++ b/v7/appcompat/res/values-b+sr+Latn/strings.xml
@@ -34,14 +34,4 @@
     <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>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"taster za razmak"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-be/strings.xml b/v7/appcompat/res/values-be/strings.xml
index f04076a..99ee19f 100644
--- a/v7/appcompat/res/values-be/strings.xml
+++ b/v7/appcompat/res/values-be/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"УКЛ."</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ВЫКЛ."</string>
     <string name="search_menu_title" msgid="146198913615257606">"Пошук"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Меню +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fn +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Прабел"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-bg/strings.xml b/v7/appcompat/res/values-bg/strings.xml
index 2c607a1..1d37d0d 100644
--- a/v7/appcompat/res/values-bg/strings.xml
+++ b/v7/appcompat/res/values-bg/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ВКЛ."</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ИЗКЛ."</string>
     <string name="search_menu_title" msgid="146198913615257606">"Търсене"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"клавиша за интервал"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-bn/strings.xml b/v7/appcompat/res/values-bn/strings.xml
index 1c62a2d..2ea7591 100644
--- a/v7/appcompat/res/values-bn/strings.xml
+++ b/v7/appcompat/res/values-bn/strings.xml
@@ -22,11 +22,11 @@
     <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>
-    <string name="abc_search_hint" msgid="7723749260725869598">"সার্চ..."</string>
+    <string name="abc_search_hint" msgid="7723749260725869598">"অনুসন্ধান..."</string>
     <string name="abc_searchview_description_query" msgid="2550479030709304392">"ক্যোয়ারী খুঁজুন"</string>
     <string name="abc_searchview_description_clear" msgid="3691816814315814921">"ক্যোয়ারী সাফ করুন"</string>
     <string name="abc_searchview_description_submit" msgid="8928215447528550784">"ক্যোয়ারী জমা দিন"</string>
-    <string name="abc_searchview_description_voice" msgid="893419373245838918">"ভয়েস সার্চ"</string>
+    <string name="abc_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>
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"চালু"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"বন্ধ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"খুঁজুন"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"মেনু+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"স্পেস"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"মুছুন"</string>
 </resources>
diff --git a/v7/appcompat/res/values-bs/strings.xml b/v7/appcompat/res/values-bs/strings.xml
index 00ebc41..07d1411 100644
--- a/v7/appcompat/res/values-bs/strings.xml
+++ b/v7/appcompat/res/values-bs/strings.xml
@@ -20,8 +20,8 @@
     <string name="abc_action_bar_home_description" msgid="4600421777120114993">"Vrati se na početnu stranicu"</string>
     <string name="abc_action_bar_up_description" msgid="1594238315039666878">"Navigiraj prema gore"</string>
     <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"Više opcija"</string>
-    <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"Suzi"</string>
-    <string name="abc_searchview_description_search" msgid="8264924765203268293">"Pretraživanje"</string>
+    <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"Skupi"</string>
+    <string name="abc_searchview_description_search" msgid="8264924765203268293">"Traži"</string>
     <string name="abc_search_hint" msgid="7723749260725869598">"Pretraži..."</string>
     <string name="abc_searchview_description_query" msgid="2550479030709304392">"Pretraži upit"</string>
     <string name="abc_searchview_description_clear" msgid="3691816814315814921">"Obriši upit"</string>
@@ -34,14 +34,4 @@
     <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>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"razmaknica"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ca/strings.xml b/v7/appcompat/res/values-ca/strings.xml
index c4f3b4d..03ebec3 100644
--- a/v7/appcompat/res/values-ca/strings.xml
+++ b/v7/appcompat/res/values-ca/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ACTIVAT"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DESACTIVAT"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Cerca"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menú+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Maj+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funció+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Espai"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Retorn"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Supr"</string>
 </resources>
diff --git a/v7/appcompat/res/values-cs/strings.xml b/v7/appcompat/res/values-cs/strings.xml
index 9111883..05cd4e0 100644
--- a/v7/appcompat/res/values-cs/strings.xml
+++ b/v7/appcompat/res/values-cs/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ZAPNUTO"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"VYPNUTO"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Hledat"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fn+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"mezerník"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-da/strings.xml b/v7/appcompat/res/values-da/strings.xml
index f05e142..813885a 100644
--- a/v7/appcompat/res/values-da/strings.xml
+++ b/v7/appcompat/res/values-da/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"TIL"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"FRA"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Søg"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fn+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"mellemrum"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-de/strings.xml b/v7/appcompat/res/values-de/strings.xml
index fb0dd6a..0b57259 100644
--- a/v7/appcompat/res/values-de/strings.xml
+++ b/v7/appcompat/res/values-de/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"An"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"Aus"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Suchen"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menütaste +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta-Taste +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Strg +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Umschalttaste +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym-Taste +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funktionstaste +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Leertaste +"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Eingabetaste"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Löschen"</string>
 </resources>
diff --git a/v7/appcompat/res/values-el/strings.xml b/v7/appcompat/res/values-el/strings.xml
index b7da605..ec7a666 100644
--- a/v7/appcompat/res/values-el/strings.xml
+++ b/v7/appcompat/res/values-el/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ΕΝΕΡΓΟΠΟΙΗΣΗ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ΑΠΕΝΕΡΓΟΠΟΙΗΣΗ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Αναζήτηση"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"διάστημα"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-en-rAU/strings.xml b/v7/appcompat/res/values-en-rAU/strings.xml
index a315670..a4d048c 100644
--- a/v7/appcompat/res/values-en-rAU/strings.xml
+++ b/v7/appcompat/res/values-en-rAU/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ON"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"OFF"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Search"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-en-rCA/strings.xml b/v7/appcompat/res/values-en-rCA/strings.xml
index a315670..a4d048c 100644
--- a/v7/appcompat/res/values-en-rCA/strings.xml
+++ b/v7/appcompat/res/values-en-rCA/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ON"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"OFF"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Search"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-en-rGB/strings.xml b/v7/appcompat/res/values-en-rGB/strings.xml
index a315670..a4d048c 100644
--- a/v7/appcompat/res/values-en-rGB/strings.xml
+++ b/v7/appcompat/res/values-en-rGB/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ON"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"OFF"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Search"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-en-rIN/strings.xml b/v7/appcompat/res/values-en-rIN/strings.xml
index a315670..a4d048c 100644
--- a/v7/appcompat/res/values-en-rIN/strings.xml
+++ b/v7/appcompat/res/values-en-rIN/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ON"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"OFF"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Search"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-en-rXC/strings.xml b/v7/appcompat/res/values-en-rXC/strings.xml
index 2e8e581..b1d5f93 100644
--- a/v7/appcompat/res/values-en-rXC/strings.xml
+++ b/v7/appcompat/res/values-en-rXC/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎‏‏‎ON‎‏‎‎‏‎"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎OFF‎‏‎‎‏‎"</string>
     <string name="search_menu_title" msgid="146198913615257606">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎Search‎‏‎‎‏‎"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎Menu+‎‏‎‎‏‎"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎Meta+‎‏‎‎‏‎"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‎‎Ctrl+‎‏‎‎‏‎"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎Alt+‎‏‎‎‏‎"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎Shift+‎‏‎‎‏‎"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎Sym+‎‏‎‎‏‎"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‏‎Function+‎‏‎‎‏‎"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‏‎‎space‎‏‎‎‏‎"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‏‏‎‎‎enter‎‏‎‎‏‎"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‎‎delete‎‏‎‎‏‎"</string>
 </resources>
diff --git a/v7/appcompat/res/values-es-rUS/strings.xml b/v7/appcompat/res/values-es-rUS/strings.xml
index 5d58df0..0cc8a70 100644
--- a/v7/appcompat/res/values-es-rUS/strings.xml
+++ b/v7/appcompat/res/values-es-rUS/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ACTIVADO"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DESACTIVADO"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Buscar"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menú+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Mayúscula+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Función+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"espacio"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"intro"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"borrar"</string>
 </resources>
diff --git a/v7/appcompat/res/values-es/strings.xml b/v7/appcompat/res/values-es/strings.xml
index 5238229..3e0828b 100644
--- a/v7/appcompat/res/values-es/strings.xml
+++ b/v7/appcompat/res/values-es/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ACTIVADO"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DESACTIVADO"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Buscar"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menú +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Mayús +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Función +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Espacio"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Intro"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Eliminar"</string>
 </resources>
diff --git a/v7/appcompat/res/values-et/strings.xml b/v7/appcompat/res/values-et/strings.xml
index b944f77..3a3dcbf 100644
--- a/v7/appcompat/res/values-et/strings.xml
+++ b/v7/appcompat/res/values-et/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"SEES"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"VÄLJAS"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Otsing"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menüü +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Tõstuklahv +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funktsiooniklahv +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"tühik"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"sisestusklahv"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"kustutamisklahv"</string>
 </resources>
diff --git a/v7/appcompat/res/values-eu/strings.xml b/v7/appcompat/res/values-eu/strings.xml
index 5a45e61..a651036 100644
--- a/v7/appcompat/res/values-eu/strings.xml
+++ b/v7/appcompat/res/values-eu/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"AKTIBATUTA"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DESAKTIBATUTA"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Bilatu"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menua +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ktrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Maius +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funtzioa +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Zuriunea"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Sartu"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Ezabatu"</string>
 </resources>
diff --git a/v7/appcompat/res/values-fa/strings.xml b/v7/appcompat/res/values-fa/strings.xml
index 35e6596..9b844b0 100644
--- a/v7/appcompat/res/values-fa/strings.xml
+++ b/v7/appcompat/res/values-fa/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"روشن"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"خاموش"</string>
     <string name="search_menu_title" msgid="146198913615257606">"جستجو"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"منو+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"‎Meta+‎"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"‎Ctrl+‎"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"‎Alt+‎"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"‎Shift+‎"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"‎Sym+‎"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"‎Function+‎"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"کلید فاصله"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-fi/strings.xml b/v7/appcompat/res/values-fi/strings.xml
index 829b6bb..e9bd952 100644
--- a/v7/appcompat/res/values-fi/strings.xml
+++ b/v7/appcompat/res/values-fi/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"KÄYTÖSSÄ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"POIS KÄYTÖSTÄ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Haku"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Valikko+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Vaihto+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fn+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"välilyönti"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-fr-rCA/strings.xml b/v7/appcompat/res/values-fr-rCA/strings.xml
index a8ef3ad..a3e763b 100644
--- a/v7/appcompat/res/values-fr-rCA/strings.xml
+++ b/v7/appcompat/res/values-fr-rCA/strings.xml
@@ -22,7 +22,7 @@
     <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"Plus d\'options"</string>
     <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"Réduire"</string>
     <string name="abc_searchview_description_search" msgid="8264924765203268293">"Rechercher"</string>
-    <string name="abc_search_hint" msgid="7723749260725869598">"Rechercher…"</string>
+    <string name="abc_search_hint" msgid="7723749260725869598">"Recherche en cours..."</string>
     <string name="abc_searchview_description_query" msgid="2550479030709304392">"Requête de recherche"</string>
     <string name="abc_searchview_description_clear" msgid="3691816814315814921">"Effacer la requête"</string>
     <string name="abc_searchview_description_submit" msgid="8928215447528550784">"Envoyer la requête"</string>
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ACTIVÉ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DÉSACTIVÉ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Rechercher"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Méta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Maj+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fonction+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"espace"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"entrée"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"supprimer"</string>
 </resources>
diff --git a/v7/appcompat/res/values-fr/strings.xml b/v7/appcompat/res/values-fr/strings.xml
index 5df86b5..1e412ec 100644
--- a/v7/appcompat/res/values-fr/strings.xml
+++ b/v7/appcompat/res/values-fr/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ACTIVÉ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DÉSACTIVÉ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Rechercher"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Méta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Maj+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fonction+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"espace"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"entrée"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"supprimer"</string>
 </resources>
diff --git a/v7/appcompat/res/values-gl/strings.xml b/v7/appcompat/res/values-gl/strings.xml
index c500af5..2af80a1 100644
--- a/v7/appcompat/res/values-gl/strings.xml
+++ b/v7/appcompat/res/values-gl/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ACTIVAR"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DESACTIVAR"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Buscar"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menú +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Maiús +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sim +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Función +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"espazo"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Intro"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"eliminar"</string>
 </resources>
diff --git a/v7/appcompat/res/values-gu/strings.xml b/v7/appcompat/res/values-gu/strings.xml
index 390d59b..7a243ed 100644
--- a/v7/appcompat/res/values-gu/strings.xml
+++ b/v7/appcompat/res/values-gu/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>
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ચાલુ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"બંધ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"શોધો"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"મેનૂ+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Spacebar"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"ડિલીટ કરો"</string>
 </resources>
diff --git a/v7/appcompat/res/values-hi/strings.xml b/v7/appcompat/res/values-hi/strings.xml
index 8a29110..a31ab90 100644
--- a/v7/appcompat/res/values-hi/strings.xml
+++ b/v7/appcompat/res/values-hi/strings.xml
@@ -21,7 +21,7 @@
     <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>
+    <string name="abc_searchview_description_search" msgid="8264924765203268293">"सर्च करें"</string>
     <string name="abc_search_hint" msgid="7723749260725869598">"खोजा जा रहा है…"</string>
     <string name="abc_searchview_description_query" msgid="2550479030709304392">"सर्च क्वेरी"</string>
     <string name="abc_searchview_description_clear" msgid="3691816814315814921">"क्‍वेरी साफ़ करें"</string>
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"चालू"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"बंद"</string>
     <string name="search_menu_title" msgid="146198913615257606">"सर्च"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-hr/strings.xml b/v7/appcompat/res/values-hr/strings.xml
index 9253fb9..27a1c2e 100644
--- a/v7/appcompat/res/values-hr/strings.xml
+++ b/v7/appcompat/res/values-hr/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"UKLJUČENO"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ISKLJUČENO"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Pretraživanje"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"razmaknica"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-hu/strings.xml b/v7/appcompat/res/values-hu/strings.xml
index 714ef47..d3e413f 100644
--- a/v7/appcompat/res/values-hu/strings.xml
+++ b/v7/appcompat/res/values-hu/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"BE"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"KI"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Keresés"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Szóköz"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-hy/strings.xml b/v7/appcompat/res/values-hy/strings.xml
index 59c9ee5..1c41ef6 100644
--- a/v7/appcompat/res/values-hy/strings.xml
+++ b/v7/appcompat/res/values-hy/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ՄԻԱՑՎԱԾ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ԱՆՋԱՏՎԱԾ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Որոնել"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"բացատ"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-in/strings.xml b/v7/appcompat/res/values-in/strings.xml
index 1ae3f90..2e9fbb7 100644
--- a/v7/appcompat/res/values-in/strings.xml
+++ b/v7/appcompat/res/values-in/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"AKTIF"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"NONAKTIF"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Telusuri"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"spasi"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-is/strings.xml b/v7/appcompat/res/values-is/strings.xml
index 3ae59da..3f61d84 100644
--- a/v7/appcompat/res/values-is/strings.xml
+++ b/v7/appcompat/res/values-is/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"KVEIKT"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"SLÖKKT"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Leita"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Valmynd+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Aðgerðarlykill+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"bilslá"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-it/strings.xml b/v7/appcompat/res/values-it/strings.xml
index 04b64ce..fbd2c58 100644
--- a/v7/appcompat/res/values-it/strings.xml
+++ b/v7/appcompat/res/values-it/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ON"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"OFF"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Ricerca"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"MENU +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"META +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"CTRL +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"ALT +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"MAIUSC +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"SYM +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"FUNZIONE +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"barra spaziatrice"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"INVIO"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"CANC"</string>
 </resources>
diff --git a/v7/appcompat/res/values-iw/strings.xml b/v7/appcompat/res/values-iw/strings.xml
index d0f2211..0a7d0bb 100644
--- a/v7/appcompat/res/values-iw/strings.xml
+++ b/v7/appcompat/res/values-iw/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"פועל"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"כבוי"</string>
     <string name="search_menu_title" msgid="146198913615257606">"חיפוש"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"תפריט+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+‎"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"מקש רווח"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ja/strings.xml b/v7/appcompat/res/values-ja/strings.xml
index db163f3..c4d0e20b 100644
--- a/v7/appcompat/res/values-ja/strings.xml
+++ b/v7/appcompat/res/values-ja/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ON"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"OFF"</string>
     <string name="search_menu_title" msgid="146198913615257606">"検索"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ka/strings.xml b/v7/appcompat/res/values-ka/strings.xml
index 6d9c08b..3b077a3 100644
--- a/v7/appcompat/res/values-ka/strings.xml
+++ b/v7/appcompat/res/values-ka/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ჩართულია"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"გამორთულია"</string>
     <string name="search_menu_title" msgid="146198913615257606">"ძიება"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"შეყვანა"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"წაშლა"</string>
 </resources>
diff --git a/v7/appcompat/res/values-kk/strings.xml b/v7/appcompat/res/values-kk/strings.xml
index 9d206bc..c32045b 100644
--- a/v7/appcompat/res/values-kk/strings.xml
+++ b/v7/appcompat/res/values-kk/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ҚОСУЛЫ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ӨШІРУЛІ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Іздеу"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Mәзір+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"бос орын"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-km/strings.xml b/v7/appcompat/res/values-km/strings.xml
index f42da7a..ffe289a 100644
--- a/v7/appcompat/res/values-km/strings.xml
+++ b/v7/appcompat/res/values-km/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"បើក"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"បិទ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"ស្វែងរក"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-kn/strings.xml b/v7/appcompat/res/values-kn/strings.xml
index ce28303..4218bd6 100644
--- a/v7/appcompat/res/values-kn/strings.xml
+++ b/v7/appcompat/res/values-kn/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ಆನ್"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ಆಫ್"</string>
     <string name="search_menu_title" msgid="146198913615257606">"ಹುಡುಕಿ"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ko/strings.xml b/v7/appcompat/res/values-ko/strings.xml
index db0903f..6c84a2a 100644
--- a/v7/appcompat/res/values-ko/strings.xml
+++ b/v7/appcompat/res/values-ko/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"사용"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"사용 안함"</string>
     <string name="search_menu_title" msgid="146198913615257606">"검색"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"스페이스바"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"입력"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"삭제"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ky/strings.xml b/v7/appcompat/res/values-ky/strings.xml
index 1aba4f0..66202f7 100644
--- a/v7/appcompat/res/values-ky/strings.xml
+++ b/v7/appcompat/res/values-ky/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"КҮЙҮК"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ӨЧҮК"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Издөө"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"боштук"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-lo/strings.xml b/v7/appcompat/res/values-lo/strings.xml
index c53a987..1b92df0 100644
--- a/v7/appcompat/res/values-lo/strings.xml
+++ b/v7/appcompat/res/values-lo/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ເປີດ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ປິດ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"ຊອກຫາ"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-lt/strings.xml b/v7/appcompat/res/values-lt/strings.xml
index ab9f25c..5793069 100644
--- a/v7/appcompat/res/values-lt/strings.xml
+++ b/v7/appcompat/res/values-lt/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ĮJUNGTI"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"IŠJUNGTA"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Paieška"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"„Menu“ +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"„Meta“ +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"„Ctrl“ +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"„Alt“ +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"„Shift“ +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"„Sym“ +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"„Function“ +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"tarpo klavišas"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"„Enter“"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"„Delete“"</string>
 </resources>
diff --git a/v7/appcompat/res/values-lv/strings.xml b/v7/appcompat/res/values-lv/strings.xml
index 67904a1..67e18d3 100644
--- a/v7/appcompat/res/values-lv/strings.xml
+++ b/v7/appcompat/res/values-lv/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"IESLĒGTS"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"IZSLĒGTS"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Meklēt"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Poga Izvēlne +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta taustiņš +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Vadīšanas taustiņš +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alternēšanas taustiņš +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Pārslēgšanas taustiņš +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Simbolu taustiņš +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funkcijas taustiņš +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"atstarpes taustiņš"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"ievadīšanas taustiņš"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"dzēšanas taustiņš"</string>
 </resources>
diff --git a/v7/appcompat/res/values-mk/strings.xml b/v7/appcompat/res/values-mk/strings.xml
index 408edb1..b12a235 100644
--- a/v7/appcompat/res/values-mk/strings.xml
+++ b/v7/appcompat/res/values-mk/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ВКЛУЧЕНО"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ИСКЛУЧЕНО"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Пребарај"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Мени+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"копче Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"копче Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"копче Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"копче Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"копче Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"копче Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"вселена"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"копче enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"избриши"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ml/strings.xml b/v7/appcompat/res/values-ml/strings.xml
index e880ebb..9033f8a 100644
--- a/v7/appcompat/res/values-ml/strings.xml
+++ b/v7/appcompat/res/values-ml/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ഓൺ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ഓഫ്"</string>
     <string name="search_menu_title" msgid="146198913615257606">"തിരയുക"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"മെനു+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"മെറ്റ+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"ഫംഗ്ഷന്‍+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"സ്‌പെയ്‌സ്"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"ഇല്ലാതാക്കുക"</string>
 </resources>
diff --git a/v7/appcompat/res/values-mn/strings.xml b/v7/appcompat/res/values-mn/strings.xml
index 856e9f6..56036ea 100644
--- a/v7/appcompat/res/values-mn/strings.xml
+++ b/v7/appcompat/res/values-mn/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ИДЭВХТЭЙ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ИДЭВХГҮЙ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Хайлт"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Цэс+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Мета+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Функц+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"зай"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"оруулах"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"устгах"</string>
 </resources>
diff --git a/v7/appcompat/res/values-mr/strings.xml b/v7/appcompat/res/values-mr/strings.xml
index ed3463c..26ada80 100644
--- a/v7/appcompat/res/values-mr/strings.xml
+++ b/v7/appcompat/res/values-mr/strings.xml
@@ -30,18 +30,8 @@
     <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" 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>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"मेनू+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"spacebar"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"एंटर करा"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"हटवा"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ms/strings.xml b/v7/appcompat/res/values-ms/strings.xml
index 8af4c13..18f84ce 100644
--- a/v7/appcompat/res/values-ms/strings.xml
+++ b/v7/appcompat/res/values-ms/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"HIDUP"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"MATI"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Cari"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fungsi+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"ruang"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"padam"</string>
 </resources>
diff --git a/v7/appcompat/res/values-my/strings.xml b/v7/appcompat/res/values-my/strings.xml
index cfd6625..cbc8791 100644
--- a/v7/appcompat/res/values-my/strings.xml
+++ b/v7/appcompat/res/values-my/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ဖွင့်"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ပိတ်"</string>
     <string name="search_menu_title" msgid="146198913615257606">"ရှာဖွေပါ"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-nb/strings.xml b/v7/appcompat/res/values-nb/strings.xml
index f9fd80e..6005234 100644
--- a/v7/appcompat/res/values-nb/strings.xml
+++ b/v7/appcompat/res/values-nb/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"PÅ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"AV"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Søk"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Meny+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funksjon+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"mellomrom"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ne/strings.xml b/v7/appcompat/res/values-ne/strings.xml
index 0a0de14..96b1042 100644
--- a/v7/appcompat/res/values-ne/strings.xml
+++ b/v7/appcompat/res/values-ne/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"सक्रिय गर्नुहोस्"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"निष्क्रिय पार्नुहोस्"</string>
     <string name="search_menu_title" msgid="146198913615257606">"खोज्नुहोस्"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-nl/strings.xml b/v7/appcompat/res/values-nl/strings.xml
index ffcb3d9..e0d2044 100644
--- a/v7/appcompat/res/values-nl/strings.xml
+++ b/v7/appcompat/res/values-nl/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"AAN"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"UIT"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Zoeken"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Functie +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"spatie"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"verwijderen"</string>
 </resources>
diff --git a/v7/appcompat/res/values-or/strings.xml b/v7/appcompat/res/values-or/strings.xml
index 86e4fb7..4dc6eb4 100644
--- a/v7/appcompat/res/values-or/strings.xml
+++ b/v7/appcompat/res/values-or/strings.xml
@@ -29,19 +29,13 @@
     <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>
+    <!-- no translation found for abc_shareactionprovider_share_with_application (3300176832234831527) -->
+    <skip />
     <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>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"ମେନୁ"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"ସ୍ପେସ୍‍"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"ଏଣ୍ଟର୍"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"ଡିଲିଟ୍‍"</string>
+    <!-- no translation found for abc_capital_on (3405795526292276155) -->
+    <skip />
+    <!-- no translation found for abc_capital_off (121134116657445385) -->
+    <skip />
+    <!-- no translation found for search_menu_title (146198913615257606) -->
+    <skip />
 </resources>
diff --git a/v7/appcompat/res/values-pa/strings.xml b/v7/appcompat/res/values-pa/strings.xml
index fc1fdba..7f28ac8 100644
--- a/v7/appcompat/res/values-pa/strings.xml
+++ b/v7/appcompat/res/values-pa/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ਤੇ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ਬੰਦ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"ਖੋਜੋ"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-pl/strings.xml b/v7/appcompat/res/values-pl/strings.xml
index af26367..d706241 100644
--- a/v7/appcompat/res/values-pl/strings.xml
+++ b/v7/appcompat/res/values-pl/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"WŁ."</string>
     <string name="abc_capital_off" msgid="121134116657445385">"WYŁ."</string>
     <string name="search_menu_title" msgid="146198913615257606">"Szukaj"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funkcyjny+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"spacja"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-pt-rBR/strings.xml b/v7/appcompat/res/values-pt-rBR/strings.xml
index 17d8593..90461ec 100644
--- a/v7/appcompat/res/values-pt-rBR/strings.xml
+++ b/v7/appcompat/res/values-pt-rBR/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ATIVAR"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DESATIVAR"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Pesquisar"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"espaço"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-pt-rPT/strings.xml b/v7/appcompat/res/values-pt-rPT/strings.xml
index f8c0fa7..40f6499c 100644
--- a/v7/appcompat/res/values-pt-rPT/strings.xml
+++ b/v7/appcompat/res/values-pt-rPT/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ATIVADO"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DESATIVADO"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Pesquisar"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Função +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"espaço"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"eliminar"</string>
 </resources>
diff --git a/v7/appcompat/res/values-pt/strings.xml b/v7/appcompat/res/values-pt/strings.xml
index 17d8593..90461ec 100644
--- a/v7/appcompat/res/values-pt/strings.xml
+++ b/v7/appcompat/res/values-pt/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ATIVAR"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DESATIVAR"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Pesquisar"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"espaço"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ro/strings.xml b/v7/appcompat/res/values-ro/strings.xml
index 86495fd..6d04be9 100644
--- a/v7/appcompat/res/values-ro/strings.xml
+++ b/v7/appcompat/res/values-ro/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ACTIVAT"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"DEZACTIVAȚI"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Căutați"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Meniu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funcție+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"spațiu"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ru/strings.xml b/v7/appcompat/res/values-ru/strings.xml
index c505bf5..2b28958 100644
--- a/v7/appcompat/res/values-ru/strings.xml
+++ b/v7/appcompat/res/values-ru/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ВКЛ."</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ОТКЛ."</string>
     <string name="search_menu_title" msgid="146198913615257606">"Поиск"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Меню +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fn +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Пробел"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Ввод"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-si/strings.xml b/v7/appcompat/res/values-si/strings.xml
index c154686d..7631288 100644
--- a/v7/appcompat/res/values-si/strings.xml
+++ b/v7/appcompat/res/values-si/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ක්‍රියාත්මකයි"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ක්‍රියාවිරහිතයි"</string>
     <string name="search_menu_title" msgid="146198913615257606">"සොයන්න"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"මකන්න"</string>
 </resources>
diff --git a/v7/appcompat/res/values-sk/strings.xml b/v7/appcompat/res/values-sk/strings.xml
index 67184b0..03faf14 100644
--- a/v7/appcompat/res/values-sk/strings.xml
+++ b/v7/appcompat/res/values-sk/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ZAPNUTÉ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"VYPNUTÉ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Vyhľadávanie"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"medzerník"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"odstrániť"</string>
 </resources>
diff --git a/v7/appcompat/res/values-sl/strings.xml b/v7/appcompat/res/values-sl/strings.xml
index e38e5ea..22b8bd4 100644
--- a/v7/appcompat/res/values-sl/strings.xml
+++ b/v7/appcompat/res/values-sl/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"VKLOPLJENO"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"IZKLOPLJENO"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Iskanje"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Meni +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fn +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"preslednica"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-sq/strings.xml b/v7/appcompat/res/values-sq/strings.xml
index 8b958a2..1a1f02e 100644
--- a/v7/appcompat/res/values-sq/strings.xml
+++ b/v7/appcompat/res/values-sq/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"AKTIV"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"JOAKTIV"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Kërko"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menyja+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funksioni+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"hapësirë"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-sr/strings.xml b/v7/appcompat/res/values-sr/strings.xml
index 4c702bc..5678341 100644
--- a/v7/appcompat/res/values-sr/strings.xml
+++ b/v7/appcompat/res/values-sr/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"УКЉУЧИ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ИСКЉУЧИ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Претражи"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"тастер за размак"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-sv/strings.xml b/v7/appcompat/res/values-sv/strings.xml
index 72b7f88..62d470f 100644
--- a/v7/appcompat/res/values-sv/strings.xml
+++ b/v7/appcompat/res/values-sv/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"PÅ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"AV"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Sök"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Meny + "</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta + "</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl + "</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt + "</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Skift + "</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Symbol + "</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Funktion + "</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"blanksteg"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"retur"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-sw/strings.xml b/v7/appcompat/res/values-sw/strings.xml
index 1c623b7..c575ae0 100644
--- a/v7/appcompat/res/values-sw/strings.xml
+++ b/v7/appcompat/res/values-sw/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"IMEWASHWA"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"IMEZIMWA"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Tafuta"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menyu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"nafasi"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"futa"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ta/strings.xml b/v7/appcompat/res/values-ta/strings.xml
index 7aa031a..971a3db 100644
--- a/v7/appcompat/res/values-ta/strings.xml
+++ b/v7/appcompat/res/values-ta/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ஆன்"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ஆஃப்"</string>
     <string name="search_menu_title" msgid="146198913615257606">"தேடு"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"மெனு மற்றும்"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"மெட்டா மற்றும்"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"கண்ட்ரோல் மற்றும்"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"ஆல்ட் மற்றும்"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"ஷிஃப்ட் மற்றும்"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"சிம்பல் மற்றும்"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"ஃபங்ஷன் மற்றும்"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"ஸ்பேஸ்"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"எண்டர்"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"டெலிட்"</string>
 </resources>
diff --git a/v7/appcompat/res/values-te/strings.xml b/v7/appcompat/res/values-te/strings.xml
index 818f0e39a..f7d7577 100644
--- a/v7/appcompat/res/values-te/strings.xml
+++ b/v7/appcompat/res/values-te/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"ఆన్ చేయి"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ఆఫ్ చేయి"</string>
     <string name="search_menu_title" msgid="146198913615257606">"వెతుకు"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"స్పేస్"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-th/strings.xml b/v7/appcompat/res/values-th/strings.xml
index 5ecec86..f8ea1cd 100644
--- a/v7/appcompat/res/values-th/strings.xml
+++ b/v7/appcompat/res/values-th/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"เปิด"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ปิด"</string>
     <string name="search_menu_title" msgid="146198913615257606">"ค้นหา"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"เมนู+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-tl/strings.xml b/v7/appcompat/res/values-tl/strings.xml
index 3ef5df6..1ad2689 100644
--- a/v7/appcompat/res/values-tl/strings.xml
+++ b/v7/appcompat/res/values-tl/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"I-ON"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"I-OFF"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Maghanap"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-tr/strings.xml b/v7/appcompat/res/values-tr/strings.xml
index 153e2c2..fae41d3 100644
--- a/v7/appcompat/res/values-tr/strings.xml
+++ b/v7/appcompat/res/values-tr/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"AÇ"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"KAPAT"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Ara"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menü+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Üst Karakter+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"İşlev+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"boşluk"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"sil"</string>
 </resources>
diff --git a/v7/appcompat/res/values-uk/strings.xml b/v7/appcompat/res/values-uk/strings.xml
index 7aed219..afc74ff 100644
--- a/v7/appcompat/res/values-uk/strings.xml
+++ b/v7/appcompat/res/values-uk/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"УВІМК."</string>
     <string name="abc_capital_off" msgid="121134116657445385">"ВИМК."</string>
     <string name="search_menu_title" msgid="146198913615257606">"Пошук"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"пробіл"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-ur/strings.xml b/v7/appcompat/res/values-ur/strings.xml
index 997d594..60ec34a 100644
--- a/v7/appcompat/res/values-ur/strings.xml
+++ b/v7/appcompat/res/values-ur/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"آن"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"آف"</string>
     <string name="search_menu_title" msgid="146198913615257606">"تلاش"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+‎"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+‎"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+‎"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+‎"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+‎"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+‎"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+‎"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-uz/strings.xml b/v7/appcompat/res/values-uz/strings.xml
index 359b96c..0417cba 100644
--- a/v7/appcompat/res/values-uz/strings.xml
+++ b/v7/appcompat/res/values-uz/strings.xml
@@ -32,16 +32,6 @@
     <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>
-    <string name="abc_capital_off" msgid="121134116657445385">"YOQILMAGAN"</string>
+    <string name="abc_capital_off" msgid="121134116657445385">"O‘CHIQ"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Qidirish"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menyu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fn+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"Probel"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-vi/strings.xml b/v7/appcompat/res/values-vi/strings.xml
index e07efed..4560b4b 100644
--- a/v7/appcompat/res/values-vi/strings.xml
+++ b/v7/appcompat/res/values-vi/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"BẬT"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"TẮT"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Tìm kiếm"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"phím cách"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"delete"</string>
 </resources>
diff --git a/v7/appcompat/res/values-zh-rCN/strings.xml b/v7/appcompat/res/values-zh-rCN/strings.xml
index 6dc1ea2..7b23457 100644
--- a/v7/appcompat/res/values-zh-rCN/strings.xml
+++ b/v7/appcompat/res/values-zh-rCN/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"开启"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"关闭"</string>
     <string name="search_menu_title" msgid="146198913615257606">"搜索"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fn+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"空格键"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter 键"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete 键"</string>
 </resources>
diff --git a/v7/appcompat/res/values-zh-rHK/strings.xml b/v7/appcompat/res/values-zh-rHK/strings.xml
index ce753fd..fc32117 100644
--- a/v7/appcompat/res/values-zh-rHK/strings.xml
+++ b/v7/appcompat/res/values-zh-rHK/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"開啟"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"關閉"</string>
     <string name="search_menu_title" msgid="146198913615257606">"搜尋"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fn +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"空白鍵"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter 鍵"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"刪除"</string>
 </resources>
diff --git a/v7/appcompat/res/values-zh-rTW/strings.xml b/v7/appcompat/res/values-zh-rTW/strings.xml
index 0f29b8e..35be873 100644
--- a/v7/appcompat/res/values-zh-rTW/strings.xml
+++ b/v7/appcompat/res/values-zh-rTW/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"開啟"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"關閉"</string>
     <string name="search_menu_title" msgid="146198913615257606">"搜尋"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Menu +"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta +"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl +"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt +"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift +"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym +"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Fn +"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"空格鍵"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"Enter 鍵"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"Delete 鍵"</string>
 </resources>
diff --git a/v7/appcompat/res/values-zu/strings.xml b/v7/appcompat/res/values-zu/strings.xml
index e3032f1..e84ba7a 100644
--- a/v7/appcompat/res/values-zu/strings.xml
+++ b/v7/appcompat/res/values-zu/strings.xml
@@ -34,14 +34,4 @@
     <string name="abc_capital_on" msgid="3405795526292276155">"VULIWE"</string>
     <string name="abc_capital_off" msgid="121134116657445385">"VALIWE"</string>
     <string name="search_menu_title" msgid="146198913615257606">"Sesha"</string>
-    <string name="abc_prepend_shortcut_label" msgid="1351762916121158029">"Imenyu+"</string>
-    <string name="abc_menu_meta_shortcut_label" msgid="7643535737296831317">"Meta+"</string>
-    <string name="abc_menu_ctrl_shortcut_label" msgid="1324831542140195728">"Ctrl+"</string>
-    <string name="abc_menu_alt_shortcut_label" msgid="1302280443949172191">"Alt+"</string>
-    <string name="abc_menu_shift_shortcut_label" msgid="8126296154200614004">"Shift+"</string>
-    <string name="abc_menu_sym_shortcut_label" msgid="9002602288060866689">"Sym+"</string>
-    <string name="abc_menu_function_shortcut_label" msgid="4792426091847145555">"Function+"</string>
-    <string name="abc_menu_space_shortcut_label" msgid="2378550843553983978">"space"</string>
-    <string name="abc_menu_enter_shortcut_label" msgid="8341180395196749340">"enter"</string>
-    <string name="abc_menu_delete_shortcut_label" msgid="8362206064229013510">"susa"</string>
 </resources>
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java b/v7/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java
index c32beab..7991c4e 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java
@@ -38,7 +38,6 @@
 import androidx.annotation.RestrictTo;
 import androidx.appcompat.view.ActionMode;
 import androidx.appcompat.widget.Toolbar;
-import androidx.appcompat.widget.VectorEnabledTintResources;
 import androidx.core.view.WindowCompat;
 import androidx.fragment.app.FragmentActivity;
 
@@ -129,6 +128,8 @@
     @NightMode
     private static int sDefaultNightMode = MODE_NIGHT_FOLLOW_SYSTEM;
 
+    private static boolean sCompatVectorFromResourcesEnabled = false;
+
     /** @hide */
     @RestrictTo(LIBRARY_GROUP)
     @IntDef({MODE_NIGHT_NO, MODE_NIGHT_YES, MODE_NIGHT_AUTO, MODE_NIGHT_FOLLOW_SYSTEM,
@@ -509,7 +510,7 @@
      * <p>Please note: this only takes effect in Activities created after this call.</p>
      */
     public static void setCompatVectorFromResourcesEnabled(boolean enabled) {
-        VectorEnabledTintResources.setCompatVectorFromResourcesEnabled(enabled);
+        sCompatVectorFromResourcesEnabled = enabled;
     }
 
     /**
@@ -519,6 +520,6 @@
      * @see #setCompatVectorFromResourcesEnabled(boolean)
      */
     public static boolean isCompatVectorFromResourcesEnabled() {
-        return VectorEnabledTintResources.isCompatVectorFromResourcesEnabled();
+        return sCompatVectorFromResourcesEnabled;
     }
 }
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/VectorEnabledTintResources.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/VectorEnabledTintResources.java
index af61860f..15fcf88 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/VectorEnabledTintResources.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/VectorEnabledTintResources.java
@@ -25,6 +25,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
+import androidx.appcompat.app.AppCompatDelegate;
 
 import java.lang.ref.WeakReference;
 
@@ -36,10 +37,9 @@
  */
 @RestrictTo(LIBRARY_GROUP)
 public class VectorEnabledTintResources extends Resources {
-    private static boolean sCompatVectorFromResourcesEnabled = false;
 
     public static boolean shouldBeUsed() {
-        return isCompatVectorFromResourcesEnabled()
+        return AppCompatDelegate.isCompatVectorFromResourcesEnabled()
                 && Build.VERSION.SDK_INT <= MAX_SDK_WHERE_REQUIRED;
     }
 
@@ -74,22 +74,4 @@
     final Drawable superGetDrawable(int id) {
         return super.getDrawable(id);
     }
-
-    /**
-     * Sets whether vector drawables on older platforms (< API 21) can be used within
-     * {@link android.graphics.drawable.DrawableContainer} resources.
-     */
-    public static void setCompatVectorFromResourcesEnabled(boolean enabled) {
-        sCompatVectorFromResourcesEnabled = enabled;
-    }
-
-    /**
-     * Returns whether vector drawables on older platforms (< API 21) can be accessed from within
-     * resources.
-     *
-     * @see #setCompatVectorFromResourcesEnabled(boolean)
-     */
-    public static boolean isCompatVectorFromResourcesEnabled() {
-        return sCompatVectorFromResourcesEnabled;
-    }
 }
\ No newline at end of file
diff --git a/wear/res/values-as/strings.xml b/wear/res/values-as/strings.xml
deleted file mode 100644
index 2a51efa..0000000
--- a/wear/res/values-as/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="ws_navigation_drawer_content_description" msgid="7216697245762194759">"নেভিগেশ্বন ড্ৰৱাৰ"</string>
-    <string name="ws_action_drawer_content_description" msgid="1837365417701148489">"কাৰ্য ড্ৰৱাৰ"</string>
-</resources>
diff --git a/wear/res/values-or/strings.xml b/wear/res/values-or/strings.xml
deleted file mode 100644
index 53e75b3..0000000
--- a/wear/res/values-or/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="ws_navigation_drawer_content_description" msgid="7216697245762194759">"ନେଭିଗେଶନ୍ ପ୍ୟାନେଲ୍"</string>
-    <string name="ws_action_drawer_content_description" msgid="1837365417701148489">"କାର୍ଯ୍ୟକାରୀ ପ୍ୟାନେଲ୍"</string>
-</resources>
diff --git a/webkit-codegen/src/test/java/androidx/webkit/internal/codegen/BoundaryInterfaceTest.java b/webkit-codegen/src/test/java/androidx/webkit/internal/codegen/BoundaryInterfaceTest.java
index ba5a9de..00736a7 100644
--- a/webkit-codegen/src/test/java/androidx/webkit/internal/codegen/BoundaryInterfaceTest.java
+++ b/webkit-codegen/src/test/java/androidx/webkit/internal/codegen/BoundaryInterfaceTest.java
@@ -18,9 +18,6 @@
 
 import static org.junit.Assert.assertEquals;
 
-import androidx.webkit.internal.codegen.representations.ClassRepr;
-import androidx.webkit.internal.codegen.representations.MethodRepr;
-
 import com.android.tools.lint.LintCoreProjectEnvironment;
 
 import com.intellij.psi.PsiClass;
@@ -30,13 +27,15 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 import java.util.Arrays;
 
+import androidx.webkit.internal.codegen.representations.ClassRepr;
+import androidx.webkit.internal.codegen.representations.MethodRepr;
+
 @RunWith(JUnit4.class)
 public class BoundaryInterfaceTest {
     private LintCoreProjectEnvironment mProjectEnv;
@@ -59,12 +58,10 @@
         testBoundaryInterfaceGeneration("SingleClassAndMethod");
     }
 
-    @Ignore
     @Test public void testWebkitReturnTypeGeneratesInvocationHandler() {
         testBoundaryInterfaceGeneration("WebKitTypeAsMethodParameter");
     }
 
-    @Ignore
     @Test public void testWebkitMethodParameterTypeGeneratesInvocationHandler() {
         testBoundaryInterfaceGeneration("WebKitTypeAsMethodReturn");
     }
diff --git a/webkit/api/current.txt b/webkit/api/current.txt
index e4e9b01..08c6a55 100644
--- a/webkit/api/current.txt
+++ b/webkit/api/current.txt
@@ -1,11 +1,5 @@
 package androidx.webkit {
 
-  public abstract class SafeBrowsingResponseCompat {
-    method public abstract void backToSafety(boolean);
-    method public abstract void proceed(boolean);
-    method public abstract void showInterstitial(boolean);
-  }
-
   public abstract class ServiceWorkerClientCompat {
     ctor public ServiceWorkerClientCompat();
     method public abstract android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebResourceRequest);
@@ -28,34 +22,6 @@
     method public abstract void setCacheMode(int);
   }
 
-  public class WebMessageCompat {
-    ctor public WebMessageCompat(java.lang.String);
-    ctor public WebMessageCompat(java.lang.String, androidx.webkit.WebMessagePortCompat[]);
-    method public java.lang.String getData();
-    method public androidx.webkit.WebMessagePortCompat[] getPorts();
-  }
-
-  public abstract class WebMessagePortCompat {
-    method public abstract void close();
-    method public abstract void postMessage(androidx.webkit.WebMessageCompat);
-    method public abstract void setWebMessageCallback(androidx.webkit.WebMessagePortCompat.WebMessageCallbackCompat);
-    method public abstract void setWebMessageCallback(android.os.Handler, androidx.webkit.WebMessagePortCompat.WebMessageCallbackCompat);
-  }
-
-  public static abstract class WebMessagePortCompat.WebMessageCallbackCompat {
-    ctor public WebMessagePortCompat.WebMessageCallbackCompat();
-    method public void onMessage(androidx.webkit.WebMessagePortCompat, androidx.webkit.WebMessageCompat);
-  }
-
-  public abstract class WebResourceErrorCompat {
-    method public abstract java.lang.CharSequence getDescription();
-    method public abstract int getErrorCode();
-  }
-
-  public class WebResourceRequestCompat {
-    method public static boolean isRedirect(android.webkit.WebResourceRequest);
-  }
-
   public class WebSettingsCompat {
     method public static int getDisabledActionModeMenuItems(android.webkit.WebSettings);
     method public static boolean getOffscreenPreRaster(android.webkit.WebSettings);
@@ -67,18 +33,12 @@
 
   public class WebViewClientCompat extends android.webkit.WebViewClient {
     ctor public WebViewClientCompat();
-    method public final void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceError);
-    method public void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, androidx.webkit.WebResourceErrorCompat);
-    method public final void onSafeBrowsingHit(android.webkit.WebView, android.webkit.WebResourceRequest, int, android.webkit.SafeBrowsingResponse);
-    method public void onSafeBrowsingHit(android.webkit.WebView, android.webkit.WebResourceRequest, int, androidx.webkit.SafeBrowsingResponseCompat);
   }
 
   public class WebViewCompat {
-    method public static androidx.webkit.WebMessagePortCompat[] createWebMessageChannel(android.webkit.WebView);
     method public static android.content.pm.PackageInfo getCurrentWebViewPackage(android.content.Context);
     method public static android.net.Uri getSafeBrowsingPrivacyPolicyUrl();
     method public static void postVisualStateCallback(android.webkit.WebView, long, androidx.webkit.WebViewCompat.VisualStateCallback);
-    method public static void postWebMessage(android.webkit.WebView, androidx.webkit.WebMessageCompat, android.net.Uri);
     method public static void setSafeBrowsingWhitelist(java.util.List<java.lang.String>, android.webkit.ValueCallback<java.lang.Boolean>);
     method public static void startSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>);
   }
@@ -89,29 +49,7 @@
 
   public class WebViewFeature {
     method public static boolean isFeatureSupported(java.lang.String);
-    field public static final java.lang.String DISABLED_ACTION_MODE_MENU_ITEMS = "DISABLED_ACTION_MODE_MENU_ITEMS";
-    field public static final java.lang.String OFF_SCREEN_PRERASTER = "OFF_SCREEN_PRERASTER";
-    field public static final java.lang.String RECEIVE_HTTP_ERROR = "RECEIVE_HTTP_ERROR";
-    field public static final java.lang.String RECEIVE_WEB_RESOURCE_ERROR = "RECEIVE_WEB_RESOURCE_ERROR";
-    field public static final java.lang.String SAFE_BROWSING_ENABLE = "SAFE_BROWSING_ENABLE";
-    field public static final java.lang.String SAFE_BROWSING_HIT = "SAFE_BROWSING_HIT";
-    field public static final java.lang.String SAFE_BROWSING_PRIVACY_POLICY_URL = "SAFE_BROWSING_PRIVACY_POLICY_URL";
-    field public static final java.lang.String SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY = "SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY";
-    field public static final java.lang.String SAFE_BROWSING_RESPONSE_PROCEED = "SAFE_BROWSING_RESPONSE_PROCEED";
-    field public static final java.lang.String SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL = "SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL";
-    field public static final java.lang.String SAFE_BROWSING_WHITELIST = "SAFE_BROWSING_WHITELIST";
-    field public static final java.lang.String SERVICE_WORKER_BASIC_USAGE = "SERVICE_WORKER_BASIC_USAGE";
-    field public static final java.lang.String SERVICE_WORKER_BLOCK_NETWORK_LOADS = "SERVICE_WORKER_BLOCK_NETWORK_LOADS";
-    field public static final java.lang.String SERVICE_WORKER_CACHE_MODE = "SERVICE_WORKER_CACHE_MODE";
-    field public static final java.lang.String SERVICE_WORKER_CONTENT_ACCESS = "SERVICE_WORKER_CONTENT_ACCESS";
-    field public static final java.lang.String SERVICE_WORKER_FILE_ACCESS = "SERVICE_WORKER_FILE_ACCESS";
-    field public static final java.lang.String SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST = "SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST";
-    field public static final java.lang.String SHOULD_OVERRIDE_WITH_REDIRECTS = "SHOULD_OVERRIDE_WITH_REDIRECTS";
-    field public static final java.lang.String START_SAFE_BROWSING = "START_SAFE_BROWSING";
     field public static final java.lang.String VISUAL_STATE_CALLBACK = "VISUAL_STATE_CALLBACK";
-    field public static final java.lang.String WEB_RESOURCE_ERROR_GET_CODE = "WEB_RESOURCE_ERROR_GET_CODE";
-    field public static final java.lang.String WEB_RESOURCE_ERROR_GET_DESCRIPTION = "WEB_RESOURCE_ERROR_GET_DESCRIPTION";
-    field public static final java.lang.String WEB_RESOURCE_REQUEST_IS_REDIRECT = "WEB_RESOURCE_REQUEST_IS_REDIRECT";
   }
 
 }
diff --git a/webkit/build.gradle b/webkit/build.gradle
index baed9cb..d610dad 100644
--- a/webkit/build.gradle
+++ b/webkit/build.gradle
@@ -40,7 +40,7 @@
     }
 
     buildTypes.all {
-        consumerProguardFiles new File(webviewBoundaryInterfacesDir, "proguard.flags") , 'proguard-rules.pro'
+        consumerProguardFiles new File(webviewBoundaryInterfacesDir, "proguard.flags")
     }
 }
 
diff --git a/webkit/proguard-rules.pro b/webkit/proguard-rules.pro
deleted file mode 100644
index 86756ab..0000000
--- a/webkit/proguard-rules.pro
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Prevent WebViewClientCompat from being renamed, since chromium depends on this name.
--keep public class androidx.webkit.WebViewClientCompat { public *; }
diff --git a/webkit/src/androidTest/java/androidx/webkit/BoundaryInterfaceTest.java b/webkit/src/androidTest/java/androidx/webkit/BoundaryInterfaceTest.java
deleted file mode 100644
index 3f9857c..0000000
--- a/webkit/src/androidTest/java/androidx/webkit/BoundaryInterfaceTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import androidx.webkit.internal.WebViewFeatureInternal;
-import androidx.webkit.internal.WebViewGlueCommunicator;
-import androidx.webkit.internal.WebkitToCompatConverter;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests related to the interface between the support library and the Chromium support library glue.
- */
-@RunWith(AndroidJUnit4.class)
-public class BoundaryInterfaceTest {
-
-    /**
-     * Test ensuring that we can create a {@link androidx.webkit.internal.WebkitToCompatConverter}.
-     * This test catches cases where we try to pass post-L android.webkit classes across the
-     * boundary - doing so will fail when we (at run-time) create a {@link java.lang.reflect.Proxy}
-     * for {@link org.chromium.support_lib_boundary.WebkitToCompatConverterBoundaryInterface} since
-     * that proxy will need to look up all the classes referenced from
-     * {@link org.chromium.support_lib_boundary.WebkitToCompatConverterBoundaryInterface}.
-     */
-    @SmallTest
-    @Test
-    public void testCreateWebkitToCompatConverter() {
-        // Use the SERVICE_WORKER_BASIC_USAGE feature as a proxy for knowing whether the current
-        // WebView APK is compatible with the support library.
-        if (WebViewFeatureInternal.SERVICE_WORKER_BASIC_USAGE.isSupportedByWebView()) {
-            WebkitToCompatConverter converter = WebViewGlueCommunicator.getCompatConverter();
-        }
-    }
-
-}
diff --git a/webkit/src/androidTest/java/androidx/webkit/IncompatibilityTest.java b/webkit/src/androidTest/java/androidx/webkit/IncompatibilityTest.java
deleted file mode 100644
index 09424c6..0000000
--- a/webkit/src/androidTest/java/androidx/webkit/IncompatibilityTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.SdkSuppress;
-import android.support.test.runner.AndroidJUnit4;
-
-import androidx.webkit.internal.WebViewFeatureInternal;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests ensuring that Android versions/setups that are incompatible with the WebView Support
- * Library are handled gracefully.
- *
- * Only L+ Android versions are compatible with the WebView Support Library, so any tests in this
- * class that guarantee certain behaviour for incompatible Android versions will only be run on
- * pre-L devices.
- */
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class IncompatibilityTest {
-    @Test
-    @SdkSuppress(maxSdkVersion = 20)
-    public void testPreLDeviceHasNoWebViewFeatures() {
-        assertEquals(0, WebViewFeatureInternal.getWebViewApkFeaturesForTesting().length);
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 20)
-    public void testPreLDeviceDoesNotSupportVisualStateCallback() {
-        assertFalse(WebViewFeature.isFeatureSupported(WebViewFeature.VISUAL_STATE_CALLBACK));
-    }
-}
diff --git a/webkit/src/androidTest/java/androidx/webkit/PostMessageTest.java b/webkit/src/androidTest/java/androidx/webkit/PostMessageTest.java
deleted file mode 100644
index 4e74419..0000000
--- a/webkit/src/androidTest/java/androidx/webkit/PostMessageTest.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit;
-
-import static junit.framework.Assert.assertEquals;
-
-import android.net.Uri;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.SdkSuppress;
-import android.support.test.runner.AndroidJUnit4;
-import android.webkit.WebView;
-
-import androidx.webkit.WebMessagePortCompat.WebMessageCallbackCompat;
-
-import junit.framework.Assert;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.CountDownLatch;
-
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class PostMessageTest {
-    public static final long TIMEOUT = 6000L;
-
-    private WebView mWebView;
-    private WebViewOnUiThread mOnUiThread;
-
-    private static final String WEBVIEW_MESSAGE = "from_webview";
-    private static final String BASE_URI = "http://www.example.com";
-
-    @Before
-    public void setUp() throws Exception {
-        mOnUiThread = new WebViewOnUiThread();
-        mOnUiThread.getSettings().setJavaScriptEnabled(true);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        if (mOnUiThread != null) {
-            mOnUiThread.cleanUp();
-        }
-    }
-
-    private static final String TITLE_FROM_POST_MESSAGE =
-            "<!DOCTYPE html><html><body>"
-                    + "    <script>"
-                    + "        var received = '';"
-                    + "        onmessage = function (e) {"
-                    + "            received += e.data;"
-                    + "            document.title = received; };"
-                    + "    </script>"
-                    + "</body></html>";
-
-    // Acks each received message from the message channel with a seq number.
-    private static final String CHANNEL_MESSAGE =
-            "<!DOCTYPE html><html><body>"
-                    + "    <script>"
-                    + "        var counter = 0;"
-                    + "        onmessage = function (e) {"
-                    + "            var myPort = e.ports[0];"
-                    + "            myPort.onmessage = function (f) {"
-                    + "                myPort.postMessage(f.data + counter++);"
-                    + "            }"
-                    + "        }"
-                    + "   </script>"
-                    + "</body></html>";
-
-    private void loadPage(String data) {
-        mOnUiThread.loadDataWithBaseURLAndWaitForCompletion(BASE_URI, data,
-                "text/html", "UTF-8", null);
-    }
-
-    private void waitForTitle(final String title) {
-        new PollingCheck(TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return mOnUiThread.getTitle().equals(title);
-            }
-        }.run();
-    }
-
-    // Post a string message to main frame and make sure it is received.
-    @Test
-    @SdkSuppress(minSdkVersion = 23) // TODO(gsennton) activate this test for pre-M devices when we
-    // can pre-install a WebView APK containing support for the WebView Support Library, see
-    // b/73454652.
-    public void testSimpleMessageToMainFrame() throws Throwable {
-        verifyPostMessageToOrigin(Uri.parse(BASE_URI));
-    }
-
-    // Post a string message to main frame passing a wildcard as target origin
-    @Test
-    @SdkSuppress(minSdkVersion = 23) // TODO (gsennton) remove this restriction when we can
-    // pre-install a WebView APK containing support for the WebView Support Library, see b/73454652.
-    public void testWildcardOriginMatchesAnything() throws Throwable {
-        verifyPostMessageToOrigin(Uri.parse("*"));
-    }
-
-    // Post a string message to main frame passing an empty string as target origin
-    @Test
-    @SdkSuppress(minSdkVersion = 23) // TODO(gsennton) activate this test for pre-M devices when we
-    // can pre-install a WebView APK containing support for the WebView Support Library, see
-    // b/73454652.
-    public void testEmptyStringOriginMatchesAnything() throws Throwable {
-        verifyPostMessageToOrigin(Uri.parse(""));
-    }
-
-    private void verifyPostMessageToOrigin(Uri origin) throws Throwable {
-        loadPage(TITLE_FROM_POST_MESSAGE);
-        WebMessageCompat message = new WebMessageCompat(WEBVIEW_MESSAGE);
-        mOnUiThread.postWebMessageCompat(message, origin);
-        waitForTitle(WEBVIEW_MESSAGE);
-    }
-
-    // Post multiple messages to main frame and make sure they are received in
-    // correct order.
-    @Test
-    @SdkSuppress(minSdkVersion = 23) // TODO(gsennton) activate this test for pre-M devices when we
-    // can pre-install a WebView APK containing support for the WebView Support Library, see
-    // b/73454652.
-    public void testMultipleMessagesToMainFrame() throws Throwable {
-        loadPage(TITLE_FROM_POST_MESSAGE);
-        for (int i = 0; i < 10; i++) {
-            mOnUiThread.postWebMessageCompat(new WebMessageCompat(Integer.toString(i)),
-                    Uri.parse(BASE_URI));
-        }
-        waitForTitle("0123456789");
-    }
-
-    // Create a message channel and make sure it can be used for data transfer to/from js.
-    @Test
-    @SdkSuppress(minSdkVersion = 23) // TODO(gsennton) activate this test for pre-M devices when we
-    // can pre-install a WebView APK containing support for the WebView Support Library, see
-    // b/73454652.
-    public void testMessageChannel() throws Throwable {
-        loadPage(CHANNEL_MESSAGE);
-        final WebMessagePortCompat[] channel = mOnUiThread.createWebMessageChannelCompat();
-        WebMessageCompat message =
-                new WebMessageCompat(WEBVIEW_MESSAGE, new WebMessagePortCompat[]{channel[1]});
-        mOnUiThread.postWebMessageCompat(message, Uri.parse(BASE_URI));
-        final int messageCount = 3;
-        final CountDownLatch latch = new CountDownLatch(messageCount);
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                for (int i = 0; i < messageCount; i++) {
-                    channel[0].postMessage(new WebMessageCompat(WEBVIEW_MESSAGE + i));
-                }
-                channel[0].setWebMessageCallback(new WebMessageCallbackCompat() {
-                    @Override
-                    public void onMessage(WebMessagePortCompat port, WebMessageCompat message) {
-                        int i = messageCount - (int) latch.getCount();
-                        assertEquals(WEBVIEW_MESSAGE + i + i, message.getData());
-                        latch.countDown();
-                    }
-                });
-            }
-        });
-        // Wait for all the responses to arrive.
-        boolean ignore = latch.await(TIMEOUT, java.util.concurrent.TimeUnit.MILLISECONDS);
-    }
-
-    // Test that a message port that is closed cannot used to send a message
-    @Test
-    @SdkSuppress(minSdkVersion = 23) // TODO(gsennton) activate this test for pre-M devices when we
-    // can pre-install a WebView APK containing support for the WebView Support Library, see
-    // b/73454652.
-    public void testClose() throws Throwable {
-        loadPage(CHANNEL_MESSAGE);
-        final WebMessagePortCompat[] channel = mOnUiThread.createWebMessageChannelCompat();
-        WebMessageCompat message =
-                new WebMessageCompat(WEBVIEW_MESSAGE, new WebMessagePortCompat[]{channel[1]});
-        mOnUiThread.postWebMessageCompat(message, Uri.parse(BASE_URI));
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    channel[0].close();
-                    channel[0].postMessage(new WebMessageCompat(WEBVIEW_MESSAGE));
-                } catch (IllegalStateException ex) {
-                    // expect to receive an exception
-                    return;
-                }
-                Assert.fail("A closed port cannot be used to transfer messages");
-            }
-        });
-    }
-
-    // Sends a new message channel from JS to Java.
-    private static final String CHANNEL_FROM_JS =
-            "<!DOCTYPE html><html><body>"
-                    + "    <script>"
-                    + "        var counter = 0;"
-                    + "        var mc = new MessageChannel();"
-                    + "        var received = '';"
-                    + "        mc.port1.onmessage = function (e) {"
-                    + "               received = e.data;"
-                    + "               document.title = e.data;"
-                    + "        };"
-                    + "        onmessage = function (e) {"
-                    + "            var myPort = e.ports[0];"
-                    + "            myPort.postMessage('', [mc.port2]);"
-                    + "        };"
-                    + "   </script>"
-                    + "</body></html>";
-
-    // Test a message port created in JS can be received and used for message transfer.
-    @Test
-    @SdkSuppress(minSdkVersion = 23) // TODO(gsennton) activate this test for pre-M devices when we
-    // can pre-install a WebView APK containing support for the WebView Support Library, see
-    // b/73454652.
-    public void testReceiveMessagePort() throws Throwable {
-        final String hello = "HELLO";
-        loadPage(CHANNEL_FROM_JS);
-        final WebMessagePortCompat[] channel = mOnUiThread.createWebMessageChannelCompat();
-        WebMessageCompat message =
-                new WebMessageCompat(WEBVIEW_MESSAGE, new WebMessagePortCompat[]{channel[1]});
-        mOnUiThread.postWebMessageCompat(message, Uri.parse(BASE_URI));
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                channel[0].setWebMessageCallback(new WebMessageCallbackCompat() {
-                    @Override
-                    public void onMessage(WebMessagePortCompat port, WebMessageCompat message) {
-                        message.getPorts()[0].postMessage(new WebMessageCompat(hello));
-                    }
-                });
-            }
-        });
-        waitForTitle(hello);
-    }
-}
diff --git a/webkit/src/androidTest/java/androidx/webkit/ServiceWorkerClientCompatTest.java b/webkit/src/androidTest/java/androidx/webkit/ServiceWorkerClientCompatTest.java
index d3a55ae..aecbc34 100644
--- a/webkit/src/androidTest/java/androidx/webkit/ServiceWorkerClientCompatTest.java
+++ b/webkit/src/androidTest/java/androidx/webkit/ServiceWorkerClientCompatTest.java
@@ -17,8 +17,8 @@
 package androidx.webkit;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assume.assumeTrue;
 
+import android.os.Build;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.webkit.JavascriptInterface;
@@ -141,9 +141,9 @@
     // Test correct invocation of shouldInterceptRequest for Service Workers.
     @Test
     public void testServiceWorkerClientInterceptCallback() throws Exception {
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_BASIC_USAGE));
-        assumeTrue(WebViewFeature.isFeatureSupported(
-                WebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST));
+        // TODO(gsennton) activate this test for pre-N devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return;
 
         final InterceptServiceWorkerClient mInterceptServiceWorkerClient =
                 new InterceptServiceWorkerClient();
diff --git a/webkit/src/androidTest/java/androidx/webkit/WebSettingsCompatTest.java b/webkit/src/androidTest/java/androidx/webkit/WebSettingsCompatTest.java
index 5dd9b54..1e5c152 100644
--- a/webkit/src/androidTest/java/androidx/webkit/WebSettingsCompatTest.java
+++ b/webkit/src/androidTest/java/androidx/webkit/WebSettingsCompatTest.java
@@ -19,8 +19,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
 
+import android.os.Build;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.webkit.WebSettings;
@@ -41,7 +41,9 @@
 
     @Test
     public void testOffscreenPreRaster() {
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.OFF_SCREEN_PRERASTER));
+        // TODO(gsennton) activate this test for pre-M devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
 
         assertFalse(WebSettingsCompat.getOffscreenPreRaster(mWebViewOnUiThread.getSettings()));
 
@@ -51,7 +53,9 @@
 
     @Test
     public void testEnableSafeBrowsing() throws Throwable {
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_ENABLE));
+        // TODO(gsennton) activate this test for old devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return;
 
         WebSettingsCompat.setSafeBrowsingEnabled(mWebViewOnUiThread.getSettings(), false);
         assertFalse(WebSettingsCompat.getSafeBrowsingEnabled(mWebViewOnUiThread.getSettings()));
@@ -59,8 +63,9 @@
 
     @Test
     public void testDisabledActionModeMenuItems() throws Throwable {
-        assumeTrue(
-                WebViewFeature.isFeatureSupported(WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS));
+        // TODO(gsennton) activate this test for old devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return;
 
         assertEquals(WebSettings.MENU_ITEM_NONE,
                 WebSettingsCompat.getDisabledActionModeMenuItems(mWebViewOnUiThread.getSettings()));
diff --git a/webkit/src/androidTest/java/androidx/webkit/WebViewClientCompatTest.java b/webkit/src/androidTest/java/androidx/webkit/WebViewClientCompatTest.java
deleted file mode 100644
index 1344f4b..0000000
--- a/webkit/src/androidTest/java/androidx/webkit/WebViewClientCompatTest.java
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit;
-
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.webkit.ValueCallback;
-import android.webkit.WebResourceRequest;
-import android.webkit.WebResourceResponse;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class WebViewClientCompatTest {
-    private WebViewOnUiThread mWebViewOnUiThread;
-
-    private static final long TEST_TIMEOUT = 20000L;
-    private static final String TEST_URL = "http://www.example.com/";
-    private static final String TEST_SAFE_BROWSING_URL =
-            "chrome://safe-browsing/match?type=malware";
-
-    @Before
-    public void setUp() {
-        mWebViewOnUiThread = new WebViewOnUiThread();
-    }
-
-    @Test
-    public void testShouldOverrideUrlLoadingDefault() {
-        // This never calls into chromium, so we don't need to do any feature checks.
-
-        final MockWebViewClient webViewClient = new MockWebViewClient();
-
-        // Create any valid WebResourceRequest, the return values don't matter much.
-        final WebResourceRequest resourceRequest = new WebResourceRequest() {
-            @Override
-            public Uri getUrl() {
-                return Uri.parse(TEST_URL);
-            }
-
-            @Override
-            public boolean isForMainFrame() {
-                return false;
-            }
-
-            @Override
-            public boolean isRedirect() {
-                return false;
-            }
-
-            @Override
-            public boolean hasGesture() {
-                return false;
-            }
-
-            @Override
-            public String getMethod() {
-                return "GET";
-            }
-
-            @Override
-            public Map<String, String> getRequestHeaders() {
-                return new HashMap<String, String>();
-            }
-        };
-
-        Assert.assertFalse(webViewClient.shouldOverrideUrlLoading(
-                mWebViewOnUiThread.getWebViewOnCurrentThread(), resourceRequest));
-    }
-
-    @Test
-    public void testShouldOverrideUrlLoading() throws InterruptedException {
-        Assume.assumeTrue(
-                WebViewFeature.isFeatureSupported(WebViewFeature.SHOULD_OVERRIDE_WITH_REDIRECTS));
-        Assume.assumeTrue(
-                WebViewFeature.isFeatureSupported(WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT));
-
-        String data = "<html><body>"
-                + "<a href=\"" + TEST_URL + "\" id=\"link\">new page</a>"
-                + "</body></html>";
-        mWebViewOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null);
-        final CountDownLatch pageFinishedLatch = new CountDownLatch(1);
-        final MockWebViewClient webViewClient = new MockWebViewClient() {
-            @Override
-            public void onPageFinished(WebView view, String url) {
-                super.onPageFinished(view, url);
-                pageFinishedLatch.countDown();
-            }
-        };
-        mWebViewOnUiThread.setWebViewClient(webViewClient);
-        mWebViewOnUiThread.getSettings().setJavaScriptEnabled(true);
-        clickOnLinkUsingJs("link", mWebViewOnUiThread);
-        pageFinishedLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
-        Assert.assertEquals(TEST_URL,
-                webViewClient.getLastShouldOverrideResourceRequest().getUrl().toString());
-
-        WebResourceRequest request = webViewClient.getLastShouldOverrideResourceRequest();
-        Assert.assertNotNull(request);
-        Assert.assertTrue(request.isForMainFrame());
-        Assert.assertFalse(WebResourceRequestCompat.isRedirect(request));
-        Assert.assertFalse(request.hasGesture());
-    }
-
-    private void clickOnLinkUsingJs(final String linkId, WebViewOnUiThread webViewOnUiThread)
-            throws InterruptedException {
-        final CountDownLatch callbackLatch = new CountDownLatch(1);
-        ValueCallback<String> callback = new ValueCallback<String>() {
-            @Override
-            public void onReceiveValue(String value) {
-                callbackLatch.countDown();
-            }
-        };
-        webViewOnUiThread.evaluateJavascript(
-                "document.getElementById('" + linkId + "').click();"
-                        + "console.log('element with id [" + linkId + "] clicked');", callback);
-        Assert.assertTrue(callbackLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
-    }
-
-    @Test
-    public void testOnReceivedError() throws Exception {
-        Assume.assumeTrue(
-                WebViewFeature.isFeatureSupported(WebViewFeature.RECEIVE_WEB_RESOURCE_ERROR));
-        Assume.assumeTrue(
-                WebViewFeature.isFeatureSupported(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE));
-
-        final MockWebViewClient webViewClient = new MockWebViewClient();
-        mWebViewOnUiThread.setWebViewClient(webViewClient);
-
-        String wrongUri = "invalidscheme://some/resource";
-        Assert.assertNull(webViewClient.getOnReceivedResourceError());
-        mWebViewOnUiThread.loadUrlAndWaitForCompletion(wrongUri);
-        Assert.assertNotNull(webViewClient.getOnReceivedResourceError());
-        Assert.assertEquals(WebViewClient.ERROR_UNSUPPORTED_SCHEME,
-                webViewClient.getOnReceivedResourceError().getErrorCode());
-    }
-
-    @Test
-    public void testOnReceivedErrorForSubresource() throws Exception {
-        Assume.assumeTrue(
-                WebViewFeature.isFeatureSupported(WebViewFeature.RECEIVE_WEB_RESOURCE_ERROR));
-
-        final MockWebViewClient webViewClient = new MockWebViewClient();
-        mWebViewOnUiThread.setWebViewClient(webViewClient);
-
-        Assert.assertNull(webViewClient.getOnReceivedResourceError());
-        String data = "<html>"
-                + "  <body>"
-                + "    <img src=\"invalidscheme://some/resource\" />"
-                + "  </body>"
-                + "</html>";
-
-        mWebViewOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null);
-        Assert.assertNotNull(webViewClient.getOnReceivedResourceError());
-        Assert.assertEquals(WebViewClient.ERROR_UNSUPPORTED_SCHEME,
-                webViewClient.getOnReceivedResourceError().getErrorCode());
-    }
-
-    @Test
-    public void testOnSafeBrowsingHitBackToSafety() throws Throwable {
-        Assume.assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_HIT));
-        Assume.assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_ENABLE));
-        Assume.assumeTrue(WebViewFeature.isFeatureSupported(
-                WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY));
-        Assume.assumeTrue(
-                WebViewFeature.isFeatureSupported(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE));
-
-        final SafeBrowsingBackToSafetyClient backToSafetyWebViewClient =
-                new SafeBrowsingBackToSafetyClient();
-        mWebViewOnUiThread.setWebViewClient(backToSafetyWebViewClient);
-        WebSettingsCompat.setSafeBrowsingEnabled(mWebViewOnUiThread.getSettings(), true);
-
-        // Load any page
-        String data = "<html><body>some safe page</body></html>";
-        mWebViewOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null);
-        final String originalUrl = mWebViewOnUiThread.getUrl();
-
-        enableSafeBrowsingAndLoadUnsafePage(backToSafetyWebViewClient);
-
-        // Back to safety should produce a network error
-        Assert.assertNotNull(backToSafetyWebViewClient.getOnReceivedResourceError());
-        Assert.assertEquals(WebViewClient.ERROR_UNSAFE_RESOURCE,
-                backToSafetyWebViewClient.getOnReceivedResourceError().getErrorCode());
-
-        // Check that we actually navigated backward
-        Assert.assertEquals(originalUrl, mWebViewOnUiThread.getUrl());
-    }
-
-    @Test
-    public void testOnSafeBrowsingHitProceed() throws Throwable {
-        Assume.assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_HIT));
-        Assume.assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_ENABLE));
-        Assume.assumeTrue(WebViewFeature.isFeatureSupported(
-                WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED));
-
-        final SafeBrowsingProceedClient proceedWebViewClient = new SafeBrowsingProceedClient();
-        mWebViewOnUiThread.setWebViewClient(proceedWebViewClient);
-        WebSettingsCompat.setSafeBrowsingEnabled(mWebViewOnUiThread.getSettings(), true);
-
-        // Load any page
-        String data = "<html><body>some safe page</body></html>";
-        mWebViewOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null);
-
-        enableSafeBrowsingAndLoadUnsafePage(proceedWebViewClient);
-
-        // Check that we actually proceeded
-        Assert.assertEquals(TEST_SAFE_BROWSING_URL, mWebViewOnUiThread.getUrl());
-    }
-
-    private void enableSafeBrowsingAndLoadUnsafePage(SafeBrowsingClient client) throws Throwable {
-        // Note: Safe Browsing depends on user opt-in as well, so we can't assume it's actually
-        // enabled. #getSafeBrowsingEnabled will tell us the true state of whether Safe Browsing is
-        // enabled.
-        boolean deviceSupportsSafeBrowsing =
-                WebSettingsCompat.getSafeBrowsingEnabled(mWebViewOnUiThread.getSettings());
-        Assume.assumeTrue(deviceSupportsSafeBrowsing);
-
-        Assert.assertNull(client.getOnReceivedResourceError());
-        mWebViewOnUiThread.loadUrlAndWaitForCompletion(TEST_SAFE_BROWSING_URL);
-
-        Assert.assertEquals(TEST_SAFE_BROWSING_URL,
-                client.getOnSafeBrowsingHitRequest().getUrl().toString());
-        Assert.assertTrue(client.getOnSafeBrowsingHitRequest().isForMainFrame());
-    }
-
-    @Test
-    public void testOnPageCommitVisibleCalled() throws Exception {
-        Assume.assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.VISUAL_STATE_CALLBACK));
-
-        final CountDownLatch callbackLatch = new CountDownLatch(1);
-
-        mWebViewOnUiThread.setWebViewClient(new WebViewClientCompat() {
-            @Override
-            public void onPageCommitVisible(WebView view, String url) {
-                Assert.assertEquals(url, "about:blank");
-                callbackLatch.countDown();
-            }
-        });
-
-        mWebViewOnUiThread.loadUrl("about:blank");
-        Assert.assertTrue(callbackLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
-    }
-
-    private class MockWebViewClient extends WebViewOnUiThread.WaitForLoadedClient {
-        private boolean mOnPageStartedCalled;
-        private boolean mOnPageFinishedCalled;
-        private boolean mOnLoadResourceCalled;
-        private WebResourceErrorCompat mOnReceivedResourceError;
-        private WebResourceResponse mOnReceivedHttpError;
-        private WebResourceRequest mLastShouldOverrideResourceRequest;
-
-        MockWebViewClient() {
-            super(mWebViewOnUiThread);
-        }
-
-        public WebResourceErrorCompat getOnReceivedResourceError() {
-            return mOnReceivedResourceError;
-        }
-
-        public WebResourceResponse getOnReceivedHttpError() {
-            return mOnReceivedHttpError;
-        }
-
-        public WebResourceRequest getLastShouldOverrideResourceRequest() {
-            return mLastShouldOverrideResourceRequest;
-        }
-
-        @Override
-        public void onPageStarted(WebView view, String url, Bitmap favicon) {
-            super.onPageStarted(view, url, favicon);
-            mOnPageStartedCalled = true;
-        }
-
-        @Override
-        public void onPageFinished(WebView view, String url) {
-            super.onPageFinished(view, url);
-            Assert.assertTrue(mOnPageStartedCalled);
-            Assert.assertTrue(mOnLoadResourceCalled);
-            mOnPageFinishedCalled = true;
-        }
-
-        @Override
-        public void onLoadResource(WebView view, String url) {
-            super.onLoadResource(view, url);
-            Assert.assertTrue(mOnPageStartedCalled);
-            mOnLoadResourceCalled = true;
-        }
-
-        @Override
-        @SuppressWarnings("deprecation")
-        public void onReceivedError(WebView view, int errorCode,
-                String description, String failingUrl) {
-            // This can be called if a test runs for a WebView which does not support the {@link
-            // WebViewFeature#RECEIVE_WEB_RESOURCE_ERROR} feature.
-        }
-
-        @Override
-        public void onReceivedError(WebView view, WebResourceRequest request,
-                WebResourceErrorCompat error) {
-            mOnReceivedResourceError = error;
-        }
-
-        @Override
-        public void onReceivedHttpError(WebView view, WebResourceRequest request,
-                WebResourceResponse errorResponse) {
-            super.onReceivedHttpError(view, request, errorResponse);
-            mOnReceivedHttpError = errorResponse;
-        }
-
-        @Override
-        @SuppressWarnings("deprecation")
-        public boolean shouldOverrideUrlLoading(WebView view, String url) {
-            // This can be called if a test runs for a WebView which does not support the {@link
-            // WebViewFeature#SHOULD_OVERRIDE_WITH_REDIRECTS} feature.
-            return false;
-        }
-
-        @Override
-        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
-            mLastShouldOverrideResourceRequest = request;
-            return false;
-        }
-    }
-
-    private class SafeBrowsingClient extends MockWebViewClient {
-        private WebResourceRequest mOnSafeBrowsingHitRequest;
-        private int mOnSafeBrowsingHitThreatType;
-
-        public WebResourceRequest getOnSafeBrowsingHitRequest() {
-            return mOnSafeBrowsingHitRequest;
-        }
-
-        public void setOnSafeBrowsingHitRequest(WebResourceRequest request) {
-            mOnSafeBrowsingHitRequest = request;
-        }
-
-        public int getOnSafeBrowsingHitThreatType() {
-            return mOnSafeBrowsingHitThreatType;
-        }
-
-        public void setOnSafeBrowsingHitThreatType(int type) {
-            mOnSafeBrowsingHitThreatType = type;
-        }
-    }
-
-    private class SafeBrowsingBackToSafetyClient extends SafeBrowsingClient {
-        @Override
-        public void onSafeBrowsingHit(WebView view, WebResourceRequest request,
-                int threatType, SafeBrowsingResponseCompat response) {
-            // Immediately go back to safety to return the network error code
-            setOnSafeBrowsingHitRequest(request);
-            setOnSafeBrowsingHitThreatType(threatType);
-            response.backToSafety(/* report */ true);
-        }
-    }
-
-    private class SafeBrowsingProceedClient extends SafeBrowsingClient {
-        @Override
-        public void onSafeBrowsingHit(WebView view, WebResourceRequest request,
-                int threatType, SafeBrowsingResponseCompat response) {
-            // Proceed through Safe Browsing warnings
-            setOnSafeBrowsingHitRequest(request);
-            setOnSafeBrowsingHitThreatType(threatType);
-            response.proceed(/* report */ true);
-        }
-    }
-}
diff --git a/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java b/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java
index 03aa946..bd77fdb 100644
--- a/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java
+++ b/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java
@@ -22,7 +22,6 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
 
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -30,10 +29,15 @@
 import android.os.Looper;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
+import android.support.test.filters.Suppress;
 import android.support.test.runner.AndroidJUnit4;
+import android.webkit.SafeBrowsingResponse;
 import android.webkit.ValueCallback;
 import android.webkit.WebResourceRequest;
 import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import androidx.core.os.BuildCompat;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -61,7 +65,9 @@
 
     @Test
     public void testVisualStateCallbackCalled() throws Exception {
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.VISUAL_STATE_CALLBACK));
+        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (!BuildCompat.isAtLeastP()) return;
 
         final CountDownLatch callbackLatch = new CountDownLatch(1);
         final long kRequest = 100;
@@ -79,10 +85,9 @@
         assertTrue(callbackLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
     }
 
+    @Suppress // TODO(gsennton) remove @Suppress when b/76202025 has been resolved
     @Test
     public void testCheckThread() {
-        // Skip this test if VisualStateCallback is not supported.
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.VISUAL_STATE_CALLBACK));
         try {
             WebViewCompat.postVisualStateCallback(mWebViewOnUiThread.getWebViewOnCurrentThread(), 5,
                     new WebViewCompat.VisualStateCallback() {
@@ -115,7 +120,9 @@
 
     @Test
     public void testStartSafeBrowsingUseApplicationContext() throws Exception {
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING));
+        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
 
         final MockContext ctx =
                 new MockContext(InstrumentationRegistry.getTargetContext().getApplicationContext());
@@ -133,14 +140,18 @@
 
     @Test
     public void testStartSafeBrowsingWithNullCallbackDoesntCrash() throws Exception {
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING));
+        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
 
         WebViewCompat.startSafeBrowsing(InstrumentationRegistry.getTargetContext(), null);
     }
 
     @Test
     public void testStartSafeBrowsingInvokesCallback() throws Exception {
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING));
+        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
 
         final CountDownLatch resultLatch = new CountDownLatch(1);
         WebViewCompat.startSafeBrowsing(
@@ -158,7 +169,9 @@
 
     @Test
     public void testSetSafeBrowsingWhitelistWithMalformedList() throws Exception {
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_WHITELIST));
+        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
 
         List whitelist = new ArrayList<String>();
         // Protocols are not supported in the whitelist
@@ -176,9 +189,9 @@
 
     @Test
     public void testSetSafeBrowsingWhitelistWithValidList() throws Exception {
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_WHITELIST));
-        // This test relies on the onSafeBrowsingHit callback to verify correctness.
-        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_HIT));
+        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
 
         List whitelist = new ArrayList<String>();
         whitelist.add("safe-browsing");
@@ -193,7 +206,7 @@
         assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
 
         final CountDownLatch resultLatch2 = new CountDownLatch(1);
-        mWebViewOnUiThread.setWebViewClient(new WebViewClientCompat() {
+        mWebViewOnUiThread.setWebViewClient(new WebViewClient() {
             @Override
             public void onPageFinished(WebView view, String url) {
                 resultLatch2.countDown();
@@ -201,7 +214,7 @@
 
             @Override
             public void onSafeBrowsingHit(WebView view, WebResourceRequest request, int threatType,
-                    SafeBrowsingResponseCompat callback) {
+                    SafeBrowsingResponse callback) {
                 Assert.fail("Should not invoke onSafeBrowsingHit");
             }
         });
@@ -214,8 +227,9 @@
 
     @Test
     public void testGetSafeBrowsingPrivacyPolicyUrl() throws Exception {
-        assumeTrue(
-                WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL));
+        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
+        // containing support for the WebView Support Library, see b/73454652.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
 
         assertNotNull(WebViewCompat.getSafeBrowsingPrivacyPolicyUrl());
         try {
diff --git a/webkit/src/androidTest/java/androidx/webkit/WebViewOnUiThread.java b/webkit/src/androidTest/java/androidx/webkit/WebViewOnUiThread.java
index bd83752..6e817c3 100644
--- a/webkit/src/androidTest/java/androidx/webkit/WebViewOnUiThread.java
+++ b/webkit/src/androidTest/java/androidx/webkit/WebViewOnUiThread.java
@@ -20,7 +20,6 @@
 import static org.junit.Assert.fail;
 
 import android.graphics.Bitmap;
-import android.net.Uri;
 import android.os.Looper;
 import android.os.SystemClock;
 import android.support.test.InstrumentationRegistry;
@@ -28,9 +27,7 @@
 import android.webkit.WebChromeClient;
 import android.webkit.WebSettings;
 import android.webkit.WebView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
+import android.webkit.WebViewClient;
 
 import java.util.concurrent.Callable;
 
@@ -68,6 +65,52 @@
         });
     }
 
+    public void loadUrl(final String url) {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.loadUrl(url);
+            }
+        });
+    }
+
+    public void setWebViewClient(final WebViewClient webviewClient) {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.setWebViewClient(webviewClient);
+            }
+        });
+    }
+
+    public void postVisualStateCallbackCompat(final long requestId,
+            final WebViewCompat.VisualStateCallback callback) {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                WebViewCompat.postVisualStateCallback(mWebView, requestId, callback);
+            }
+        });
+    }
+
+    public WebSettings getSettings() {
+        return getValue(new ValueGetter<WebSettings>() {
+            @Override
+            public WebSettings capture() {
+                return mWebView.getSettings();
+            }
+        });
+    }
+
+    public void addJavascriptInterface(final Object object, final String name) {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.addJavascriptInterface(object, name);
+            }
+        });
+    }
+
     /**
      * Called after a test is complete and the WebView should be disengaged from
      * the tests.
@@ -85,6 +128,10 @@
         });
     }
 
+    WebView getWebViewOnCurrentThread() {
+        return mWebView;
+    }
+
     /**
      * Called from WaitForLoadedClient.
      */
@@ -109,45 +156,9 @@
         this.notifyAll();
     }
 
-    public void setWebViewClient(final WebViewClientCompat webviewClient) {
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setWebViewClient(webviewClient);
-            }
-        });
-    }
-
-    public WebMessagePortCompat[] createWebMessageChannelCompat() {
-        return getValue(new ValueGetter<WebMessagePortCompat[]>() {
-            @Override
-            public WebMessagePortCompat[] capture() {
-                return WebViewCompat.createWebMessageChannel(mWebView);
-            }
-        });
-    }
-
-    public void postWebMessageCompat(final WebMessageCompat message, final Uri targetOrigin) {
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                WebViewCompat.postWebMessage(mWebView, message, targetOrigin);
-            }
-        });
-    }
-
-    public void addJavascriptInterface(final Object object, final String name) {
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.addJavascriptInterface(object, name);
-            }
-        });
-    }
-
     /**
-     * Calls loadUrl on the WebView and then waits onPageFinished
-     * and onProgressChange to reach 100.
+     * Calls loadUrl on the WebView and then waits onPageFinished,
+     * onNewPicture and onProgressChange to reach 100.
      * Test fails if the load timeout elapses.
      * @param url The URL to load.
      */
@@ -160,45 +171,6 @@
         });
     }
 
-    public void loadUrl(final String url) {
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadUrl(url);
-            }
-        });
-    }
-
-    /**
-     * Calls {@link WebView#loadData} on the WebView and then waits onPageFinished
-     * and onProgressChange to reach 100.
-     * Test fails if the load timeout elapses.
-     * @param data The data to load.
-     * @param mimeType The mimeType to pass to loadData.
-     * @param encoding The encoding to pass to loadData.
-     */
-    public void loadDataAndWaitForCompletion(@NonNull final String data,
-            @Nullable final String mimeType, @Nullable final String encoding) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadData(data, mimeType, encoding);
-            }
-        });
-    }
-
-    public void loadDataWithBaseURLAndWaitForCompletion(final String baseUrl,
-            final String data, final String mimeType, final String encoding,
-            final String historyUrl) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding,
-                        historyUrl);
-            }
-        });
-    }
-
     /**
      * Use this only when JavaScript causes a page load to wait for the
      * page load to complete. Otherwise use loadUrlAndWaitForCompletion or
@@ -223,43 +195,6 @@
         }
     }
 
-    public String getTitle() {
-        return getValue(new ValueGetter<String>() {
-            @Override
-            public String capture() {
-                return mWebView.getTitle();
-            }
-        });
-    }
-
-    public WebSettings getSettings() {
-        return getValue(new ValueGetter<WebSettings>() {
-            @Override
-            public WebSettings capture() {
-                return mWebView.getSettings();
-            }
-        });
-    }
-
-    public String getUrl() {
-        return getValue(new ValueGetter<String>() {
-            @Override
-            public String capture() {
-                return mWebView.getUrl();
-            }
-        });
-    }
-
-    public void postVisualStateCallbackCompat(final long requestId,
-            final WebViewCompat.VisualStateCallback callback) {
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                WebViewCompat.postVisualStateCallback(mWebView, requestId, callback);
-            }
-        });
-    }
-
     void evaluateJavascript(final String script, final ValueCallback<String> result) {
         InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
             @Override
@@ -269,30 +204,6 @@
         });
     }
 
-    WebView getWebViewOnCurrentThread() {
-        return mWebView;
-    }
-
-    private <T> T getValue(ValueGetter<T> getter) {
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(getter);
-        return getter.getValue();
-    }
-
-    private abstract class ValueGetter<T> implements Runnable {
-        private T mValue;
-
-        @Override
-        public void run() {
-            mValue = capture();
-        }
-
-        protected abstract T capture();
-
-        public T getValue() {
-            return mValue;
-        }
-    }
-
     /**
      * Returns true if the current thread is the UI thread based on the
      * Looper.
@@ -393,6 +304,26 @@
         }
     }
 
+    private <T> T getValue(ValueGetter<T> getter) {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(getter);
+        return getter.getValue();
+    }
+
+    private abstract class ValueGetter<T> implements Runnable {
+        private T mValue;
+
+        @Override
+        public void run() {
+            mValue = capture();
+        }
+
+        protected abstract T capture();
+
+        public T getValue() {
+            return mValue;
+        }
+    }
+
     /**
      * A WebChromeClient used to capture the onProgressChanged for use
      * in waitFor functions. If a test must override the WebChromeClient,
@@ -420,7 +351,7 @@
      * needs the waitForCompletion capability then it should derive from
      * WaitForLoadedClient or call WebViewOnUiThread.onPageFinished.
      */
-    public static class WaitForLoadedClient extends WebViewClientCompat {
+    public static class WaitForLoadedClient extends WebViewClient {
         private WebViewOnUiThread mOnUiThread;
 
         WaitForLoadedClient(WebViewOnUiThread onUiThread) {
diff --git a/webkit/src/main/java/androidx/webkit/SafeBrowsingResponseCompat.java b/webkit/src/main/java/androidx/webkit/SafeBrowsingResponseCompat.java
deleted file mode 100644
index 76121f3..0000000
--- a/webkit/src/main/java/androidx/webkit/SafeBrowsingResponseCompat.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit;
-
-import android.webkit.SafeBrowsingResponse;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.annotation.RequiresFeature;
-import androidx.webkit.internal.WebViewFeatureInternal;
-
-import org.chromium.support_lib_boundary.SafeBrowsingResponseBoundaryInterface;
-import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
-
-import java.lang.reflect.InvocationHandler;
-
-/**
- * Compatibility version of {@link SafeBrowsingResponse}.
- */
-public abstract class SafeBrowsingResponseCompat {
-    /**
-     * Display the default interstitial.
-     *
-     * @param allowReporting {@code true} if the interstitial should show a reporting checkbox.
-     */
-    @RequiresFeature(name = WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
-    public abstract void showInterstitial(boolean allowReporting);
-
-    /**
-     * Act as if the user clicked "visit this unsafe site."
-     *
-     * @param report {@code true} to enable Safe Browsing reporting.
-     */
-    @RequiresFeature(name = WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
-    public abstract void proceed(boolean report);
-
-    /**
-     * Act as if the user clicked "back to safety."
-     *
-     * @param report {@code true} to enable Safe Browsing reporting.
-     */
-    @RequiresFeature(name = WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
-    public abstract void backToSafety(boolean report);
-
-    /**
-     * This class cannot be created by applications. The support library should instantiate this
-     * with {@link #fromInvocationHandler} or {@link #fromSafeBrowsingResponse}.
-     */
-    private SafeBrowsingResponseCompat() {
-    }
-
-    /**
-     * Conversion helper to create a SafeBrowsingResponseCompat which delegates calls to {@param
-     * handler}. The InvocationHandler must be created by {@link
-     * BoundaryInterfaceReflectionUtil#createInvocationHandlerFor} using {@link
-     * SafeBrowsingResponseBoundaryInterface}.
-     *
-     * @param handler The InvocationHandler that chromium passed in the callback.
-     */
-    @NonNull
-    /* package */ static SafeBrowsingResponseCompat fromInvocationHandler(
-            @NonNull InvocationHandler handler) {
-        final SafeBrowsingResponseBoundaryInterface responseDelegate =
-                BoundaryInterfaceReflectionUtil.castToSuppLibClass(
-                        SafeBrowsingResponseBoundaryInterface.class, handler);
-        return new SafeBrowsingResponseCompat() {
-            @Override
-            public void showInterstitial(boolean allowReporting) {
-                final WebViewFeatureInternal webViewFeature =
-                        WebViewFeatureInternal.getFeature(
-                                WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL);
-                if (!webViewFeature.isSupportedByWebView()) {
-                    throw WebViewFeatureInternal.getUnsupportedOperationException();
-                }
-                responseDelegate.showInterstitial(allowReporting);
-            }
-
-            @Override
-            public void proceed(boolean report) {
-                final WebViewFeatureInternal webViewFeature =
-                        WebViewFeatureInternal.getFeature(
-                                WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED);
-                if (!webViewFeature.isSupportedByWebView()) {
-                    throw WebViewFeatureInternal.getUnsupportedOperationException();
-                }
-                responseDelegate.proceed(report);
-            }
-
-            @Override
-            public void backToSafety(boolean report) {
-                final WebViewFeatureInternal webViewFeature =
-                        WebViewFeatureInternal.getFeature(
-                                WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY);
-                if (!webViewFeature.isSupportedByWebView()) {
-                    throw WebViewFeatureInternal.getUnsupportedOperationException();
-                }
-                responseDelegate.backToSafety(report);
-            }
-        };
-    }
-
-    /**
-     * Conversion helper to create a SafeBrowsingResponseCompat which delegates calls to {@param
-     * response}.
-     *
-     * @param response The SafeBrowsingResponse that chromium passed in the callback.
-     */
-    @NonNull
-    @RequiresApi(27)
-    /* package */ static SafeBrowsingResponseCompat fromSafeBrowsingResponse(
-            @NonNull final SafeBrowsingResponse response) {
-        // Frameworks support is implied by the API level.
-        return new SafeBrowsingResponseCompat() {
-            @Override
-            public void showInterstitial(boolean allowReporting) {
-                response.showInterstitial(allowReporting);
-            }
-
-            @Override
-            public void proceed(boolean report) {
-                response.proceed(report);
-            }
-
-            @Override
-            public void backToSafety(boolean report) {
-                response.backToSafety(report);
-            }
-        };
-    }
-}
diff --git a/webkit/src/main/java/androidx/webkit/ServiceWorkerClientCompat.java b/webkit/src/main/java/androidx/webkit/ServiceWorkerClientCompat.java
index 5c3c5ff..19aab8c 100644
--- a/webkit/src/main/java/androidx/webkit/ServiceWorkerClientCompat.java
+++ b/webkit/src/main/java/androidx/webkit/ServiceWorkerClientCompat.java
@@ -43,10 +43,6 @@
      * @see android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView,
      * WebResourceRequest)
      *
-     * This method is called only if
-     * {@link WebViewFeature#SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST} is supported. You can check
-     * whether that flag is supported using {@link WebViewFeature#isFeatureSupported(String)}.
-     *
      */
     public abstract WebResourceResponse shouldInterceptRequest(@NonNull WebResourceRequest request);
 }
diff --git a/webkit/src/main/java/androidx/webkit/ServiceWorkerControllerCompat.java b/webkit/src/main/java/androidx/webkit/ServiceWorkerControllerCompat.java
index 79b714a..3eb55d2 100644
--- a/webkit/src/main/java/androidx/webkit/ServiceWorkerControllerCompat.java
+++ b/webkit/src/main/java/androidx/webkit/ServiceWorkerControllerCompat.java
@@ -16,11 +16,18 @@
 
 package androidx.webkit;
 
+import android.os.Build;
+import android.webkit.ServiceWorkerController;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.RequiresFeature;
+import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
-import androidx.webkit.internal.ServiceWorkerControllerImpl;
+import androidx.webkit.internal.FrameworkServiceWorkerController;
+import androidx.webkit.internal.ServiceWorkerControllerAdapter;
+import androidx.webkit.internal.WebViewGlueCommunicator;
+
+// TODO(gsennton) guard APIs with isFeatureSupported(String)
 
 /**
  * Manages Service Workers used by WebView.
@@ -54,14 +61,28 @@
      * @return the default ServiceWorkerController instance
      */
     @NonNull
-    @RequiresFeature(name = WebViewFeature.SERVICE_WORKER_BASIC_USAGE,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static ServiceWorkerControllerCompat getInstance() {
         return LAZY_HOLDER.INSTANCE;
     }
 
     private static class LAZY_HOLDER {
-        static final ServiceWorkerControllerCompat INSTANCE = new ServiceWorkerControllerImpl();
+        static final ServiceWorkerControllerCompat INSTANCE =
+                Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+                        ? getFrameworkControllerCompat() : getSupportLibraryControllerCompat();
+    }
+
+    /**
+     * Return a version of {@link ServiceWorkerControllerCompat} that only uses framework APIs.
+     */
+    @RequiresApi(Build.VERSION_CODES.N)
+    private static ServiceWorkerControllerCompat getFrameworkControllerCompat() {
+        return new FrameworkServiceWorkerController(
+                ServiceWorkerController.getInstance());
+    }
+
+    private static ServiceWorkerControllerCompat getSupportLibraryControllerCompat() {
+        return new ServiceWorkerControllerAdapter(
+                WebViewGlueCommunicator.getFactory().getServiceWorkerController());
     }
 
     /**
diff --git a/webkit/src/main/java/androidx/webkit/ServiceWorkerWebSettingsCompat.java b/webkit/src/main/java/androidx/webkit/ServiceWorkerWebSettingsCompat.java
index 6763db4..61c46c3 100644
--- a/webkit/src/main/java/androidx/webkit/ServiceWorkerWebSettingsCompat.java
+++ b/webkit/src/main/java/androidx/webkit/ServiceWorkerWebSettingsCompat.java
@@ -19,7 +19,6 @@
 import android.webkit.WebSettings;
 
 import androidx.annotation.IntDef;
-import androidx.annotation.RequiresFeature;
 import androidx.annotation.RestrictTo;
 
 import java.lang.annotation.Retention;
@@ -59,8 +58,6 @@
      * {@link WebSettings#LOAD_DEFAULT}.
      *
      */
-    @RequiresFeature(name = WebViewFeature.SERVICE_WORKER_CACHE_MODE,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public abstract void setCacheMode(@CacheMode int mode);
 
     /**
@@ -71,8 +68,6 @@
      * @see #setCacheMode
      *
      */
-    @RequiresFeature(name = WebViewFeature.SERVICE_WORKER_CACHE_MODE,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public abstract @CacheMode int getCacheMode();
 
     /**
@@ -81,8 +76,6 @@
      * {@link WebSettings#setAllowContentAccess}.
      *
      */
-    @RequiresFeature(name = WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public abstract void setAllowContentAccess(boolean allow);
 
     /**
@@ -92,8 +85,6 @@
      * @see #setAllowContentAccess
      *
      */
-    @RequiresFeature(name = WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public abstract boolean getAllowContentAccess();
 
     /**
@@ -102,8 +93,6 @@
      * {@link WebSettings#setAllowFileAccess}.
      *
      */
-    @RequiresFeature(name = WebViewFeature.SERVICE_WORKER_FILE_ACCESS,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public abstract void setAllowFileAccess(boolean allow);
 
     /**
@@ -113,8 +102,6 @@
      * @see #setAllowFileAccess
      *
      */
-    @RequiresFeature(name = WebViewFeature.SERVICE_WORKER_FILE_ACCESS,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public abstract boolean getAllowFileAccess();
 
     /**
@@ -125,8 +112,6 @@
      * @param flag {@code true} means block network loads by the Service Workers
      *
      */
-    @RequiresFeature(name = WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public abstract void setBlockNetworkLoads(boolean flag);
 
     /**
@@ -138,7 +123,5 @@
      * @see #setBlockNetworkLoads
      *
      */
-    @RequiresFeature(name = WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public abstract boolean getBlockNetworkLoads();
 }
diff --git a/webkit/src/main/java/androidx/webkit/WebMessageCompat.java b/webkit/src/main/java/androidx/webkit/WebMessageCompat.java
deleted file mode 100644
index e1b1193..0000000
--- a/webkit/src/main/java/androidx/webkit/WebMessageCompat.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit;
-
-import androidx.annotation.Nullable;
-
-/**
- * The Java representation of the HTML5 PostMessage event. See
- * https://html.spec.whatwg.org/multipage/comms.html#the-messageevent-interfaces
- * for definition of a MessageEvent in HTML5.
- */
-public class WebMessageCompat {
-
-    private String mData;
-    private WebMessagePortCompat[] mPorts;
-
-    /**
-     * Creates a WebMessage.
-     * @param data  the data of the message.
-     */
-    public WebMessageCompat(@Nullable String data) {
-        mData = data;
-    }
-
-    /**
-     * Creates a WebMessage.
-     * @param data  the data of the message.
-     * @param ports  the ports that are sent with the message.
-     */
-    public WebMessageCompat(@Nullable String data, @Nullable WebMessagePortCompat[] ports) {
-        mData = data;
-        mPorts = ports;
-    }
-
-    /**
-     * Returns the data of the message.
-     */
-    public @Nullable String getData() {
-        return mData;
-    }
-
-    /**
-     * Returns the ports that are sent with the message, or {@code null} if no port
-     * is sent.
-     */
-    @Nullable
-    public WebMessagePortCompat[] getPorts() {
-        return mPorts;
-    }
-}
diff --git a/webkit/src/main/java/androidx/webkit/WebMessagePortCompat.java b/webkit/src/main/java/androidx/webkit/WebMessagePortCompat.java
deleted file mode 100644
index f6efd0a..0000000
--- a/webkit/src/main/java/androidx/webkit/WebMessagePortCompat.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit;
-
-import android.os.Handler;
-import android.webkit.WebMessagePort;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
-
-/**
- * <p>The Java representation of the
- * <a href="https://html.spec.whatwg.org/multipage/comms.html#messageport">
- * HTML5 message ports.</a>
- *
- * <p>A Message port represents one endpoint of a Message Channel. In Android
- * webview, there is no separate Message Channel object. When a message channel
- * is created, both ports are tangled to each other and started, and then
- * returned in a MessagePort array, see {@link WebViewCompat#createWebMessageChannel}
- * for creating a message channel.
- *
- * <p>When a message port is first created or received via transfer, it does not
- * have a WebMessageCallback to receive web messages. The messages are queued until
- * a WebMessageCallback is set.
- *
- * <p>A message port should be closed when it is not used by the embedder application
- * anymore. A closed port cannot be transferred or cannot be reopened to send
- * messages. Close can be called multiple times.
- *
- * <p>When a port is transferred to JS, it cannot be used to send or receive messages
- * at the Java side anymore. Different from HTML5 Spec, a port cannot be transferred
- * if one of these has ever happened: i. a message callback was set, ii. a message was
- * posted on it. A transferred port cannot be closed by the application, since
- * the ownership is also transferred.
- *
- * <p>It is possible to transfer both ports of a channel to JS, for example for
- * communication between subframes.
- */
-public abstract class WebMessagePortCompat {
-    /**
-     * The listener for handling MessagePort events. The message callback
-     * methods are called on the main thread. If the embedder application
-     * wants to receive the messages on a different thread, it can do this
-     * by passing a Handler in
-     *  {@link WebMessagePortCompat#setWebMessageCallback(Handler, WebMessageCallbackCompat)}.
-     * In the latter case, the application should be extra careful for thread safety
-     * since WebMessagePort methods should be called on main thread.
-     */
-    public abstract static class WebMessageCallbackCompat {
-        /**
-         * Message callback for receiving onMessage events.
-         *
-         * @param port  the WebMessagePort that the message is destined for
-         * @param message  the message from the entangled port.
-         */
-        public void onMessage(@NonNull WebMessagePortCompat port,
-                @Nullable WebMessageCompat message) { }
-    }
-
-    /**
-     * @hide disallow app devs to extend this class.
-     */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    public WebMessagePortCompat() { }
-
-    /**
-     * Post a WebMessage to the entangled port.
-     *
-     * @param message  the message from Java to JS.
-     *
-     * @throws IllegalStateException If message port is already transferred or closed.
-     */
-    public abstract void postMessage(@NonNull WebMessageCompat message);
-
-    /**
-     * Close the message port and free any resources associated with it.
-     */
-    public abstract void close();
-
-    /**
-     * Sets a callback to receive message events on the main thread.
-     *
-     * @param callback  the message callback.
-     */
-    public abstract void setWebMessageCallback(@NonNull WebMessageCallbackCompat callback);
-
-    /**
-     * Sets a callback to receive message events on the handler that is provided
-     * by the application. If the handler is null the message events are received on the main
-     * thread.
-     *
-     * @param handler   the handler to receive the message events.
-     * @param callback  the message callback.
-     */
-    public abstract void setWebMessageCallback(@Nullable Handler handler,
-            @NonNull WebMessageCallbackCompat callback);
-
-    /**
-     * Internal getter returning the private {@link WebMessagePort} implementing this class.
-     * @hide
-     */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    public abstract WebMessagePort getFrameworkPort();
-}
diff --git a/webkit/src/main/java/androidx/webkit/WebResourceErrorCompat.java b/webkit/src/main/java/androidx/webkit/WebResourceErrorCompat.java
deleted file mode 100644
index 3d8b99a..0000000
--- a/webkit/src/main/java/androidx/webkit/WebResourceErrorCompat.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit;
-
-import android.webkit.WebResourceError;
-import android.webkit.WebViewClient;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresFeature;
-import androidx.annotation.RestrictTo;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Compatibility version of {@link WebResourceError}.
- */
-public abstract class WebResourceErrorCompat {
-    /** @hide */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    @IntDef(value = {
-            WebViewClient.ERROR_UNKNOWN,
-            WebViewClient.ERROR_HOST_LOOKUP,
-            WebViewClient.ERROR_UNSUPPORTED_AUTH_SCHEME,
-            WebViewClient.ERROR_AUTHENTICATION,
-            WebViewClient.ERROR_PROXY_AUTHENTICATION,
-            WebViewClient.ERROR_CONNECT,
-            WebViewClient.ERROR_IO,
-            WebViewClient.ERROR_TIMEOUT,
-            WebViewClient.ERROR_REDIRECT_LOOP,
-            WebViewClient.ERROR_UNSUPPORTED_SCHEME,
-            WebViewClient.ERROR_FAILED_SSL_HANDSHAKE,
-            WebViewClient.ERROR_BAD_URL,
-            WebViewClient.ERROR_FILE,
-            WebViewClient.ERROR_FILE_NOT_FOUND,
-            WebViewClient.ERROR_TOO_MANY_REQUESTS,
-            WebViewClient.ERROR_UNSAFE_RESOURCE,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface NetErrorCode {}
-
-    /**
-     * Gets the error code of the error. The code corresponds to one
-     * of the {@code ERROR_*} constants in {@link WebViewClient}.
-     *
-     * @return The error code of the error
-     */
-    @RequiresFeature(name = WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
-    public abstract @NetErrorCode int getErrorCode();
-
-    /**
-     * Gets the string describing the error. Descriptions are localized,
-     * and thus can be used for communicating the problem to the user.
-     *
-     * @return The description of the error
-     */
-    @NonNull
-    @RequiresFeature(name = WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
-    public abstract CharSequence getDescription();
-
-    /**
-     * This class cannot be created by applications.
-     * @hide
-     */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    public WebResourceErrorCompat() {
-    }
-}
diff --git a/webkit/src/main/java/androidx/webkit/WebResourceRequestCompat.java b/webkit/src/main/java/androidx/webkit/WebResourceRequestCompat.java
deleted file mode 100644
index 783efca..0000000
--- a/webkit/src/main/java/androidx/webkit/WebResourceRequestCompat.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit;
-
-import android.annotation.SuppressLint;
-import android.webkit.WebResourceRequest;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresFeature;
-import androidx.webkit.internal.WebResourceRequestAdapter;
-import androidx.webkit.internal.WebViewFeatureInternal;
-import androidx.webkit.internal.WebViewGlueCommunicator;
-
-// TODO(gsennton) add a test for this class
-
-/**
- * Compatibility version of {@link WebResourceRequest}.
- */
-public class WebResourceRequestCompat {
-
-    // Developers should not be able to instantiate this class.
-    private WebResourceRequestCompat() {}
-
-    /**
-     * Gets whether the request was a result of a server-side redirect.
-     *
-     * @return whether the request was a result of a server-side redirect.
-     */
-    @SuppressLint("NewApi")
-    @RequiresFeature(name = WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
-    public static boolean isRedirect(@NonNull WebResourceRequest request) {
-        WebViewFeatureInternal feature = WebViewFeatureInternal.WEB_RESOURCE_REQUEST_IS_REDIRECT;
-        if (feature.isSupportedByFramework()) {
-            return request.isRedirect();
-        } else if (feature.isSupportedByWebView()) {
-            return getAdapter(request).isRedirect();
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    private static WebResourceRequestAdapter getAdapter(WebResourceRequest request) {
-        return WebViewGlueCommunicator.getCompatConverter().convertWebResourceRequest(request);
-    }
-}
diff --git a/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java b/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
index bff6170..12d7e63 100644
--- a/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
+++ b/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
@@ -16,27 +16,27 @@
 
 package androidx.webkit;
 
-import android.annotation.SuppressLint;
+import android.os.Build;
 import android.webkit.WebSettings;
 
-import androidx.annotation.IntDef;
-import androidx.annotation.RequiresFeature;
-import androidx.annotation.RestrictTo;
-import androidx.webkit.internal.WebSettingsAdapter;
-import androidx.webkit.internal.WebViewFeatureInternal;
-import androidx.webkit.internal.WebViewGlueCommunicator;
-
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+import androidx.annotation.IntDef;
+import androidx.annotation.RestrictTo;
+import androidx.webkit.internal.WebSettingsAdapter;
+import androidx.webkit.internal.WebViewGlueCommunicator;
+
 /**
  * Compatibility version of {@link android.webkit.WebSettings}
  */
 public class WebSettingsCompat {
     private WebSettingsCompat() {}
 
+    // TODO(gsennton): add feature detection
+
     /**
      * Sets whether this WebView should raster tiles when it is
      * offscreen but attached to a window. Turning this on can avoid
@@ -50,18 +50,11 @@
      *   visible WebViews and WebViews about to be animated to visible.
      * </ul>
      */
-    @SuppressLint("NewApi")
-    @RequiresFeature(name = WebViewFeature.OFF_SCREEN_PRERASTER,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static void setOffscreenPreRaster(WebSettings webSettings, boolean enabled) {
-        WebViewFeatureInternal webviewFeature =
-                WebViewFeatureInternal.getFeature(WebViewFeature.OFF_SCREEN_PRERASTER);
-        if (webviewFeature.isSupportedByFramework()) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
             webSettings.setOffscreenPreRaster(enabled);
-        } else if (webviewFeature.isSupportedByWebView()) {
-            getAdapter(webSettings).setOffscreenPreRaster(enabled);
         } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
+            getAdapter(webSettings).setOffscreenPreRaster(enabled);
         }
     }
 
@@ -71,18 +64,11 @@
      * @return {@code true} if this WebView will raster tiles when it is
      * offscreen but attached to a window.
      */
-    @SuppressLint("NewApi")
-    @RequiresFeature(name = WebViewFeature.OFF_SCREEN_PRERASTER,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static boolean getOffscreenPreRaster(WebSettings webSettings) {
-        WebViewFeatureInternal webviewFeature =
-                WebViewFeatureInternal.getFeature(WebViewFeature.OFF_SCREEN_PRERASTER);
-        if (webviewFeature.isSupportedByFramework()) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
             return webSettings.getOffscreenPreRaster();
-        } else if (webviewFeature.isSupportedByWebView()) {
-            return getAdapter(webSettings).getOffscreenPreRaster();
         } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
+            return getAdapter(webSettings).getOffscreenPreRaster();
         }
     }
 
@@ -100,18 +86,11 @@
      *
      * @param enabled Whether Safe Browsing is enabled.
      */
-    @SuppressLint("NewApi")
-    @RequiresFeature(name = WebViewFeature.SAFE_BROWSING_ENABLE,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static void setSafeBrowsingEnabled(WebSettings webSettings, boolean enabled) {
-        WebViewFeatureInternal webviewFeature =
-                WebViewFeatureInternal.getFeature(WebViewFeature.SAFE_BROWSING_ENABLE);
-        if (webviewFeature.isSupportedByFramework()) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             webSettings.setSafeBrowsingEnabled(enabled);
-        } else if (webviewFeature.isSupportedByWebView()) {
-            getAdapter(webSettings).setSafeBrowsingEnabled(enabled);
         } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
+            getAdapter(webSettings).setSafeBrowsingEnabled(enabled);
         }
     }
 
@@ -121,18 +100,11 @@
      *
      * @return {@code true} if Safe Browsing is enabled and {@code false} otherwise.
      */
-    @SuppressLint("NewApi")
-    @RequiresFeature(name = WebViewFeature.SAFE_BROWSING_ENABLE,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static boolean getSafeBrowsingEnabled(WebSettings webSettings) {
-        WebViewFeatureInternal webviewFeature =
-                WebViewFeatureInternal.getFeature(WebViewFeature.SAFE_BROWSING_ENABLE);
-        if (webviewFeature.isSupportedByFramework()) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             return webSettings.getSafeBrowsingEnabled();
-        } else if (webviewFeature.isSupportedByWebView()) {
-            return getAdapter(webSettings).getSafeBrowsingEnabled();
         } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
+            return getAdapter(webSettings).getSafeBrowsingEnabled();
         }
     }
 
@@ -154,19 +126,12 @@
      * Disables the action mode menu items according to {@code menuItems} flag.
      * @param menuItems an integer field flag for the menu items to be disabled.
      */
-    @SuppressLint("NewApi")
-    @RequiresFeature(name = WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static void setDisabledActionModeMenuItems(WebSettings webSettings,
             @MenuItemFlags int menuItems) {
-        WebViewFeatureInternal webviewFeature =
-                WebViewFeatureInternal.getFeature(WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS);
-        if (webviewFeature.isSupportedByFramework()) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             webSettings.setDisabledActionModeMenuItems(menuItems);
-        } else if (webviewFeature.isSupportedByWebView()) {
-            getAdapter(webSettings).setDisabledActionModeMenuItems(menuItems);
         } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
+            getAdapter(webSettings).setDisabledActionModeMenuItems(menuItems);
         }
     }
 
@@ -176,18 +141,11 @@
      *
      * @return all the disabled menu item flags combined with bitwise OR.
      */
-    @SuppressLint("NewApi")
-    @RequiresFeature(name = WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static @MenuItemFlags int getDisabledActionModeMenuItems(WebSettings webSettings) {
-        WebViewFeatureInternal webviewFeature =
-                WebViewFeatureInternal.getFeature(WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS);
-        if (webviewFeature.isSupportedByFramework()) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             return webSettings.getDisabledActionModeMenuItems();
-        } else if (webviewFeature.isSupportedByWebView()) {
-            return getAdapter(webSettings).getDisabledActionModeMenuItems();
         } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
+            return getAdapter(webSettings).getDisabledActionModeMenuItems();
         }
     }
 
diff --git a/webkit/src/main/java/androidx/webkit/WebViewClientCompat.java b/webkit/src/main/java/androidx/webkit/WebViewClientCompat.java
index 3dcfcc5..8c690f9 100644
--- a/webkit/src/main/java/androidx/webkit/WebViewClientCompat.java
+++ b/webkit/src/main/java/androidx/webkit/WebViewClientCompat.java
@@ -17,8 +17,6 @@
 package androidx.webkit;
 
 import android.os.Build;
-import android.webkit.SafeBrowsingResponse;
-import android.webkit.WebResourceError;
 import android.webkit.WebResourceRequest;
 import android.webkit.WebResourceResponse;
 import android.webkit.WebView;
@@ -28,11 +26,8 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
-import androidx.webkit.internal.WebResourceErrorImpl;
-import androidx.webkit.internal.WebViewFeatureInternal;
 
 import org.chromium.support_lib_boundary.WebViewClientBoundaryInterface;
-import org.chromium.support_lib_boundary.util.Features;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -46,14 +41,6 @@
 // still construct a WebViewClientCompat on a pre-Lollipop devices, and explicitly invoke these
 // methods, so each of these methods must also handle this case.
 public class WebViewClientCompat extends WebViewClient implements WebViewClientBoundaryInterface {
-    private static final String[] sSupportedFeatures = new String[] {
-        Features.VISUAL_STATE_CALLBACK,
-        Features.RECEIVE_WEB_RESOURCE_ERROR,
-        Features.RECEIVE_HTTP_ERROR,
-        Features.SHOULD_OVERRIDE_WITH_REDIRECTS,
-        Features.SAFE_BROWSING_HIT,
-    };
-
     /** @hide */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     @IntDef(value = {
@@ -65,141 +52,33 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface SafeBrowsingThreat {}
 
-    /**
-     * Returns the list of features this client supports. This feature list should always be a
-     * subset of the Features declared in WebViewFeature.
-     *
-     * @hide
-     */
-    @Override
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    public final String[] getSupportedFeatures() {
-        return sSupportedFeatures;
-    }
-
-    /**
-     * Notify the host application that {@link android.webkit.WebView} content left over from
-     * previous page navigations will no longer be drawn.
-     *
-     * <p>This callback can be used to determine the point at which it is safe to make a recycled
-     * {@link android.webkit.WebView} visible, ensuring that no stale content is shown. It is called
-     * at the earliest point at which it can be guaranteed that {@link WebView#onDraw} will no
-     * longer draw any content from previous navigations. The next draw will display either the
-     * {@link WebView#setBackgroundColor background color} of the {@link WebView}, or some of the
-     * contents of the newly loaded page.
-     *
-     * <p>This method is called when the body of the HTTP response has started loading, is reflected
-     * in the DOM, and will be visible in subsequent draws. This callback occurs early in the
-     * document loading process, and as such you should expect that linked resources (for example,
-     * CSS and images) may not be available.
-     *
-     * <p>For more fine-grained notification of visual state updates, see {@link
-     * WebViewCompat#postVisualStateCallback}.
-     *
-     * <p>Please note that all the conditions and recommendations applicable to
-     * {@link WebViewCompat#postVisualStateCallback} also apply to this API.
-     *
-     * <p>This callback is only called for main frame navigations.
-     *
-     * <p>This method is called only if {@link WebViewFeature#VISUAL_STATE_CALLBACK} is supported.
-     * You can check whether that flag is supported using {@link
-     * WebViewFeature#isFeatureSupported(String)}.
-     *
-     * @param view The {@link android.webkit.WebView} for which the navigation occurred.
-     * @param url  The URL corresponding to the page navigation that triggered this callback.
-     */
     @Override
     public void onPageCommitVisible(@NonNull WebView view, @NonNull String url) {
     }
 
     /**
-     * Invoked by chromium (for WebView APks 67+) for the {@code onReceivedError} event.
-     * Applications are not meant to override this, and should instead override the non-final {@link
-     * onReceivedError(WebView, WebResourceRequest, WebResourceErrorCompat)} method.
+     * Invoked by chromium for the {@code onReceivedError} event. Applications are not meant to
+     * override this, and should instead override the non-final {@code onReceivedError} method.
+     * TODO(ntfschr): link to that method once it's implemented.
      *
      * @hide
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     @Override
-    @RequiresApi(21)
     public final void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest request,
-            /* WebResourceError */ @NonNull InvocationHandler handler) {
-        onReceivedError(view, request, new WebResourceErrorImpl(handler));
+            /* WebResourceError */ @NonNull InvocationHandler error) {
+        // TODO(ntfschr): implement this (b/73151460).
     }
 
-    /**
-     * Invoked by chromium (in legacy WebView APKs) for the {@code onReceivedError} event on {@link
-     * Build.VERSION_CODES.M} and above. Applications are not meant to override this, and should
-     * instead override the non-final {@link onReceivedError(WebView, WebResourceRequest,
-     * WebResourceErrorCompat)} method.
-     *
-     * @hide
-     */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    @Override
-    @RequiresApi(23)
-    public final void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest request,
-            @NonNull WebResourceError error) {
-        if (Build.VERSION.SDK_INT < 23) return;
-        onReceivedError(view, request, new WebResourceErrorImpl(error));
-    }
-
-    /**
-     * Report web resource loading error to the host application. These errors usually indicate
-     * inability to connect to the server. Note that unlike the deprecated version of the callback,
-     * the new version will be called for any resource (iframe, image, etc.), not just for the main
-     * page. Thus, it is recommended to perform minimum required work in this callback.
-     *
-     * <p>This method is called only if {@link WebViewFeature#RECEIVE_WEB_RESOURCE_ERROR} is
-     * supported. You can check whether that flag is supported using {@link
-     * WebViewFeature#isFeatureSupported(String)}.
-     *
-     * @param view The WebView that is initiating the callback.
-     * @param request The originating request.
-     * @param error Information about the error occurred.
-     */
-    @SuppressWarnings("deprecation") // for invoking the old onReceivedError.
-    @RequiresApi(21)
-    public void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest request,
-            @NonNull WebResourceErrorCompat error) {
-        if (Build.VERSION.SDK_INT < 21) return;
-        if (!WebViewFeature.isFeatureSupported(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE)
-                || !WebViewFeature.isFeatureSupported(
-                        WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION)) {
-            // If the WebView APK drops supports for these APIs in the future, simply do nothing.
-            return;
-        }
-        if (request.isForMainFrame()) {
-            onReceivedError(view,
-                    error.getErrorCode(), error.getDescription().toString(),
-                    request.getUrl().toString());
-        }
-    }
-
-    /**
-     * Notify the host application that an HTTP error has been received from the server while
-     * loading a resource.  HTTP errors have status codes &gt;= 400.  This callback will be called
-     * for any resource (iframe, image, etc.), not just for the main page. Thus, it is recommended
-     * to perform minimum required work in this callback. Note that the content of the server
-     * response may not be provided within the {@code errorResponse} parameter.
-     *
-     * <p>This method is called only if {@link WebViewFeature#RECEIVE_HTTP_ERROR} is supported. You
-     * can check whether that flag is supported using {@link
-     * WebViewFeature#isFeatureSupported(String)}.
-     *
-     * @param view The WebView that is initiating the callback.
-     * @param request The originating request.
-     * @param errorResponse Information about the error occurred.
-     */
     @Override
     public void onReceivedHttpError(@NonNull WebView view, @NonNull WebResourceRequest request,
             @NonNull WebResourceResponse errorResponse) {
     }
 
     /**
-     * Invoked by chromium (for WebView APks 67+) for the {@code onSafeBrowsingHit} event.
-     * Applications are not meant to override this, and should instead override the non-final {@link
-     * onSafeBrowsingHit(WebView, WebResourceRequest, int, SafeBrowsingResponseCompat)} method.
+     * Invoked by chromium for the {@code onSafeBrowsingHit} event. Applications are not meant to
+     * override this, and should instead override the non-final {@code onSafeBrowsingHit} method.
+     * TODO(ntfschr): link to that method once it's implemented.
      *
      * @hide
      */
@@ -207,85 +86,14 @@
     @Override
     public final void onSafeBrowsingHit(@NonNull WebView view, @NonNull WebResourceRequest request,
             @SafeBrowsingThreat int threatType,
-            /* SafeBrowsingResponse */ @NonNull InvocationHandler handler) {
-        onSafeBrowsingHit(view, request, threatType,
-                SafeBrowsingResponseCompat.fromInvocationHandler(handler));
+            /* SafeBrowsingResponse */ @NonNull InvocationHandler callback) {
+        // TODO(ntfschr): implement this (b/73151460).
     }
 
-    /**
-     * Invoked by chromium (in legacy WebView APKs) for the {@code onSafeBrowsingHit} event on
-     * {@link Build.VERSION_CODES.O_MR1} and above. Applications are not meant to override this, and
-     * should instead override the non-final {@link onSafeBrowsingHit(WebView, WebResourceRequest,
-     * int, SafeBrowsingResponseCompat)} method.
-     *
-     * @hide
-     */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    // Default behavior in WebViewClient is to invoke the other (deprecated)
+    // shouldOverrideUrlLoading method.
     @Override
-    @RequiresApi(27)
-    public final void onSafeBrowsingHit(@NonNull WebView view, @NonNull WebResourceRequest request,
-            @SafeBrowsingThreat int threatType, @NonNull SafeBrowsingResponse response) {
-        onSafeBrowsingHit(view, request, threatType,
-                SafeBrowsingResponseCompat.fromSafeBrowsingResponse(response));
-    }
-
-    /**
-     * Notify the host application that a loading URL has been flagged by Safe Browsing.
-     *
-     * The application must invoke the callback to indicate the preferred response. The default
-     * behavior is to show an interstitial to the user, with the reporting checkbox visible.
-     *
-     * If the application needs to show its own custom interstitial UI, the callback can be invoked
-     * asynchronously with {@link SafeBrowsingResponseCompat#backToSafety} or {@link
-     * SafeBrowsingResponseCompat#proceed}, depending on user response.
-     *
-     * @param view The WebView that hit the malicious resource.
-     * @param request Object containing the details of the request.
-     * @param threatType The reason the resource was caught by Safe Browsing, corresponding to a
-     *                   {@code SAFE_BROWSING_THREAT_*} value.
-     * @param callback Applications must invoke one of the callback methods.
-     */
-    public void onSafeBrowsingHit(@NonNull WebView view, @NonNull WebResourceRequest request,
-            @SafeBrowsingThreat int threatType, @NonNull SafeBrowsingResponseCompat callback) {
-        if (WebViewFeature.isFeatureSupported(
-                WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL)) {
-            callback.showInterstitial(true);
-        } else {
-            // This should not happen, but in case the WebView APK eventually drops support for
-            // showInterstitial(), raise a runtime exception and require the WebView APK to handle
-            // this.
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    /**
-     * Give the host application a chance to take over the control when a new
-     * url is about to be loaded in the current WebView. If WebViewClient is not
-     * provided, by default WebView will ask Activity Manager to choose the
-     * proper handler for the url. If WebViewClient is provided, return {@code true}
-     * means the host application handles the url, while return {@code false} means the
-     * current WebView handles the url.
-     *
-     * <p>Notes:
-     * <ul>
-     * <li>This method is not called for requests using the POST &quot;method&quot;.</li>
-     * <li>This method is also called for subframes with non-http schemes, thus it is
-     * strongly disadvised to unconditionally call {@link WebView#loadUrl(String)}
-     * with the request's url from inside the method and then return {@code true},
-     * as this will make WebView to attempt loading a non-http url, and thus fail.</li>
-     * </ul>
-     *
-     * <p>This method is called only if {@link WebViewFeature#SHOULD_OVERRIDE_WITH_REDIRECTS} is
-     * supported. You can check whether that flag is supported using {@link
-     * WebViewFeature#isFeatureSupported(String)}.
-     *
-     * @param view The WebView that is initiating the callback.
-     * @param request Object containing the details of the request.
-     * @return {@code true} if the host application wants to leave the current WebView
-     *         and handle the url itself, otherwise return {@code false}.
-     */
-    @Override
-    @SuppressWarnings("deprecation") // for invoking the old shouldOverrideUrlLoading.
+    @SuppressWarnings("deprecation")
     @RequiresApi(21)
     public boolean shouldOverrideUrlLoading(@NonNull WebView view,
             @NonNull WebResourceRequest request) {
diff --git a/webkit/src/main/java/androidx/webkit/WebViewCompat.java b/webkit/src/main/java/androidx/webkit/WebViewCompat.java
index 1172997..88de335 100644
--- a/webkit/src/main/java/androidx/webkit/WebViewCompat.java
+++ b/webkit/src/main/java/androidx/webkit/WebViewCompat.java
@@ -16,7 +16,6 @@
 
 package androidx.webkit;
 
-import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -30,11 +29,10 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresFeature;
 import androidx.core.os.BuildCompat;
-import androidx.webkit.internal.WebMessagePortImpl;
 import androidx.webkit.internal.WebViewFeatureInternal;
 import androidx.webkit.internal.WebViewGlueCommunicator;
 import androidx.webkit.internal.WebViewProviderAdapter;
-import androidx.webkit.internal.WebViewProviderFactory;
+import androidx.webkit.internal.WebViewProviderFactoryAdapter;
 
 import org.chromium.support_lib_boundary.WebViewProviderBoundaryInterface;
 
@@ -46,9 +44,6 @@
  * Compatibility version of {@link android.webkit.WebView}
  */
 public class WebViewCompat {
-    private static final Uri WILDCARD_URI = Uri.parse("*");
-    private static final Uri EMPTY_URI = Uri.parse("");
-
     private WebViewCompat() {} // Don't allow instances of this class to be constructed.
 
     /**
@@ -140,7 +135,7 @@
             checkThread(webview);
             getProvider(webview).insertVisualStateCallback(requestId, callback);
         } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
+            WebViewFeatureInternal.throwUnsupportedOperationException("postVisualStateCallback");
         }
     }
 
@@ -162,19 +157,12 @@
      * @param callback will be called on the UI thread with {@code true} if initialization is
      * successful, {@code false} otherwise.
      */
-    @SuppressLint("NewApi")
-    @RequiresFeature(name = WebViewFeature.START_SAFE_BROWSING,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static void startSafeBrowsing(@NonNull Context context,
             @Nullable ValueCallback<Boolean> callback) {
-        WebViewFeatureInternal webviewFeature =
-                WebViewFeatureInternal.getFeature(WebViewFeature.START_SAFE_BROWSING);
-        if (webviewFeature.isSupportedByFramework()) {
+        if (Build.VERSION.SDK_INT >= 27) {
             WebView.startSafeBrowsing(context, callback);
-        } else if (webviewFeature.isSupportedByWebView()) {
+        } else { // TODO(gsennton): guard with WebViewApk.hasFeature(SafeBrowsing)
             getFactory().getStatics().initSafeBrowsing(context, callback);
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
         }
     }
 
@@ -201,19 +189,12 @@
      * whitelist. It will be called with {@code false} if any hosts are malformed. The callback
      * will be run on the UI thread
      */
-    @SuppressLint("NewApi")
-    @RequiresFeature(name = WebViewFeature.SAFE_BROWSING_WHITELIST,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static void setSafeBrowsingWhitelist(@NonNull List<String> hosts,
             @Nullable ValueCallback<Boolean> callback) {
-        WebViewFeatureInternal webviewFeature =
-                WebViewFeatureInternal.getFeature(WebViewFeature.SAFE_BROWSING_WHITELIST);
-        if (webviewFeature.isSupportedByFramework()) {
+        if (Build.VERSION.SDK_INT >= 27) {
             WebView.setSafeBrowsingWhitelist(hosts, callback);
-        } else if (webviewFeature.isSupportedByWebView()) {
+        } else { // TODO(gsennton): guard with WebViewApk.hasFeature(SafeBrowsing)
             getFactory().getStatics().setSafeBrowsingWhitelist(hosts, callback);
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
         }
     }
 
@@ -222,19 +203,12 @@
      *
      * @return the url pointing to a privacy policy document which can be displayed to users.
      */
-    @SuppressLint("NewApi")
     @NonNull
-    @RequiresFeature(name = WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL,
-            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static Uri getSafeBrowsingPrivacyPolicyUrl() {
-        WebViewFeatureInternal webviewFeature =
-                WebViewFeatureInternal.getFeature(WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL);
-        if (webviewFeature.isSupportedByFramework()) {
+        if (Build.VERSION.SDK_INT >= 27) {
             return WebView.getSafeBrowsingPrivacyPolicyUrl();
-        } else if (webviewFeature.isSupportedByWebView()) {
+        } else { // TODO(gsennton): guard with WebViewApk.hasFeature(SafeBrowsing)
             return getFactory().getStatics().getSafeBrowsingPrivacyPolicyUrl();
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
         }
     }
 
@@ -284,7 +258,7 @@
     private static PackageInfo getLoadedWebViewPackageInfo()
             throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException,
             IllegalAccessException {
-        Class<?> webViewFactoryClass = Class.forName("android.webkit.WebViewFactory");
+        Class webViewFactoryClass = Class.forName("android.webkit.WebViewFactory");
         PackageInfo webviewPackageInfo =
                 (PackageInfo) webViewFactoryClass.getMethod(
                         "getLoadedPackageInfo").invoke(null);
@@ -300,13 +274,13 @@
         try {
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
                     && Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
-                Class<?> webViewFactoryClass = null;
+                Class webViewFactoryClass = null;
                 webViewFactoryClass = Class.forName("android.webkit.WebViewFactory");
 
                 webviewPackageName = (String) webViewFactoryClass.getMethod(
                         "getWebViewPackageName").invoke(null);
             } else {
-                Class<?> webviewUpdateServiceClass =
+                Class webviewUpdateServiceClass =
                         Class.forName("android.webkit.WebViewUpdateService");
                 webviewPackageName = (String) webviewUpdateServiceClass.getMethod(
                         "getCurrentWebViewPackageName").invoke(null);
@@ -333,58 +307,7 @@
         return new WebViewProviderAdapter(createProvider(webview));
     }
 
-    /**
-     * Creates a message channel to communicate with JS and returns the message
-     * ports that represent the endpoints of this message channel. The HTML5 message
-     * channel functionality is described
-     * <a href="https://html.spec.whatwg.org/multipage/comms.html#messagechannel">here
-     * </a>
-     *
-     * <p>The returned message channels are entangled and already in started state.
-     *
-     * @return an array of size two, containing the two message ports that form the message channel.
-     */
-    public static @NonNull WebMessagePortCompat[] createWebMessageChannel(
-            @NonNull WebView webview) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            return WebMessagePortImpl.portsToCompat(webview.createWebMessageChannel());
-        } else { // TODO(gsennton) add reflection-based implementation
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    /**
-     * Post a message to main frame. The embedded application can restrict the
-     * messages to a certain target origin. See
-     * <a href="https://html.spec.whatwg.org/multipage/comms.html#posting-messages">
-     * HTML5 spec</a> for how target origin can be used.
-     * <p>
-     * A target origin can be set as a wildcard ("*"). However this is not recommended.
-     * See the page above for security issues.
-     *
-     * @param message the WebMessage
-     * @param targetOrigin the target origin.
-     */
-    public static void postWebMessage(@NonNull WebView webview, @NonNull WebMessageCompat message,
-            @NonNull Uri targetOrigin) {
-        // The wildcard ("*") Uri was first supported in WebView 60, see
-        // crrev/5ec5b67cbab33cea51b0ee11a286c885c2de4d5d, so on some Android versions using "*"
-        // won't work. WebView has always supported using an empty Uri "" as a wildcard - so convert
-        // "*" into "" here.
-        if (WILDCARD_URI.equals(targetOrigin)) {
-            targetOrigin = EMPTY_URI;
-        }
-
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            webview.postWebMessage(
-                    WebMessagePortImpl.compatToFrameworkMessage(message),
-                    targetOrigin);
-        } else { // TODO(gsennton) add reflection-based implementation
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    private static WebViewProviderFactory getFactory() {
+    private static WebViewProviderFactoryAdapter getFactory() {
         return WebViewGlueCommunicator.getFactory();
     }
 
@@ -399,7 +322,7 @@
                 throw new RuntimeException("A WebView method was called on thread '"
                         + Thread.currentThread().getName() + "'. "
                         + "All WebView methods must be called on the same thread. "
-                        + "(Expected Looper " + webview.getWebViewLooper() + " called on "
+                        + "(Expected Looper " + webview.getLooper() + " called on "
                         + Looper.myLooper() + ", FYI main Looper is " + Looper.getMainLooper()
                         + ")");
             }
diff --git a/webkit/src/main/java/androidx/webkit/WebViewFeature.java b/webkit/src/main/java/androidx/webkit/WebViewFeature.java
index e750295..d514477 100644
--- a/webkit/src/main/java/androidx/webkit/WebViewFeature.java
+++ b/webkit/src/main/java/androidx/webkit/WebViewFeature.java
@@ -16,11 +16,6 @@
 
 package androidx.webkit;
 
-import android.content.Context;
-import android.webkit.ValueCallback;
-import android.webkit.WebResourceRequest;
-import android.webkit.WebSettings;
-
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.StringDef;
@@ -32,7 +27,6 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
-import java.util.List;
 
 /**
  * Utility class for checking which WebView Support Library features are supported on the device.
@@ -47,28 +41,6 @@
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     @StringDef(value = {
             VISUAL_STATE_CALLBACK,
-            OFF_SCREEN_PRERASTER,
-            SAFE_BROWSING_ENABLE,
-            DISABLED_ACTION_MODE_MENU_ITEMS,
-            START_SAFE_BROWSING,
-            SAFE_BROWSING_WHITELIST,
-            SAFE_BROWSING_PRIVACY_POLICY_URL,
-            SERVICE_WORKER_BASIC_USAGE,
-            SERVICE_WORKER_CACHE_MODE,
-            SERVICE_WORKER_CONTENT_ACCESS,
-            SERVICE_WORKER_FILE_ACCESS,
-            SERVICE_WORKER_BLOCK_NETWORK_LOADS,
-            SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST,
-            RECEIVE_WEB_RESOURCE_ERROR,
-            RECEIVE_HTTP_ERROR,
-            SHOULD_OVERRIDE_WITH_REDIRECTS,
-            SAFE_BROWSING_HIT,
-            WEB_RESOURCE_REQUEST_IS_REDIRECT,
-            WEB_RESOURCE_ERROR_GET_DESCRIPTION,
-            WEB_RESOURCE_ERROR_GET_CODE,
-            SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY,
-            SAFE_BROWSING_RESPONSE_PROCEED,
-            SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL
     })
     @Retention(RetentionPolicy.SOURCE)
     @Target({ElementType.PARAMETER, ElementType.METHOD})
@@ -78,190 +50,11 @@
      * Feature for {@link #isFeatureSupported(String)}.
      * This feature covers
      * {@link androidx.webkit.WebViewCompat#postVisualStateCallback(android.webkit.WebView, long,
-     * WebViewCompat.VisualStateCallback)}, and {@link
-     * WebViewClientCompat#onPageCommitVisible(
-     * android.webkit.WebView, String)}.
+     * WebViewCompat.VisualStateCallback)}.
      */
     public static final String VISUAL_STATE_CALLBACK = Features.VISUAL_STATE_CALLBACK;
 
     /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link androidx.webkit.WebSettingsCompat#getOffscreenPreRaster(WebSettings)}, and
-     * {@link androidx.webkit.WebSettingsCompat#setOffscreenPreRaster(WebSettings, boolean)}.
-     */
-    public static final String OFF_SCREEN_PRERASTER = Features.OFF_SCREEN_PRERASTER;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link androidx.webkit.WebSettingsCompat#getSafeBrowsingEnabled(WebSettings)}, and
-     * {@link androidx.webkit.WebSettingsCompat#setSafeBrowsingEnabled(WebSettings, boolean)}.
-     */
-    public static final String SAFE_BROWSING_ENABLE = Features.SAFE_BROWSING_ENABLE;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link androidx.webkit.WebSettingsCompat#getDisabledActionModeMenuItems(WebSettings)}, and
-     * {@link androidx.webkit.WebSettingsCompat#setDisabledActionModeMenuItems(WebSettings, int)}.
-     */
-    public static final String DISABLED_ACTION_MODE_MENU_ITEMS =
-            Features.DISABLED_ACTION_MODE_MENU_ITEMS;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link androidx.webkit.WebViewCompat#startSafeBrowsing(Context, ValueCallback)}.
-     */
-    public static final String START_SAFE_BROWSING = Features.START_SAFE_BROWSING;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link androidx.webkit.WebViewCompat#setSafeBrowsingWhitelist(List, ValueCallback)}.
-     */
-    public static final String SAFE_BROWSING_WHITELIST = Features.SAFE_BROWSING_WHITELIST;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link WebViewCompat#getSafeBrowsingPrivacyPolicyUrl()}.
-     */
-    public static final String SAFE_BROWSING_PRIVACY_POLICY_URL =
-            Features.SAFE_BROWSING_PRIVACY_POLICY_URL;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link ServiceWorkerControllerCompat#getInstance()}.
-     */
-    public static final String SERVICE_WORKER_BASIC_USAGE = Features.SERVICE_WORKER_BASIC_USAGE;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link ServiceWorkerWebSettingsCompat#getCacheMode()}, and
-     * {@link ServiceWorkerWebSettingsCompat#setCacheMode(int)}.
-     */
-    public static final String SERVICE_WORKER_CACHE_MODE = Features.SERVICE_WORKER_CACHE_MODE;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link ServiceWorkerWebSettingsCompat#getAllowContentAccess()}, and
-     * {@link ServiceWorkerWebSettingsCompat#setAllowContentAccess(boolean)}.
-     */
-    public static final String SERVICE_WORKER_CONTENT_ACCESS =
-            Features.SERVICE_WORKER_CONTENT_ACCESS;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link ServiceWorkerWebSettingsCompat#getAllowFileAccess()}, and
-     * {@link ServiceWorkerWebSettingsCompat#setAllowFileAccess(boolean)}.
-     */
-    public static final String SERVICE_WORKER_FILE_ACCESS = Features.SERVICE_WORKER_FILE_ACCESS;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link ServiceWorkerWebSettingsCompat#getBlockNetworkLoads()}, and
-     * {@link ServiceWorkerWebSettingsCompat#setBlockNetworkLoads(boolean)}.
-     */
-    public static final String SERVICE_WORKER_BLOCK_NETWORK_LOADS =
-            Features.SERVICE_WORKER_BLOCK_NETWORK_LOADS;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link ServiceWorkerClientCompat#shouldInterceptRequest(WebResourceRequest)}.
-     */
-    public static final String SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST =
-            Features.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link WebViewClientCompat#onReceivedError(android.webkit.WebView, WebResourceRequest,
-     * WebResourceErrorCompat)}.
-     */
-    public static final String RECEIVE_WEB_RESOURCE_ERROR = Features.RECEIVE_WEB_RESOURCE_ERROR;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link WebViewClientCompat#onReceivedHttpError(android.webkit.WebView, WebResourceRequest,
-     * WebResourceResponse)}.
-     */
-    public static final String RECEIVE_HTTP_ERROR = Features.RECEIVE_HTTP_ERROR;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link WebViewClientCompat#shouldOverrideUrlLoading(android.webkit.WebView,
-     * WebResourceRequest)}.
-     */
-    public static final String SHOULD_OVERRIDE_WITH_REDIRECTS =
-            Features.SHOULD_OVERRIDE_WITH_REDIRECTS;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link WebViewClientCompat#onSafeBrowsingHit(android.webkit.WebView,
-     * WebResourceRequest, int, SafeBrowsingResponseCompat)}.
-     */
-    public static final String SAFE_BROWSING_HIT = Features.SAFE_BROWSING_HIT;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link WebResourceRequestCompat#isRedirect(WebResourceRequest)}.
-     */
-    public static final String WEB_RESOURCE_REQUEST_IS_REDIRECT =
-            Features.WEB_RESOURCE_REQUEST_IS_REDIRECT;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link WebResourceErrorCompat#getDescription()}.
-     */
-    public static final String WEB_RESOURCE_ERROR_GET_DESCRIPTION =
-            Features.WEB_RESOURCE_ERROR_GET_DESCRIPTION;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link WebResourceErrorCompat#getErrorCode()}.
-     */
-    public static final String WEB_RESOURCE_ERROR_GET_CODE =
-            Features.WEB_RESOURCE_ERROR_GET_CODE;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link SafeBrowsingResponseCompat#backToSafety(boolean)}.
-     */
-    public static final String SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY =
-            Features.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link SafeBrowsingResponseCompat#proceed(boolean)}.
-     */
-    public static final String SAFE_BROWSING_RESPONSE_PROCEED =
-            Features.SAFE_BROWSING_RESPONSE_PROCEED;
-
-    /**
-     * Feature for {@link #isFeatureSupported(String)}.
-     * This feature covers
-     * {@link SafeBrowsingResponseCompat#showInterstitial(boolean)}.
-     */
-    public static final String SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL =
-            Features.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL;
-
-    /**
      * Return whether a feature is supported at run-time. This depends on the Android version of the
      * device and the WebView APK on the device.
      */
diff --git a/webkit/src/main/java/androidx/webkit/internal/FrameworkServiceWorkerController.java b/webkit/src/main/java/androidx/webkit/internal/FrameworkServiceWorkerController.java
new file mode 100644
index 0000000..2e02777
--- /dev/null
+++ b/webkit/src/main/java/androidx/webkit/internal/FrameworkServiceWorkerController.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.webkit.internal;
+
+import android.os.Build;
+import android.webkit.ServiceWorkerController;
+
+import androidx.annotation.RequiresApi;
+import androidx.webkit.ServiceWorkerClientCompat;
+import androidx.webkit.ServiceWorkerControllerCompat;
+import androidx.webkit.ServiceWorkerWebSettingsCompat;
+
+/**
+ * Implementation of {@link ServiceWorkerControllerCompat} meant for use on up-to-date platforms.
+ * This class does not use reflection to bypass framework APIs - instead it uses android.webkit
+ * APIs.
+ */
+@RequiresApi(Build.VERSION_CODES.N)
+public class FrameworkServiceWorkerController extends ServiceWorkerControllerCompat {
+    private final ServiceWorkerController mImpl;
+    private ServiceWorkerWebSettingsCompat mSettings;
+
+    public FrameworkServiceWorkerController(ServiceWorkerController impl) {
+        mImpl = impl;
+    }
+
+    @Override
+    public ServiceWorkerWebSettingsCompat getServiceWorkerWebSettings() {
+        if (mSettings == null) {
+            mSettings = new FrameworksServiceWorkerWebSettings(mImpl.getServiceWorkerWebSettings());
+        }
+        return mSettings;
+    }
+
+    @Override
+    public void setServiceWorkerClient(ServiceWorkerClientCompat client) {
+        mImpl.setServiceWorkerClient(new FrameworkServiceWorkerClient(client));
+    }
+}
diff --git a/webkit/src/main/java/androidx/webkit/internal/FrameworksServiceWorkerWebSettings.java b/webkit/src/main/java/androidx/webkit/internal/FrameworksServiceWorkerWebSettings.java
new file mode 100644
index 0000000..4373756
--- /dev/null
+++ b/webkit/src/main/java/androidx/webkit/internal/FrameworksServiceWorkerWebSettings.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.webkit.internal;
+
+import android.os.Build;
+import android.webkit.ServiceWorkerWebSettings;
+
+import androidx.annotation.RequiresApi;
+import androidx.webkit.ServiceWorkerWebSettingsCompat;
+
+/**
+ * Implementation of {@link ServiceWorkerWebSettingsCompat} meant for use on up-to-date platforms.
+ * This class does not use reflection to bypass framework APIs - instead it uses android.webkit
+ * APIs.
+ */
+@RequiresApi(Build.VERSION_CODES.N)
+public class FrameworksServiceWorkerWebSettings extends ServiceWorkerWebSettingsCompat {
+    private final ServiceWorkerWebSettings mImpl;
+
+    public FrameworksServiceWorkerWebSettings(ServiceWorkerWebSettings impl) {
+        mImpl = impl;
+    }
+
+    @Override
+    public void setCacheMode(int mode) {
+        mImpl.setCacheMode(mode);
+    }
+
+    @Override
+    public int getCacheMode() {
+        return mImpl.getCacheMode();
+    }
+
+    @Override
+    public void setAllowContentAccess(boolean allow) {
+        mImpl.setAllowContentAccess(allow);
+    }
+
+    @Override
+    public boolean getAllowContentAccess() {
+        return mImpl.getAllowContentAccess();
+    }
+
+    @Override
+    public void setAllowFileAccess(boolean allow) {
+        mImpl.setAllowContentAccess(allow);
+    }
+
+    @Override
+    public boolean getAllowFileAccess() {
+        return mImpl.getAllowFileAccess();
+    }
+
+    @Override
+    public void setBlockNetworkLoads(boolean flag) {
+        mImpl.setAllowContentAccess(flag);
+    }
+
+    @Override
+    public boolean getBlockNetworkLoads() {
+        return mImpl.getBlockNetworkLoads();
+    }
+}
diff --git a/webkit/src/main/java/androidx/webkit/internal/IncompatibleApkWebViewProviderFactory.java b/webkit/src/main/java/androidx/webkit/internal/IncompatibleApkWebViewProviderFactory.java
deleted file mode 100644
index 71d5768..0000000
--- a/webkit/src/main/java/androidx/webkit/internal/IncompatibleApkWebViewProviderFactory.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit.internal;
-
-import android.webkit.WebView;
-
-import org.chromium.support_lib_boundary.ServiceWorkerControllerBoundaryInterface;
-import org.chromium.support_lib_boundary.StaticsBoundaryInterface;
-import org.chromium.support_lib_boundary.WebViewProviderBoundaryInterface;
-import org.chromium.support_lib_boundary.WebkitToCompatConverterBoundaryInterface;
-
-/**
- * This is a stub class used when the WebView Support Library is invoked on a device incompatible
- * with the library (either a pre-L device or a device without a compatible WebView APK).
- * The only method in this class that should be called is {@link #getWebViewFeatures()}.
- */
-public class IncompatibleApkWebViewProviderFactory implements WebViewProviderFactory {
-    private static final String[] EMPTY_STRING_ARRAY = new String[0];
-    private static final String UNSUPPORTED_EXCEPTION_EXPLANATION =
-            "This should never happen, if this method was called it means we're trying to reach "
-            + "into WebView APK code on an incompatible device. This most likely means the current "
-            + "method is being called too early, or is being called on start-up rather than lazily";
-
-    @Override
-    public WebViewProviderBoundaryInterface createWebView(WebView webview) {
-        throw new UnsupportedOperationException(UNSUPPORTED_EXCEPTION_EXPLANATION);
-    }
-
-    @Override
-    public WebkitToCompatConverterBoundaryInterface getWebkitToCompatConverter() {
-        throw new UnsupportedOperationException(UNSUPPORTED_EXCEPTION_EXPLANATION);
-    }
-
-    @Override
-    public StaticsBoundaryInterface getStatics() {
-        throw new UnsupportedOperationException(UNSUPPORTED_EXCEPTION_EXPLANATION);
-    }
-
-    @Override
-    public String[] getWebViewFeatures() {
-        return EMPTY_STRING_ARRAY;
-    }
-
-    @Override
-    public ServiceWorkerControllerBoundaryInterface getServiceWorkerController() {
-        throw new UnsupportedOperationException(UNSUPPORTED_EXCEPTION_EXPLANATION);
-    }
-}
diff --git a/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerClientAdapter.java b/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerClientAdapter.java
index f96bbd1..3ffeb83 100644
--- a/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerClientAdapter.java
+++ b/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerClientAdapter.java
@@ -22,7 +22,6 @@
 import androidx.webkit.ServiceWorkerClientCompat;
 
 import org.chromium.support_lib_boundary.ServiceWorkerClientBoundaryInterface;
-import org.chromium.support_lib_boundary.util.Features;
 
 /**
  * Adapter between {@link ServiceWorkerClientCompat} and
@@ -40,9 +39,4 @@
     public WebResourceResponse shouldInterceptRequest(WebResourceRequest request) {
         return mClient.shouldInterceptRequest(request);
     }
-
-    @Override
-    public String[] getSupportedFeatures() {
-        return new String[] { Features.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST };
-    }
 }
diff --git a/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerControllerAdapter.java b/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerControllerAdapter.java
new file mode 100644
index 0000000..4baa3ea
--- /dev/null
+++ b/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerControllerAdapter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.webkit.internal;
+
+import androidx.webkit.ServiceWorkerClientCompat;
+import androidx.webkit.ServiceWorkerControllerCompat;
+import androidx.webkit.ServiceWorkerWebSettingsCompat;
+
+import org.chromium.support_lib_boundary.ServiceWorkerControllerBoundaryInterface;
+import org.chromium.support_lib_boundary.ServiceWorkerWebSettingsBoundaryInterface;
+import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
+
+/**
+ * Adapter between {@link ServiceWorkerControllerCompat} and
+ * {@link ServiceWorkerControllerBoundaryInterface} (the corresponding interface shared with the
+ * support library glue in the WebView APK).
+ */
+public class ServiceWorkerControllerAdapter extends ServiceWorkerControllerCompat {
+    private final ServiceWorkerControllerBoundaryInterface mImpl;
+    private final ServiceWorkerWebSettingsCompat mWebSettings;
+
+    public ServiceWorkerControllerAdapter(ServiceWorkerControllerBoundaryInterface impl) {
+        mImpl = impl;
+        mWebSettings = new ServiceWorkerWebSettingsAdapter(
+                BoundaryInterfaceReflectionUtil.castToSuppLibClass(
+                        ServiceWorkerWebSettingsBoundaryInterface.class,
+                        mImpl.getServiceWorkerWebSettings()));
+    }
+
+    @Override
+    public ServiceWorkerWebSettingsCompat getServiceWorkerWebSettings() {
+        return mWebSettings;
+    }
+
+    @Override
+    public void setServiceWorkerClient(ServiceWorkerClientCompat client) {
+        mImpl.setServiceWorkerClient(BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
+                new ServiceWorkerClientAdapter(client)));
+    }
+}
diff --git a/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerControllerImpl.java b/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerControllerImpl.java
deleted file mode 100644
index 3787a92..0000000
--- a/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerControllerImpl.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit.internal;
-
-import android.annotation.SuppressLint;
-import android.webkit.ServiceWorkerController;
-
-import androidx.annotation.RequiresApi;
-import androidx.webkit.ServiceWorkerClientCompat;
-import androidx.webkit.ServiceWorkerControllerCompat;
-import androidx.webkit.ServiceWorkerWebSettingsCompat;
-
-import org.chromium.support_lib_boundary.ServiceWorkerControllerBoundaryInterface;
-import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
-
-/**
- * Implementation of {@link ServiceWorkerControllerCompat}.
- * This class uses either the framework, the WebView APK, or both, to implement
- * {@link ServiceWorkerControllerCompat} functionality.
- */
-public class ServiceWorkerControllerImpl extends ServiceWorkerControllerCompat {
-    private ServiceWorkerController mFrameworksImpl;
-    private ServiceWorkerControllerBoundaryInterface mBoundaryInterface;
-    private final ServiceWorkerWebSettingsCompat mWebSettings;
-
-    @SuppressLint("NewApi")
-    public ServiceWorkerControllerImpl() {
-        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_BASIC_USAGE;
-        if (feature.isSupportedByFramework()) {
-            mFrameworksImpl = ServiceWorkerController.getInstance();
-            // The current WebView APK might not be compatible with the support library, so set the
-            // boundary interface to null for now.
-            mBoundaryInterface = null;
-            mWebSettings = new ServiceWorkerWebSettingsImpl(
-                    mFrameworksImpl.getServiceWorkerWebSettings());
-        } else if (feature.isSupportedByWebView()) {
-            mFrameworksImpl = null;
-            mBoundaryInterface = WebViewGlueCommunicator.getFactory().getServiceWorkerController();
-            mWebSettings = new ServiceWorkerWebSettingsImpl(
-                    mBoundaryInterface.getServiceWorkerWebSettings());
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @RequiresApi(24)
-    private ServiceWorkerController getFrameworksImpl() {
-        if (mFrameworksImpl == null) {
-            mFrameworksImpl = ServiceWorkerController.getInstance();
-        }
-        return mFrameworksImpl;
-    }
-
-    private ServiceWorkerControllerBoundaryInterface getBoundaryInterface() {
-        if (mBoundaryInterface == null) {
-            mBoundaryInterface = WebViewGlueCommunicator.getFactory().getServiceWorkerController();
-        }
-        return mBoundaryInterface;
-    }
-
-    @Override
-    public ServiceWorkerWebSettingsCompat getServiceWorkerWebSettings() {
-        return mWebSettings;
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public void setServiceWorkerClient(ServiceWorkerClientCompat client)  {
-        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_BASIC_USAGE;
-        if (feature.isSupportedByFramework()) {
-            getFrameworksImpl().setServiceWorkerClient(new FrameworkServiceWorkerClient(client));
-        } else if (feature.isSupportedByWebView()) {
-            getBoundaryInterface().setServiceWorkerClient(
-                    BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
-                            new ServiceWorkerClientAdapter(client)));
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-}
diff --git a/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerWebSettingsAdapter.java b/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerWebSettingsAdapter.java
new file mode 100644
index 0000000..fd49396
--- /dev/null
+++ b/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerWebSettingsAdapter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.webkit.internal;
+
+import androidx.webkit.ServiceWorkerWebSettingsCompat;
+
+import org.chromium.support_lib_boundary.ServiceWorkerWebSettingsBoundaryInterface;
+
+/**
+ * Adapter between {@link ServiceWorkerWebSettingsCompat} and
+ * {@link ServiceWorkerWebSettingsBoundaryInterface} (the corresponding interface shared with the
+ * support library glue in the WebView APK).
+ */
+public class ServiceWorkerWebSettingsAdapter extends ServiceWorkerWebSettingsCompat {
+    private final ServiceWorkerWebSettingsBoundaryInterface mImpl;
+
+    public ServiceWorkerWebSettingsAdapter(ServiceWorkerWebSettingsBoundaryInterface impl) {
+        mImpl = impl;
+    }
+
+    @Override
+    public void setCacheMode(int mode) {
+        mImpl.setCacheMode(mode);
+    }
+
+    @Override
+    public int getCacheMode() {
+        return mImpl.getCacheMode();
+    }
+
+    @Override
+    public void setAllowContentAccess(boolean allow) {
+        mImpl.setAllowContentAccess(allow);
+    }
+
+    @Override
+    public boolean getAllowContentAccess() {
+        return mImpl.getAllowContentAccess();
+    }
+
+    @Override
+    public void setAllowFileAccess(boolean allow) {
+        mImpl.setAllowFileAccess(allow);
+    }
+
+    @Override
+    public boolean getAllowFileAccess() {
+        return mImpl.getAllowFileAccess();
+    }
+
+    @Override
+    public void setBlockNetworkLoads(boolean flag) {
+        mImpl.setBlockNetworkLoads(flag);
+    }
+
+    @Override
+    public boolean getBlockNetworkLoads() {
+        return mImpl.getBlockNetworkLoads();
+    }
+}
diff --git a/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerWebSettingsImpl.java b/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerWebSettingsImpl.java
deleted file mode 100644
index cad3ccb..0000000
--- a/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerWebSettingsImpl.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit.internal;
-
-import android.annotation.SuppressLint;
-import android.webkit.ServiceWorkerWebSettings;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.webkit.ServiceWorkerWebSettingsCompat;
-
-import org.chromium.support_lib_boundary.ServiceWorkerWebSettingsBoundaryInterface;
-import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
-
-/**
- * Implementation of {@link ServiceWorkerWebSettingsCompat}.
- * This class uses either the framework, the WebView APK, or both, to implement
- * {@link ServiceWorkerWebSettingsCompat} functionality.
- */
-public class ServiceWorkerWebSettingsImpl extends ServiceWorkerWebSettingsCompat {
-    private ServiceWorkerWebSettings mFrameworksImpl;
-    private ServiceWorkerWebSettingsBoundaryInterface mBoundaryInterface;
-
-    /**
-     * This class handles three different scenarios:
-     * 1. The Android version on the device is high enough to support all APIs used.
-     * 2. The Android version on the device is too low to support any ServiceWorkerWebSettings APIs
-     * so we use the support library glue instead through
-     * {@link ServiceWorkerWebSettingsBoundaryInterface}.
-     * 3. The Android version on the device is high enough to support some ServiceWorkerWebSettings
-     * APIs, so we call into them using {@link android.webkit.ServiceWorkerWebSettings}, but the
-     * rest of the APIs are only supported by the support library glue, so whenever we call such an
-     * API we fetch a {@link ServiceWorkerWebSettingsBoundaryInterface} corresponding to our
-     * {@link android.webkit.ServiceWorkerWebSettings}.
-     */
-    public ServiceWorkerWebSettingsImpl(@NonNull ServiceWorkerWebSettings settings) {
-        mFrameworksImpl = settings;
-    }
-
-    public ServiceWorkerWebSettingsImpl(@NonNull InvocationHandler invocationHandler) {
-        mBoundaryInterface = BoundaryInterfaceReflectionUtil.castToSuppLibClass(
-                ServiceWorkerWebSettingsBoundaryInterface.class, invocationHandler);
-    }
-
-    @RequiresApi(24)
-    private ServiceWorkerWebSettings getFrameworksImpl() {
-        if (mFrameworksImpl == null) {
-            mFrameworksImpl =
-                    WebViewGlueCommunicator.getCompatConverter().convertServiceWorkerSettings(
-                            Proxy.getInvocationHandler(mBoundaryInterface));
-        }
-        return mFrameworksImpl;
-    }
-
-    private ServiceWorkerWebSettingsBoundaryInterface getBoundaryInterface() {
-        if (mBoundaryInterface == null) {
-            // If the boundary interface is null we must have a working frameworks implementation to
-            // convert into a boundary interface.
-            // The case of the boundary interface being null here only occurs if we created the
-            // ServiceWorkerWebSettingsImpl using a frameworks API, but now want to call an API on
-            // the ServiceWorkerWebSettingsImpl that is only supported by the support library glue.
-            // This could happen for example if we introduce a new ServiceWorkerWebSettings API in
-            // level 30 and we run the support library on an N device (whose framework supports
-            // ServiceWorkerWebSettings).
-            mBoundaryInterface = BoundaryInterfaceReflectionUtil.castToSuppLibClass(
-                    ServiceWorkerWebSettingsBoundaryInterface.class,
-                    WebViewGlueCommunicator.getCompatConverter().convertServiceWorkerSettings(
-                            mFrameworksImpl));
-        }
-        return mBoundaryInterface;
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public void setCacheMode(int mode) {
-        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CACHE_MODE;
-        if (feature.isSupportedByFramework()) {
-            getFrameworksImpl().setCacheMode(mode);
-        } else if (feature.isSupportedByWebView()) {
-            getBoundaryInterface().setCacheMode(mode);
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public int getCacheMode() {
-        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CACHE_MODE;
-        if (feature.isSupportedByFramework()) {
-            return getFrameworksImpl().getCacheMode();
-        } else if (feature.isSupportedByWebView()) {
-            return getBoundaryInterface().getCacheMode();
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public void setAllowContentAccess(boolean allow) {
-        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CONTENT_ACCESS;
-        if (feature.isSupportedByFramework()) {
-            getFrameworksImpl().setAllowContentAccess(allow);
-        } else if (feature.isSupportedByWebView()) {
-            getBoundaryInterface().setAllowContentAccess(allow);
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public boolean getAllowContentAccess() {
-        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CONTENT_ACCESS;
-        if (feature.isSupportedByFramework()) {
-            return getFrameworksImpl().getAllowContentAccess();
-        } else if (feature.isSupportedByWebView()) {
-            return getBoundaryInterface().getAllowContentAccess();
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public void setAllowFileAccess(boolean allow) {
-        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_FILE_ACCESS;
-        if (feature.isSupportedByFramework()) {
-            getFrameworksImpl().setAllowFileAccess(allow);
-        } else if (feature.isSupportedByWebView()) {
-            getBoundaryInterface().setAllowFileAccess(allow);
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public boolean getAllowFileAccess() {
-        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_FILE_ACCESS;
-        if (feature.isSupportedByFramework()) {
-            return getFrameworksImpl().getAllowFileAccess();
-        } else if (feature.isSupportedByWebView()) {
-            return getBoundaryInterface().getAllowFileAccess();
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public void setBlockNetworkLoads(boolean flag) {
-        final WebViewFeatureInternal feature =
-                WebViewFeatureInternal.SERVICE_WORKER_BLOCK_NETWORK_LOADS;
-        if (feature.isSupportedByFramework()) {
-            getFrameworksImpl().setBlockNetworkLoads(flag);
-        } else if (feature.isSupportedByWebView()) {
-            getBoundaryInterface().setBlockNetworkLoads(flag);
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public boolean getBlockNetworkLoads() {
-        final WebViewFeatureInternal feature =
-                WebViewFeatureInternal.SERVICE_WORKER_BLOCK_NETWORK_LOADS;
-        if (feature.isSupportedByFramework()) {
-            return getFrameworksImpl().getBlockNetworkLoads();
-        } else if (feature.isSupportedByWebView()) {
-            return getBoundaryInterface().getBlockNetworkLoads();
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-}
diff --git a/webkit/src/main/java/androidx/webkit/internal/SupportLibraryInfo.java b/webkit/src/main/java/androidx/webkit/internal/SupportLibraryInfo.java
new file mode 100644
index 0000000..da8a02c
--- /dev/null
+++ b/webkit/src/main/java/androidx/webkit/internal/SupportLibraryInfo.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.webkit.internal;
+
+import org.chromium.support_lib_boundary.SupportLibraryInfoBoundaryInterface;
+import org.chromium.support_lib_boundary.util.Features;
+
+/**
+ * Contains information about the Android Support Library part of the WebView Support Library - this
+ * information is passed to the WebView APK code with the first WebView Support Library call.
+ */
+public class SupportLibraryInfo implements SupportLibraryInfoBoundaryInterface {
+    // Features supported by the support library itself (regardless of what the WebView APK
+    // supports).
+    private static final String[] SUPPORTED_FEATURES =
+            new String[] {
+                    Features.VISUAL_STATE_CALLBACK
+            };
+
+    @Override
+    public String[] getSupportedFeatures() {
+        return SUPPORTED_FEATURES;
+    }
+}
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebMessagePortImpl.java b/webkit/src/main/java/androidx/webkit/internal/WebMessagePortImpl.java
deleted file mode 100644
index 2de5105..0000000
--- a/webkit/src/main/java/androidx/webkit/internal/WebMessagePortImpl.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit.internal;
-
-import android.annotation.SuppressLint;
-import android.os.Build;
-import android.os.Handler;
-import android.webkit.WebMessage;
-import android.webkit.WebMessagePort;
-
-import androidx.annotation.RequiresApi;
-import androidx.webkit.WebMessageCompat;
-import androidx.webkit.WebMessagePortCompat;
-
-/**
- * Implementation of {@link WebMessagePortCompat}.
- * This class uses either the framework, the WebView APK, or both, to implement
- * {@link WebMessagePortCompat} functionality.
- */
-public class WebMessagePortImpl extends WebMessagePortCompat {
-    private final WebMessagePort mFrameworksImpl;
-    // TODO(gsennton) add WebMessagePortBoundaryInterface variable
-
-    public WebMessagePortImpl(WebMessagePort frameworksImpl) {
-        mFrameworksImpl = frameworksImpl;
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public void postMessage(WebMessageCompat message) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            mFrameworksImpl.postMessage(compatToFrameworkMessage(message));
-        } else { // TODO(gsennton) add reflection-based implementation
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public void close() {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            mFrameworksImpl.close();
-        } else { // TODO(gsennton) add reflection-based implementation
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @Override
-    public void setWebMessageCallback(final WebMessageCallbackCompat callback) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            mFrameworksImpl.setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
-                @Override
-                @SuppressWarnings("NewApi")
-                public void onMessage(WebMessagePort port, WebMessage message) {
-                    callback.onMessage(new WebMessagePortImpl(port),
-                            frameworkMessageToCompat(message));
-                }
-            });
-        } else { // TODO(gsennton) add reflection-based implementation
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @Override
-    public void setWebMessageCallback(Handler handler, final WebMessageCallbackCompat callback) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            mFrameworksImpl.setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
-                @Override
-                @SuppressWarnings("NewApi")
-                public void onMessage(WebMessagePort port, WebMessage message) {
-                    callback.onMessage(new WebMessagePortImpl(port),
-                            frameworkMessageToCompat(message));
-                }
-            }, handler);
-        } else { // TODO(gsennton) add reflection-based implementation
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @Override
-    public WebMessagePort getFrameworkPort() {
-        return mFrameworksImpl;
-    }
-
-    /**
-     * Convert an array of {@link WebMessagePort} objects into an array containing objects of the
-     * corresponding support library class {@link WebMessagePortCompat}.
-     */
-    public static WebMessagePortCompat[] portsToCompat(WebMessagePort[] ports) {
-        if (ports == null) return null;
-        WebMessagePortCompat[] compatPorts = new WebMessagePortCompat[ports.length];
-        for (int n = 0; n < ports.length; n++) {
-            compatPorts[n] = new WebMessagePortImpl(ports[n]);
-        }
-        return compatPorts;
-    }
-
-    /**
-     * Convert an array of {@link WebMessagePortCompat} objects into an array containing objects of
-     * the corresponding framework class {@link WebMessagePort}.
-     */
-    public static WebMessagePort[] compatToPorts(WebMessagePortCompat[] compatPorts) {
-        if (compatPorts == null) return null;
-        WebMessagePort[] ports = new WebMessagePort[compatPorts.length];
-        for (int n = 0; n < ports.length; n++) {
-            ports[n] = compatPorts[n].getFrameworkPort();
-        }
-        return ports;
-    }
-
-    /**
-     * Convert a {@link WebMessageCompat} into the corresponding framework class {@link WebMessage}.
-     */
-    @RequiresApi(23)
-    public static WebMessage compatToFrameworkMessage(WebMessageCompat message) {
-        return new WebMessage(
-                message.getData(),
-                compatToPorts(message.getPorts()));
-    }
-
-    /**
-     * Convert a {@link WebMessage} into the corresponding support library class
-     * {@link WebMessageCompat}.
-     */
-    @RequiresApi(23)
-    public static WebMessageCompat frameworkMessageToCompat(WebMessage message) {
-        return new WebMessageCompat(
-                message.getData(),
-                portsToCompat(message.getPorts()));
-    }
-}
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebResourceErrorImpl.java b/webkit/src/main/java/androidx/webkit/internal/WebResourceErrorImpl.java
deleted file mode 100644
index a27f61c..0000000
--- a/webkit/src/main/java/androidx/webkit/internal/WebResourceErrorImpl.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit.internal;
-
-import android.annotation.SuppressLint;
-import android.webkit.WebResourceError;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.webkit.WebResourceErrorCompat;
-import androidx.webkit.WebViewFeature;
-
-import org.chromium.support_lib_boundary.WebResourceErrorBoundaryInterface;
-import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
-
-/**
- * Implementation of {@link WebResourceErrorCompat}.
- * This class uses either the framework, the WebView APK, or both, to implement
- * {@link WebResourceErrorCompat} functionality.
- *
- */
-public class WebResourceErrorImpl extends WebResourceErrorCompat {
-    /**
-     * Frameworks implementation - do not use this directly, instead use
-     * {@link #getFrameworksImpl()} to ensure this variable has been instantiated correctly.
-     */
-    private WebResourceError mFrameworksImpl;
-
-    /**
-     * Support library glue implementation - do not use this directly, instead use
-     * {@link #getBoundaryInterface()} to ensure this variable has been instantiated correctly.
-     */
-    private WebResourceErrorBoundaryInterface mBoundaryInterface;
-
-    public WebResourceErrorImpl(@NonNull InvocationHandler invocationHandler) {
-        mBoundaryInterface = BoundaryInterfaceReflectionUtil.castToSuppLibClass(
-                WebResourceErrorBoundaryInterface.class, invocationHandler);
-    }
-
-    public WebResourceErrorImpl(@NonNull WebResourceError error) {
-        mFrameworksImpl = error;
-    }
-
-    @RequiresApi(23)
-    private WebResourceError getFrameworksImpl() {
-        if (mFrameworksImpl == null) {
-            mFrameworksImpl = WebViewGlueCommunicator.getCompatConverter().convertWebResourceError(
-                    Proxy.getInvocationHandler(mBoundaryInterface));
-        }
-        return mFrameworksImpl;
-    }
-
-    private WebResourceErrorBoundaryInterface getBoundaryInterface() {
-        if (mBoundaryInterface == null) {
-            mBoundaryInterface = BoundaryInterfaceReflectionUtil.castToSuppLibClass(
-                    WebResourceErrorBoundaryInterface.class,
-                    WebViewGlueCommunicator.getCompatConverter().convertWebResourceError(
-                            mFrameworksImpl));
-        }
-        return mBoundaryInterface;
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public int getErrorCode() {
-        final WebViewFeatureInternal feature =
-                WebViewFeatureInternal.getFeature(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE);
-        if (feature.isSupportedByFramework()) {
-            return getFrameworksImpl().getErrorCode();
-        } else if (feature.isSupportedByWebView()) {
-            return getBoundaryInterface().getErrorCode();
-        } else {
-            throw WebViewFeatureInternal.getUnsupportedOperationException();
-        }
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public CharSequence getDescription() {
-        final WebViewFeatureInternal feature = WebViewFeatureInternal.getFeature(
-                        WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION);
-        if (feature.isSupportedByFramework()) {
-            return getFrameworksImpl().getDescription();
-        } else if (feature.isSupportedByWebView()) {
-            return getBoundaryInterface().getDescription();
-        }
-        throw WebViewFeatureInternal.getUnsupportedOperationException();
-    }
-}
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebResourceRequestAdapter.java b/webkit/src/main/java/androidx/webkit/internal/WebResourceRequestAdapter.java
deleted file mode 100644
index 0d6a05d..0000000
--- a/webkit/src/main/java/androidx/webkit/internal/WebResourceRequestAdapter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit.internal;
-
-import android.webkit.WebResourceRequest;
-
-import org.chromium.support_lib_boundary.WebResourceRequestBoundaryInterface;
-
-/**
- * Adapter between {@link androidx.webkit.WebResourceRequestCompat} and
- * {@link org.chromium.support_lib_boundary.WebResourceRequestBoundaryInterface}.
- */
-public class WebResourceRequestAdapter {
-    private final WebResourceRequestBoundaryInterface mBoundaryInterface;
-
-    public WebResourceRequestAdapter(WebResourceRequestBoundaryInterface boundaryInterface) {
-        mBoundaryInterface = boundaryInterface;
-    }
-
-    /**
-     * Adapter method for
-     * {@link androidx.webkit.WebResourceRequestCompat#isRedirect(WebResourceRequest)}.
-     */
-    public boolean isRedirect() {
-        return mBoundaryInterface.isRedirect();
-    }
-}
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java b/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
index 916da9d..d16713c 100644
--- a/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
+++ b/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
@@ -16,21 +16,11 @@
 
 package androidx.webkit.internal;
 
-import android.content.Context;
 import android.os.Build;
-import android.webkit.ValueCallback;
-import android.webkit.WebResourceRequest;
-import android.webkit.WebSettings;
 
-import androidx.webkit.ServiceWorkerClientCompat;
-import androidx.webkit.WebResourceRequestCompat;
-import androidx.webkit.WebViewClientCompat;
-import androidx.webkit.WebViewCompat;
 import androidx.webkit.WebViewFeature;
 import androidx.webkit.WebViewFeature.WebViewSupportFeature;
 
-import java.util.List;
-
 /**
  * Enum representing a WebView feature, this provides functionality for determining whether a
  * feature is supported by the current framework and/or WebView APK.
@@ -39,166 +29,9 @@
     /**
      * This feature covers
      * {@link androidx.webkit.WebViewCompat#postVisualStateCallback(android.webkit.WebView, long,
-     * androidx.webkit.WebViewCompat.VisualStateCallback)}, and
-     * {@link WebViewClientCompat#onPageCommitVisible(android.webkit.WebView, String)}.
+     * androidx.webkit.WebViewCompat.VisualStateCallback)}.
      */
-    VISUAL_STATE_CALLBACK_FEATURE(WebViewFeature.VISUAL_STATE_CALLBACK, Build.VERSION_CODES.M),
-
-    /**
-     * This feature covers
-     * {@link androidx.webkit.WebSettingsCompat#getOffscreenPreRaster(WebSettings)}, and
-     * {@link androidx.webkit.WebSettingsCompat#setOffscreenPreRaster(WebSettings, boolean)}.
-     */
-    OFF_SCREEN_PRERASTER(WebViewFeature.OFF_SCREEN_PRERASTER, Build.VERSION_CODES.M),
-
-    /**
-     * This feature covers
-     * {@link androidx.webkit.WebSettingsCompat#getSafeBrowsingEnabled(WebSettings)}, and
-     * {@link androidx.webkit.WebSettingsCompat#setSafeBrowsingEnabled(WebSettings, boolean)}.
-     */
-    SAFE_BROWSING_ENABLE(WebViewFeature.SAFE_BROWSING_ENABLE, Build.VERSION_CODES.O),
-
-    /**
-     * This feature covers
-     * {@link androidx.webkit.WebSettingsCompat#getDisabledActionModeMenuItems(WebSettings)}, and
-     * {@link androidx.webkit.WebSettingsCompat#setDisabledActionModeMenuItems(WebSettings, int)}.
-     */
-    DISABLED_ACTION_MODE_MENU_ITEMS(WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS,
-                                    Build.VERSION_CODES.N),
-
-    /**
-     * This feature covers
-     * {@link androidx.webkit.WebViewCompat#startSafeBrowsing(Context, ValueCallback)}.
-     */
-    START_SAFE_BROWSING(WebViewFeature.START_SAFE_BROWSING, Build.VERSION_CODES.O_MR1),
-
-    /**
-     * This feature covers
-     * {@link androidx.webkit.WebViewCompat#setSafeBrowsingWhitelist(List, ValueCallback)}.
-     */
-    SAFE_BROWSING_WHITELIST(WebViewFeature.SAFE_BROWSING_WHITELIST, Build.VERSION_CODES.O_MR1),
-
-    /**
-     * This feature covers
-     * {@link WebViewCompat#getSafeBrowsingPrivacyPolicyUrl()}.
-     */
-    SAFE_BROWSING_PRIVACY_POLICY_URL(WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL,
-            Build.VERSION_CODES.O_MR1),
-
-    /**
-     * This feature covers
-     * {@link androidx.webkit.ServiceWorkerControllerCompat#getInstance()}.
-     */
-    SERVICE_WORKER_BASIC_USAGE(WebViewFeature.SERVICE_WORKER_BASIC_USAGE, Build.VERSION_CODES.N),
-
-    /**
-     * This feature covers
-     * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#getCacheMode()}, and
-     * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#setCacheMode(int)}.
-     */
-    SERVICE_WORKER_CACHE_MODE(WebViewFeature.SERVICE_WORKER_CACHE_MODE, Build.VERSION_CODES.N),
-
-    /**
-     * This feature covers
-     * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#getAllowContentAccess()}, and
-     * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#setAllowContentAccess(boolean)}.
-     */
-    SERVICE_WORKER_CONTENT_ACCESS(WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS,
-            Build.VERSION_CODES.N),
-
-    /**
-     * This feature covers
-     * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#getAllowFileAccess()}, and
-     * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#setAllowFileAccess(boolean)}.
-     */
-    SERVICE_WORKER_FILE_ACCESS(WebViewFeature.SERVICE_WORKER_FILE_ACCESS, Build.VERSION_CODES.N),
-
-    /**
-     * This feature covers
-     * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#getBlockNetworkLoads()}, and
-     * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#setBlockNetworkLoads(boolean)}.
-     */
-    SERVICE_WORKER_BLOCK_NETWORK_LOADS(WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS,
-            Build.VERSION_CODES.N),
-
-    /**
-     * This feature covers
-     * {@link ServiceWorkerClientCompat#shouldInterceptRequest(WebResourceRequest)}.
-     */
-    SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST(WebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST,
-            Build.VERSION_CODES.N),
-
-    /**
-     * This feature covers
-     * {@link WebViewClientCompat#onReceivedError(android.webkit.WebView, WebResourceRequest,
-     * WebResourceErrorCompat)}.
-     */
-    RECEIVE_WEB_RESOURCE_ERROR(WebViewFeature.RECEIVE_WEB_RESOURCE_ERROR, Build.VERSION_CODES.M),
-
-    /**
-     * This feature covers
-     * {@link WebViewClientCompat#onReceivedHttpError(android.webkit.WebView, WebResourceRequest,
-     * WebResourceResponse)}.
-     */
-    RECEIVE_HTTP_ERROR(WebViewFeature.RECEIVE_HTTP_ERROR, Build.VERSION_CODES.M),
-
-    /**
-     * This feature covers
-     * {@link WebViewClientCompat#shouldOverrideUrlLoading(android.webkit.WebView,
-     * WebResourceRequest)}.
-     */
-    SHOULD_OVERRIDE_WITH_REDIRECTS(WebViewFeature.SHOULD_OVERRIDE_WITH_REDIRECTS,
-            Build.VERSION_CODES.N),
-
-    /**
-     * This feature covers
-     * {@link WebViewClientCompat#onSafeBrowsingHit(android.webkit.WebView,
-     * WebResourceRequest, int, SafeBrowsingResponseCompat)}.
-     */
-    SAFE_BROWSING_HIT(WebViewFeature.SAFE_BROWSING_HIT, Build.VERSION_CODES.O_MR1),
-
-    /**
-     * This feature covers
-     * {@link WebResourceRequestCompat#isRedirect(WebResourceRequest)}.
-     */
-    WEB_RESOURCE_REQUEST_IS_REDIRECT(WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT,
-            Build.VERSION_CODES.N),
-
-    /**
-     * This feature covers
-     * {@link WebResourceErrorCompat#getDescription()}.
-     */
-    WEB_RESOURCE_ERROR_GET_DESCRIPTION(WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION,
-            Build.VERSION_CODES.M),
-
-    /**
-     * This feature covers
-     * {@link WebResourceErrorCompat#getErrorCode()}.
-     */
-    WEB_RESOURCE_ERROR_GET_CODE(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE,
-            Build.VERSION_CODES.M),
-
-    /**
-     * This feature covers
-     * {@link SafeBrowsingResponseCompat#backToSafety(boolean)}.
-     */
-    SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY,
-            Build.VERSION_CODES.O_MR1),
-
-    /**
-     * This feature covers
-     * {@link SafeBrowsingResponseCompat#proceed(boolean)}.
-     */
-    SAFE_BROWSING_RESPONSE_PROCEED(WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED,
-            Build.VERSION_CODES.O_MR1),
-
-    /**
-     * This feature covers
-     * {@link SafeBrowsingResponseCompat#showInterstitial(boolean)}.
-     */
-    SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL(
-            WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL,
-            Build.VERSION_CODES.O_MR1);
+    VISUAL_STATE_CALLBACK_FEATURE(WebViewFeature.VISUAL_STATE_CALLBACK, Build.VERSION_CODES.M);
 
     private final String mFeatureValue;
     private final int mOsVersion;
@@ -212,10 +45,12 @@
      * Return the {@link WebViewFeatureInternal} corresponding to {@param feature}.
      */
     public static WebViewFeatureInternal getFeature(@WebViewSupportFeature String feature) {
-        for (WebViewFeatureInternal internalFeature : WebViewFeatureInternal.values()) {
-            if (internalFeature.mFeatureValue.equals(feature)) return internalFeature;
+        switch (feature) {
+            case WebViewFeature.VISUAL_STATE_CALLBACK:
+                return VISUAL_STATE_CALLBACK_FEATURE;
+            default:
+                throw new RuntimeException("Unknown feature " + feature);
         }
-        throw new RuntimeException("Unknown feature " + feature);
     }
 
     /**
@@ -242,17 +77,12 @@
                 WebViewGlueCommunicator.getFactory().getWebViewFeatures();
     }
 
-
-    public static String[] getWebViewApkFeaturesForTesting() {
-        return LAZY_HOLDER.WEBVIEW_APK_FEATURES;
-    }
-
     /**
      * Utility method for throwing an exception explaining that the feature the app trying to use
      * isn't supported.
      */
-    public static UnsupportedOperationException getUnsupportedOperationException() {
-        return new UnsupportedOperationException("This method is not supported by the current "
-                + "version of the framework and the current WebView APK");
+    public static void throwUnsupportedOperationException(String feature) {
+        throw new UnsupportedOperationException("Feature " + feature
+                + " is not supported by the current version of the framework and WebView APK");
     }
 }
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebViewGlueCommunicator.java b/webkit/src/main/java/androidx/webkit/internal/WebViewGlueCommunicator.java
index ea4460f..33ac145 100644
--- a/webkit/src/main/java/androidx/webkit/internal/WebViewGlueCommunicator.java
+++ b/webkit/src/main/java/androidx/webkit/internal/WebViewGlueCommunicator.java
@@ -16,7 +16,6 @@
 
 package androidx.webkit.internal;
 
-import android.os.Build;
 import android.webkit.WebView;
 
 import androidx.core.os.BuildCompat;
@@ -40,57 +39,49 @@
     /**
      * Fetch the one global support library WebViewProviderFactory from the WebView glue layer.
      */
-    public static WebViewProviderFactory getFactory() {
+    public static WebViewProviderFactoryAdapter getFactory() {
         return LAZY_FACTORY_HOLDER.INSTANCE;
     }
 
     public static WebkitToCompatConverter getCompatConverter() {
-        return LAZY_COMPAT_CONVERTER_HOLDER.INSTANCE;
+        return LAZY_FACTORY_HOLDER.COMPAT_CONVERTER;
     }
 
     private static class LAZY_FACTORY_HOLDER {
-        private static final WebViewProviderFactory INSTANCE =
-                        WebViewGlueCommunicator.createGlueProviderFactory();
+        static final WebViewProviderFactoryAdapter INSTANCE =
+                new WebViewProviderFactoryAdapter(
+                        WebViewGlueCommunicator.createGlueProviderFactory());
+        static final WebkitToCompatConverter COMPAT_CONVERTER =
+                new WebkitToCompatConverter(
+                        INSTANCE.getWebkitToCompatConverter());
     }
 
-    private static class LAZY_COMPAT_CONVERTER_HOLDER {
-        static final WebkitToCompatConverter INSTANCE = new WebkitToCompatConverter(
-                WebViewGlueCommunicator.getFactory().getWebkitToCompatConverter());
-    }
-
-    private static InvocationHandler fetchGlueProviderFactoryImpl() throws IllegalAccessException,
-            InvocationTargetException, ClassNotFoundException, NoSuchMethodException {
-        Class<?> glueFactoryProviderFetcherClass = Class.forName(
-                GLUE_FACTORY_PROVIDER_FETCHER_CLASS, false, getWebViewClassLoader());
-        Method createProviderFactoryMethod = glueFactoryProviderFetcherClass.getDeclaredMethod(
-                GLUE_FACTORY_PROVIDER_FETCHER_METHOD);
-        return (InvocationHandler) createProviderFactoryMethod.invoke(null);
-    }
-
-    private static WebViewProviderFactory createGlueProviderFactory() {
-        // We do not support pre-L devices since their WebView APKs cannot be updated.
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
-            return new IncompatibleApkWebViewProviderFactory();
-        }
-        InvocationHandler invocationHandler;
+    private static InvocationHandler fetchGlueProviderFactoryImpl() {
         try {
-            invocationHandler = fetchGlueProviderFactoryImpl();
-            // The only way we should fail to fetch the provider-factory is if the class we are
-            // calling into doesn't exist - any other kind of failure is unexpected and should cause
-            // a run-time exception.
+            Class<?> glueFactoryProviderFetcherClass = Class.forName(
+                    GLUE_FACTORY_PROVIDER_FETCHER_CLASS, false, getWebViewClassLoader());
+            Method createProviderFactoryMethod = glueFactoryProviderFetcherClass.getDeclaredMethod(
+                    GLUE_FACTORY_PROVIDER_FETCHER_METHOD, InvocationHandler.class);
+            return (InvocationHandler) createProviderFactoryMethod.invoke(null,
+                    BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
+                            new SupportLibraryInfo()));
         } catch (IllegalAccessException e) {
             throw new RuntimeException(e);
         } catch (InvocationTargetException e) {
             throw new RuntimeException(e);
         } catch (ClassNotFoundException e) {
-            // If WebView APK support library glue entry point doesn't exist then return a Provider
-            // factory that declares that there are no features available.
-            return new IncompatibleApkWebViewProviderFactory();
+            throw new RuntimeException(e);
         } catch (NoSuchMethodException e) {
             throw new RuntimeException(e);
         }
-        return new WebViewProviderFactoryAdapter(BoundaryInterfaceReflectionUtil.castToSuppLibClass(
-                WebViewProviderFactoryBoundaryInterface.class, invocationHandler));
+        // TODO(gsennton) if the above happens we should avoid throwing an exception! And probably
+        // declare that the list of features supported by the WebView APK is empty.
+    }
+
+    private static WebViewProviderFactoryBoundaryInterface createGlueProviderFactory() {
+        InvocationHandler invocationHandler = fetchGlueProviderFactoryImpl();
+        return BoundaryInterfaceReflectionUtil.castToSuppLibClass(
+                WebViewProviderFactoryBoundaryInterface.class, invocationHandler);
     }
 
     /**
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactory.java b/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactory.java
deleted file mode 100644
index 5e4669a..0000000
--- a/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactory.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit.internal;
-
-import android.webkit.WebView;
-
-import org.chromium.support_lib_boundary.ServiceWorkerControllerBoundaryInterface;
-import org.chromium.support_lib_boundary.StaticsBoundaryInterface;
-import org.chromium.support_lib_boundary.WebViewProviderBoundaryInterface;
-import org.chromium.support_lib_boundary.WebkitToCompatConverterBoundaryInterface;
-
-/**
- * Interface representing {@link android.webkit.WebViewProviderFactory}.
- * On device with a compatible WebView APK this interface is implemented by a class defined in the
- * WebView APK itself.
- * On devices without a compatible WebView APK this interface is implemented by a stub class
- * {@link androidx.webkit.internal.IncompatibleWebViewProviderFactory}.
- */
-public interface WebViewProviderFactory {
-    /**
-     * Create a support library version of {@link android.webkit.WebViewProvider}.
-     */
-    WebViewProviderBoundaryInterface createWebView(WebView webview);
-
-    /**
-     * Create the boundary interface for {@link androidx.webkit.internal.WebkitToCompatConverter}
-     * which converts android.webkit classes into their corresponding support library classes.
-     */
-    WebkitToCompatConverterBoundaryInterface getWebkitToCompatConverter();
-
-    /**
-     * Fetch the boundary interface representing
-     * {@link android.webkit.WebViewFactoryProvider#Statics}.
-     */
-    StaticsBoundaryInterface getStatics();
-
-    /**
-     * Fetch the features supported by the current WebView APK.
-     */
-    String[] getWebViewFeatures();
-
-    /**
-     * Fetch the boundary interface representing {@link android.webkit.ServiceWorkerController}.
-     */
-    ServiceWorkerControllerBoundaryInterface getServiceWorkerController();
-}
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactoryAdapter.java b/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactoryAdapter.java
index 43e5eae..efe0e64 100644
--- a/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactoryAdapter.java
+++ b/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactoryAdapter.java
@@ -29,7 +29,7 @@
  * Adapter for WebViewProviderFactoryBoundaryInterface providing static WebView functionality
  * similar to that provided by {@link android.webkit.WebViewFactoryProvider}.
  */
-public class WebViewProviderFactoryAdapter implements WebViewProviderFactory {
+public class WebViewProviderFactoryAdapter {
     WebViewProviderFactoryBoundaryInterface mImpl;
 
     public WebViewProviderFactoryAdapter(WebViewProviderFactoryBoundaryInterface impl) {
@@ -41,7 +41,6 @@
      * {@link android.webkit.WebViewProvider} - the class used to implement
      * {@link androidx.webkit.WebViewCompat}.
      */
-    @Override
     public WebViewProviderBoundaryInterface createWebView(WebView webview) {
         return BoundaryInterfaceReflectionUtil.castToSuppLibClass(
                 WebViewProviderBoundaryInterface.class, mImpl.createWebView(webview));
@@ -52,7 +51,6 @@
      * {@link androidx.webkit.internal.WebkitToCompatConverter}, which converts android.webkit
      * classes into their corresponding support library classes.
      */
-    @Override
     public WebkitToCompatConverterBoundaryInterface getWebkitToCompatConverter() {
         return BoundaryInterfaceReflectionUtil.castToSuppLibClass(
                 WebkitToCompatConverterBoundaryInterface.class, mImpl.getWebkitToCompatConverter());
@@ -62,7 +60,6 @@
      * Adapter method for fetching the support library class representing
      * {@link android.webkit.WebViewFactoryProvider#Statics}.
      */
-    @Override
     public StaticsBoundaryInterface getStatics() {
         return BoundaryInterfaceReflectionUtil.castToSuppLibClass(
                 StaticsBoundaryInterface.class, mImpl.getStatics());
@@ -71,7 +68,6 @@
     /**
      * Adapter method for fetching the features supported by the current WebView APK.
      */
-    @Override
     public String[] getWebViewFeatures() {
         return mImpl.getSupportedFeatures();
     }
@@ -80,7 +76,6 @@
      * Adapter method for fetching the support library class representing
      * {@link android.webkit.ServiceWorkerController}.
      */
-    @Override
     public ServiceWorkerControllerBoundaryInterface getServiceWorkerController() {
         return BoundaryInterfaceReflectionUtil.castToSuppLibClass(
                 ServiceWorkerControllerBoundaryInterface.class, mImpl.getServiceWorkerController());
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebkitToCompatConverter.java b/webkit/src/main/java/androidx/webkit/internal/WebkitToCompatConverter.java
index 2e18bb9..a07cf07 100644
--- a/webkit/src/main/java/androidx/webkit/internal/WebkitToCompatConverter.java
+++ b/webkit/src/main/java/androidx/webkit/internal/WebkitToCompatConverter.java
@@ -16,22 +16,12 @@
 
 package androidx.webkit.internal;
 
-import android.webkit.ServiceWorkerWebSettings;
-import android.webkit.WebResourceError;
-import android.webkit.WebResourceRequest;
 import android.webkit.WebSettings;
 
-import androidx.annotation.RequiresApi;
-import androidx.webkit.WebResourceErrorCompat;
-
-import org.chromium.support_lib_boundary.ServiceWorkerWebSettingsBoundaryInterface;
-import org.chromium.support_lib_boundary.WebResourceRequestBoundaryInterface;
 import org.chromium.support_lib_boundary.WebSettingsBoundaryInterface;
 import org.chromium.support_lib_boundary.WebkitToCompatConverterBoundaryInterface;
 import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
 
-import java.lang.reflect.InvocationHandler;
-
 /**
  * A class providing functionality for converting android.webkit classes into support library
  * classes.
@@ -52,55 +42,4 @@
         return new WebSettingsAdapter(BoundaryInterfaceReflectionUtil.castToSuppLibClass(
                 WebSettingsBoundaryInterface.class, mImpl.convertSettings(webSettings)));
     }
-
-    /**
-     * Return a {@link WebResourceRequestAdapter} linked to the given {@link WebResourceRequest} so
-     * that calls on either of those objects affect the other object.
-     */
-    public WebResourceRequestAdapter convertWebResourceRequest(WebResourceRequest request) {
-        return new WebResourceRequestAdapter(BoundaryInterfaceReflectionUtil.castToSuppLibClass(
-                WebResourceRequestBoundaryInterface.class,
-                mImpl.convertWebResourceRequest(request)));
-    }
-
-    /**
-     * Return a {@link ServiceWorkerWebSettingsBoundaryInterface} linked to the given
-     * {@link ServiceWorkerWebSettings} such that calls on either of those objects affect the other
-     * object.
-     */
-    public InvocationHandler convertServiceWorkerSettings(
-            ServiceWorkerWebSettings settings) {
-        return mImpl.convertServiceWorkerSettings(settings);
-    }
-
-    /**
-     * Convert from an {@link InvocationHandler} representing an
-     * {@link androidx.webkit.ServiceWorkerWebSettingsCompat} into a
-     * {@link ServiceWorkerWebSettings}.
-     */
-    @RequiresApi(24)
-    public ServiceWorkerWebSettings convertServiceWorkerSettings(
-            /* SupportLibServiceWorkerSettings */ InvocationHandler serviceWorkerSettings) {
-        return (ServiceWorkerWebSettings) mImpl.convertServiceWorkerSettings(serviceWorkerSettings);
-    }
-
-    /**
-     * Return a {@link InvocationHandler} linked to the given
-     * {@link WebResourceError}such that calls on either of those objects affect the other
-     * object.
-     */
-    InvocationHandler convertWebResourceError(WebResourceError webResourceError) {
-        return mImpl.convertWebResourceError(webResourceError);
-    }
-
-
-    /**
-     * Convert from an {@link InvocationHandler} representing a {@link WebResourceErrorCompat} into
-     * a {@link WebResourceError}.
-     */
-    @RequiresApi(23)
-    WebResourceError convertWebResourceError(
-            /* SupportLibWebResourceError */ InvocationHandler webResourceError) {
-        return (WebResourceError) mImpl.convertWebResourceError(webResourceError);
-    }
 }
diff --git a/work/integration-tests/testapp/build.gradle b/work/integration-tests/testapp/build.gradle
index 7c51a4b..1b84be5 100644
--- a/work/integration-tests/testapp/build.gradle
+++ b/work/integration-tests/testapp/build.gradle
@@ -37,8 +37,8 @@
     implementation project(':work:work-runtime')
     implementation project(':work:work-firebase')
     implementation "android.arch.lifecycle:extensions:1.1.0"
-    implementation "android.arch.persistence.room:runtime:1.1.0"
-    annotationProcessor "android.arch.persistence.room:compiler:1.1.0"
+    implementation "android.arch.persistence.room:runtime:1.1.1-rc1"
+    annotationProcessor "android.arch.persistence.room:compiler:1.1.1-rc1"
     implementation MULTIDEX
     implementation "com.android.support:recyclerview-v7:26.1.0"
     implementation "com.android.support:appcompat-v7:26.1.0"
diff --git a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/ToastWorker.java b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/ToastWorker.java
index 37cd7fc..9f117ec 100644
--- a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/ToastWorker.java
+++ b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/ToastWorker.java
@@ -45,12 +45,16 @@
     @Override
     public @NonNull Result doWork() {
         Data input = getInputData();
-        final String message = input.getString(ARG_MESSAGE, "completed!");
+        String message = input.getString(ARG_MESSAGE);
+        if (message == null) {
+            message = "completed!";
+        }
+        final String displayMessage = message;
         new Handler(Looper.getMainLooper()).post(new Runnable() {
             @Override
             public void run() {
-                Log.d("ToastWorker", message);
-                Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
+                Log.d("ToastWorker", displayMessage);
+                Toast.makeText(getApplicationContext(), displayMessage, Toast.LENGTH_SHORT).show();
             }
         });
         return Result.SUCCESS;
diff --git a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/imageprocessing/ImageProcessingWorker.java b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/imageprocessing/ImageProcessingWorker.java
index 0fa1c5b..e28d942 100644
--- a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/imageprocessing/ImageProcessingWorker.java
+++ b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/imageprocessing/ImageProcessingWorker.java
@@ -47,7 +47,7 @@
     public @NonNull Result doWork() {
         Log.d(TAG, "Started");
 
-        String uriString = getInputData().getString(URI_KEY, null);
+        String uriString = getInputData().getString(URI_KEY);
         if (TextUtils.isEmpty(uriString)) {
             Log.e(TAG, "Invalid URI!");
             return Result.FAILURE;
diff --git a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/imageprocessing/ImageSetupWorker.java b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/imageprocessing/ImageSetupWorker.java
index 304e7fe..1d3520f 100644
--- a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/imageprocessing/ImageSetupWorker.java
+++ b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/imageprocessing/ImageSetupWorker.java
@@ -37,7 +37,7 @@
     public @NonNull Result doWork() {
         Log.d(TAG, "Started");
 
-        String uriString = getInputData().getString(URI_KEY, null);
+        String uriString = getInputData().getString(URI_KEY);
         if (TextUtils.isEmpty(uriString)) {
             Log.e(TAG, "Invalid URI!");
             return Result.FAILURE;
diff --git a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/sherlockholmes/TextMappingWorker.java b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/sherlockholmes/TextMappingWorker.java
index fcc7540..2fca443 100644
--- a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/sherlockholmes/TextMappingWorker.java
+++ b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/sherlockholmes/TextMappingWorker.java
@@ -57,7 +57,7 @@
     @Override
     public @NonNull Result doWork() {
         Data input = getInputData();
-        String inputFileName = input.getString(INPUT_FILE, null);
+        String inputFileName = input.getString(INPUT_FILE);
         String outputFileName = "out_" + inputFileName;
 
         AssetManager assetManager = getApplicationContext().getAssets();
diff --git a/work/workmanager-ktx/src/androidTest/java/androidx/work/DataTest.kt b/work/workmanager-ktx/src/androidTest/java/androidx/work/DataTest.kt
index 20b19f6f..0cd1eda 100644
--- a/work/workmanager-ktx/src/androidTest/java/androidx/work/DataTest.kt
+++ b/work/workmanager-ktx/src/androidTest/java/androidx/work/DataTest.kt
@@ -32,10 +32,10 @@
         val data = map.toWorkData()
         assertEquals(data.getInt("one", 0), 1)
         assertEquals(data.getLong("two", 0L), 2L)
-        assertEquals(data.getString("three", null), "Three")
+        assertEquals(data.getString("three"), "Three")
         val longArray = data.getLongArray("four")
         assertNotNull(longArray)
-        assertEquals(longArray.size, 2)
+        assertEquals(longArray!!.size, 2)
         assertEquals(longArray[0], 1L)
         assertEquals(longArray[1], 2L)
     }
diff --git a/work/workmanager/build.gradle b/work/workmanager/build.gradle
index fedc052..172c5ff 100644
--- a/work/workmanager/build.gradle
+++ b/work/workmanager/build.gradle
@@ -43,10 +43,10 @@
 
 dependencies {
     api "android.arch.lifecycle:extensions:1.1.0"
-    implementation "android.arch.persistence.room:runtime:1.1.0"
-    annotationProcessor "android.arch.persistence.room:compiler:1.1.0"
+    implementation "android.arch.persistence.room:runtime:1.1.1-rc1"
+    annotationProcessor "android.arch.persistence.room:compiler:1.1.1-rc1"
     androidTestImplementation "android.arch.core:core-testing:1.1.0"
-    androidTestImplementation "android.arch.persistence.room:testing:1.1.0"
+    androidTestImplementation "android.arch.persistence.room:testing:1.1.1-rc1"
     androidTestImplementation(TEST_RUNNER)
     androidTestImplementation(ESPRESSO_CORE)
     androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has its own MockMaker
diff --git a/work/workmanager/src/androidTest/java/androidx/work/WorkDatabaseMigrationTest.java b/work/workmanager/src/androidTest/java/androidx/work/WorkDatabaseMigrationTest.java
index c131117..0cba3cf 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/WorkDatabaseMigrationTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/WorkDatabaseMigrationTest.java
@@ -18,6 +18,12 @@
 
 import static android.database.sqlite.SQLiteDatabase.CONFLICT_FAIL;
 
+import static androidx.work.impl.WorkDatabaseMigrations.MIGRATION_3_4;
+import static androidx.work.impl.WorkDatabaseMigrations.VERSION_1;
+import static androidx.work.impl.WorkDatabaseMigrations.VERSION_2;
+import static androidx.work.impl.WorkDatabaseMigrations.VERSION_3;
+import static androidx.work.impl.WorkDatabaseMigrations.VERSION_4;
+
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 
@@ -25,16 +31,21 @@
 import android.arch.persistence.db.framework.FrameworkSQLiteOpenHelperFactory;
 import android.arch.persistence.room.testing.MigrationTestHelper;
 import android.content.ContentValues;
+import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteException;
+import android.os.Build;
+import android.support.annotation.NonNull;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 
 import androidx.work.impl.WorkDatabase;
 import androidx.work.impl.WorkDatabaseMigrations;
+import androidx.work.impl.WorkManagerImpl;
 import androidx.work.impl.model.WorkSpec;
 import androidx.work.impl.model.WorkTypeConverters;
+import androidx.work.impl.utils.Preferences;
 import androidx.work.worker.TestWorker;
 
 import org.junit.Before;
@@ -51,8 +62,6 @@
 
     private static final String TEST_DATABASE = "workdatabase-test";
     private static final boolean VALIDATE_DROPPED_TABLES = true;
-    private static final int OLD_VERSION = 1;
-    private static final int NEW_VERSION = 2;
     private static final String COLUMN_WORKSPEC_ID = "work_spec_id";
     private static final String COLUMN_SYSTEM_ID = "system_id";
     private static final String COLUMN_ALARM_ID = "alarm_id";
@@ -69,6 +78,7 @@
     private static final String TABLE_WORKTAG = "WorkTag";
     private static final String TABLE_WORKNAME = "WorkName";
 
+    private Context mContext;
     private File mDatabasePath;
 
     @Rule
@@ -80,6 +90,7 @@
     @Before
     public void setUp() {
         // Delete the database if it exists.
+        mContext = InstrumentationRegistry.getTargetContext();
         mDatabasePath = InstrumentationRegistry.getContext().getDatabasePath(TEST_DATABASE);
         if (mDatabasePath.exists()) {
             mDatabasePath.delete();
@@ -90,11 +101,143 @@
     @MediumTest
     public void testMigrationVersion1To2() throws IOException {
         SupportSQLiteDatabase database =
-                mMigrationTestHelper.createDatabase(TEST_DATABASE, OLD_VERSION);
+                mMigrationTestHelper.createDatabase(TEST_DATABASE, VERSION_1);
 
-        String workSpecId0 = UUID.randomUUID().toString();
+        String[] prepopulatedWorkSpecIds = new String[]{
+                UUID.randomUUID().toString(),
+                UUID.randomUUID().toString()
+        };
+        for (String workSpecId : prepopulatedWorkSpecIds) {
+            ContentValues contentValues = contentValues(workSpecId);
+            database.insert("workspec", CONFLICT_FAIL, contentValues);
+
+            if (workSpecId.equals(prepopulatedWorkSpecIds[0])) {
+                ContentValues tagValues = new ContentValues();
+                tagValues.put("tag", TestWorker.class.getName());
+                tagValues.put("work_spec_id", workSpecId);
+                database.insert("worktag", CONFLICT_FAIL, tagValues);
+            }
+        }
+
+        String workSpecId1 = UUID.randomUUID().toString();
+        String workSpecId2 = UUID.randomUUID().toString();
+
+        // insert alarmInfos
+        database.execSQL(INSERT_ALARM_INFO, new Object[]{workSpecId1, 1});
+        database.execSQL(INSERT_ALARM_INFO, new Object[]{workSpecId2, 2});
+
+        database.close();
+
+        database = mMigrationTestHelper.runMigrationsAndValidate(
+                TEST_DATABASE,
+                VERSION_2,
+                VALIDATE_DROPPED_TABLES,
+                WorkDatabaseMigrations.MIGRATION_1_2);
+
+        Cursor tagCursor = database.query("SELECT * FROM worktag");
+        assertThat(tagCursor.getCount(), is(prepopulatedWorkSpecIds.length));
+        boolean[] foundWorkSpecId = new boolean[prepopulatedWorkSpecIds.length];
+        for (int i = 0; i < prepopulatedWorkSpecIds.length; ++i) {
+            tagCursor.moveToPosition(i);
+            assertThat(tagCursor.getString(tagCursor.getColumnIndex("tag")),
+                    is(TestWorker.class.getName()));
+            String currentId = tagCursor.getString(tagCursor.getColumnIndex("work_spec_id"));
+            for (int j = 0; j < prepopulatedWorkSpecIds.length; ++j) {
+                if (prepopulatedWorkSpecIds[j].equals(currentId)) {
+                    foundWorkSpecId[j] = true;
+                    break;
+                }
+            }
+        }
+        for (int i = 0; i < prepopulatedWorkSpecIds.length; ++i) {
+            assertThat(foundWorkSpecId[i], is(true));
+        }
+        tagCursor.close();
+
+        Cursor cursor = database.query(CHECK_SYSTEM_ID_INFO);
+        assertThat(cursor.getCount(), is(2));
+        cursor.moveToFirst();
+        assertThat(cursor.getString(cursor.getColumnIndex(COLUMN_WORKSPEC_ID)), is(workSpecId1));
+        assertThat(cursor.getInt(cursor.getColumnIndex(COLUMN_SYSTEM_ID)), is(1));
+        cursor.moveToNext();
+        assertThat(cursor.getString(cursor.getColumnIndex(COLUMN_WORKSPEC_ID)), is(workSpecId2));
+        assertThat(cursor.getInt(cursor.getColumnIndex(COLUMN_SYSTEM_ID)), is(2));
+        cursor.close();
+
+        assertThat(checkExists(database, TABLE_ALARM_INFO), is(false));
+        assertThat(checkExists(database, TABLE_WORKSPEC), is(true));
+        assertThat(checkExists(database, TABLE_WORKTAG), is(true));
+        assertThat(checkExists(database, TABLE_WORKNAME), is(true));
+        database.close();
+    }
+
+    @Test
+    @MediumTest
+    public void testMigrationVersion2To3() throws IOException {
+        SupportSQLiteDatabase database =
+                mMigrationTestHelper.createDatabase(TEST_DATABASE, VERSION_2);
+        WorkDatabaseMigrations.WorkMigration migration2To3 =
+                new WorkDatabaseMigrations.WorkMigration(mContext, VERSION_2, VERSION_3);
+
+        database = mMigrationTestHelper.runMigrationsAndValidate(
+                TEST_DATABASE,
+                VERSION_3,
+                VALIDATE_DROPPED_TABLES,
+                migration2To3);
+
+        Preferences preferences = new Preferences(mContext);
+        assertThat(preferences.needsReschedule(), is(true));
+        database.close();
+    }
+
+    @Test
+    @MediumTest
+    public void testMigrationVersion3To4() throws IOException {
+        SupportSQLiteDatabase database =
+                mMigrationTestHelper.createDatabase(TEST_DATABASE, VERSION_3);
+
+        String oneTimeWorkSpecId = UUID.randomUUID().toString();
+        long scheduleRequestedAt = System.currentTimeMillis();
+        ContentValues oneTimeWorkSpecContentValues = contentValues(oneTimeWorkSpecId);
+        oneTimeWorkSpecContentValues.put("schedule_requested_at", scheduleRequestedAt);
+
+        String periodicWorkSpecId = UUID.randomUUID().toString();
+        ContentValues periodicWorkSpecContentValues = contentValues(periodicWorkSpecId);
+        periodicWorkSpecContentValues.put("interval_duration", 15 * 60 * 1000L);
+
+        database.insert("workspec", CONFLICT_FAIL, oneTimeWorkSpecContentValues);
+        database.insert("workspec", CONFLICT_FAIL, periodicWorkSpecContentValues);
+
+        database = mMigrationTestHelper.runMigrationsAndValidate(
+                TEST_DATABASE,
+                VERSION_4,
+                VALIDATE_DROPPED_TABLES,
+                MIGRATION_3_4);
+
+        Cursor cursor = database.query("SELECT * from workspec");
+        assertThat(cursor.getCount(), is(2));
+        cursor.moveToFirst();
+        assertThat(cursor.getString(cursor.getColumnIndex("id")),
+                is(oneTimeWorkSpecId));
+        assertThat(cursor.getLong(cursor.getColumnIndex("schedule_requested_at")),
+                is(scheduleRequestedAt));
+        cursor.moveToNext();
+        assertThat(cursor.getString(cursor.getColumnIndex("id")),
+                is(periodicWorkSpecId));
+        if (Build.VERSION.SDK_INT >= WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL) {
+            assertThat(cursor.getLong(cursor.getColumnIndex("schedule_requested_at")),
+                    is(0L));
+        } else {
+            assertThat(cursor.getLong(cursor.getColumnIndex("schedule_requested_at")),
+                    is(WorkSpec.SCHEDULE_NOT_REQUESTED_YET));
+        }
+        database.close();
+    }
+
+    @NonNull
+    private ContentValues contentValues(String workSpecId) {
         ContentValues contentValues = new ContentValues();
-        contentValues.put("id", workSpecId0);
+        contentValues.put("id", workSpecId);
         contentValues.put("state", WorkTypeConverters.StateIds.ENQUEUED);
         contentValues.put("worker_class_name", TestWorker.class.getName());
         contentValues.put("input_merger_class_name", OverwritingInputMerger.class.getName());
@@ -117,131 +260,7 @@
         contentValues.put("period_start_time", 0L);
         contentValues.put("minimum_retention_duration", 0L);
         contentValues.put("schedule_requested_at", WorkSpec.SCHEDULE_NOT_REQUESTED_YET);
-        database.insert("workspec", CONFLICT_FAIL, contentValues);
-
-        String workSpecId1 = UUID.randomUUID().toString();
-        String workSpecId2 = UUID.randomUUID().toString();
-
-        // insert alarmInfos
-        database.execSQL(INSERT_ALARM_INFO, new Object[]{workSpecId1, 1});
-        database.execSQL(INSERT_ALARM_INFO, new Object[]{workSpecId2, 2});
-
-        database.close();
-
-        database = mMigrationTestHelper.runMigrationsAndValidate(
-                TEST_DATABASE,
-                NEW_VERSION,
-                VALIDATE_DROPPED_TABLES,
-                WorkDatabaseMigrations.MIGRATION_1_2);
-
-        Cursor tagCursor = database.query("SELECT * FROM worktag");
-        assertThat(tagCursor.getCount(), is(1));
-        tagCursor.moveToFirst();
-        assertThat(tagCursor.getString(tagCursor.getColumnIndex("tag")),
-                is(TestWorker.class.getName()));
-        assertThat(tagCursor.getString(tagCursor.getColumnIndex("work_spec_id")), is(workSpecId0));
-        tagCursor.close();
-
-        Cursor cursor = database.query(CHECK_SYSTEM_ID_INFO);
-        assertThat(cursor.getCount(), is(2));
-        cursor.moveToFirst();
-        assertThat(cursor.getString(cursor.getColumnIndex(COLUMN_WORKSPEC_ID)), is(workSpecId1));
-        assertThat(cursor.getInt(cursor.getColumnIndex(COLUMN_SYSTEM_ID)), is(1));
-        cursor.moveToNext();
-        assertThat(cursor.getString(cursor.getColumnIndex(COLUMN_WORKSPEC_ID)), is(workSpecId2));
-        assertThat(cursor.getInt(cursor.getColumnIndex(COLUMN_SYSTEM_ID)), is(2));
-        cursor.close();
-
-        assertThat(checkExists(database, TABLE_ALARM_INFO), is(false));
-        assertThat(checkExists(database, TABLE_WORKSPEC), is(true));
-        assertThat(checkExists(database, TABLE_WORKTAG), is(true));
-        assertThat(checkExists(database, TABLE_WORKNAME), is(true));
-        database.close();
-    }
-
-    @Test
-    @MediumTest
-    public void testMigrationVersion2To1() throws IOException {
-        SupportSQLiteDatabase database =
-                mMigrationTestHelper.createDatabase(TEST_DATABASE, NEW_VERSION);
-
-        String workSpecId1 = UUID.randomUUID().toString();
-        String workSpecId2 = UUID.randomUUID().toString();
-
-        // insert SystemIdInfo
-        database.execSQL(INSERT_SYSTEM_ID_INFO, new Object[]{workSpecId1, 1});
-        database.execSQL(INSERT_SYSTEM_ID_INFO, new Object[]{workSpecId2, 2});
-
-        database.close();
-
-
-        database = mMigrationTestHelper.runMigrationsAndValidate(
-                TEST_DATABASE,
-                OLD_VERSION,
-                VALIDATE_DROPPED_TABLES,
-                WorkDatabaseMigrations.MIGRATION_2_1);
-
-        Cursor cursor = database.query(CHECK_ALARM_INFO);
-        assertThat(cursor.getCount(), is(2));
-        cursor.moveToFirst();
-        assertThat(cursor.getString(cursor.getColumnIndex(COLUMN_WORKSPEC_ID)), is(workSpecId1));
-        assertThat(cursor.getInt(cursor.getColumnIndex(COLUMN_ALARM_ID)), is(1));
-        cursor.moveToNext();
-        assertThat(cursor.getString(cursor.getColumnIndex(COLUMN_WORKSPEC_ID)), is(workSpecId2));
-        assertThat(cursor.getInt(cursor.getColumnIndex(COLUMN_ALARM_ID)), is(2));
-        cursor.close();
-
-        assertThat(checkExists(database, TABLE_SYSTEM_ID_INFO), is(false));
-        assertThat(checkExists(database, TABLE_WORKSPEC), is(true));
-        assertThat(checkExists(database, TABLE_WORKTAG), is(true));
-        assertThat(checkExists(database, TABLE_WORKNAME), is(true));
-        database.close();
-    }
-
-    @Test
-    @MediumTest
-    public void testMigrationVersion1To2To1() throws IOException {
-        SupportSQLiteDatabase database =
-                mMigrationTestHelper.createDatabase(TEST_DATABASE, OLD_VERSION);
-
-        String workSpecId1 = UUID.randomUUID().toString();
-        String workSpecId2 = UUID.randomUUID().toString();
-
-        // insert alarmInfos
-        database.execSQL(INSERT_ALARM_INFO, new Object[]{workSpecId1, 1});
-        database.execSQL(INSERT_ALARM_INFO, new Object[]{workSpecId2, 2});
-
-        database.close();
-
-        database = mMigrationTestHelper.runMigrationsAndValidate(
-                TEST_DATABASE,
-                NEW_VERSION,
-                VALIDATE_DROPPED_TABLES,
-                WorkDatabaseMigrations.MIGRATION_1_2);
-
-        database.close();
-
-        database = mMigrationTestHelper.runMigrationsAndValidate(
-                TEST_DATABASE,
-                OLD_VERSION,
-                VALIDATE_DROPPED_TABLES,
-                WorkDatabaseMigrations.MIGRATION_2_1);
-
-        Cursor cursor = database.query(CHECK_ALARM_INFO);
-        assertThat(cursor.getCount(), is(2));
-        cursor.moveToFirst();
-        assertThat(cursor.getString(cursor.getColumnIndex(COLUMN_WORKSPEC_ID)), is(workSpecId1));
-        assertThat(cursor.getInt(cursor.getColumnIndex(COLUMN_ALARM_ID)), is(1));
-        cursor.moveToNext();
-        assertThat(cursor.getString(cursor.getColumnIndex(COLUMN_WORKSPEC_ID)), is(workSpecId2));
-        assertThat(cursor.getInt(cursor.getColumnIndex(COLUMN_ALARM_ID)), is(2));
-        cursor.close();
-
-        assertThat(checkExists(database, TABLE_SYSTEM_ID_INFO), is(false));
-        assertThat(checkExists(database, TABLE_WORKSPEC), is(true));
-        assertThat(checkExists(database, TABLE_WORKTAG), is(true));
-        assertThat(checkExists(database, TABLE_WORKNAME), is(true));
-        database.close();
+        return contentValues;
     }
 
     private boolean checkExists(SupportSQLiteDatabase database, String tableName) {
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplLargeExecutorTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplLargeExecutorTest.java
index 72ebe94..23996eb 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplLargeExecutorTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplLargeExecutorTest.java
@@ -18,6 +18,7 @@
 
 import static androidx.work.worker.CheckLimitsWorker.KEY_EXCEEDS_SCHEDULER_LIMIT;
 import static androidx.work.worker.CheckLimitsWorker.KEY_LIMIT_TO_ENFORCE;
+import static androidx.work.worker.CheckLimitsWorker.KEY_RECURSIVE;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -65,8 +66,7 @@
 @RunWith(AndroidJUnit4.class)
 public class WorkManagerImplLargeExecutorTest {
 
-    private static final int NUM_WORKERS = 500;
-    private static final int TEST_TIMEOUT_SECONDS = 30;
+    private static final int NUM_WORKERS = 200;
 
     // ThreadPoolExecutor parameters.
     private static final int MIN_POOL_SIZE = 0;
@@ -172,7 +172,66 @@
                 });
 
         continuation.enqueue();
-        latch.await(TEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        latch.await(120L, TimeUnit.SECONDS);
+        assertThat(latch.getCount(), is(0L));
+    }
+
+    @Test
+    @LargeTest
+    @SdkSuppress(maxSdkVersion = 22)
+    public void testSchedulerLimitsRecursive() throws InterruptedException {
+        List<OneTimeWorkRequest> workRequests = new ArrayList<>(NUM_WORKERS);
+        final Set<UUID> completed = new HashSet<>(NUM_WORKERS);
+        final int schedulerLimit = mWorkManagerImpl
+                .getConfiguration()
+                .getMaxSchedulerLimit();
+
+        final Data input = new Data.Builder()
+                .putBoolean(KEY_RECURSIVE, true)
+                .putInt(KEY_LIMIT_TO_ENFORCE, schedulerLimit)
+                .build();
+
+        for (int i = 0; i < NUM_WORKERS; i++) {
+            OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(CheckLimitsWorker.class)
+                    .setInputData(input)
+                    .build();
+
+            workRequests.add(request);
+        }
+
+
+        final CountDownLatch latch = new CountDownLatch(NUM_WORKERS * 2); // recursive
+        WorkContinuation continuation = mWorkManagerImpl.beginWith(workRequests);
+
+        // There are more workers being enqueued recursively so use implicit tags.
+        mWorkManagerImpl.getStatusesByTag(CheckLimitsWorker.class.getName())
+                .observe(mLifecycleOwner, new Observer<List<WorkStatus>>() {
+                    @Override
+                    public void onChanged(@Nullable List<WorkStatus> workStatuses) {
+                        if (workStatuses == null || workStatuses.isEmpty()) {
+                            return;
+                        }
+
+                        for (WorkStatus workStatus: workStatuses) {
+                            if (workStatus.getState().isFinished()) {
+
+                                Data output = workStatus.getOutputData();
+
+                                boolean exceededLimits = output.getBoolean(
+                                        KEY_EXCEEDS_SCHEDULER_LIMIT, true);
+
+                                assertThat(exceededLimits, is(false));
+                                if (!completed.contains(workStatus.getId())) {
+                                    completed.add(workStatus.getId());
+                                    latch.countDown();
+                                }
+                            }
+                        }
+                    }
+                });
+
+        continuation.enqueue();
+        latch.await(240L, TimeUnit.SECONDS);
         assertThat(latch.getCount(), is(0L));
     }
 }
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java
index 3e01164..4e1dc8f 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java
@@ -27,6 +27,7 @@
 import static androidx.work.State.FAILED;
 import static androidx.work.State.RUNNING;
 import static androidx.work.State.SUCCEEDED;
+import static androidx.work.impl.model.WorkSpec.SCHEDULE_NOT_REQUESTED_YET;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
@@ -1405,6 +1406,7 @@
         WorkDatabase.generateCleanupCallback().onOpen(db);
 
         assertThat(workSpecDao.getState(work.getStringId()), is(ENQUEUED));
+        assertThat(work.getWorkSpec().scheduleRequestedAt, is(SCHEDULE_NOT_REQUESTED_YET));
     }
 
     @Test
@@ -1508,7 +1510,7 @@
         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getStringId());
         assertThat(workSpec.workerClassName, is(ConstraintTrackingWorker.class.getName()));
         assertThat(workSpec.input.getString(
-                ConstraintTrackingWorker.ARGUMENT_CLASS_NAME, null),
+                ConstraintTrackingWorker.ARGUMENT_CLASS_NAME),
                 is(TestWorker.class.getName()));
     }
 
@@ -1526,7 +1528,7 @@
         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getStringId());
         assertThat(workSpec.workerClassName, is(ConstraintTrackingWorker.class.getName()));
         assertThat(workSpec.input.getString(
-                ConstraintTrackingWorker.ARGUMENT_CLASS_NAME, null),
+                ConstraintTrackingWorker.ARGUMENT_CLASS_NAME),
                 is(TestWorker.class.getName()));
     }
 
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java
index 739fcf7..44e65f8 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java
@@ -31,6 +31,7 @@
 import static org.hamcrest.Matchers.contains;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.greaterThan;
+import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -38,6 +39,7 @@
 
 import android.content.Context;
 import android.net.Uri;
+import android.os.Build;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.LargeTest;
 import android.support.test.filters.SmallTest;
@@ -507,6 +509,7 @@
         insertWork(periodicWork);
         new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, periodicWorkId)
                 .withListener(mMockListener)
+                .withSchedulers(Collections.singletonList(mMockScheduler))
                 .build()
                 .run();
 
@@ -514,6 +517,15 @@
         verify(mMockListener).onExecuted(periodicWorkId, true, false);
         assertThat(periodicWorkSpecAfterFirstRun.runAttemptCount, is(0));
         assertThat(periodicWorkSpecAfterFirstRun.state, is(ENQUEUED));
+        // SystemAlarmScheduler needs to reschedule the same worker.
+        if (Build.VERSION.SDK_INT <= WorkManagerImpl.MAX_PRE_JOB_SCHEDULER_API_LEVEL) {
+            ArgumentCaptor<WorkSpec> captor = ArgumentCaptor.forClass(WorkSpec.class);
+            verify(mMockScheduler, atLeast(1))
+                    .schedule(captor.capture());
+
+            WorkSpec workSpec = captor.getValue();
+            assertThat(workSpec.id, is(periodicWorkId));
+        }
     }
 
     @Test
@@ -563,16 +575,34 @@
     @Test
     @SmallTest
     public void testScheduler() {
-        OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
-        insertWork(work);
-        Scheduler mockScheduler = mock(Scheduler.class);
+        OneTimeWorkRequest prerequisiteWork =
+                new OneTimeWorkRequest.Builder(TestWorker.class).build();
+        OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class)
+                .setInitialState(BLOCKED).build();
+        Dependency dependency = new Dependency(work.getStringId(), prerequisiteWork.getStringId());
 
-        new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
-                .withSchedulers(Collections.singletonList(mockScheduler))
+        mDatabase.beginTransaction();
+        try {
+            insertWork(prerequisiteWork);
+            insertWork(work);
+            mDependencyDao.insertDependency(dependency);
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        new WorkerWrapper.Builder(
+                mContext,
+                mConfiguration,
+                mDatabase,
+                prerequisiteWork.getStringId())
+                .withSchedulers(Collections.singletonList(mMockScheduler))
                 .build()
                 .run();
 
-        verify(mockScheduler).schedule();
+        ArgumentCaptor<WorkSpec> captor = ArgumentCaptor.forClass(WorkSpec.class);
+        verify(mMockScheduler).schedule(captor.capture());
+        assertThat(captor.getValue().id, is(work.getStringId()));
     }
 
     @Test
@@ -603,7 +633,7 @@
                 new Extras(input, Collections.<String>emptyList(), null, 1));
 
         assertThat(worker, is(notNullValue()));
-        assertThat(worker.getInputData().getString(key, null), is(expectedValue));
+        assertThat(worker.getInputData().getString(key), is(expectedValue));
 
         work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
         worker = WorkerWrapper.workerFromWorkSpec(
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/SystemAlarmDispatcherTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/SystemAlarmDispatcherTest.java
index cfe2cef..2944087 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/SystemAlarmDispatcherTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/SystemAlarmDispatcherTest.java
@@ -389,6 +389,7 @@
         // Use a mocked scheduler in this test.
         Scheduler scheduler = mock(Scheduler.class);
         doCallRealMethod().when(mWorkManager).rescheduleEligibleWork();
+        when(mWorkManager.getApplicationContext()).thenReturn(mContext);
         when(mWorkManager.getSchedulers()).thenReturn(Collections.singletonList(scheduler));
 
         OneTimeWorkRequest failed = new OneTimeWorkRequest.Builder(TestWorker.class)
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/WorkTimerTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/WorkTimerTest.java
index 78986c3..700071a 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/WorkTimerTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/WorkTimerTest.java
@@ -49,7 +49,7 @@
     public void testTimer_withListenerAndCleanUp() throws InterruptedException {
         TestTimeLimitExceededListener listenerSpy = spy(mListener);
         mWorkTimer.startTimer(WORKSPEC_ID_1, 0, listenerSpy);
-        Thread.sleep(10); // introduce a small delay
+        Thread.sleep(100); // introduce a small delay
         verify(listenerSpy, times(1)).onTimeLimitExceeded(WORKSPEC_ID_1);
         assertThat(mWorkTimer.getTimerMap().size(), is(0));
         assertThat(mWorkTimer.getListeners().size(), is(0));
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/utils/ForceStopRunnableTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/utils/ForceStopRunnableTest.java
index 323757a..3d6b4c0 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/utils/ForceStopRunnableTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/utils/ForceStopRunnableTest.java
@@ -18,7 +18,6 @@
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -76,37 +75,28 @@
     @Test
     public void testReschedulesOnForceStop() {
         ForceStopRunnable runnable = spy(mRunnable);
-        when(runnable.shouldCancelPersistedJobs()).thenReturn(false);
+        when(runnable.shouldRescheduleWorkers()).thenReturn(false);
         when(runnable.isForceStopped()).thenReturn(true);
         runnable.run();
         verify(mWorkManager, times(1)).rescheduleEligibleWork();
+        verify(mWorkManager, times(1)).onForceStopRunnableCompleted();
     }
 
     @Test
     public void test_doNothingWhenNotForceStopped() {
         ForceStopRunnable runnable = spy(mRunnable);
-        when(runnable.shouldCancelPersistedJobs()).thenReturn(false);
+        when(runnable.shouldRescheduleWorkers()).thenReturn(false);
         when(runnable.isForceStopped()).thenReturn(false);
         runnable.run();
         verify(mWorkManager, times(0)).rescheduleEligibleWork();
+        verify(mWorkManager, times(1)).onForceStopRunnableCompleted();
     }
 
     @Test
-    public void test_cancelAllJobSchedulerJobs() {
+    public void test_rescheduleWorkers_updatesSharedPreferences() {
         ForceStopRunnable runnable = spy(mRunnable);
-        doNothing().when(runnable).cancelAllInJobScheduler();
-        when(runnable.shouldCancelPersistedJobs()).thenReturn(true);
+        when(runnable.shouldRescheduleWorkers()).thenReturn(true);
         runnable.run();
-        verify(runnable, times(1)).cancelAllInJobScheduler();
-        verify(mPreferences, times(1)).setMigratedPersistedJobs();
-    }
-
-    @Test
-    public void test_doNothingWhenThereIsNothingToCancel() {
-        ForceStopRunnable runnable = spy(mRunnable);
-        doNothing().when(runnable).cancelAllInJobScheduler();
-        when(runnable.shouldCancelPersistedJobs()).thenReturn(false);
-        runnable.run();
-        verify(runnable, times(0)).cancelAllInJobScheduler();
+        verify(mPreferences, times(1)).setNeedsReschedule(false);
     }
 }
diff --git a/work/workmanager/src/androidTest/java/androidx/work/worker/CheckLimitsWorker.java b/work/workmanager/src/androidTest/java/androidx/work/worker/CheckLimitsWorker.java
index 1176364..f0fb9a1 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/worker/CheckLimitsWorker.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/worker/CheckLimitsWorker.java
@@ -21,6 +21,7 @@
 import android.support.annotation.NonNull;
 
 import androidx.work.Data;
+import androidx.work.OneTimeWorkRequest;
 import androidx.work.Worker;
 import androidx.work.impl.Scheduler;
 import androidx.work.impl.WorkManagerImpl;
@@ -30,6 +31,7 @@
 
 public class CheckLimitsWorker extends Worker {
     /* The limit to enforce */
+    public static final String KEY_RECURSIVE = "recursive";
     public static final String KEY_LIMIT_TO_ENFORCE = "limit";
 
     /* The output key which tells us if we exceeded the scheduler limits. */
@@ -39,6 +41,7 @@
     @Override
     public Result doWork() {
         Data input = getInputData();
+        boolean isRecursive = input.getBoolean(KEY_RECURSIVE, false);
         int limitToEnforce = input.getInt(KEY_LIMIT_TO_ENFORCE, Scheduler.MAX_SCHEDULER_LIMIT);
         WorkManagerImpl workManager = WorkManagerImpl.getInstance();
         List<WorkSpec> eligibleWorkSpecs = workManager.getWorkDatabase()
@@ -49,8 +52,19 @@
         Data output = new Data.Builder()
                 .putBoolean(KEY_EXCEEDS_SCHEDULER_LIMIT, exceedsLimits)
                 .build();
-
         setOutputData(output);
+        if (isRecursive) {
+            // kick off another Worker, which is not recursive.
+            Data newRequestData = new Data.Builder()
+                    .putAll(getInputData())
+                    .putBoolean(KEY_RECURSIVE, false)
+                    .build();
+
+            OneTimeWorkRequest newRequest = new OneTimeWorkRequest.Builder(CheckLimitsWorker.class)
+                    .setInputData(newRequestData)
+                    .build();
+            workManager.enqueue(newRequest);
+        }
         return SUCCESS;
     }
 }
diff --git a/work/workmanager/src/main/java/androidx/work/Configuration.java b/work/workmanager/src/main/java/androidx/work/Configuration.java
index 77f5ffa9..a74c4b5 100644
--- a/work/workmanager/src/main/java/androidx/work/Configuration.java
+++ b/work/workmanager/src/main/java/androidx/work/Configuration.java
@@ -103,7 +103,7 @@
         }
     }
 
-    private Executor createDefaultExecutor() {
+    private @NonNull Executor createDefaultExecutor() {
         return Executors.newFixedThreadPool(
                 // This value is the same as the core pool size for AsyncTask#THREAD_POOL_EXECUTOR.
                 Math.max(2, Math.min(Runtime.getRuntime().availableProcessors() - 1, 4)));
@@ -125,7 +125,7 @@
          * @param executor An {@link Executor} for processing work
          * @return This {@link Builder} instance
          */
-        public Builder setExecutor(@NonNull Executor executor) {
+        public @NonNull Builder setExecutor(@NonNull Executor executor) {
             mExecutor = executor;
             return this;
         }
@@ -139,7 +139,9 @@
          * @return This {@link Builder} instance
          * @throws IllegalArgumentException when the size of the range is < 1000
          */
-        public Builder setJobSchedulerJobIdRange(int minJobSchedulerId, int maxJobSchedulerId) {
+        public @NonNull Builder setJobSchedulerJobIdRange(
+                int minJobSchedulerId,
+                int maxJobSchedulerId) {
             if ((maxJobSchedulerId - minJobSchedulerId) < 1000) {
                 throw new IllegalArgumentException(
                         "WorkManager needs a range of at least 1000 job ids.");
@@ -167,7 +169,7 @@
          * @throws IllegalArgumentException when the number of jobs <
          *                                  {@link Configuration#MIN_SCHEDULER_LIMIT}
          */
-        public Builder setMaxSchedulerLimit(int maxSchedulerLimit) {
+        public @NonNull Builder setMaxSchedulerLimit(int maxSchedulerLimit) {
             if (maxSchedulerLimit < MIN_SCHEDULER_LIMIT) {
                 throw new IllegalArgumentException(
                         "WorkManager needs to be able to schedule at least 20 jobs in "
@@ -185,7 +187,7 @@
          * @deprecated Use the {@link Configuration.Builder#setExecutor(Executor)} method instead
          */
         @Deprecated
-        public Builder withExecutor(@NonNull Executor executor) {
+        public @NonNull Builder withExecutor(@NonNull Executor executor) {
             mExecutor = executor;
             return this;
         }
@@ -195,7 +197,7 @@
          *
          * @return A {@link Configuration} object with this {@link Builder}'s parameters.
          */
-        public Configuration build() {
+        public @NonNull Configuration build() {
             return new Configuration(this);
         }
     }
diff --git a/work/workmanager/src/main/java/androidx/work/Constraints.java b/work/workmanager/src/main/java/androidx/work/Constraints.java
index d6d6ad6..8b8a740 100644
--- a/work/workmanager/src/main/java/androidx/work/Constraints.java
+++ b/work/workmanager/src/main/java/androidx/work/Constraints.java
@@ -20,6 +20,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
 
 /**
@@ -29,23 +30,24 @@
 
     public static final Constraints NONE = new Constraints.Builder().build();
 
+    // TODO(sumir): Need to make this @NonNull, but that requires a db migration.
     @ColumnInfo(name = "required_network_type")
-    NetworkType mRequiredNetworkType;
+    private NetworkType mRequiredNetworkType;
 
     @ColumnInfo(name = "requires_charging")
-    boolean mRequiresCharging;
+    private boolean mRequiresCharging;
 
     @ColumnInfo(name = "requires_device_idle")
-    boolean mRequiresDeviceIdle;
+    private boolean mRequiresDeviceIdle;
 
     @ColumnInfo(name = "requires_battery_not_low")
-    boolean mRequiresBatteryNotLow;
+    private boolean mRequiresBatteryNotLow;
 
     @ColumnInfo(name = "requires_storage_not_low")
-    boolean mRequiresStorageNotLow;
+    private boolean mRequiresStorageNotLow;
 
     @ColumnInfo(name = "content_uri_triggers")
-    ContentUriTriggers mContentUriTriggers;
+    private @Nullable ContentUriTriggers mContentUriTriggers;
 
     public Constraints() { // stub required for room
     }
@@ -116,12 +118,12 @@
     }
 
     @RequiresApi(24)
-    public void setContentUriTriggers(ContentUriTriggers mContentUriTriggers) {
+    public void setContentUriTriggers(@Nullable ContentUriTriggers mContentUriTriggers) {
         this.mContentUriTriggers = mContentUriTriggers;
     }
 
     @RequiresApi(24)
-    public ContentUriTriggers getContentUriTriggers() {
+    public @Nullable ContentUriTriggers getContentUriTriggers() {
         return mContentUriTriggers;
     }
 
@@ -130,7 +132,7 @@
      */
     @RequiresApi(24)
     public boolean hasContentUriTriggers() {
-        return mContentUriTriggers.size() > 0;
+        return mContentUriTriggers != null && mContentUriTriggers.size() > 0;
     }
 
     @Override
@@ -180,7 +182,7 @@
          * @param requiresCharging true if device must be plugged in, false otherwise
          * @return current builder
          */
-        public Builder setRequiresCharging(boolean requiresCharging) {
+        public @NonNull Builder setRequiresCharging(boolean requiresCharging) {
             this.mRequiresCharging = requiresCharging;
             return this;
         }
@@ -193,7 +195,7 @@
          * @return current builder
          */
         @RequiresApi(23)
-        public Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) {
+        public @NonNull Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) {
             this.mRequiresDeviceIdle = requiresDeviceIdle;
             return this;
         }
@@ -205,7 +207,7 @@
          * @param networkType type of network required
          * @return current builder
          */
-        public Builder setRequiredNetworkType(@NonNull NetworkType networkType) {
+        public @NonNull Builder setRequiredNetworkType(@NonNull NetworkType networkType) {
             this.mRequiredNetworkType = networkType;
             return this;
         }
@@ -218,7 +220,7 @@
          *                              false otherwise
          * @return current builder
          */
-        public Builder setRequiresBatteryNotLow(boolean requiresBatteryNotLow) {
+        public @NonNull Builder setRequiresBatteryNotLow(boolean requiresBatteryNotLow) {
             this.mRequiresBatteryNotLow = requiresBatteryNotLow;
             return this;
         }
@@ -231,7 +233,7 @@
          *                              threshold, false otherwise
          * @return current builder
          */
-        public Builder setRequiresStorageNotLow(boolean requiresStorageNotLow) {
+        public @NonNull Builder setRequiresStorageNotLow(boolean requiresStorageNotLow) {
             this.mRequiresStorageNotLow = requiresStorageNotLow;
             return this;
         }
@@ -246,7 +248,7 @@
          * @return The current {@link Builder}
          */
         @RequiresApi(24)
-        public Builder addContentUriTrigger(Uri uri, boolean triggerForDescendants) {
+        public @NonNull Builder addContentUriTrigger(Uri uri, boolean triggerForDescendants) {
             mContentUriTriggers.add(uri, triggerForDescendants);
             return this;
         }
@@ -256,7 +258,7 @@
          *
          * @return new {@link Constraints} which can be attached to a {@link WorkRequest}
          */
-        public Constraints build() {
+        public @NonNull Constraints build() {
             return new Constraints(this);
         }
     }
diff --git a/work/workmanager/src/main/java/androidx/work/ContentUriTriggers.java b/work/workmanager/src/main/java/androidx/work/ContentUriTriggers.java
index 0702cc0..ca6dd30 100644
--- a/work/workmanager/src/main/java/androidx/work/ContentUriTriggers.java
+++ b/work/workmanager/src/main/java/androidx/work/ContentUriTriggers.java
@@ -27,6 +27,7 @@
  * Stores a set of {@link Trigger}s
  */
 public final class ContentUriTriggers implements Iterable<ContentUriTriggers.Trigger> {
+
     private final Set<Trigger> mTriggers = new HashSet<>();
 
     /**
@@ -35,7 +36,7 @@
      * @param triggerForDescendants {@code true} if any changes in descendants cause this
      *                              {@link WorkRequest} to run
      */
-    public void add(Uri uri, boolean triggerForDescendants) {
+    public void add(@NonNull Uri uri, boolean triggerForDescendants) {
         Trigger trigger = new Trigger(uri, triggerForDescendants);
         mTriggers.add(trigger);
     }
@@ -73,18 +74,15 @@
      */
 
     public static final class Trigger {
-        @NonNull
-        private final Uri mUri;
+        private final @NonNull Uri mUri;
         private final boolean mTriggerForDescendants;
 
-        public Trigger(@NonNull Uri uri,
-                       boolean triggerForDescendants) {
+        Trigger(@NonNull Uri uri, boolean triggerForDescendants) {
             mUri = uri;
             mTriggerForDescendants = triggerForDescendants;
         }
 
-        @NonNull
-        public Uri getUri() {
+        public @NonNull Uri getUri() {
             return mUri;
         }
 
diff --git a/work/workmanager/src/main/java/androidx/work/Data.java b/work/workmanager/src/main/java/androidx/work/Data.java
index 376a00d..b687a36 100644
--- a/work/workmanager/src/main/java/androidx/work/Data.java
+++ b/work/workmanager/src/main/java/androidx/work/Data.java
@@ -18,6 +18,7 @@
 
 import android.arch.persistence.room.TypeConverter;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
 
 import java.io.ByteArrayInputStream;
@@ -60,7 +61,7 @@
      * @param defaultValue The default value to return if the key is not found
      * @return The value specified by the key if it exists; the default value otherwise
      */
-    public boolean getBoolean(String key, boolean defaultValue) {
+    public boolean getBoolean(@NonNull String key, boolean defaultValue) {
         Object value = mValues.get(key);
         if (value instanceof Boolean) {
             return (boolean) value;
@@ -75,7 +76,7 @@
      * @param key The key for the argument
      * @return The value specified by the key if it exists; {@code null} otherwise
      */
-    public boolean[] getBooleanArray(String key) {
+    public @NonNull boolean[] getBooleanArray(@NonNull String key) {
         Object value = mValues.get(key);
         if (value instanceof Boolean[]) {
             Boolean[] array = (Boolean[]) value;
@@ -97,7 +98,7 @@
      * @param defaultValue The default value to return if the key is not found
      * @return The value specified by the key if it exists; the default value otherwise
      */
-    public int getInt(String key, int defaultValue) {
+    public int getInt(@NonNull String key, int defaultValue) {
         Object value = mValues.get(key);
         if (value instanceof Integer) {
             return (int) value;
@@ -112,7 +113,7 @@
      * @param key The key for the argument
      * @return The value specified by the key if it exists; {@code null} otherwise
      */
-    public int[] getIntArray(String key) {
+    public @NonNull int[] getIntArray(@NonNull String key) {
         Object value = mValues.get(key);
         if (value instanceof Integer[]) {
             Integer[] array = (Integer[]) value;
@@ -133,7 +134,7 @@
      * @param defaultValue The default value to return if the key is not found
      * @return The value specified by the key if it exists; the default value otherwise
      */
-    public long getLong(String key, long defaultValue) {
+    public long getLong(@NonNull String key, long defaultValue) {
         Object value = mValues.get(key);
         if (value instanceof Long) {
             return (long) value;
@@ -148,7 +149,7 @@
      * @param key The key for the argument
      * @return The value specified by the key if it exists; {@code null} otherwise
      */
-    public long[] getLongArray(String key) {
+    public @Nullable long[] getLongArray(@NonNull String key) {
         Object value = mValues.get(key);
         if (value instanceof Long[]) {
             Long[] array = (Long[]) value;
@@ -169,7 +170,7 @@
      * @param defaultValue The default value to return if the key is not found
      * @return The value specified by the key if it exists; the default value otherwise
      */
-    public float getFloat(String key, float defaultValue) {
+    public float getFloat(@NonNull String key, float defaultValue) {
         Object value = mValues.get(key);
         if (value instanceof Float) {
             return (float) value;
@@ -184,7 +185,7 @@
      * @param key The key for the argument
      * @return The value specified by the key if it exists; {@code null} otherwise
      */
-    public float[] getFloatArray(String key) {
+    public @Nullable float[] getFloatArray(@NonNull String key) {
         Object value = mValues.get(key);
         if (value instanceof Float[]) {
             Float[] array = (Float[]) value;
@@ -205,7 +206,7 @@
      * @param defaultValue The default value to return if the key is not found
      * @return The value specified by the key if it exists; the default value otherwise
      */
-    public double getDouble(String key, double defaultValue) {
+    public double getDouble(@NonNull String key, double defaultValue) {
         Object value = mValues.get(key);
         if (value instanceof Double) {
             return (double) value;
@@ -220,7 +221,7 @@
      * @param key The key for the argument
      * @return The value specified by the key if it exists; {@code null} otherwise
      */
-    public double[] getDoubleArray(String key) {
+    public @Nullable double[] getDoubleArray(@NonNull String key) {
         Object value = mValues.get(key);
         if (value instanceof Double[]) {
             Double[] array = (Double[]) value;
@@ -238,15 +239,14 @@
      * Get the String value for the given key.
      *
      * @param key The key for the argument
-     * @param defaultValue The default value to return if the key is not found
      * @return The value specified by the key if it exists; the default value otherwise
      */
-    public String getString(String key, String defaultValue) {
+    public @Nullable String getString(@NonNull String key) {
         Object value = mValues.get(key);
         if (value instanceof String) {
             return (String) value;
         } else {
-            return defaultValue;
+            return null;
         }
     }
 
@@ -256,7 +256,7 @@
      * @param key The key for the argument
      * @return The value specified by the key if it exists; {@code null} otherwise
      */
-    public String[] getStringArray(String key) {
+    public @Nullable String[] getStringArray(@NonNull String key) {
         Object value = mValues.get(key);
         if (value instanceof String[]) {
             return (String[]) value;
@@ -271,7 +271,7 @@
      * @return A {@link Map} of key-value pairs for this object; this Map is unmodifiable and should
      * be used for reads only.
      */
-    public Map<String, Object> getKeyValueMap() {
+    public @NonNull Map<String, Object> getKeyValueMap() {
         return Collections.unmodifiableMap(mValues);
     }
 
@@ -292,7 +292,7 @@
      *         {@link #MAX_DATA_BYTES}
      */
     @TypeConverter
-    public static byte[] toByteArray(Data data) throws IllegalStateException {
+    public static @NonNull byte[] toByteArray(@NonNull Data data) throws IllegalStateException {
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         ObjectOutputStream objectOutputStream = null;
         try {
@@ -334,7 +334,7 @@
      * @throws IllegalStateException if bytes is bigger than {@link #MAX_DATA_BYTES}
      */
     @TypeConverter
-    public static Data fromByteArray(byte[] bytes) throws IllegalStateException {
+    public static @NonNull Data fromByteArray(@NonNull byte[] bytes) throws IllegalStateException {
         if (bytes.length > MAX_DATA_BYTES) {
             throw new IllegalStateException(
                     "Data cannot occupy more than " + MAX_DATA_BYTES + "KB when serialized");
@@ -438,7 +438,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putBoolean(String key, boolean value) {
+        public @NonNull Builder putBoolean(@NonNull String key, boolean value) {
             mValues.put(key, value);
             return this;
         }
@@ -450,7 +450,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putBooleanArray(String key, boolean[] value) {
+        public @NonNull Builder putBooleanArray(@NonNull String key, boolean[] value) {
             mValues.put(key, convertPrimitiveBooleanArray(value));
             return this;
         }
@@ -462,7 +462,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putInt(String key, int value) {
+        public @NonNull Builder putInt(@NonNull String key, int value) {
             mValues.put(key, value);
             return this;
         }
@@ -474,7 +474,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putIntArray(String key, int[] value) {
+        public @NonNull Builder putIntArray(@NonNull String key, int[] value) {
             mValues.put(key, convertPrimitiveIntArray(value));
             return this;
         }
@@ -486,7 +486,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putLong(String key, long value) {
+        public @NonNull Builder putLong(@NonNull String key, long value) {
             mValues.put(key, value);
             return this;
         }
@@ -498,7 +498,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putLongArray(String key, long[] value) {
+        public @NonNull Builder putLongArray(@NonNull String key, long[] value) {
             mValues.put(key, convertPrimitiveLongArray(value));
             return this;
         }
@@ -510,7 +510,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putFloat(String key, float value) {
+        public @NonNull Builder putFloat(@NonNull String key, float value) {
             mValues.put(key, value);
             return this;
         }
@@ -522,7 +522,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putFloatArray(String key, float[] value) {
+        public @NonNull Builder putFloatArray(String key, float[] value) {
             mValues.put(key, convertPrimitiveFloatArray(value));
             return this;
         }
@@ -534,7 +534,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putDouble(String key, double value) {
+        public @NonNull Builder putDouble(@NonNull String key, double value) {
             mValues.put(key, value);
             return this;
         }
@@ -546,7 +546,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putDoubleArray(String key, double[] value) {
+        public @NonNull Builder putDoubleArray(@NonNull String key, double[] value) {
             mValues.put(key, convertPrimitiveDoubleArray(value));
             return this;
         }
@@ -558,7 +558,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putString(String key, String value) {
+        public @NonNull Builder putString(@NonNull String key, String value) {
             mValues.put(key, value);
             return this;
         }
@@ -570,7 +570,7 @@
          * @param value The value for this argument
          * @return The {@link Builder}
          */
-        public Builder putStringArray(String key, String[] value) {
+        public @NonNull Builder putStringArray(@NonNull String key, String[] value) {
             mValues.put(key, value);
             return this;
         }
@@ -584,7 +584,7 @@
          * @param data {@link Data} containing key-value pairs to add
          * @return The {@link Builder}
          */
-        public Builder putAll(@NonNull Data data) {
+        public @NonNull Builder putAll(@NonNull Data data) {
             putAll(data.mValues);
             return this;
         }
@@ -597,7 +597,7 @@
          * @param values A {@link Map} of key-value pairs to add
          * @return The {@link Builder}
          */
-        public Builder putAll(Map<String, Object> values) {
+        public @NonNull Builder putAll(@NonNull Map<String, Object> values) {
             for (Map.Entry<String, Object> entry : values.entrySet()) {
                 String key = entry.getKey();
                 Object value = entry.getValue();
@@ -643,7 +643,7 @@
          * @return The {@link Data} object containing all key-value pairs specified by this
          *         {@link Builder}.
          */
-        public Data build() {
+        public @NonNull Data build() {
             return new Data(mValues);
         }
     }
diff --git a/work/workmanager/src/main/java/androidx/work/OneTimeWorkRequest.java b/work/workmanager/src/main/java/androidx/work/OneTimeWorkRequest.java
index 57849be..22778e4 100644
--- a/work/workmanager/src/main/java/androidx/work/OneTimeWorkRequest.java
+++ b/work/workmanager/src/main/java/androidx/work/OneTimeWorkRequest.java
@@ -83,7 +83,7 @@
          * @param timeUnit The units of time for {@code duration}
          * @return The current {@link Builder}
          */
-        public Builder setInitialDelay(long duration, @NonNull TimeUnit timeUnit) {
+        public @NonNull Builder setInitialDelay(long duration, @NonNull TimeUnit timeUnit) {
             mWorkSpec.initialDelay = timeUnit.toMillis(duration);
             return this;
         }
@@ -95,7 +95,7 @@
          * @return The current {@link Builder}
          */
         @RequiresApi(26)
-        public Builder setInitialDelay(Duration duration) {
+        public @NonNull Builder setInitialDelay(@NonNull Duration duration) {
             mWorkSpec.initialDelay = duration.toMillis();
             return this;
         }
@@ -110,14 +110,14 @@
          *                    {@link OneTimeWorkRequest}
          * @return The current {@link Builder}
          */
-        public Builder setInputMerger(@NonNull Class<? extends InputMerger> inputMerger) {
+        public @NonNull Builder setInputMerger(@NonNull Class<? extends InputMerger> inputMerger) {
             mWorkSpec.inputMergerClassName = inputMerger.getName();
             return this;
         }
 
 
         @Override
-        public OneTimeWorkRequest build() {
+        public @NonNull OneTimeWorkRequest build() {
             if (mBackoffCriteriaSet
                     && Build.VERSION.SDK_INT >= 23
                     && mWorkSpec.constraints.requiresDeviceIdle()) {
@@ -128,7 +128,7 @@
         }
 
         @Override
-        Builder getThis() {
+        @NonNull Builder getThis() {
             return this;
         }
     }
diff --git a/work/workmanager/src/main/java/androidx/work/PeriodicWorkRequest.java b/work/workmanager/src/main/java/androidx/work/PeriodicWorkRequest.java
index fe1a387..33f5492 100644
--- a/work/workmanager/src/main/java/androidx/work/PeriodicWorkRequest.java
+++ b/work/workmanager/src/main/java/androidx/work/PeriodicWorkRequest.java
@@ -151,7 +151,7 @@
         }
 
         @Override
-        public PeriodicWorkRequest build() {
+        public @NonNull PeriodicWorkRequest build() {
             if (mBackoffCriteriaSet
                     && Build.VERSION.SDK_INT >= 23
                     && mWorkSpec.constraints.requiresDeviceIdle()) {
@@ -162,7 +162,7 @@
         }
 
         @Override
-        Builder getThis() {
+        @NonNull Builder getThis() {
             return this;
         }
     }
diff --git a/work/workmanager/src/main/java/androidx/work/State.java b/work/workmanager/src/main/java/androidx/work/State.java
index a654456..3541fac 100644
--- a/work/workmanager/src/main/java/androidx/work/State.java
+++ b/work/workmanager/src/main/java/androidx/work/State.java
@@ -17,45 +17,45 @@
 package androidx.work;
 
 /**
- * The current status of a unit of work.
+ * The current state of a unit of work.
  */
 public enum State {
 
     /**
-     * The status for work that is enqueued (hasn't completed and isn't running)
+     * The state for work that is enqueued (hasn't completed and isn't running)
      */
     ENQUEUED,
 
     /**
-     * The status for work that is currently being executed
+     * The state for work that is currently being executed
      */
     RUNNING,
 
     /**
-     * The status for work that has completed successfully
+     * The state for work that has completed successfully
      */
     SUCCEEDED,
 
     /**
-     * The status for work that has completed in a failure state
+     * The state for work that has completed in a failure state
      */
     FAILED,
 
     /**
-     * The status for work that is currently blocked because its prerequisites haven't finished
+     * The state for work that is currently blocked because its prerequisites haven't finished
      * successfully
      */
     BLOCKED,
 
     /**
-     * The status for work that has been cancelled and will not execute
+     * The state for work that has been cancelled and will not execute
      */
     CANCELLED;
 
     /**
      * Returns {@code true} if this State is considered finished.
      *
-     * @return {@code true} for {@link #SUCCEEDED}, {@link #FAILED}, and {@link #CANCELLED} States
+     * @return {@code true} for {@link #SUCCEEDED}, {@link #FAILED}, and {@link #CANCELLED} states
      */
     public boolean isFinished() {
         return (this == SUCCEEDED || this == FAILED || this == CANCELLED);
diff --git a/work/workmanager/src/main/java/androidx/work/SynchronousWorkContinuation.java b/work/workmanager/src/main/java/androidx/work/SynchronousWorkContinuation.java
index 0b27021..3a38ee7 100644
--- a/work/workmanager/src/main/java/androidx/work/SynchronousWorkContinuation.java
+++ b/work/workmanager/src/main/java/androidx/work/SynchronousWorkContinuation.java
@@ -16,6 +16,7 @@
 
 package androidx.work;
 
+import android.support.annotation.NonNull;
 import android.support.annotation.WorkerThread;
 
 import java.util.List;
@@ -41,5 +42,5 @@
      * @return A {@link  List} of {@link WorkStatus}es
      */
     @WorkerThread
-    List<WorkStatus> getStatusesSync();
+    @NonNull List<WorkStatus> getStatusesSync();
 }
diff --git a/work/workmanager/src/main/java/androidx/work/SynchronousWorkManager.java b/work/workmanager/src/main/java/androidx/work/SynchronousWorkManager.java
index 9f633d8..3bb6b4d 100644
--- a/work/workmanager/src/main/java/androidx/work/SynchronousWorkManager.java
+++ b/work/workmanager/src/main/java/androidx/work/SynchronousWorkManager.java
@@ -17,6 +17,7 @@
 package androidx.work;
 
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.WorkerThread;
 
 import java.util.List;
@@ -124,7 +125,8 @@
      * own repository that must be updated or deleted in case someone cancels their work without
      * their prior knowledge.
      *
-     * @return The timestamp in milliseconds when a method that cancelled all work was last invoked
+     * @return The timestamp in milliseconds when a method that cancelled all work was last invoked;
+     *         this timestamp may be {@code 0L} if this never occurred.
      */
     @WorkerThread
     long getLastCancelAllTimeMillisSync();
@@ -148,10 +150,11 @@
      * expected to be called from a background thread.
      *
      * @param id The id of the work
-     * @return A {@link WorkStatus} associated with {@code id}
+     * @return A {@link WorkStatus} associated with {@code id}, or {@code null} if {@code id} is not
+     *         known to WorkManager
      */
     @WorkerThread
-    WorkStatus getStatusByIdSync(@NonNull UUID id);
+    @Nullable WorkStatus getStatusByIdSync(@NonNull UUID id);
 
     /**
      * Gets the {@link WorkStatus} for all work with a given tag in a synchronous fashion.  This
@@ -161,7 +164,7 @@
      * @return A list of {@link WorkStatus} for work tagged with {@code tag}
      */
     @WorkerThread
-    List<WorkStatus> getStatusesByTagSync(@NonNull String tag);
+    @NonNull List<WorkStatus> getStatusesByTagSync(@NonNull String tag);
 
     /**
      * Gets the {@link WorkStatus} for all work for the chain of work with a given unique name in a
@@ -171,5 +174,5 @@
      * @return A list of {@link WorkStatus} for work in the chain named {@code uniqueWorkName}
      */
     @WorkerThread
-    List<WorkStatus> getStatusesForUniqueWorkSync(@NonNull String uniqueWorkName);
+    @NonNull List<WorkStatus> getStatusesForUniqueWorkSync(@NonNull String uniqueWorkName);
 }
diff --git a/work/workmanager/src/main/java/androidx/work/WorkContinuation.java b/work/workmanager/src/main/java/androidx/work/WorkContinuation.java
index 80acc82..5c781b3 100644
--- a/work/workmanager/src/main/java/androidx/work/WorkContinuation.java
+++ b/work/workmanager/src/main/java/androidx/work/WorkContinuation.java
@@ -36,7 +36,7 @@
      * @return A {@link WorkContinuation} that allows for further chaining of dependent
      *         {@link OneTimeWorkRequest}
      */
-    public final WorkContinuation then(@NonNull OneTimeWorkRequest... work) {
+    public final @NonNull WorkContinuation then(@NonNull OneTimeWorkRequest... work) {
         return then(Arrays.asList(work));
     }
 
@@ -48,7 +48,7 @@
      * @return A {@link WorkContinuation} that allows for further chaining of dependent
      *         {@link OneTimeWorkRequest}
      */
-    public abstract WorkContinuation then(@NonNull List<OneTimeWorkRequest> work);
+    public abstract @NonNull WorkContinuation then(@NonNull List<OneTimeWorkRequest> work);
 
     /**
      * Returns a {@link LiveData} list of {@link WorkStatus} that provides information about work,
@@ -57,7 +57,7 @@
      *
      * @return A {@link LiveData} containing a list of {@link WorkStatus}es
      */
-    public abstract LiveData<List<WorkStatus>> getStatuses();
+    public abstract @NonNull LiveData<List<WorkStatus>> getStatuses();
 
     /**
      * Enqueues the instance of {@link WorkContinuation} on the background thread.
@@ -70,7 +70,7 @@
      * @return A {@link SynchronousWorkContinuation} object, which gives access to synchronous
      *         methods
      */
-    public abstract SynchronousWorkContinuation synchronous();
+    public abstract @NonNull SynchronousWorkContinuation synchronous();
 
     /**
      * Combines multiple {@link WorkContinuation}s to allow for complex chaining.
@@ -79,7 +79,7 @@
      *                      return value
      * @return A {@link WorkContinuation} that allows further chaining
      */
-    public static WorkContinuation combine(@NonNull WorkContinuation... continuations) {
+    public static @NonNull WorkContinuation combine(@NonNull WorkContinuation... continuations) {
         return combine(Arrays.asList(continuations));
     }
 
@@ -90,7 +90,7 @@
      *                      return value
      * @return A {@link WorkContinuation} that allows further chaining
      */
-    public static WorkContinuation combine(@NonNull List<WorkContinuation> continuations) {
+    public static @NonNull WorkContinuation combine(@NonNull List<WorkContinuation> continuations) {
         if (continuations.size() < 2) {
             throw new IllegalArgumentException(
                     "WorkContinuation.combine() needs at least 2 continuations.");
@@ -109,7 +109,7 @@
      *                      {@link OneTimeWorkRequest} provided.
      * @return A {@link WorkContinuation} that allows further chaining
      */
-    public static WorkContinuation combine(
+    public static @NonNull WorkContinuation combine(
             @NonNull OneTimeWorkRequest work,
             @NonNull WorkContinuation... continuations) {
         return combine(work, Arrays.asList(continuations));
@@ -125,7 +125,7 @@
      *                      {@link OneTimeWorkRequest} provided.
      * @return A {@link WorkContinuation} that allows further chaining
      */
-    public static WorkContinuation combine(
+    public static @NonNull WorkContinuation combine(
             @NonNull OneTimeWorkRequest work,
             @NonNull List<WorkContinuation> continuations) {
         return continuations.get(0).combineInternal(work, continuations);
@@ -135,7 +135,7 @@
      * @hide
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    protected abstract WorkContinuation combineInternal(
+    protected abstract @NonNull WorkContinuation combineInternal(
             @Nullable OneTimeWorkRequest work,
             @NonNull List<WorkContinuation> continuations);
 }
diff --git a/work/workmanager/src/main/java/androidx/work/WorkManager.java b/work/workmanager/src/main/java/androidx/work/WorkManager.java
index 5960e50..939192a 100644
--- a/work/workmanager/src/main/java/androidx/work/WorkManager.java
+++ b/work/workmanager/src/main/java/androidx/work/WorkManager.java
@@ -121,15 +121,35 @@
     /**
      * Retrieves the {@code default} singleton instance of {@link WorkManager}.
      *
-     * @return The singleton instance of {@link WorkManager}
+     * @return The singleton instance of {@link WorkManager}; this may be {@code null} in unusual
+     *         circumstances where you have disabled automatic initialization and have failed to
+     *         manually call {@link #initialize(Context, Configuration)}.
+     * @throws IllegalStateException If WorkManager is not initialized properly.  This is most
+     *         likely because you disabled the automatic initialization but forgot to manually
+     *         call {@link WorkManager#initialize(Context, Configuration)}.
      */
-    public static WorkManager getInstance() {
-        return WorkManagerImpl.getInstance();
+    public static @NonNull WorkManager getInstance() {
+        WorkManager workManager = WorkManagerImpl.getInstance();
+        if (workManager == null) {
+            throw new IllegalStateException("WorkManager is not initialized properly.  The most "
+                    + "likely cause is that you disabled WorkManagerInitializer in your manifest "
+                    + "but forgot to call WorkManager#initialize in your Application#onCreate or a "
+                    + "ContentProvider.");
+        } else {
+            return workManager;
+        }
     }
 
     /**
-     * Used to do a one-time initialization of the {@link WorkManager} singleton with the default
-     * configuration.
+     * Used to do a one-time initialization of the {@link WorkManager} singleton with a custom
+     * {@link Configuration}.  By default, this method should not be called because WorkManager is
+     * automatically initialized.  To initialize WorkManager yourself, please follow these steps:
+     * <p><ul>
+     * <li>Disable {@code androidx.work.impl.WorkManagerInitializer} in your manifest
+     * <li>In {@code Application#onCreate} or a {@code ContentProvider}, call this method before
+     * calling {@link WorkManager#getInstance()}
+     * </ul></p>
+     * This method has no effect if WorkManager is already initialized.
      *
      * @param context A {@link Context} object for configuration purposes. Internally, this class
      *                will call {@link Context#getApplicationContext()}, so you may safely pass in
@@ -164,7 +184,7 @@
      * @return A {@link WorkContinuation} that allows for further chaining of dependent
      *         {@link OneTimeWorkRequest}
      */
-    public final WorkContinuation beginWith(@NonNull OneTimeWorkRequest...work) {
+    public final @NonNull WorkContinuation beginWith(@NonNull OneTimeWorkRequest...work) {
         return beginWith(Arrays.asList(work));
     }
 
@@ -176,7 +196,7 @@
      * @return A {@link WorkContinuation} that allows for further chaining of dependent
      *         {@link OneTimeWorkRequest}
      */
-    public abstract WorkContinuation beginWith(@NonNull List<OneTimeWorkRequest> work);
+    public abstract @NonNull WorkContinuation beginWith(@NonNull List<OneTimeWorkRequest> work);
 
     /**
      * This method allows you to begin unique chains of work for situations where you only want one
@@ -201,7 +221,7 @@
      *             as a child of all leaf nodes labelled with {@code uniqueWorkName}.
      * @return A {@link WorkContinuation} that allows further chaining
      */
-    public final WorkContinuation beginUniqueWork(
+    public final @NonNull WorkContinuation beginUniqueWork(
             @NonNull String uniqueWorkName,
             @NonNull ExistingWorkPolicy existingWorkPolicy,
             @NonNull OneTimeWorkRequest... work) {
@@ -231,7 +251,7 @@
      *             as a child of all leaf nodes labelled with {@code uniqueWorkName}.
      * @return A {@link WorkContinuation} that allows further chaining
      */
-    public abstract WorkContinuation beginUniqueWork(
+    public abstract @NonNull WorkContinuation beginUniqueWork(
             @NonNull String uniqueWorkName,
             @NonNull ExistingWorkPolicy existingWorkPolicy,
             @NonNull List<OneTimeWorkRequest> work);
@@ -307,17 +327,19 @@
      * must be updated or deleted in case someone cancels their work without their prior knowledge.
      *
      * @return A {@link LiveData} of the timestamp in milliseconds when method that cancelled all
-     *         work was last invoked
+     *         work was last invoked; this timestamp may be {@code 0L} if this never occurred.
      */
-    public abstract LiveData<Long> getLastCancelAllTimeMillis();
+    public abstract @NonNull LiveData<Long> getLastCancelAllTimeMillis();
 
     /**
      * Gets a {@link LiveData} of the {@link WorkStatus} for a given work id.
      *
      * @param id The id of the work
-     * @return A {@link LiveData} of the {@link WorkStatus} associated with {@code id}
+     * @return A {@link LiveData} of the {@link WorkStatus} associated with {@code id}; note that
+     *         this {@link WorkStatus} may be {@code null} if {@code id} is not known to
+     *         WorkManager.
      */
-    public abstract LiveData<WorkStatus> getStatusById(@NonNull UUID id);
+    public abstract @NonNull LiveData<WorkStatus> getStatusById(@NonNull UUID id);
 
     /**
      * Gets a {@link LiveData} of the {@link WorkStatus} for all work for a given tag.
@@ -325,7 +347,7 @@
      * @param tag The tag of the work
      * @return A {@link LiveData} list of {@link WorkStatus} for work tagged with {@code tag}
      */
-    public abstract LiveData<List<WorkStatus>> getStatusesByTag(@NonNull String tag);
+    public abstract @NonNull LiveData<List<WorkStatus>> getStatusesByTag(@NonNull String tag);
 
     /**
      * Gets a {@link LiveData} of the {@link WorkStatus} for all work in a work chain with a given
@@ -335,7 +357,7 @@
      * @return A {@link LiveData} of the {@link WorkStatus} for work in the chain named
      *         {@code uniqueWorkName}
      */
-    public abstract LiveData<List<WorkStatus>> getStatusesForUniqueWork(
+    public abstract @NonNull LiveData<List<WorkStatus>> getStatusesForUniqueWork(
             @NonNull String uniqueWorkName);
 
     /**
@@ -343,7 +365,7 @@
      *
      * @return A {@link SynchronousWorkManager} object, which gives access to synchronous methods
      */
-    public abstract SynchronousWorkManager synchronous();
+    public abstract @NonNull SynchronousWorkManager synchronous();
 
     /**
      * @hide
diff --git a/work/workmanager/src/main/java/androidx/work/WorkRequest.java b/work/workmanager/src/main/java/androidx/work/WorkRequest.java
index cfb72b8..7a9602c 100644
--- a/work/workmanager/src/main/java/androidx/work/WorkRequest.java
+++ b/work/workmanager/src/main/java/androidx/work/WorkRequest.java
@@ -68,7 +68,7 @@
      *
      * @return The identifier for this unit of work
      */
-    public UUID getId() {
+    public @NonNull UUID getId() {
         return mId;
     }
 
@@ -79,7 +79,7 @@
      * @hide
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    public String getStringId() {
+    public @NonNull String getStringId() {
         return mId.toString();
     }
 
@@ -90,7 +90,7 @@
      * @hide
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    public WorkSpec getWorkSpec() {
+    public @NonNull WorkSpec getWorkSpec() {
         return mWorkSpec;
     }
 
@@ -101,7 +101,7 @@
      * @hide
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    public Set<String> getTags() {
+    public @NonNull Set<String> getTags() {
         return mTags;
     }
 
@@ -136,7 +136,7 @@
          * @param timeUnit The {@link TimeUnit} for {@code backoffDelay}
          * @return The current {@link Builder}
          */
-        public B setBackoffCriteria(
+        public @NonNull B setBackoffCriteria(
                 @NonNull BackoffPolicy backoffPolicy,
                 long backoffDelay,
                 @NonNull TimeUnit timeUnit) {
@@ -152,7 +152,7 @@
          * @param constraints The constraints for the work
          * @return The current {@link Builder}
          */
-        public B setConstraints(@NonNull Constraints constraints) {
+        public @NonNull B setConstraints(@NonNull Constraints constraints) {
             mWorkSpec.constraints = constraints;
             return getThis();
         }
@@ -163,7 +163,7 @@
          * @param inputData key/value pairs that will be provided to the {@link Worker} class
          * @return The current {@link Builder}
          */
-        public B setInputData(@NonNull Data inputData) {
+        public @NonNull B setInputData(@NonNull Data inputData) {
             mWorkSpec.input = inputData;
             return getThis();
         }
@@ -175,7 +175,7 @@
          * @param tag A tag for identifying the work in queries.
          * @return The current {@link Builder}
          */
-        public B addTag(@NonNull String tag) {
+        public @NonNull B addTag(@NonNull String tag) {
             mTags.add(tag);
             return getThis();
         }
@@ -196,7 +196,7 @@
          * @param timeUnit The unit of time for {@code duration}
          * @return The current {@link Builder}
          */
-        public B keepResultsForAtLeast(long duration, @NonNull TimeUnit timeUnit) {
+        public @NonNull B keepResultsForAtLeast(long duration, @NonNull TimeUnit timeUnit) {
             mWorkSpec.minimumRetentionDuration = timeUnit.toMillis(duration);
             return getThis();
         }
@@ -216,7 +216,7 @@
          * @return The current {@link Builder}
          */
         @RequiresApi(26)
-        public B keepResultsForAtLeast(@NonNull Duration duration) {
+        public @NonNull B keepResultsForAtLeast(@NonNull Duration duration) {
             mWorkSpec.minimumRetentionDuration = duration.toMillis();
             return getThis();
         }
@@ -226,9 +226,9 @@
          *
          * @return The concrete implementation of the work associated with this builder
          */
-        public abstract W build();
+        public abstract @NonNull W build();
 
-        abstract B getThis();
+        abstract @NonNull B getThis();
 
         /**
          * Set the initial state for this work.  Used in testing only.
@@ -239,7 +239,7 @@
          */
         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
         @VisibleForTesting
-        public B setInitialState(@NonNull State state) {
+        public @NonNull B setInitialState(@NonNull State state) {
             mWorkSpec.state = state;
             return getThis();
         }
@@ -253,7 +253,7 @@
          */
         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
         @VisibleForTesting
-        public B setInitialRunAttemptCount(int runAttemptCount) {
+        public @NonNull B setInitialRunAttemptCount(int runAttemptCount) {
             mWorkSpec.runAttemptCount = runAttemptCount;
             return getThis();
         }
@@ -268,7 +268,7 @@
          */
         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
         @VisibleForTesting
-        public B setPeriodStartTime(long periodStartTime, @NonNull TimeUnit timeUnit) {
+        public @NonNull B setPeriodStartTime(long periodStartTime, @NonNull TimeUnit timeUnit) {
             mWorkSpec.periodStartTime = timeUnit.toMillis(periodStartTime);
             return getThis();
         }
@@ -283,7 +283,7 @@
          */
         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
         @VisibleForTesting
-        public B setScheduleRequestedAt(
+        public @NonNull B setScheduleRequestedAt(
                 long scheduleRequestedAt,
                 @NonNull TimeUnit timeUnit) {
             mWorkSpec.scheduleRequestedAt = timeUnit.toMillis(scheduleRequestedAt);
diff --git a/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java b/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java
index 4944549..041f788 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java
@@ -65,41 +65,38 @@
             @NonNull Configuration configuration,
             @NonNull WorkDatabase workDatabase,
             List<Scheduler> schedulers) {
-
-        WorkSpecDao workSpecDao = workDatabase.workSpecDao();
-        List<WorkSpec> eligibleWorkSpecs =
-                workSpecDao.getEligibleWorkForScheduling(
-                        configuration.getMaxSchedulerLimit());
-        scheduleInternal(workDatabase, schedulers, eligibleWorkSpecs);
-    }
-
-    private static void scheduleInternal(
-            @NonNull WorkDatabase workDatabase,
-            List<Scheduler> schedulers,
-            List<WorkSpec> workSpecs) {
-
-        if (workSpecs == null || schedulers == null) {
+        if (schedulers == null || schedulers.size() == 0) {
             return;
         }
 
-        long now = System.currentTimeMillis();
         WorkSpecDao workSpecDao = workDatabase.workSpecDao();
-        // Mark all the WorkSpecs as scheduled.
-        // Calls to Scheduler#schedule() could potentially result in more schedules
-        // on a separate thread. Therefore, this needs to be done first.
+        List<WorkSpec> eligibleWorkSpecs;
+
         workDatabase.beginTransaction();
         try {
-            for (WorkSpec workSpec : workSpecs) {
-                workSpecDao.markWorkSpecScheduled(workSpec.id, now);
+            eligibleWorkSpecs = workSpecDao.getEligibleWorkForScheduling(
+                    configuration.getMaxSchedulerLimit());
+            if (eligibleWorkSpecs != null && eligibleWorkSpecs.size() > 0) {
+                long now = System.currentTimeMillis();
+
+                // Mark all the WorkSpecs as scheduled.
+                // Calls to Scheduler#schedule() could potentially result in more schedules
+                // on a separate thread. Therefore, this needs to be done first.
+                for (WorkSpec workSpec : eligibleWorkSpecs) {
+                    workSpecDao.markWorkSpecScheduled(workSpec.id, now);
+                }
             }
             workDatabase.setTransactionSuccessful();
         } finally {
             workDatabase.endTransaction();
         }
-        WorkSpec[] eligibleWorkSpecsArray = workSpecs.toArray(new WorkSpec[0]);
-        // Delegate to the underlying scheduler.
-        for (Scheduler scheduler : schedulers) {
-            scheduler.schedule(eligibleWorkSpecsArray);
+
+        if (eligibleWorkSpecs != null && eligibleWorkSpecs.size() > 0) {
+            WorkSpec[] eligibleWorkSpecsArray = eligibleWorkSpecs.toArray(new WorkSpec[0]);
+            // Delegate to the underlying scheduler.
+            for (Scheduler scheduler : schedulers) {
+                scheduler.schedule(eligibleWorkSpecsArray);
+            }
         }
     }
 
diff --git a/work/workmanager/src/main/java/androidx/work/impl/WorkContinuationImpl.java b/work/workmanager/src/main/java/androidx/work/impl/WorkContinuationImpl.java
index 3713dca..6fdc186 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/WorkContinuationImpl.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/WorkContinuationImpl.java
@@ -148,7 +148,7 @@
     }
 
     @Override
-    public WorkContinuation then(List<OneTimeWorkRequest> work) {
+    public @NonNull WorkContinuation then(List<OneTimeWorkRequest> work) {
         // TODO (rahulrav@) We need to decide if we want to allow chaining of continuations after
         // an initial call to enqueue()
         return new WorkContinuationImpl(mWorkManagerImpl,
@@ -159,12 +159,12 @@
     }
 
     @Override
-    public LiveData<List<WorkStatus>> getStatuses() {
+    public @NonNull LiveData<List<WorkStatus>> getStatuses() {
         return mWorkManagerImpl.getStatusesById(mAllIds);
     }
 
     @Override
-    public List<WorkStatus> getStatusesSync() {
+    public @NonNull List<WorkStatus> getStatusesSync() {
         if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
             throw new IllegalStateException("Cannot getStatusesSync on main thread!");
         }
@@ -201,12 +201,12 @@
     }
 
     @Override
-    public SynchronousWorkContinuation synchronous() {
+    public @NonNull SynchronousWorkContinuation synchronous() {
         return this;
     }
 
     @Override
-    protected WorkContinuation combineInternal(
+    protected @NonNull WorkContinuation combineInternal(
             @Nullable OneTimeWorkRequest work,
             @NonNull List<WorkContinuation> continuations) {
 
diff --git a/work/workmanager/src/main/java/androidx/work/impl/WorkDatabase.java b/work/workmanager/src/main/java/androidx/work/impl/WorkDatabase.java
index e5d5f9d..b8bc72c 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/WorkDatabase.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/WorkDatabase.java
@@ -16,6 +16,9 @@
 
 package androidx.work.impl;
 
+import static androidx.work.impl.WorkDatabaseMigrations.MIGRATION_3_4;
+import static androidx.work.impl.WorkDatabaseMigrations.VERSION_2;
+import static androidx.work.impl.WorkDatabaseMigrations.VERSION_3;
 import static androidx.work.impl.model.WorkTypeConverters.StateIds.COMPLETED_STATES;
 import static androidx.work.impl.model.WorkTypeConverters.StateIds.ENQUEUED;
 import static androidx.work.impl.model.WorkTypeConverters.StateIds.RUNNING;
@@ -56,12 +59,14 @@
         WorkTag.class,
         SystemIdInfo.class,
         WorkName.class},
-        version = 2)
+        version = 4)
 @TypeConverters(value = {Data.class, WorkTypeConverters.class})
 public abstract class WorkDatabase extends RoomDatabase {
 
     private static final String DB_NAME = "androidx.work.workdb";
-    private static final String CLEANUP_SQL = "UPDATE workspec SET state=" + ENQUEUED
+    private static final String CLEANUP_SQL = "UPDATE workspec "
+            + "SET state=" + ENQUEUED + ","
+            + " schedule_requested_at=" + WorkSpec.SCHEDULE_NOT_REQUESTED_YET
             + " WHERE state=" + RUNNING;
 
     // Delete rows in the workspec table that...
@@ -82,7 +87,7 @@
     /**
      * Creates an instance of the WorkDatabase.
      *
-     * @param context A context (this method will use the application context from it)
+     * @param context         A context (this method will use the application context from it)
      * @param useTestDatabase {@code true} to generate an in-memory database that allows main thread
      *                        access
      * @return The created WorkDatabase
@@ -95,9 +100,13 @@
         } else {
             builder = Room.databaseBuilder(context, WorkDatabase.class, DB_NAME);
         }
+
         return builder.addCallback(generateCleanupCallback())
                 .addMigrations(WorkDatabaseMigrations.MIGRATION_1_2)
-                .addMigrations(WorkDatabaseMigrations.MIGRATION_2_1)
+                .addMigrations(
+                        new WorkDatabaseMigrations.WorkMigration(context, VERSION_2, VERSION_3))
+                .addMigrations(MIGRATION_3_4)
+                .fallbackToDestructiveMigration()
                 .build();
     }
 
diff --git a/work/workmanager/src/main/java/androidx/work/impl/WorkDatabaseMigrations.java b/work/workmanager/src/main/java/androidx/work/impl/WorkDatabaseMigrations.java
index 82a26ac..d75b514 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/WorkDatabaseMigrations.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/WorkDatabaseMigrations.java
@@ -18,9 +18,15 @@
 
 import android.arch.persistence.db.SupportSQLiteDatabase;
 import android.arch.persistence.room.migration.Migration;
+import android.content.Context;
+import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.annotation.RestrictTo;
 
+import androidx.work.impl.model.WorkSpec;
+import androidx.work.impl.model.WorkTypeConverters;
+import androidx.work.impl.utils.Preferences;
+
 /**
  * Migration helpers for {@link androidx.work.impl.WorkDatabase}.
  *
@@ -34,30 +40,27 @@
     }
 
     // Known WorkDatabase versions
-    private static final int VERSION_1 = 1;
-    private static final int VERSION_2 = 2;
+    public static final int VERSION_1 = 1;
+    public static final int VERSION_2 = 2;
+    public static final int VERSION_3 = 3;
+    public static final int VERSION_4 = 4;
 
     private static final String CREATE_SYSTEM_ID_INFO =
             "CREATE TABLE IF NOT EXISTS `SystemIdInfo` (`work_spec_id` TEXT NOT NULL, `system_id`"
                     + " INTEGER NOT NULL, PRIMARY KEY(`work_spec_id`), FOREIGN KEY(`work_spec_id`)"
                     + " REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )";
 
-    private static final String CREATE_ALARM_INFO =
-            "CREATE TABLE IF NOT EXISTS `alarmInfo` (`work_spec_id` TEXT NOT NULL, `alarm_id`"
-                    + " INTEGER NOT NULL, PRIMARY KEY(`work_spec_id`), FOREIGN KEY"
-                    + "(`work_spec_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE "
-                    + "CASCADE )";
-
     private static final String MIGRATE_ALARM_INFO_TO_SYSTEM_ID_INFO =
             "INSERT INTO SystemIdInfo(work_spec_id, system_id) "
                     + "SELECT work_spec_id, alarm_id AS system_id FROM alarmInfo";
 
-    private static final String MIGRATE_SYSTEM_ID_INFO_TO_ALARM_INFO =
-            "INSERT INTO alarmInfo(work_spec_id, alarm_id) "
-                    + "SELECT work_spec_id, system_id AS alarm_id FROM SystemIdInfo";
+    private static final String PERIODIC_WORK_SET_SCHEDULE_REQUESTED_AT =
+            "UPDATE workspec SET schedule_requested_at=0"
+                    + " WHERE state NOT IN " + WorkTypeConverters.StateIds.COMPLETED_STATES
+                    + " AND schedule_requested_at=" + WorkSpec.SCHEDULE_NOT_REQUESTED_YET
+                    + " AND interval_duration<>0";
 
     private static final String REMOVE_ALARM_INFO = "DROP TABLE IF EXISTS alarmInfo";
-    private static final String REMOVE_SYSTEM_ID_INFO = "DROP TABLE IF EXISTS SystemIdInfo";
 
     /**
      * Removes the {@code alarmInfo} table and substitutes it for a more general
@@ -70,22 +73,39 @@
             database.execSQL(CREATE_SYSTEM_ID_INFO);
             database.execSQL(MIGRATE_ALARM_INFO_TO_SYSTEM_ID_INFO);
             database.execSQL(REMOVE_ALARM_INFO);
-            database.execSQL("INSERT INTO worktag(tag, work_spec_id) "
+            database.execSQL("INSERT OR IGNORE INTO worktag(tag, work_spec_id) "
                     + "SELECT worker_class_name AS tag, id AS work_spec_id FROM workspec");
         }
     };
 
     /**
-     * Removes the {@code alarmInfo} table and substitutes it for a more general
-     * {@code SystemIdInfo} table.
+     * A {@link WorkDatabase} migration that reschedules all eligible Workers.
      */
-    public static Migration MIGRATION_2_1 = new Migration(VERSION_2, VERSION_1) {
+    public static class WorkMigration extends Migration {
+        final Context mContext;
+
+        public WorkMigration(@NonNull Context context, int startVersion, int endVersion) {
+            super(startVersion, endVersion);
+            mContext = context;
+        }
+
         @Override
         public void migrate(@NonNull SupportSQLiteDatabase database) {
-            database.execSQL(CREATE_ALARM_INFO);
-            database.execSQL(MIGRATE_SYSTEM_ID_INFO_TO_ALARM_INFO);
-            database.execSQL(REMOVE_SYSTEM_ID_INFO);
-            // Don't remove implicit tags; they may have been added by the developer.
+            Preferences preferences = new Preferences(mContext);
+            preferences.setNeedsReschedule(true);
+        }
+    }
+
+    /**
+     * Marks {@code SCHEDULE_REQUESTED_AT} to something other than
+     * {@code SCHEDULE_NOT_REQUESTED_AT}.
+     */
+    public static Migration MIGRATION_3_4 = new Migration(VERSION_3, VERSION_4) {
+        @Override
+        public void migrate(@NonNull SupportSQLiteDatabase database) {
+            if (Build.VERSION.SDK_INT >= WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL) {
+                database.execSQL(PERIODIC_WORK_SET_SCHEDULE_REQUESTED_AT);
+            }
         }
     };
 }
diff --git a/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java b/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
index 0dcdda3..763a454 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
@@ -18,7 +18,9 @@
 
 import android.arch.core.util.Function;
 import android.arch.lifecycle.LiveData;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.os.Build;
 import android.os.Looper;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
@@ -37,6 +39,7 @@
 import androidx.work.WorkRequest;
 import androidx.work.WorkStatus;
 import androidx.work.impl.background.greedy.GreedyScheduler;
+import androidx.work.impl.background.systemjob.SystemJobScheduler;
 import androidx.work.impl.model.WorkSpec;
 import androidx.work.impl.model.WorkSpecDao;
 import androidx.work.impl.utils.CancelWorkRunnable;
@@ -72,6 +75,8 @@
     private List<Scheduler> mSchedulers;
     private Processor mProcessor;
     private Preferences mPreferences;
+    private boolean mForceStopRunnableCompleted;
+    private BroadcastReceiver.PendingResult mRescheduleReceiverResult;
 
     private static WorkManagerImpl sDelegatedInstance = null;
     private static WorkManagerImpl sDefaultInstance = null;
@@ -97,7 +102,7 @@
      * @hide
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    public static WorkManagerImpl getInstance() {
+    public static @Nullable WorkManagerImpl getInstance() {
         synchronized (sLock) {
             if (sDelegatedInstance != null) {
                 return sDelegatedInstance;
@@ -172,6 +177,7 @@
                 getSchedulers(),
                 configuration.getExecutor());
         mPreferences = new Preferences(mContext);
+        mForceStopRunnableCompleted = false;
 
         // Checks for app force stops.
         mTaskExecutor.executeOnBackgroundThread(new ForceStopRunnable(context, this));
@@ -265,12 +271,12 @@
     }
 
     @Override
-    public WorkContinuation beginWith(@NonNull List<OneTimeWorkRequest> work) {
+    public @NonNull WorkContinuation beginWith(@NonNull List<OneTimeWorkRequest> work) {
         return new WorkContinuationImpl(this, work);
     }
 
     @Override
-    public WorkContinuation beginUniqueWork(
+    public @NonNull WorkContinuation beginUniqueWork(
             @NonNull String uniqueWorkName,
             @NonNull ExistingWorkPolicy existingWorkPolicy,
             @NonNull List<OneTimeWorkRequest> work) {
@@ -370,7 +376,7 @@
     }
 
     @Override
-    public LiveData<Long> getLastCancelAllTimeMillis() {
+    public @NonNull LiveData<Long> getLastCancelAllTimeMillis() {
         return mPreferences.getLastCancelAllTimeMillisLiveData();
     }
 
@@ -392,7 +398,7 @@
     }
 
     @Override
-    public LiveData<WorkStatus> getStatusById(@NonNull UUID id) {
+    public @NonNull LiveData<WorkStatus> getStatusById(@NonNull UUID id) {
         WorkSpecDao dao = mWorkDatabase.workSpecDao();
         LiveData<List<WorkSpec.WorkStatusPojo>> inputLiveData =
                 dao.getWorkStatusPojoLiveDataForIds(Collections.singletonList(id.toString()));
@@ -423,7 +429,7 @@
     }
 
     @Override
-    public LiveData<List<WorkStatus>> getStatusesByTag(@NonNull String tag) {
+    public @NonNull LiveData<List<WorkStatus>> getStatusesByTag(@NonNull String tag) {
         WorkSpecDao workSpecDao = mWorkDatabase.workSpecDao();
         LiveData<List<WorkSpec.WorkStatusPojo>> inputLiveData =
                 workSpecDao.getWorkStatusPojoLiveDataForTag(tag);
@@ -431,7 +437,7 @@
     }
 
     @Override
-    public List<WorkStatus> getStatusesByTagSync(@NonNull String tag) {
+    public @NonNull List<WorkStatus> getStatusesByTagSync(@NonNull String tag) {
         assertBackgroundThread("Cannot call getStatusesByTagSync on main thread!");
         WorkSpecDao workSpecDao = mWorkDatabase.workSpecDao();
         List<WorkSpec.WorkStatusPojo> input = workSpecDao.getWorkStatusPojoForTag(tag);
@@ -439,7 +445,8 @@
     }
 
     @Override
-    public LiveData<List<WorkStatus>> getStatusesForUniqueWork(@NonNull String uniqueWorkName) {
+    public @NonNull LiveData<List<WorkStatus>> getStatusesForUniqueWork(
+            @NonNull String uniqueWorkName) {
         WorkSpecDao workSpecDao = mWorkDatabase.workSpecDao();
         LiveData<List<WorkSpec.WorkStatusPojo>> inputLiveData =
                 workSpecDao.getWorkStatusPojoLiveDataForName(uniqueWorkName);
@@ -447,7 +454,7 @@
     }
 
     @Override
-    public List<WorkStatus> getStatusesForUniqueWorkSync(@NonNull String uniqueWorkName) {
+    public @NonNull List<WorkStatus> getStatusesForUniqueWorkSync(@NonNull String uniqueWorkName) {
         assertBackgroundThread("Cannot call getStatusesByNameBlocking on main thread!");
         WorkSpecDao workSpecDao = mWorkDatabase.workSpecDao();
         List<WorkSpec.WorkStatusPojo> input = workSpecDao.getWorkStatusPojoForName(uniqueWorkName);
@@ -455,7 +462,7 @@
     }
 
     @Override
-    public SynchronousWorkManager synchronous() {
+    public @NonNull SynchronousWorkManager synchronous() {
         return this;
     }
 
@@ -510,6 +517,11 @@
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public void rescheduleEligibleWork() {
+        // TODO (rahulrav@) Make every scheduler do its own cancelAll().
+        if (Build.VERSION.SDK_INT >= WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL) {
+            SystemJobScheduler.jobSchedulerCancelAll(getApplicationContext());
+        }
+
         // Reset scheduled state.
         getWorkDatabase().workSpecDao().resetScheduledState();
 
@@ -519,6 +531,42 @@
         Schedulers.schedule(getConfiguration(), getWorkDatabase(), getSchedulers());
     }
 
+    /**
+     * A way for {@link ForceStopRunnable} to tell {@link WorkManagerImpl} that it has completed.
+     *
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public void onForceStopRunnableCompleted() {
+        synchronized (sLock) {
+            mForceStopRunnableCompleted = true;
+            if (mRescheduleReceiverResult != null) {
+                mRescheduleReceiverResult.finish();
+                mRescheduleReceiverResult = null;
+            }
+        }
+    }
+
+    /**
+     * This method is invoked by
+     * {@link androidx.work.impl.background.systemalarm.RescheduleReceiver}
+     * after a call to {@link BroadcastReceiver#goAsync()}. Once {@link ForceStopRunnable} is done,
+     * we can safely call {@link BroadcastReceiver.PendingResult#finish()}.
+     *
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public void setReschedulePendingResult(
+            @NonNull BroadcastReceiver.PendingResult rescheduleReceiverResult) {
+        synchronized (sLock) {
+            mRescheduleReceiverResult = rescheduleReceiverResult;
+            if (mForceStopRunnableCompleted) {
+                mRescheduleReceiverResult.finish();
+                mRescheduleReceiverResult = null;
+            }
+        }
+    }
+
     private void assertBackgroundThread(String errorMessage) {
         if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
             throw new IllegalStateException(errorMessage);
diff --git a/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java b/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java
index 0b8c44c..87f922f 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java
@@ -21,8 +21,10 @@
 import static androidx.work.State.FAILED;
 import static androidx.work.State.RUNNING;
 import static androidx.work.State.SUCCEEDED;
+import static androidx.work.impl.model.WorkSpec.SCHEDULE_NOT_REQUESTED_YET;
 
 import android.content.Context;
+import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
@@ -94,18 +96,28 @@
             return;
         }
 
-        mWorkSpec = mWorkSpecDao.getWorkSpec(mWorkSpecId);
-        if (mWorkSpec == null) {
-            Log.e(TAG,  String.format("Didn't find WorkSpec for id %s", mWorkSpecId));
-            notifyListener(false, false);
-            return;
-        }
+        mWorkDatabase.beginTransaction();
+        try {
+            mWorkSpec = mWorkSpecDao.getWorkSpec(mWorkSpecId);
+            if (mWorkSpec == null) {
+                Log.e(TAG, String.format("Didn't find WorkSpec for id %s", mWorkSpecId));
+                notifyListener(false, false);
+                return;
+            }
 
-        // Do a quick check to make sure we don't need to bail out in case this work is already
-        // running, finished, or is blocked.
-        if (mWorkSpec.state != ENQUEUED) {
-            notifyIncorrectStatus();
-            return;
+            // Do a quick check to make sure we don't need to bail out in case this work is already
+            // running, finished, or is blocked.
+            if (mWorkSpec.state != ENQUEUED) {
+                notifyIncorrectStatus();
+                mWorkDatabase.setTransactionSuccessful();
+                return;
+            }
+
+            // Needed for nested transactions, such as when we're in a dependent work request when
+            // using a SynchronousExecutor.
+            mWorkDatabase.setTransactionSuccessful();
+        } finally {
+            mWorkDatabase.endTransaction();
         }
 
         // Merge inputs.  This can be potentially expensive code, so this should not be done inside
@@ -157,6 +169,11 @@
                 result = mWorker.doWork();
             } catch (Exception | Error e) {
                 result = Worker.Result.FAILURE;
+                Log.e(TAG,
+                        String.format(
+                                "Worker %s failed because it threw an exception/error",
+                                mWorkSpecId),
+                        e);
             }
 
             try {
@@ -275,9 +292,9 @@
             if (currentState == ENQUEUED) {
                 mWorkSpecDao.setState(RUNNING, mWorkSpecId);
                 mWorkSpecDao.incrementWorkSpecRunAttemptCount(mWorkSpecId);
-                mWorkDatabase.setTransactionSuccessful();
                 setToRunning = true;
             }
+            mWorkDatabase.setTransactionSuccessful();
         } finally {
             mWorkDatabase.endTransaction();
         }
@@ -339,11 +356,29 @@
             mWorkSpecDao.setPeriodStartTime(mWorkSpecId, nextPeriodStartTime);
             mWorkSpecDao.setState(ENQUEUED, mWorkSpecId);
             mWorkSpecDao.resetWorkSpecRunAttemptCount(mWorkSpecId);
+            if (Build.VERSION.SDK_INT < WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL) {
+                // We only need to reset the schedule_requested_at bit for the AlarmManager
+                // implementation because AlarmManager does not know about periodic WorkRequests.
+                // Otherwise we end up double scheduling the Worker with an identical jobId, and
+                // JobScheduler treats it as the first schedule for a PeriodicWorker. With the
+                // AlarmManager implementation, this is not an problem as AlarmManager only cares
+                // about the actual alarm itself.
+
+                // We need to tell the schedulers that this WorkSpec is no longer occupying a slot.
+                mWorkSpecDao.markWorkSpecScheduled(mWorkSpecId, SCHEDULE_NOT_REQUESTED_YET);
+            }
             mWorkDatabase.setTransactionSuccessful();
         } finally {
             mWorkDatabase.endTransaction();
             notifyListener(isSuccessful, false);
         }
+
+        // We need to tell the Schedulers to pick up this newly ENQUEUED Worker.
+        // TODO (rahulrav@) Move this into the Scheduler itself.
+        if (Build.VERSION.SDK_INT <= WorkManagerImpl.MAX_PRE_JOB_SCHEDULER_API_LEVEL) {
+            // Reschedule the periodic work.
+            Schedulers.schedule(mConfiguration, mWorkDatabase, mSchedulers);
+        }
     }
 
     private void setSucceededAndNotify() {
diff --git a/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java b/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
index a331479..b8adec2 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
@@ -20,15 +20,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
 import android.util.Log;
 
-import androidx.work.WorkManager;
 import androidx.work.impl.WorkManagerImpl;
 
-import java.util.concurrent.TimeUnit;
-
 /**
  * Reschedules alarms on BOOT_COMPLETED and other similar scenarios.
  */
@@ -39,22 +34,15 @@
     @Override
     public void onReceive(Context context, Intent intent) {
         if (Build.VERSION.SDK_INT >= WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL) {
-            if (WorkManager.getInstance() == null) {
+            WorkManagerImpl workManager = WorkManagerImpl.getInstance();
+            if (workManager == null) {
                 // WorkManager has not already been initialized.
                 Log.e(TAG,
                         "Cannot reschedule jobs. WorkManager needs to be initialized via a "
                                 + "ContentProvider#onCreate() or an Application#onCreate().");
             } else {
-                // This helps set up rescheduling of Jobs with JobScheduler. We are doing nothing
-                // for 10 seconds, to give ForceStopRunnable a chance to reschedule.
-                Handler handler = new Handler(Looper.getMainLooper());
                 final PendingResult pendingResult = goAsync();
-                handler.postDelayed(new Runnable() {
-                    @Override
-                    public void run() {
-                        pendingResult.finish();
-                    }
-                }, TimeUnit.SECONDS.toMillis(10));
+                workManager.setReschedulePendingResult(pendingResult);
             }
         } else {
             Intent reschedule = CommandHandler.createRescheduleIntent(context);
diff --git a/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpec.java b/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpec.java
index 6f5120d..52d3090 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpec.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpec.java
@@ -114,6 +114,14 @@
     @ColumnInfo(name = "minimum_retention_duration")
     public long minimumRetentionDuration;
 
+    /**
+     * This field tells us if this {@link WorkSpec} instance, is actually currently scheduled and
+     * being counted against the {@code SCHEDULER_LIMIT}. This bit is reset for PeriodicWorkRequests
+     * in API < 23, because AlarmManager does not know of PeriodicWorkRequests. So for the next
+     * request to be rescheduled this field has to be reset to {@code SCHEDULE_NOT_REQUESTED_AT}.
+     * For the JobScheduler implementation, we don't reset this field because JobScheduler natively
+     * supports PeriodicWorkRequests.
+     */
     @ColumnInfo(name = "schedule_requested_at")
     public long scheduleRequestedAt = SCHEDULE_NOT_REQUESTED_YET;
 
diff --git a/work/workmanager/src/main/java/androidx/work/impl/utils/ForceStopRunnable.java b/work/workmanager/src/main/java/androidx/work/impl/utils/ForceStopRunnable.java
index 87de105..c01e4fd 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/utils/ForceStopRunnable.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/utils/ForceStopRunnable.java
@@ -20,10 +20,8 @@
 import static android.app.PendingIntent.FLAG_NO_CREATE;
 import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
 
-import android.annotation.TargetApi;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
-import android.app.job.JobScheduler;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -34,7 +32,6 @@
 import android.util.Log;
 
 import androidx.work.impl.WorkManagerImpl;
-import androidx.work.impl.background.systemjob.SystemJobScheduler;
 
 import java.util.concurrent.TimeUnit;
 
@@ -67,16 +64,16 @@
 
     @Override
     public void run() {
-        if (shouldCancelPersistedJobs()) {
-            cancelAllInJobScheduler();
-            Log.d(TAG, "Migrating persisted jobs.");
+        if (shouldRescheduleWorkers()) {
+            Log.d(TAG, "Rescheduling Workers.");
             mWorkManager.rescheduleEligibleWork();
             // Mark the jobs as migrated.
-            mWorkManager.getPreferences().setMigratedPersistedJobs();
+            mWorkManager.getPreferences().setNeedsReschedule(false);
         } else if (isForceStopped()) {
             Log.d(TAG, "Application was force-stopped, rescheduling.");
             mWorkManager.rescheduleEligibleWork();
         }
+        mWorkManager.onForceStopRunnableCompleted();
     }
 
     /**
@@ -98,12 +95,11 @@
     }
 
     /**
-     * @return {@code true} If persisted jobs in JobScheduler need to be cancelled.
+     * @return {@code true} If we need to reschedule Workers.
      */
     @VisibleForTesting
-    public boolean shouldCancelPersistedJobs() {
-        return Build.VERSION.SDK_INT >= WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL
-                && mWorkManager.getPreferences().shouldMigratePersistedJobs();
+    public boolean shouldRescheduleWorkers() {
+        return mWorkManager.getPreferences().needsReschedule();
     }
 
     /**
@@ -128,16 +124,7 @@
         return intent;
     }
 
-    /**
-     * Cancels all the persisted jobs in {@link JobScheduler}.
-     */
-    @VisibleForTesting
-    @TargetApi(WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL)
-    public void cancelAllInJobScheduler() {
-        SystemJobScheduler.jobSchedulerCancelAll(mContext);
-    }
-
-    private void setAlarm(int alarmId) {
+    void setAlarm(int alarmId) {
         AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
         // Using FLAG_UPDATE_CURRENT, because we only ever want once instance of this alarm.
         PendingIntent pendingIntent = getPendingIntent(alarmId, FLAG_UPDATE_CURRENT);
diff --git a/work/workmanager/src/main/java/androidx/work/impl/utils/Preferences.java b/work/workmanager/src/main/java/androidx/work/impl/utils/Preferences.java
index 49cd262..d8b9484 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/utils/Preferences.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/utils/Preferences.java
@@ -20,7 +20,9 @@
 import android.arch.lifecycle.MutableLiveData;
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.support.annotation.NonNull;
 import android.support.annotation.RestrictTo;
+import android.support.annotation.VisibleForTesting;
 
 /**
  * Preferences for WorkManager.
@@ -35,13 +37,17 @@
     private static final String PREFERENCES_FILE_NAME = "androidx.work.util.preferences";
 
     private static final String KEY_LAST_CANCEL_ALL_TIME_MS = "last_cancel_all_time_ms";
-    private static final String KEY_MIGRATE_PERSISTED_JOBS = "migrate_persisted_jobs";
+    private static final String KEY_RESCHEDULE_NEEDED = "reschedule_needed";
 
     private SharedPreferences mSharedPreferences;
 
-    public Preferences(Context context) {
-        mSharedPreferences =
-                context.getSharedPreferences(PREFERENCES_FILE_NAME, Context.MODE_PRIVATE);
+    public Preferences(@NonNull Context context) {
+        this(context.getSharedPreferences(PREFERENCES_FILE_NAME, Context.MODE_PRIVATE));
+    }
+
+    @VisibleForTesting
+    public Preferences(@NonNull SharedPreferences preferences) {
+        mSharedPreferences = preferences;
     }
 
     /**
@@ -69,20 +75,19 @@
     }
 
     /**
-     * @return {@code true} When we should migrate from persisted jobs to non-persisted jobs in
-     * {@link android.app.job.JobScheduler}
+     * @return {@code true} When we should reschedule workers.
      */
-    public boolean shouldMigratePersistedJobs() {
+    public boolean needsReschedule() {
+        // This preference is being set by a Room Migration.
         // TODO Remove this before WorkManager 1.0 beta.
-        return mSharedPreferences.getBoolean(KEY_MIGRATE_PERSISTED_JOBS, true);
+        return mSharedPreferences.getBoolean(KEY_RESCHEDULE_NEEDED, false);
     }
 
     /**
-     * Updates the key which indicates that we have migrated all our persisted jobs in
-     * {@link android.app.job.JobScheduler}.
+     * Updates the key which indicates that we have rescheduled jobs.
      */
-    public void setMigratedPersistedJobs() {
-        mSharedPreferences.edit().putBoolean(KEY_MIGRATE_PERSISTED_JOBS, true).apply();
+    public void setNeedsReschedule(boolean needsReschedule) {
+        mSharedPreferences.edit().putBoolean(KEY_RESCHEDULE_NEEDED, needsReschedule).apply();
     }
 
     /**
diff --git a/work/workmanager/src/main/java/androidx/work/impl/workers/ConstraintTrackingWorker.java b/work/workmanager/src/main/java/androidx/work/impl/workers/ConstraintTrackingWorker.java
index 116e96c..e023fed 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/workers/ConstraintTrackingWorker.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/workers/ConstraintTrackingWorker.java
@@ -64,7 +64,7 @@
 
     @Override
     public @NonNull Result doWork() {
-        String className = getInputData().getString(ARGUMENT_CLASS_NAME, null);
+        String className = getInputData().getString(ARGUMENT_CLASS_NAME);
         if (TextUtils.isEmpty(className)) {
             Log.d(TAG, "No worker to delegate to.");
             return Result.FAILURE;
diff --git a/work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/3.json b/work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/3.json
new file mode 100644
index 0000000..69e73eb
--- /dev/null
+++ b/work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/3.json
@@ -0,0 +1,363 @@
+{
+  "formatVersion": 1,
+  "database": {
+    "version": 3,
+    "identityHash": "c45e5fcbdf3824dead9778f19e2fd8af",
+    "entities": [
+      {
+        "tableName": "Dependency",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`work_spec_id` TEXT NOT NULL, `prerequisite_id` TEXT NOT NULL, PRIMARY KEY(`work_spec_id`, `prerequisite_id`), FOREIGN KEY(`work_spec_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE , FOREIGN KEY(`prerequisite_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
+        "fields": [
+          {
+            "fieldPath": "workSpecId",
+            "columnName": "work_spec_id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "prerequisiteId",
+            "columnName": "prerequisite_id",
+            "affinity": "TEXT",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "work_spec_id",
+            "prerequisite_id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [
+          {
+            "name": "index_Dependency_work_spec_id",
+            "unique": false,
+            "columnNames": [
+              "work_spec_id"
+            ],
+            "createSql": "CREATE  INDEX `index_Dependency_work_spec_id` ON `${TABLE_NAME}` (`work_spec_id`)"
+          },
+          {
+            "name": "index_Dependency_prerequisite_id",
+            "unique": false,
+            "columnNames": [
+              "prerequisite_id"
+            ],
+            "createSql": "CREATE  INDEX `index_Dependency_prerequisite_id` ON `${TABLE_NAME}` (`prerequisite_id`)"
+          }
+        ],
+        "foreignKeys": [
+          {
+            "table": "WorkSpec",
+            "onDelete": "CASCADE",
+            "onUpdate": "CASCADE",
+            "columns": [
+              "work_spec_id"
+            ],
+            "referencedColumns": [
+              "id"
+            ]
+          },
+          {
+            "table": "WorkSpec",
+            "onDelete": "CASCADE",
+            "onUpdate": "CASCADE",
+            "columns": [
+              "prerequisite_id"
+            ],
+            "referencedColumns": [
+              "id"
+            ]
+          }
+        ]
+      },
+      {
+        "tableName": "WorkSpec",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `state` INTEGER NOT NULL, `worker_class_name` TEXT NOT NULL, `input_merger_class_name` TEXT, `input` BLOB NOT NULL, `output` BLOB NOT NULL, `initial_delay` INTEGER NOT NULL, `interval_duration` INTEGER NOT NULL, `flex_duration` INTEGER NOT NULL, `run_attempt_count` INTEGER NOT NULL, `backoff_policy` INTEGER NOT NULL, `backoff_delay_duration` INTEGER NOT NULL, `period_start_time` INTEGER NOT NULL, `minimum_retention_duration` INTEGER NOT NULL, `schedule_requested_at` INTEGER NOT NULL, `required_network_type` INTEGER, `requires_charging` INTEGER NOT NULL, `requires_device_idle` INTEGER NOT NULL, `requires_battery_not_low` INTEGER NOT NULL, `requires_storage_not_low` INTEGER NOT NULL, `content_uri_triggers` BLOB, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "state",
+            "columnName": "state",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "workerClassName",
+            "columnName": "worker_class_name",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "inputMergerClassName",
+            "columnName": "input_merger_class_name",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "input",
+            "columnName": "input",
+            "affinity": "BLOB",
+            "notNull": true
+          },
+          {
+            "fieldPath": "output",
+            "columnName": "output",
+            "affinity": "BLOB",
+            "notNull": true
+          },
+          {
+            "fieldPath": "initialDelay",
+            "columnName": "initial_delay",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "intervalDuration",
+            "columnName": "interval_duration",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "flexDuration",
+            "columnName": "flex_duration",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "runAttemptCount",
+            "columnName": "run_attempt_count",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "backoffPolicy",
+            "columnName": "backoff_policy",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "backoffDelayDuration",
+            "columnName": "backoff_delay_duration",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "periodStartTime",
+            "columnName": "period_start_time",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "minimumRetentionDuration",
+            "columnName": "minimum_retention_duration",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "scheduleRequestedAt",
+            "columnName": "schedule_requested_at",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "constraints.mRequiredNetworkType",
+            "columnName": "required_network_type",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "constraints.mRequiresCharging",
+            "columnName": "requires_charging",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "constraints.mRequiresDeviceIdle",
+            "columnName": "requires_device_idle",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "constraints.mRequiresBatteryNotLow",
+            "columnName": "requires_battery_not_low",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "constraints.mRequiresStorageNotLow",
+            "columnName": "requires_storage_not_low",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "constraints.mContentUriTriggers",
+            "columnName": "content_uri_triggers",
+            "affinity": "BLOB",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [
+          {
+            "name": "index_WorkSpec_schedule_requested_at",
+            "unique": false,
+            "columnNames": [
+              "schedule_requested_at"
+            ],
+            "createSql": "CREATE  INDEX `index_WorkSpec_schedule_requested_at` ON `${TABLE_NAME}` (`schedule_requested_at`)"
+          }
+        ],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "WorkTag",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tag` TEXT NOT NULL, `work_spec_id` TEXT NOT NULL, PRIMARY KEY(`tag`, `work_spec_id`), FOREIGN KEY(`work_spec_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
+        "fields": [
+          {
+            "fieldPath": "tag",
+            "columnName": "tag",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "workSpecId",
+            "columnName": "work_spec_id",
+            "affinity": "TEXT",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "tag",
+            "work_spec_id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [
+          {
+            "name": "index_WorkTag_work_spec_id",
+            "unique": false,
+            "columnNames": [
+              "work_spec_id"
+            ],
+            "createSql": "CREATE  INDEX `index_WorkTag_work_spec_id` ON `${TABLE_NAME}` (`work_spec_id`)"
+          }
+        ],
+        "foreignKeys": [
+          {
+            "table": "WorkSpec",
+            "onDelete": "CASCADE",
+            "onUpdate": "CASCADE",
+            "columns": [
+              "work_spec_id"
+            ],
+            "referencedColumns": [
+              "id"
+            ]
+          }
+        ]
+      },
+      {
+        "tableName": "SystemIdInfo",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`work_spec_id` TEXT NOT NULL, `system_id` INTEGER NOT NULL, PRIMARY KEY(`work_spec_id`), FOREIGN KEY(`work_spec_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
+        "fields": [
+          {
+            "fieldPath": "workSpecId",
+            "columnName": "work_spec_id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "systemId",
+            "columnName": "system_id",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "work_spec_id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": [
+          {
+            "table": "WorkSpec",
+            "onDelete": "CASCADE",
+            "onUpdate": "CASCADE",
+            "columns": [
+              "work_spec_id"
+            ],
+            "referencedColumns": [
+              "id"
+            ]
+          }
+        ]
+      },
+      {
+        "tableName": "WorkName",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `work_spec_id` TEXT NOT NULL, PRIMARY KEY(`name`, `work_spec_id`), FOREIGN KEY(`work_spec_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
+        "fields": [
+          {
+            "fieldPath": "name",
+            "columnName": "name",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "workSpecId",
+            "columnName": "work_spec_id",
+            "affinity": "TEXT",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "name",
+            "work_spec_id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [
+          {
+            "name": "index_WorkName_work_spec_id",
+            "unique": false,
+            "columnNames": [
+              "work_spec_id"
+            ],
+            "createSql": "CREATE  INDEX `index_WorkName_work_spec_id` ON `${TABLE_NAME}` (`work_spec_id`)"
+          }
+        ],
+        "foreignKeys": [
+          {
+            "table": "WorkSpec",
+            "onDelete": "CASCADE",
+            "onUpdate": "CASCADE",
+            "columns": [
+              "work_spec_id"
+            ],
+            "referencedColumns": [
+              "id"
+            ]
+          }
+        ]
+      }
+    ],
+    "setupQueries": [
+      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"c45e5fcbdf3824dead9778f19e2fd8af\")"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/4.json b/work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/4.json
new file mode 100644
index 0000000..63c3005
--- /dev/null
+++ b/work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/4.json
@@ -0,0 +1,363 @@
+{
+  "formatVersion": 1,
+  "database": {
+    "version": 4,
+    "identityHash": "c45e5fcbdf3824dead9778f19e2fd8af",
+    "entities": [
+      {
+        "tableName": "Dependency",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`work_spec_id` TEXT NOT NULL, `prerequisite_id` TEXT NOT NULL, PRIMARY KEY(`work_spec_id`, `prerequisite_id`), FOREIGN KEY(`work_spec_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE , FOREIGN KEY(`prerequisite_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
+        "fields": [
+          {
+            "fieldPath": "workSpecId",
+            "columnName": "work_spec_id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "prerequisiteId",
+            "columnName": "prerequisite_id",
+            "affinity": "TEXT",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "work_spec_id",
+            "prerequisite_id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [
+          {
+            "name": "index_Dependency_work_spec_id",
+            "unique": false,
+            "columnNames": [
+              "work_spec_id"
+            ],
+            "createSql": "CREATE  INDEX `index_Dependency_work_spec_id` ON `${TABLE_NAME}` (`work_spec_id`)"
+          },
+          {
+            "name": "index_Dependency_prerequisite_id",
+            "unique": false,
+            "columnNames": [
+              "prerequisite_id"
+            ],
+            "createSql": "CREATE  INDEX `index_Dependency_prerequisite_id` ON `${TABLE_NAME}` (`prerequisite_id`)"
+          }
+        ],
+        "foreignKeys": [
+          {
+            "table": "WorkSpec",
+            "onDelete": "CASCADE",
+            "onUpdate": "CASCADE",
+            "columns": [
+              "work_spec_id"
+            ],
+            "referencedColumns": [
+              "id"
+            ]
+          },
+          {
+            "table": "WorkSpec",
+            "onDelete": "CASCADE",
+            "onUpdate": "CASCADE",
+            "columns": [
+              "prerequisite_id"
+            ],
+            "referencedColumns": [
+              "id"
+            ]
+          }
+        ]
+      },
+      {
+        "tableName": "WorkSpec",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `state` INTEGER NOT NULL, `worker_class_name` TEXT NOT NULL, `input_merger_class_name` TEXT, `input` BLOB NOT NULL, `output` BLOB NOT NULL, `initial_delay` INTEGER NOT NULL, `interval_duration` INTEGER NOT NULL, `flex_duration` INTEGER NOT NULL, `run_attempt_count` INTEGER NOT NULL, `backoff_policy` INTEGER NOT NULL, `backoff_delay_duration` INTEGER NOT NULL, `period_start_time` INTEGER NOT NULL, `minimum_retention_duration` INTEGER NOT NULL, `schedule_requested_at` INTEGER NOT NULL, `required_network_type` INTEGER, `requires_charging` INTEGER NOT NULL, `requires_device_idle` INTEGER NOT NULL, `requires_battery_not_low` INTEGER NOT NULL, `requires_storage_not_low` INTEGER NOT NULL, `content_uri_triggers` BLOB, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "state",
+            "columnName": "state",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "workerClassName",
+            "columnName": "worker_class_name",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "inputMergerClassName",
+            "columnName": "input_merger_class_name",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "input",
+            "columnName": "input",
+            "affinity": "BLOB",
+            "notNull": true
+          },
+          {
+            "fieldPath": "output",
+            "columnName": "output",
+            "affinity": "BLOB",
+            "notNull": true
+          },
+          {
+            "fieldPath": "initialDelay",
+            "columnName": "initial_delay",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "intervalDuration",
+            "columnName": "interval_duration",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "flexDuration",
+            "columnName": "flex_duration",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "runAttemptCount",
+            "columnName": "run_attempt_count",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "backoffPolicy",
+            "columnName": "backoff_policy",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "backoffDelayDuration",
+            "columnName": "backoff_delay_duration",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "periodStartTime",
+            "columnName": "period_start_time",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "minimumRetentionDuration",
+            "columnName": "minimum_retention_duration",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "scheduleRequestedAt",
+            "columnName": "schedule_requested_at",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "constraints.mRequiredNetworkType",
+            "columnName": "required_network_type",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "constraints.mRequiresCharging",
+            "columnName": "requires_charging",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "constraints.mRequiresDeviceIdle",
+            "columnName": "requires_device_idle",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "constraints.mRequiresBatteryNotLow",
+            "columnName": "requires_battery_not_low",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "constraints.mRequiresStorageNotLow",
+            "columnName": "requires_storage_not_low",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "constraints.mContentUriTriggers",
+            "columnName": "content_uri_triggers",
+            "affinity": "BLOB",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [
+          {
+            "name": "index_WorkSpec_schedule_requested_at",
+            "unique": false,
+            "columnNames": [
+              "schedule_requested_at"
+            ],
+            "createSql": "CREATE  INDEX `index_WorkSpec_schedule_requested_at` ON `${TABLE_NAME}` (`schedule_requested_at`)"
+          }
+        ],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "WorkTag",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tag` TEXT NOT NULL, `work_spec_id` TEXT NOT NULL, PRIMARY KEY(`tag`, `work_spec_id`), FOREIGN KEY(`work_spec_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
+        "fields": [
+          {
+            "fieldPath": "tag",
+            "columnName": "tag",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "workSpecId",
+            "columnName": "work_spec_id",
+            "affinity": "TEXT",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "tag",
+            "work_spec_id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [
+          {
+            "name": "index_WorkTag_work_spec_id",
+            "unique": false,
+            "columnNames": [
+              "work_spec_id"
+            ],
+            "createSql": "CREATE  INDEX `index_WorkTag_work_spec_id` ON `${TABLE_NAME}` (`work_spec_id`)"
+          }
+        ],
+        "foreignKeys": [
+          {
+            "table": "WorkSpec",
+            "onDelete": "CASCADE",
+            "onUpdate": "CASCADE",
+            "columns": [
+              "work_spec_id"
+            ],
+            "referencedColumns": [
+              "id"
+            ]
+          }
+        ]
+      },
+      {
+        "tableName": "SystemIdInfo",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`work_spec_id` TEXT NOT NULL, `system_id` INTEGER NOT NULL, PRIMARY KEY(`work_spec_id`), FOREIGN KEY(`work_spec_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
+        "fields": [
+          {
+            "fieldPath": "workSpecId",
+            "columnName": "work_spec_id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "systemId",
+            "columnName": "system_id",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "work_spec_id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": [
+          {
+            "table": "WorkSpec",
+            "onDelete": "CASCADE",
+            "onUpdate": "CASCADE",
+            "columns": [
+              "work_spec_id"
+            ],
+            "referencedColumns": [
+              "id"
+            ]
+          }
+        ]
+      },
+      {
+        "tableName": "WorkName",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `work_spec_id` TEXT NOT NULL, PRIMARY KEY(`name`, `work_spec_id`), FOREIGN KEY(`work_spec_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
+        "fields": [
+          {
+            "fieldPath": "name",
+            "columnName": "name",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "workSpecId",
+            "columnName": "work_spec_id",
+            "affinity": "TEXT",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "name",
+            "work_spec_id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [
+          {
+            "name": "index_WorkName_work_spec_id",
+            "unique": false,
+            "columnNames": [
+              "work_spec_id"
+            ],
+            "createSql": "CREATE  INDEX `index_WorkName_work_spec_id` ON `${TABLE_NAME}` (`work_spec_id`)"
+          }
+        ],
+        "foreignKeys": [
+          {
+            "table": "WorkSpec",
+            "onDelete": "CASCADE",
+            "onUpdate": "CASCADE",
+            "columns": [
+              "work_spec_id"
+            ],
+            "referencedColumns": [
+              "id"
+            ]
+          }
+        ]
+      }
+    ],
+    "setupQueries": [
+      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"c45e5fcbdf3824dead9778f19e2fd8af\")"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/work/workmanager/src/test/java/androidx/work/DataTest.java b/work/workmanager/src/test/java/androidx/work/DataTest.java
index 3573b0a..04b502b 100644
--- a/work/workmanager/src/test/java/androidx/work/DataTest.java
+++ b/work/workmanager/src/test/java/androidx/work/DataTest.java
@@ -19,6 +19,7 @@
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 
 import org.junit.Test;
@@ -125,14 +126,14 @@
         Data data = dataBuilder.build();
         assertThat(data.getInt("int", 0), is(1));
         assertThat(data.getFloat("float", 0f), is(99f));
-        assertThat(data.getString("String", null), is("two"));
+        assertThat(data.getString("String"), is("two"));
         long[] longArray = data.getLongArray("long array");
         assertThat(longArray, is(notNullValue()));
         assertThat(longArray.length, is(3));
         assertThat(longArray[0], is(1L));
         assertThat(longArray[1], is(2L));
         assertThat(longArray[2], is(3L));
-        assertThat(data.getString("null", "dummy"), is("dummy"));
+        assertThat(data.getString("null"), is(nullValue()));
     }
 
     @Test
diff --git a/work/workmanager/src/test/java/androidx/work/OverwritingInputMergerTest.java b/work/workmanager/src/test/java/androidx/work/OverwritingInputMergerTest.java
index 40e703c..b210a6d 100644
--- a/work/workmanager/src/test/java/androidx/work/OverwritingInputMergerTest.java
+++ b/work/workmanager/src/test/java/androidx/work/OverwritingInputMergerTest.java
@@ -42,7 +42,7 @@
         Data output = getOutputFor(input);
 
         assertThat(output.size(), is(1));
-        assertThat(output.getString(key, null), is(value));
+        assertThat(output.getString(key), is(value));
     }
 
     @Test
@@ -67,9 +67,9 @@
         Data output = getOutputFor(input1, input2);
 
         assertThat(output.size(), is(3));
-        assertThat(output.getString(key1, null), is(value1a));
-        assertThat(output.getString(key2, null), is(value2));
-        assertThat(output.getString(key3, null), is(value3));
+        assertThat(output.getString(key1), is(value1a));
+        assertThat(output.getString(key2), is(value2));
+        assertThat(output.getString(key3), is(value3));
     }
 
     private Data getOutputFor(Data... inputs) {