Merge "No functional changes, just an effort to cleanup some code to decrease complexity." into oc-mr1-jetpack-dev
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
index 69b75b4..d6a1399 100644
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -91,6 +91,13 @@
         <option name="DOWHILE_BRACE_FORCE" value="3" />
         <option name="WHILE_BRACE_FORCE" value="3" />
         <option name="FOR_BRACE_FORCE" value="3" />
+        <JetCodeStyleSettings>
+          <option name="PACKAGES_TO_USE_STAR_IMPORTS">
+            <value />
+          </option>
+          <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
+          <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
+        </JetCodeStyleSettings>
         <Objective-C-extensions>
           <file>
             <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
@@ -305,9 +312,14 @@
             </rules>
           </arrangement>
         </codeStyleSettings>
+        <codeStyleSettings language="kotlin">
+          <option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
+          <option name="CALL_PARAMETERS_WRAP" value="1" />
+          <option name="METHOD_PARAMETERS_WRAP" value="5" />
+          <option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
+        </codeStyleSettings>
       </value>
     </option>
     <option name="USE_PER_PROJECT_SETTINGS" value="true" />
-    <option name="PREFERRED_PROJECT_CODE_STYLE" value="AndroidStyle" />
   </component>
 </project>
\ No newline at end of file
diff --git a/OWNERS b/OWNERS
index 049932f..0de3634 100644
--- a/OWNERS
+++ b/OWNERS
@@ -5,6 +5,7 @@
 clarabayarri@google.com
 ilake@google.com
 kirillg@google.com
+kkam@google.com
 mount@google.com
 sergeyv@google.com
 yboyar@google.com
\ No newline at end of file
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index ecc61dd..7a349d5 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,5 +1,6 @@
 [Hook Scripts]
 checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} -c ${REPO_ROOT}/frameworks/support/development/checkstyle/config/support-lib.xml -p development/checkstyle/prebuilt/com.android.support.checkstyle.jar
+ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
 
 [Builtin Hooks]
 commit_msg_changeid_field = true
diff --git a/annotations/src/main/java/android/support/annotation/IntDef.java b/annotations/src/main/java/android/support/annotation/IntDef.java
index f621b7f..9945726 100644
--- a/annotations/src/main/java/android/support/annotation/IntDef.java
+++ b/annotations/src/main/java/android/support/annotation/IntDef.java
@@ -46,12 +46,14 @@
  *      flag = true,
  *      value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
  * </code></pre>
+ *
+ * @see LongDef
  */
 @Retention(SOURCE)
 @Target({ANNOTATION_TYPE})
 public @interface IntDef {
     /** Defines the allowed constants for this element */
-    long[] value() default {};
+    int[] value() default {};
 
     /** Defines whether the constants can be used as a flag, or just as an enum (the default) */
     boolean flag() default false;
diff --git a/annotations/src/main/java/android/support/annotation/LongDef.java b/annotations/src/main/java/android/support/annotation/LongDef.java
new file mode 100644
index 0000000..3dea338
--- /dev/null
+++ b/annotations/src/main/java/android/support/annotation/LongDef.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.support.annotation;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that the annotated long element represents
+ * a logical type and that its value should be one of the explicitly
+ * named constants. If the LongDef#flag() attribute is set to true,
+ * multiple constants can be combined.
+ * <p>
+ * Example:
+ * <pre><code>
+ *  &#64;Retention(SOURCE)
+ *  &#64;LongDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
+ *  public @interface NavigationMode {}
+ *  public static final long NAVIGATION_MODE_STANDARD = 0;
+ *  public static final long NAVIGATION_MODE_LIST = 1;
+ *  public static final long NAVIGATION_MODE_TABS = 2;
+ *  ...
+ *  public abstract void setNavigationMode(@NavigationMode long mode);
+ *  &#64;NavigationMode
+ *  public abstract long getNavigationMode();
+ * </code></pre>
+ * For a flag, set the flag attribute:
+ * <pre><code>
+ *  &#64;LongDef(
+ *      flag = true,
+ *      value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
+ * </code></pre>
+ *
+ * @see IntDef
+ */
+@Retention(SOURCE)
+@Target({ANNOTATION_TYPE})
+public @interface LongDef {
+    /** Defines the allowed constants for this element */
+    long[] value() default {};
+
+    /** Defines whether the constants can be used as a flag, or just as an enum (the default) */
+    boolean flag() default false;
+}
\ No newline at end of file
diff --git a/app-toolkit/common/build.gradle b/app-toolkit/common/build.gradle
index 9604210..bd10317 100644
--- a/app-toolkit/common/build.gradle
+++ b/app-toolkit/common/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension;
@@ -25,12 +26,10 @@
 dependencies {
     compile libs.support.annotations
 
-    testCompile libs.junit
-    testCompile libs.mockito_core
+    testCompile(JUNIT)
+    testCompile(MOCKITO_CORE)
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Arch-Common"
     publish = true
diff --git a/app-toolkit/core-testing/build.gradle b/app-toolkit/core-testing/build.gradle
index adb93e6..dca8810 100644
--- a/app-toolkit/core-testing/build.gradle
+++ b/app-toolkit/core-testing/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -29,21 +30,18 @@
 }
 
 dependencies {
-    api project(":arch:runtime")
+    api(project(":arch:runtime"))
     api libs.support.annotations
-    api libs.junit
-    api libs.mockito_core, { exclude group: 'net.bytebuddy' }
+    api(JUNIT)
+    api(MOCKITO_CORE, libs.exclude_bytebuddy)
 
-    testImplementation libs.junit
-    testImplementation libs.support.annotations
+    testImplementation(JUNIT)
 
-    androidTestImplementation libs.junit
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
+    androidTestImplementation(JUNIT)
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Core-Testing"
     publish = true
diff --git a/app-toolkit/dependencies.gradle b/app-toolkit/dependencies.gradle
index e760149..b794c10 100644
--- a/app-toolkit/dependencies.gradle
+++ b/app-toolkit/dependencies.gradle
@@ -22,33 +22,7 @@
     ffLibs = libs
 }
 def ffVersions = [:]
-ffVersions.kotlin = "1.1.51"
-ffVersions.auto_common = "0.6"
-ffVersions.javapoet = "1.8.0"
-ffVersions.compile_testing = "0.11"
 ffVersions.support_lib = "26.1.0"
-ffVersions.intellij_annotations = "12.0"
-ffVersions.rxjava2 = "2.0.6"
-ffVersions.reactivestreams = "1.0.0"
-// this Xerial version is newer than we want but we need it to fix
-// https://github.com/xerial/sqlite-jdbc/issues/97
-// https://github.com/xerial/sqlite-jdbc/issues/267
-ffVersions.xerial = "3.20.1"
-ffVersions.antlr = "4.5.3"
-ffVersions.commons_codec = "1.10"
-ffVersions.gson = "2.8.0"
-ffVersions.guava = "21.0"
-ffVersions.jsr250 = "1.2"
-
-ffLibs.kotlin = [
-        stdlib : "org.jetbrains.kotlin:kotlin-stdlib:$ffVersions.kotlin",
-]
-ffLibs.auto_common = "com.google.auto:auto-common:$ffVersions.auto_common"
-ffLibs.apache = [
-    commons : [
-            codec : "commons-codec:commons-codec:$ffVersions.commons_codec"
-    ]
-]
 
 def getSupportLib(String name, String version, String artifactName = null) {
     def sourceProject = findProject(name)
@@ -74,17 +48,6 @@
     exclude group: 'android.arch.lifecycle'
 }
 
-ffLibs.javapoet = "com.squareup:javapoet:$ffVersions.javapoet"
-ffLibs.antlr = "org.antlr:antlr4:$ffVersions.antlr"
-ffLibs.xerial = "org.xerial:sqlite-jdbc:$ffVersions.xerial"
-ffLibs.google_compile_testing = "com.google.testing.compile:compile-testing:$ffVersions.compile_testing"
-ffLibs.ij_annotations = "com.intellij:annotations:$ffVersions.intellij_annotations"
-ffLibs.reactive_streams = "org.reactivestreams:reactive-streams:$ffVersions.reactivestreams"
-ffLibs.rx_java = "io.reactivex.rxjava2:rxjava:$ffVersions.rxjava2"
-ffLibs.gson = "com.google.code.gson:gson:$ffVersions.gson"
-ffLibs.guava= "com.google.guava:guava:$ffVersions.guava"
-ffLibs.jsr250 = "javax.annotation:javax.annotation-api:$ffVersions.jsr250"
-
 ext.tools = [:]
 ext.tools.current_sdk = gradle.ext.currentSdk
 ext.tools.build_tools_version = rootProject.ext.buildToolsVersion
diff --git a/app-toolkit/init.gradle b/app-toolkit/init.gradle
index 1d6b752..3e20eaa 100644
--- a/app-toolkit/init.gradle
+++ b/app-toolkit/init.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import android.support.DacOptions
 import android.support.LibraryVersions
 import org.gradle.internal.os.OperatingSystem
 
@@ -67,10 +68,7 @@
 
 if (ext.inAppToolkitProject) {
     // always build offline docs for flatfoot specific builds.
-    ext.docs.dac = [
-            libraryroot: "android/arch",
-            dataname: "ARCH_DATA"
-    ]
+    ext.docsDac = new DacOptions("android/arch", "ARCH_DATA")
     repos.addMavenRepositories(repositories)
     init.setupRepoOutAndBuildNumber()
     init.configureSubProjects()
@@ -110,21 +108,6 @@
                 task.enabled = false
             }
         }
-    } else {
-        def checkApi = project.tasks.create("checkVersion") {
-            doFirst {
-                if (project.version == null
-                        || project.version == LibraryVersions.SUPPORT_LIBRARY.toString()) {
-                    throw new GradleException("bad version for $project with $project.version")
-                }
-            }
-        }
-
-        project.tasks.whenTaskAdded { task ->
-            if (task instanceof Upload) {
-                task.dependsOn checkApi
-            }
-        }
     }
 
     project.tasks.whenTaskAdded { task ->
@@ -136,69 +119,3 @@
         }
     }
 }
-
-def createKotlinCheckstyle(Project project) {
-    def fs = files();
-    if (project.sourceSets.hasProperty('main')) {
-        fs += files(project.sourceSets.main.allJava.srcDirs.collect { fileTree(it) })
-    }
-    if (project.sourceSets.hasProperty('test')) {
-        fs += files(project.sourceSets.test.allJava.srcDirs.collect { fileTree(it) })
-    }
-    if (project.hasProperty('android')) {
-        fs += files(project.android.sourceSets.main.java.getSrcDirs().collect {fileTree(it)})
-        fs += files(project.android.sourceSets.test.java.getSrcDirs().collect {fileTree(it)})
-        fs += files(project.android.sourceSets.androidTest.java.getSrcDirs().collect {fileTree(it)})
-    }
-    fs = fs.filter{file -> file.name.endsWith(".kt")}
-    def kotlinCheckstyle = createCheckstyleTask(project, 'checkstyleKotlin',
-            "${project.rootProject.ext.supportRootFolder}/app-toolkit/kotlin-checkstyle.xml",
-            fs.files)
-
-    project.tasks.findByName("check").dependsOn(kotlinCheckstyle)
-    // poor man's line length check
-    def lineCheck = project.tasks.create(name : "lineLengthCheck") {
-        fs.each { sourceDir ->
-                  fileTree(dir : sourceDir, include : "**/*.kt").each{ file ->
-                      file.readLines().eachWithIndex { line, index ->
-                          if (line.size() > 100) {
-                              project.logger.error("line too long: file: $file" +
-                                      " index:$index line: $line")
-                          }
-                      }
-                  }
-        }
-    }
-    kotlinCheckstyle.dependsOn(lineCheck)
-}
-
-def createAndroidCheckstyle(Project project) {
-    def fs = files()
-    if (project.hasProperty('android')) {
-        fs += files(project.android.sourceSets.main.java.getSrcDirs().collect {fileTree(it)})
-    }
-    if (project.sourceSets.hasProperty('main')) {
-        fs += files(project.sourceSets.main.allJava)
-    }
-    fs = fs.filter{file -> file.name.endsWith(".java")}
-
-    def checkStyle = createCheckstyleTask(project, 'checkstyleAndroid',
-            "${project.rootProject.ext.checkoutRoot}/prebuilts/checkstyle/android-style.xml",
-            fs.files)
-    project.tasks.findByName("check").dependsOn(checkStyle)
-}
-
-def createCheckstyleTask(project, taskName, configFile, inputFiles) {
-    def arguments = ['-c', configFile]
-    arguments.addAll(inputFiles)
-    def checkStyle = project.tasks.create(name : taskName, type: JavaExec) {
-        inputs.files(inputFiles).skipWhenEmpty()
-        main = "com.puppycrawl.tools.checkstyle.Main"
-        args = arguments
-        classpath = files(file("${project.rootProject.ext.checkoutRoot}/prebuilts/checkstyle/checkstyle.jar").path)
-    }
-    return checkStyle;
-}
-
-ext.createKotlinCheckstyle = this.&createKotlinCheckstyle
-ext.createAndroidCheckstyle = this.&createAndroidCheckstyle
diff --git a/app-toolkit/runtime/build.gradle b/app-toolkit/runtime/build.gradle
index 3b46384..83d4293 100644
--- a/app-toolkit/runtime/build.gradle
+++ b/app-toolkit/runtime/build.gradle
@@ -30,11 +30,9 @@
 
 dependencies {
     api libs.support.annotations
-    api project(":arch:common")
+    api(project(":arch:common"))
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Arch-Runtime"
     publish = true
diff --git a/app-toolkit/runtime/lint-baseline.xml b/app-toolkit/runtime/lint-baseline.xml
deleted file mode 100644
index 2cadde1..0000000
--- a/app-toolkit/runtime/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0">
-
-</issues>
diff --git a/app-toolkit/runtime/src/main/java/android/arch/core/executor/ArchTaskExecutor.java b/app-toolkit/runtime/src/main/java/android/arch/core/executor/ArchTaskExecutor.java
index 2401a73..6276ee3 100644
--- a/app-toolkit/runtime/src/main/java/android/arch/core/executor/ArchTaskExecutor.java
+++ b/app-toolkit/runtime/src/main/java/android/arch/core/executor/ArchTaskExecutor.java
@@ -64,6 +64,7 @@
      *
      * @return The singleton ArchTaskExecutor.
      */
+    @NonNull
     public static ArchTaskExecutor getInstance() {
         if (sInstance != null) {
             return sInstance;
diff --git a/app-toolkit/runtime/src/main/java/android/arch/core/executor/TaskExecutor.java b/app-toolkit/runtime/src/main/java/android/arch/core/executor/TaskExecutor.java
index 055b476..7175801 100644
--- a/app-toolkit/runtime/src/main/java/android/arch/core/executor/TaskExecutor.java
+++ b/app-toolkit/runtime/src/main/java/android/arch/core/executor/TaskExecutor.java
@@ -16,6 +16,7 @@
 
 package android.arch.core.executor;
 
+import android.support.annotation.NonNull;
 import android.support.annotation.RestrictTo;
 
 /**
@@ -33,14 +34,14 @@
      *
      * @param runnable The runnable to run in the disk IO thread pool.
      */
-    public abstract void executeOnDiskIO(Runnable runnable);
+    public abstract void executeOnDiskIO(@NonNull Runnable runnable);
 
     /**
      * Posts the given task to the main thread.
      *
      * @param runnable The runnable to run on the main thread.
      */
-    public abstract void postToMainThread(Runnable runnable);
+    public abstract void postToMainThread(@NonNull Runnable runnable);
 
     /**
      * Executes the given task on the main thread.
@@ -49,7 +50,7 @@
      *
      * @param runnable The runnable to run on the main thread.
      */
-    public void executeOnMainThread(Runnable runnable) {
+    public void executeOnMainThread(@NonNull Runnable runnable) {
         if (isMainThread()) {
             runnable.run();
         } else {
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 9c0d8af..718110f 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -12,6 +12,10 @@
         classpath build_libs.kotlin.gradle_plugin
     }
 }
+def runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null
+if (runningInBuildServer) {
+    System.setProperty("kotlin.compiler.execution.strategy", "in-process")
+}
 
 apply from: "build_dependencies.gradle"
 
diff --git a/buildSrc/build_dependencies.gradle b/buildSrc/build_dependencies.gradle
index dc41841..be135b9 100644
--- a/buildSrc/build_dependencies.gradle
+++ b/buildSrc/build_dependencies.gradle
@@ -27,8 +27,8 @@
 
 // jarjar plugin
 build_libs.jarjar_gradle = 'org.anarres.jarjar:jarjar-gradle:1.0.0'
-build_libs.error_prone = 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.10'
+build_libs.error_prone = 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.13'
 build_libs.jacoco = 'org.jacoco:org.jacoco.core:0.7.8'
-build_libs.kotlin = [gradle_plugin: "org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.51"]
+build_libs.kotlin = [gradle_plugin: "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.0"]
 
 rootProject.ext['build_libs'] = build_libs
diff --git a/buildSrc/dependencies.gradle b/buildSrc/dependencies.gradle
index b61cfc6..48d3eb9 100644
--- a/buildSrc/dependencies.gradle
+++ b/buildSrc/dependencies.gradle
@@ -16,14 +16,13 @@
 // Add ext.libs for library versions
 def libs = [:]
 
-// Testing dependencies
-libs.mockito_core = 'org.mockito:mockito-core:2.7.6'
-libs.dexmaker_mockito = 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0'
-libs.junit = 'junit:junit:4.12'
-libs.test_runner = 'com.android.support.test:runner:1.0.1'
-libs.test_rules = 'com.android.support.test:rules:1.0.1'
-libs.espresso_core = 'com.android.support.test.espresso:espresso-core:3.0.1'
-libs.espresso_contrib = 'com.android.support.test.espresso:espresso-contrib:3.0.1'
+libs.exclude_bytebuddy = {
+    exclude group: 'net.bytebuddy'
+}
+
+libs.exclude_support = {
+    exclude group: 'com.android.support'
+}
 
 //arch components
 libs.arch_lifecycle_runtime = "android.arch.lifecycle:runtime:1.0.3@aar"
diff --git a/buildSrc/diff_and_docs.gradle b/buildSrc/diff_and_docs.gradle
deleted file mode 100644
index 2fcc893..0000000
--- a/buildSrc/diff_and_docs.gradle
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import android.support.Version
-import android.support.checkapi.ApiXmlConversionTask
-import android.support.checkapi.CheckApiTask
-import android.support.checkapi.UpdateApiTask
-import android.support.doclava.DoclavaTask
-import android.support.jdiff.JDiffTask
-import com.android.build.gradle.api.LibraryVariant
-import groovy.io.FileType
-import groovy.transform.Field
-import org.gradle.api.tasks.compile.JavaCompile
-
-// Set up platform API files for federation.
-if (project.androidApiTxt != null) {
-    task generateSdkApi(type: Copy) {
-        description = 'Copies the API files for the current SDK.'
-
-        // Export the API files so this looks like a DoclavaTask.
-        ext.apiFile = new File(project.docsDir, 'release/sdk_current.txt')
-        ext.removedApiFile = new File(project.docsDir, 'release/sdk_removed.txt')
-
-        from project.androidApiTxt.absolutePath
-        into apiFile.parent
-        rename { apiFile.name }
-
-        // Register the fake removed file as an output.
-        outputs.file removedApiFile
-
-        doLast {
-            removedApiFile.createNewFile()
-        }
-    }
-} else {
-    task generateSdkApi(type: DoclavaTask, dependsOn: [configurations.doclava]) {
-        description = 'Generates API files for the current SDK.'
-
-        docletpath = configurations.doclava.resolve()
-        destinationDir = project.docsDir
-
-        classpath = project.androidJar
-        source zipTree(project.androidSrcJar)
-
-        apiFile = new File(project.docsDir, 'release/sdk_current.txt')
-        removedApiFile = new File(project.docsDir, 'release/sdk_removed.txt')
-        generateDocs = false
-
-        options {
-            addStringOption "stubpackages", "android.*"
-        }
-    }
-}
-
-// configuration file for setting up api diffs and api docs
-void registerAndroidProjectForDocsTask(Task task, LibraryVariant releaseVariant) {
-    task.dependsOn releaseVariant.javaCompile
-    task.source {
-        // Exclude generated R.java files that don't belong to this project.
-        String packageDir = releaseVariant.getApplicationId().replace('.', '/')
-        return releaseVariant.javaCompile.source.filter { File file ->
-            return !file.name.equals('R.java') || file.parent.endsWith(packageDir)
-        }
-    }
-    task.classpath += releaseVariant.getCompileClasspath(null) +
-            files(releaseVariant.javaCompile.destinationDir)
-}
-
-// configuration file for setting up api diffs and api docs
-void registerJavaProjectForDocsTask(Task task, JavaCompile javaCompileTask) {
-    task.dependsOn javaCompileTask
-    task.source javaCompileTask.source
-    task.classpath += files(javaCompileTask.classpath) +
-            files(javaCompileTask.destinationDir)
-}
-
-// Generates online docs.
-task generateDocs(type: DoclavaTask, dependsOn: [configurations.doclava, generateSdkApi]) {
-    ext.artifacts = []
-    ext.sinces = []
-
-    def offlineDocs = project.docs.offline
-    group = JavaBasePlugin.DOCUMENTATION_GROUP
-    description = 'Generates d.android.com-style documentation. To generate offline docs use ' +
-            '\'-PofflineDocs=true\' parameter.'
-
-    docletpath = configurations.doclava.resolve()
-    destinationDir = new File(project.docsDir, offlineDocs ? "offline" : "online")
-
-    // Base classpath is Android SDK, sub-projects add their own.
-    classpath = project.ext.androidJar
-
-    // Default hidden errors + hidden superclass (111) and
-    // deprecation mismatch (113) to match framework docs.
-    final def hidden = [105, 106, 107, 111, 112, 113, 115, 116, 121]
-
-    doclavaErrors = (101..122) - hidden
-    doclavaWarnings = []
-    doclavaHidden += hidden
-
-    // Track API change history prior to split versioning.
-    def apiFilePattern = /(\d+\.\d+\.\d).txt/
-    File apiDir = new File(supportRootFolder, 'api')
-    apiDir.eachFileMatch FileType.FILES, ~apiFilePattern, { File apiFile ->
-        def apiLevel = (apiFile.name =~ apiFilePattern)[0][1]
-        sinces.add([apiFile.absolutePath, apiLevel])
-    }
-
-    options {
-        addStringOption 'templatedir',
-                "${supportRootFolder}/../../external/doclava/res/assets/templates-sdk"
-        addStringOption 'samplesdir', "${supportRootFolder}/samples"
-        addMultilineMultiValueOption("federate").setValue([
-                ['Android', 'https://developer.android.com']
-        ])
-        addMultilineMultiValueOption("federationapi").setValue([
-                ['Android', generateSdkApi.apiFile.absolutePath]
-        ])
-        addMultilineMultiValueOption("hdf").setValue([
-                ['android.whichdoc', 'online'],
-                ['android.hasSamples', 'true'],
-                ['dac', 'true']
-        ])
-
-        // Specific to reference docs.
-        if (!offlineDocs) {
-            addStringOption "toroot", "/"
-            addBooleanOption "devsite", true
-            addStringOption "dac_libraryroot", project.docs.dac.libraryroot
-            addStringOption "dac_dataname", project.docs.dac.dataname
-        }
-    }
-
-    exclude '**/BuildConfig.java'
-
-    doFirst {
-        if (artifacts.size() > 0) {
-            options.addMultilineMultiValueOption("artifact").setValue(artifacts)
-        }
-        if (sinces.size() > 0) {
-            options.addMultilineMultiValueOption("since").setValue(sinces)
-        }
-    }
-}
-
-// Generates a distribution artifact for online docs.
-task distDocs(type: Zip, dependsOn: generateDocs) {
-    group = JavaBasePlugin.DOCUMENTATION_GROUP
-    description = 'Generates distribution artifact for d.android.com-style documentation.'
-
-    from generateDocs.destinationDir
-    destinationDir project.distDir
-    baseName = "android-support-docs"
-    version = project.buildNumber
-
-    doLast {
-        logger.lifecycle("'Wrote API reference to ${archivePath}")
-    }
-}
-
-@Field def MSG_HIDE_API =
-        "If you are adding APIs that should be excluded from the public API surface,\n" +
-        "consider using package or private visibility. If the API must have public\n" +
-        "visibility, you may exclude it from public API by using the @hide javadoc\n" +
-        "annotation paired with the @RestrictTo(LIBRARY_GROUP) code annotation."
-
-// Check that the API we're building hasn't broken compatibility with the
-// previously released version. These types of changes are forbidden.
-@Field def CHECK_API_CONFIG_RELEASE = [
-    onFailMessage:
-            "Compatibility with previously released public APIs has been broken. Please\n" +
-            "verify your change with Support API Council and provide error output,\n" +
-            "including the error messages and associated SHAs.\n" +
-            "\n" +
-            "If you are removing APIs, they must be deprecated first before being removed\n" +
-            "in a subsequent release.\n" +
-            "\n" + MSG_HIDE_API,
-    errors: (7..18),
-    warnings: [],
-    hidden: (2..6) + (19..30)
-]
-
-// Check that the API we're building hasn't changed from the development
-// version. These types of changes require an explicit API file update.
-@Field def CHECK_API_CONFIG_DEVELOP = [
-    onFailMessage:
-            "Public API definition has changed. Please run ./gradlew updateApi to confirm\n" +
-            "these changes are intentional by updating the public API definition.\n" +
-            "\n" + MSG_HIDE_API,
-    errors: (2..30)-[22],
-    warnings: [],
-    hidden: [22]
-]
-
-// This is a patch or finalized release. Check that the API we're building
-// hasn't changed from the current.
-@Field def CHECK_API_CONFIG_PATCH = [
-        onFailMessage:
-                "Public API definition may not change in finalized or patch releases.\n" +
-                "\n" + MSG_HIDE_API,
-        errors: (2..30)-[22],
-        warnings: [],
-        hidden: [22]
-]
-
-CheckApiTask createCheckApiTask(Project project, String taskName, def checkApiConfig,
-                                File oldApi, File newApi, File whitelist = null) {
-    return project.tasks.create(name: taskName, type: CheckApiTask.class) {
-        doclavaClasspath = project.generateApi.docletpath
-
-        onFailMessage = checkApiConfig.onFailMessage
-        checkApiErrors = checkApiConfig.errors
-        checkApiWarnings = checkApiConfig.warnings
-        checkApiHidden = checkApiConfig.hidden
-
-        newApiFile = newApi
-        oldApiFile = oldApi
-
-        whitelistErrorsFile = whitelist
-
-        doFirst {
-            logger.lifecycle "Verifying ${newApi.name} against ${oldApi ? oldApi.name : "nothing"}..."
-        }
-    }
-}
-
-DoclavaTask createGenerateApiTask(Project project) {
-    // Generates API files
-    return project.tasks.create(name: "generateApi", type: DoclavaTask.class,
-            dependsOn: configurations.doclava) {
-        docletpath = configurations.doclava.resolve()
-        destinationDir = project.docsDir
-
-        // Base classpath is Android SDK, sub-projects add their own.
-        classpath = rootProject.ext.androidJar
-        apiFile = new File(project.docsDir, 'release/' + project.name + '/current.txt')
-        generateDocs = false
-
-        options {
-            addBooleanOption "stubsourceonly", true
-        }
-        exclude '**/BuildConfig.java'
-        exclude '**/R.java'
-    }
-}
-
-/**
- * Returns the API file for the specified reference version.
- *
- * @param refApi the reference API version, ex. 25.0.0-SNAPSHOT
- * @return the most recently released API file
- */
-File getApiFile(File rootDir, Version refVersion, boolean forceRelease = false) {
-    File apiDir = new File(rootDir, 'api')
-
-    if (!refVersion.isSnapshot() || forceRelease) {
-        // Release API file is always X.Y.0.txt.
-        return new File(apiDir, "$refVersion.major.$refVersion.minor.0.txt")
-    }
-
-    // Non-release API file is always current.txt.
-    return new File(apiDir, 'current.txt')
-}
-
-File getLastReleasedApiFile(File rootFolder, String refApi) {
-    Version refVersion = new Version(refApi)
-    File apiDir = new File(rootFolder, 'api')
-
-    File lastFile = null
-    Version lastVersion = null
-
-    // Only look at released versions and snapshots thereof, ex. X.Y.0.txt.
-    apiDir.eachFileMatch FileType.FILES, ~/(\d+)\.(\d+)\.0\.txt/, { File file ->
-        Version version = new Version(stripExtension(file.name))
-        if ((lastFile == null || lastVersion < version) && version < refVersion) {
-            lastFile = file
-            lastVersion = version
-        }
-    }
-
-    return lastFile
-}
-
-boolean hasApiFolder(Project project) {
-    new File(project.projectDir, "api").exists()
-}
-
-String stripExtension(String fileName) {
-    return fileName[0..fileName.lastIndexOf('.') - 1]
-}
-
-void initializeApiChecksForProject(Project project) {
-    if (!project.hasProperty("docsDir")) {
-        project.ext.docsDir = new File(rootProject.docsDir, project.name)
-    }
-    def artifact = project.group + ":" + project.name + ":" + project.version
-    def version = new Version(project.version)
-    def workingDir = project.projectDir
-
-    DoclavaTask generateApi = createGenerateApiTask(project)
-    createVerifyUpdateApiAllowedTask(project)
-
-    // Make sure the API surface has not broken since the last release.
-    File lastReleasedApiFile = getLastReleasedApiFile(workingDir, project.version)
-
-    def whitelistFile = lastReleasedApiFile == null ? null : new File(
-            lastReleasedApiFile.parentFile, stripExtension(lastReleasedApiFile.name) + ".ignore")
-    def checkApiRelease = createCheckApiTask(project, "checkApiRelease", CHECK_API_CONFIG_RELEASE,
-            lastReleasedApiFile, generateApi.apiFile, whitelistFile).dependsOn(generateApi)
-
-    // Allow a comma-delimited list of whitelisted errors.
-    if (project.hasProperty("ignore")) {
-        checkApiRelease.whitelistErrors = ignore.split(',')
-    }
-
-    // Check whether the development API surface has changed.
-    def verifyConfig = version.isPatch() ? CHECK_API_CONFIG_PATCH : CHECK_API_CONFIG_DEVELOP
-    File currentApiFile = getApiFile(workingDir, new Version(project.version))
-    def checkApi = createCheckApiTask(project, "checkApi", verifyConfig,
-            currentApiFile, project.generateApi.apiFile)
-            .dependsOn(generateApi, checkApiRelease)
-
-    checkApi.group JavaBasePlugin.VERIFICATION_GROUP
-    checkApi.description 'Verify the API surface.'
-
-    createUpdateApiTask(project)
-    createNewApiXmlTask(project)
-    createOldApiXml(project)
-    createGenerateDiffsTask(project)
-
-    // Track API change history.
-    def apiFilePattern = /(\d+\.\d+\.\d).txt/
-    File apiDir = new File(project.projectDir, 'api')
-    apiDir.eachFileMatch FileType.FILES, ~apiFilePattern, { File apiFile ->
-        def apiLevel = (apiFile.name =~ apiFilePattern)[0][1]
-        rootProject.generateDocs.sinces.add([apiFile.absolutePath, apiLevel])
-    }
-
-    // Associate current API surface with the Maven artifact.
-    rootProject.generateDocs.artifacts.add([generateApi.apiFile.absolutePath, artifact])
-    rootProject.generateDocs.dependsOn generateApi
-
-    rootProject.createArchive.dependsOn checkApi
-}
-
-Task createVerifyUpdateApiAllowedTask(Project project) {
-    project.tasks.create(name: "verifyUpdateApiAllowed") {
-        // This could be moved to doFirst inside updateApi, but using it as a
-        // dependency with no inputs forces it to run even when updateApi is a
-        // no-op.
-        doLast {
-            def rootFolder = project.projectDir
-            Version version = new Version(project.version)
-
-            if (version.isPatch()) {
-                throw new GradleException("Public APIs may not be modified in patch releases.")
-            } else if (version.isSnapshot() && getApiFile(rootFolder, version, true).exists()) {
-                throw new GradleException("Inconsistent version. Public API file already exists.")
-            } else if (!version.isSnapshot() && getApiFile(rootFolder, version).exists()
-                    && !project.hasProperty("force")) {
-                throw new GradleException("Public APIs may not be modified in finalized releases.")
-            }
-        }
-    }
-}
-
-UpdateApiTask createUpdateApiTask(Project project) {
-    project.tasks.create(name: "updateApi", type: UpdateApiTask,
-            dependsOn: [project.checkApiRelease, project.verifyUpdateApiAllowed]) {
-        group JavaBasePlugin.VERIFICATION_GROUP
-        description 'Updates the candidate API file to incorporate valid changes.'
-        newApiFile = project.checkApiRelease.newApiFile
-        oldApiFile = getApiFile(project.projectDir, new Version(project.version))
-        whitelistErrors = project.checkApiRelease.whitelistErrors
-        whitelistErrorsFile = project.checkApiRelease.whitelistErrorsFile
-
-        doFirst {
-            // Replace the expected whitelist with the detected whitelist.
-            whitelistErrors = project.checkApiRelease.detectedWhitelistErrors
-        }
-    }
-}
-
-/**
- * Converts the <code>toApi</code>.txt file (or current.txt if not explicitly
- * defined using -PtoApi=<file>) to XML format for use by JDiff.
- */
-ApiXmlConversionTask createNewApiXmlTask(Project project) {
-    project.tasks.create(name: "newApiXml", type: ApiXmlConversionTask, dependsOn: configurations.doclava) {
-        classpath configurations.doclava.resolve()
-
-        if (project.hasProperty("toApi")) {
-            // Use an explicit API file.
-            inputApiFile = new File(project.projectDir, "api/${toApi}.txt")
-        } else {
-            // Use the current API file (e.g. current.txt).
-            inputApiFile = project.generateApi.apiFile
-            dependsOn project.generateApi
-        }
-
-        outputApiXmlFile = new File(project.docsDir,
-                "release/" + stripExtension(inputApiFile.name) + ".xml")
-    }
-}
-
-/**
- * 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.
- */
-ApiXmlConversionTask createOldApiXml(Project project) {
-    project.tasks.create(name: "oldApiXml", type: ApiXmlConversionTask, dependsOn: configurations.doclava) {
-        classpath configurations.doclava.resolve()
-
-        def rootFolder = project.projectDir
-        if (project.hasProperty("fromApi")) {
-            // Use an explicit API file.
-            inputApiFile = new File(rootFolder, "api/${fromApi}.txt")
-        } else if (project.hasProperty("toApi") && toApi.matches(~/(\d+\.){2}\d+/)) {
-            // If toApi matches released API (X.Y.Z) format, use the most recently
-            // released API file prior to toApi.
-            inputApiFile = getLastReleasedApiFile(rootFolder, toApi)
-        } else {
-            // Use the most recently released API file.
-            inputApiFile = getApiFile(rootFolder, new Version(project.version))
-        }
-
-        outputApiXmlFile = new File(project.docsDir,
-                "release/" + stripExtension(inputApiFile.name) + ".xml")
-    }
-}
-
-/**
- * Generates API diffs.
- * <p>
- * By default, diffs are generated for the delta between current.txt and the
- * next most recent X.Y.Z.txt API file. Behavior may be changed by specifying
- * one or both of -PtoApi and -PfromApi.
- * <p>
- * If both fromApi and toApi are specified, diffs will be generated for
- * fromApi -> toApi. For example, 25.0.0 -> 26.0.0 diffs could be generated by
- * using:
- * <br><code>
- *   ./gradlew generateDiffs -PfromApi=25.0.0 -PtoApi=26.0.0
- * </code>
- * <p>
- * If only toApi is specified, it MUST be specified as X.Y.Z and diffs will be
- * generated for (release before toApi) -> toApi. For example, 24.2.0 -> 25.0.0
- * diffs could be generated by using:
- * <br><code>
- *   ./gradlew generateDiffs -PtoApi=25.0.0
- * </code>
- * <p>
- * If only fromApi is specified, diffs will be generated for fromApi -> current.
- * For example, lastApiReview -> current diffs could be generated by using:
- * <br><code>
- *   ./gradlew generateDiffs -PfromApi=lastApiReview
- * </code>
- * <p>
- */
-JDiffTask createGenerateDiffsTask(Project project) {
-    project.tasks.create(name: "generateDiffs", type: JDiffTask,
-            dependsOn: [configurations.jdiff, configurations.doclava,
-                        project.oldApiXml, project.newApiXml, rootProject.generateDocs]) {
-        // Base classpath is Android SDK, sub-projects add their own.
-        classpath = rootProject.ext.androidJar
-
-        // JDiff properties.
-        oldApiXmlFile = project.oldApiXml.outputApiXmlFile
-        newApiXmlFile = project.newApiXml.outputApiXmlFile
-
-        String newApi = newApiXmlFile.name
-        int lastDot = newApi.lastIndexOf('.')
-        newApi = newApi.substring(0, lastDot)
-
-        if (project == rootProject) {
-            newJavadocPrefix = "../../../../reference/"
-            destinationDir = new File(rootProject.docsDir, "online/sdk/support_api_diff/$newApi")
-        } else {
-            newJavadocPrefix = "../../../../../reference/"
-            destinationDir = new File(rootProject.docsDir,
-                    "online/sdk/support_api_diff/$project.name/$newApi")
-        }
-
-        // Javadoc properties.
-        docletpath = configurations.jdiff.resolve()
-        title = "Support&nbsp;Library&nbsp;API&nbsp;Differences&nbsp;Report"
-
-        exclude '**/BuildConfig.java'
-        exclude '**/R.java'
-    }
-}
-
-boolean hasJavaSources(releaseVariant) {
-    def fs = releaseVariant.javaCompile.source.filter { file ->
-        file.name != "R.java" && file.name != "BuildConfig.java"
-    }
-    return !fs.isEmpty();
-}
-
-subprojects { subProject ->
-    subProject.afterEvaluate { project ->
-        if (project.hasProperty("noDocs") && project.noDocs) {
-            logger.warn("Project $project.name specified noDocs, ignoring API tasks.")
-            return
-        }
-        if (project.hasProperty("supportLibrary") && !project.supportLibrary.publish) {
-            logger.warn("Project $project.name is not published, ignoring API tasks.")
-            return
-        }
-        if (project.hasProperty('android') && project.android.hasProperty('libraryVariants')) {
-            project.android.libraryVariants.all { variant ->
-                if (variant.name == 'release') {
-                    registerAndroidProjectForDocsTask(rootProject.generateDocs, variant)
-                    if (!hasJavaSources(variant)) {
-                        return
-                    }
-                    if (!hasApiFolder(project)) {
-                        logger.warn("Project $project.name doesn't have an api folder, " +
-                                "ignoring API tasks.")
-                        return
-                    }
-                    initializeApiChecksForProject(project)
-                    registerAndroidProjectForDocsTask(project.generateApi, variant)
-                    registerAndroidProjectForDocsTask(project.generateDiffs, variant)
-                }
-            }
-        } else if (project.hasProperty("compileJava")) {
-            registerJavaProjectForDocsTask(rootProject.generateDocs, project.compileJava)
-            if (!hasApiFolder(project)) {
-                logger.warn("Project $project.name doesn't have an api folder, " +
-                        "ignoring API tasks.")
-                return
-            }
-            project.afterEvaluate {
-                initializeApiChecksForProject(project)
-                registerJavaProjectForDocsTask(project.generateApi, project.compileJava)
-                registerJavaProjectForDocsTask(project.generateDiffs, project.compileJava)
-            }
-        }
-    }
-}
diff --git a/buildSrc/init.gradle b/buildSrc/init.gradle
index ccbd35a..a0df393 100644
--- a/buildSrc/init.gradle
+++ b/buildSrc/init.gradle
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+
+import android.support.DacOptions
+import android.support.DiffAndDocs
 import android.support.LibraryVersions
 import com.android.build.gradle.internal.coverage.JacocoPlugin
 import com.android.build.gradle.internal.coverage.JacocoReportTask
@@ -33,12 +36,7 @@
 ext.runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null
 
 apply from: "${supportRoot}/buildSrc/dependencies.gradle"
-ext.docs = [:]
-ext.docs.offline = rootProject.getProperties().containsKey("offlineDocs")
-ext.docs.dac = [
-        libraryroot: "android/support",
-        dataname: "SUPPORT_DATA"
-]
+ext.docsDac = new DacOptions("android/support", "SUPPORT_DATA")
 
 def enableDoclavaAndJDiff(p) {
     p.configurations {
@@ -52,7 +50,7 @@
         jdiff libs.xml_parser_apis
         jdiff libs.xerces_impl
     }
-    apply from: "${ext.supportRootFolder}/buildSrc/diff_and_docs.gradle"
+    DiffAndDocs.configureDiffAndDocs(rootProject, createArchive, supportRootFolder)
 }
 
 def getFullSdkPath() {
@@ -64,7 +62,7 @@
 }
 
 def setSdkInLocalPropertiesFile() {
-    ext.buildToolsVersion = '27.0.0'
+    ext.buildToolsVersion = '27.0.1'
     final String fullSdkPath = getFullSdkPath();
     if (file(fullSdkPath).exists()) {
         gradle.ext.currentSdk = 26
diff --git a/buildSrc/src/main/groovy/android/support/doclava/DoclavaJavadocOptionFileOption.java b/buildSrc/src/main/groovy/android/support/doclava/DoclavaJavadocOptionFileOption.java
deleted file mode 100644
index db3f318..0000000
--- a/buildSrc/src/main/groovy/android/support/doclava/DoclavaJavadocOptionFileOption.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.doclava;
-
-import org.gradle.external.javadoc.internal.AbstractJavadocOptionFileOption;
-import org.gradle.external.javadoc.internal.JavadocOptionFileWriterContext;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * This class is used to hold complex argument(s) to doclava
- */
-public class DoclavaJavadocOptionFileOption extends
-        AbstractJavadocOptionFileOption<Iterable<String>> {
-
-    public DoclavaJavadocOptionFileOption(String option) {
-        super(option, null);
-    }
-
-    public DoclavaJavadocOptionFileOption(String option, Iterable<String> value) {
-        super(option, value);
-    }
-
-    @Override
-    public void write(JavadocOptionFileWriterContext writerContext) throws IOException {
-        writerContext.writeOptionHeader(getOption());
-
-        final Iterable<String> args = getValue();
-        if (args != null) {
-            final Iterator<String> iter = args.iterator();
-            while (true) {
-                writerContext.writeValue(iter.next());
-                if (!iter.hasNext()) {
-                    break;
-                }
-                writerContext.write(" ");
-            }
-        }
-
-        writerContext.newLine();
-    }
-
-    /**
-     * @return a deep copy of the option
-     */
-    public DoclavaJavadocOptionFileOption duplicate() {
-        final Iterable<String> value = getValue();
-        final ArrayList<String> valueCopy;
-        if (value != null) {
-            valueCopy = new ArrayList<>();
-            for (String item : value) {
-                valueCopy.add(item);
-            }
-        } else {
-            valueCopy = null;
-        }
-        return new DoclavaJavadocOptionFileOption(getOption(), valueCopy);
-    }
-}
diff --git a/buildSrc/src/main/groovy/android/support/doclava/DoclavaTask.groovy b/buildSrc/src/main/groovy/android/support/doclava/DoclavaTask.groovy
deleted file mode 100644
index 651446f..0000000
--- a/buildSrc/src/main/groovy/android/support/doclava/DoclavaTask.groovy
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.doclava
-
-import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.InputFiles
-import org.gradle.api.tasks.javadoc.Javadoc
-import org.gradle.api.tasks.Optional
-import org.gradle.api.tasks.OutputDirectory
-import org.gradle.api.tasks.OutputFile
-import org.gradle.external.javadoc.JavadocOptionFileOption
-
-public class DoclavaTask extends Javadoc {
-
-    // external/doclava/src/com/google/doclava/Errors.java
-    public static final def DEFAULT_DOCLAVA_ERRORS = Collections.unmodifiableSet([
-            101,    // unresolved link
-            103,    // unknown tag
-            104,    // unknown param name
-    ] as Set)
-
-    public static final def DEFAULT_DOCLAVA_WARNINGS = Collections.unmodifiableSet([
-            121,    // hidden type param
-    ] as Set)
-
-
-    public static final def DEFAULT_DOCLAVA_HIDDEN = Collections.unmodifiableSet([
-            111,    // hidden super class
-            113,    // @deprecation mismatch
-    ] as Set)
-
-
-    // All lowercase name to match MinimalJavadocOptions#docletpath
-    private Collection<File> mDocletpath
-
-    // doclava error types which will cause the build to fail
-    @Input
-    Collection doclavaErrors = DEFAULT_DOCLAVA_ERRORS
-    @Input
-    Collection doclavaWarnings = DEFAULT_DOCLAVA_WARNINGS
-    // spammy doclava warnings which we want to hide
-    @Input
-    Collection doclavaHidden = DEFAULT_DOCLAVA_HIDDEN
-
-    /**
-     * If non-null, the list of packages that will be treated as if they were
-     * marked with {@literal @hide}.<br>
-     * Packages names will be matched exactly; sub-packages are not automatically recognized.
-     */
-    @Optional
-    @Input
-    Collection hiddenPackages
-
-    /**
-     * If non-null and not-empty, the whitelist of packages that will be present in the generated
-     * stubs; if null or empty, then all packages have stubs generated.<br>
-     * Wildcards are accepted.
-     */
-    @Optional
-    @Input
-    Set<String> stubPackages
-
-    @Input
-    boolean generateDocs = true
-
-    /**
-     * If non-null, the location of where to place the generated api file.
-     * If this is non-null, then {@link #removedApiFile} must be non-null as well.
-     */
-    @Optional
-    @OutputFile
-    File apiFile
-
-    /**
-     * If non-null, the location of where to place the generated removed api file.
-     * If this is non-null, then {@link #apiFile} must be non-null as well.
-     */
-    @Optional
-    @OutputFile
-    File removedApiFile
-
-    /**
-     * If non-null, the location of the generated keep list.
-     */
-    @Optional
-    @OutputFile
-    File keepListFile
-
-    /**
-     * If non-null, the location to put the generated stub sources.
-     */
-    @Optional
-    @OutputDirectory
-    File stubsDir
-
-    public DoclavaTask() {
-        failOnError = true
-        options.doclet = "com.google.doclava.Doclava"
-        options.encoding("UTF-8")
-        options.quiet()
-        // doclava doesn't understand '-doctitle'
-        title = null
-        maxMemory = "1280m"
-        // If none of generateDocs, apiFile, keepListFile, or stubJarsDir are true, then there is
-        // no work to do.
-        onlyIf( { getGenerateDocs() ||
-                getApiFile() != null ||
-                getKeepListFile() != null ||
-                getStubsDir() != null } )
-    }
-
-    /**
-     * The doclet path which has the {@code com.gogole.doclava.Doclava} class.
-     * This option will override any doclet path set in this instance's {@link #options JavadocOptions}.
-     * @see MinimalJavadocOptions#getDocletpath()
-     */
-    @InputFiles
-    public Collection<File> getDocletpath() {
-        return mDocletpath
-    }
-
-    /**
-     * Sets the doclet path which has the {@code com.gogole.doclava.Doclava} class.
-     * This option will override any doclet path set in this instance's {@link #options JavadocOptions}.
-     * @see MinimalJavadocOptions#setDocletpath(java.util.List)
-     */
-    public void setDocletpath(Collection<File> docletpath) {
-        mDocletpath = docletpath
-        // Go ahead and keep the docletpath in our JavadocOptions object in sync.
-        options.docletpath = docletpath as List
-    }
-
-    public void setDoclavaErrors(Collection errors) {
-        // Make it serializable.
-        doclavaErrors = errors as int[]
-    }
-
-    public void setDoclavaWarnings(Collection warnings) {
-        // Make it serializable.
-        doclavaWarnings = warnings as int[]
-    }
-
-    public void setDoclavaHidden(Collection hidden) {
-        // Make it serializable.
-        doclavaHidden = hidden as int[]
-    }
-
-    /**
-     * "Configures" this DoclavaTask with parameters that might not be at their final values
-     * until this task is run.
-     */
-    private configureDoclava() {
-        options.docletpath = getDocletpath() as List
-
-        // configure doclava error/warning/hide levels
-        JavadocOptionFileOption hide = options.addMultilineMultiValueOption("hide")
-        hide.setValue(getDoclavaHidden().collect({ [it.toString()] }))
-
-        JavadocOptionFileOption warning = options.addMultilineMultiValueOption("warning")
-        warning.setValue(getDoclavaWarnings().collect({ [it.toString()] }))
-
-        JavadocOptionFileOption error = options.addMultilineMultiValueOption("error")
-        error.setValue(getDoclavaErrors().collect({ [it.toString()] }))
-
-        Collection hiddenPackages = getHiddenPackages()
-        if (hiddenPackages) {
-            JavadocOptionFileOption hidePackage =
-                    options.addMultilineMultiValueOption("hidePackage")
-            hidePackage.setValue(hiddenPackages.collect({ [it.toString()] }))
-        }
-
-        if (!getGenerateDocs()) {
-            options.addOption(new DoclavaJavadocOptionFileOption('nodocs'))
-        }
-
-        // If requested, generate the API files.
-        File apiFile = getApiFile()
-        if (apiFile != null) {
-            options.addStringOption('api', apiFile.absolutePath)
-
-            File removedApiFile = getRemovedApiFile()
-            if (removedApiFile != null) {
-                options.addStringOption('removedApi', removedApiFile.absolutePath)
-            }
-        }
-
-        // If requested, generate the keep list.
-        File keepListFile = getKeepListFile()
-        if (keepListFile != null) {
-            options.addStringOption('proguard', keepListFile.absolutePath)
-        }
-        // If requested, generate stubs.
-        File stubsDir = getStubsDir()
-        if (stubsDir != null) {
-            options.addStringOption('stubs', stubsDir.absolutePath)
-            Set<String> stubPackages = getStubPackages()
-            if (stubPackages) {
-                options.addStringOption('stubpackages', stubPackages.join(':'))
-            }
-        }
-        // Always treat this as an Android docs task.
-        options.addOption(new DoclavaJavadocOptionFileOption('android'))
-    }
-
-    @Override
-    public void generate() {
-        configureDoclava()
-        super.generate()
-    }
-}
diff --git a/buildSrc/src/main/java/android/support/LibraryVersions.java b/buildSrc/src/main/java/android/support/LibraryVersions.java
index 27a52bd..c8dd1e3 100644
--- a/buildSrc/src/main/java/android/support/LibraryVersions.java
+++ b/buildSrc/src/main/java/android/support/LibraryVersions.java
@@ -43,7 +43,7 @@
     /**
      * Version code for RecyclerView & Room paging
      */
-    public static final Version PAGING = new Version("1.0.0-alpha3");
+    public static final Version PAGING = new Version("1.0.0-alpha4-1");
 
     private static final Version LIFECYCLES = new Version("1.0.3");
 
diff --git a/buildSrc/src/main/java/android/support/checkapi/UpdateApiTask.java b/buildSrc/src/main/java/android/support/checkapi/UpdateApiTask.java
index de2db91..15e9104 100644
--- a/buildSrc/src/main/java/android/support/checkapi/UpdateApiTask.java
+++ b/buildSrc/src/main/java/android/support/checkapi/UpdateApiTask.java
@@ -29,7 +29,6 @@
 import java.io.File;
 import java.nio.charset.Charset;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 /**
@@ -120,11 +119,6 @@
         }
 
         if (mWhitelistErrorsFile != null && !mWhitelistErrors.isEmpty()) {
-            if (mWhitelistErrorsFile.exists()) {
-                List<String> lines =
-                        Files.readLines(mWhitelistErrorsFile, Charset.defaultCharset());
-                mWhitelistErrors.removeAll(lines);
-            }
             try (BufferedWriter writer = Files.newWriter(
                     mWhitelistErrorsFile, Charset.defaultCharset())) {
                 for (String error : mWhitelistErrors) {
diff --git a/buildSrc/src/main/kotlin/android/support/DiffAndDocs.kt b/buildSrc/src/main/kotlin/android/support/DiffAndDocs.kt
new file mode 100644
index 0000000..4c57721
--- /dev/null
+++ b/buildSrc/src/main/kotlin/android/support/DiffAndDocs.kt
@@ -0,0 +1,663 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support
+
+import android.support.checkapi.ApiXmlConversionTask
+import android.support.checkapi.CheckApiTask
+import android.support.checkapi.UpdateApiTask
+import android.support.doclava.DoclavaTask
+import android.support.jdiff.JDiffTask
+import com.android.build.gradle.LibraryExtension
+import com.android.build.gradle.api.LibraryVariant
+import org.gradle.api.GradleException
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.file.FileCollection
+import org.gradle.api.plugins.JavaBasePlugin
+import org.gradle.api.tasks.Copy
+import org.gradle.api.tasks.TaskContainer
+import org.gradle.api.tasks.bundling.Zip
+import org.gradle.api.tasks.compile.JavaCompile
+import org.gradle.api.tasks.javadoc.Javadoc
+import java.io.File
+
+data class DacOptions(val libraryroot: String, val dataname: String)
+
+object DiffAndDocs {
+    @JvmStatic
+    fun configureDiffAndDocs(
+            root: Project,
+            createArchiveTask: Task,
+            supportRootFolder: File) = configure(root, createArchiveTask, supportRootFolder)
+}
+
+private data class CheckApiConfig(
+        val onFailMessage: String,
+        val errors: List<Int>,
+        val warnings: List<Int>,
+        val hidden: List<Int>)
+
+private const val MSG_HIDE_API =
+        "If you are adding APIs that should be excluded from the public API surface,\n" +
+                "consider using package or private visibility. If the API must have public\n" +
+                "visibility, you may exclude it from public API by using the @hide javadoc\n" +
+                "annotation paired with the @RestrictTo(LIBRARY_GROUP) code annotation."
+
+private fun hasJavaSources(variant: LibraryVariant) = !variant.javaCompile.source
+        .filter { file -> file.name != "R.java" && file.name != "BuildConfig.java" }
+        .isEmpty
+
+private val CHECK_API_CONFIG_RELEASE = CheckApiConfig(
+        onFailMessage =
+        "Compatibility with previously released public APIs has been broken. Please\n" +
+                "verify your change with Support API Council and provide error output,\n" +
+                "including the error messages and associated SHAs.\n" +
+                "\n" +
+                "If you are removing APIs, they must be deprecated first before being removed\n" +
+                "in a subsequent release.\n" +
+                "\n" + MSG_HIDE_API,
+        errors = (7..18).toList(),
+        warnings = emptyList(),
+        hidden = (2..6) + (19..30)
+)
+
+// Check that the API we're building hasn't changed from the development
+// version. These types of changes require an explicit API file update.
+private val CHECK_API_CONFIG_DEVELOP = CheckApiConfig(
+        onFailMessage =
+        "Public API definition has changed. Please run ./gradlew updateApi to confirm\n" +
+                "these changes are intentional by updating the public API definition.\n" +
+                "\n" + MSG_HIDE_API,
+        errors = (2..30) - listOf(22),
+        warnings = emptyList(),
+        hidden = listOf(22)
+)
+
+// This is a patch or finalized release. Check that the API we're building
+// hasn't changed from the current.
+private val CHECK_API_CONFIG_PATCH = CHECK_API_CONFIG_DEVELOP.copy(
+        onFailMessage = "Public API definition may not change in finalized or patch releases.\n" +
+                "\n" + MSG_HIDE_API)
+
+private fun hasApiFolder(project: Project) = File(project.projectDir, "api").exists()
+
+private fun stripExtension(fileName: String) = fileName.substringBeforeLast('.')
+
+private fun getLastReleasedApiFile(rootFolder: File, refApi: String): File? {
+    val refVersion = Version(refApi)
+    val apiDir = File(rootFolder, "api")
+
+    var lastFile: File? = null
+    var lastVersion: Version? = null
+    val regex = Regex("(\\d+)\\.(\\d+)\\.0\\.txt")
+    // Only look at released versions and snapshots thereof, ex. X.Y.0.txt.
+    apiDir.listFiles().filter { file ->
+        regex.matches(file.name) && file.isFile
+    }.forEach { file ->
+        val version = Version(stripExtension(file.name))
+
+        if ((lastFile == null || lastVersion!! < version) && version < refVersion) {
+            lastFile = file
+            lastVersion = version
+        }
+    }
+    return lastFile
+}
+
+private fun getApiFile(rootDir: File, refVersion: Version): File {
+    return getApiFile(rootDir, refVersion, false)
+}
+
+/**
+ * Returns the API file for the specified reference version.
+ *
+ * @param refVersion the reference API version, ex. 25.0.0-SNAPSHOT
+ * @return the most recently released API file
+ */
+private fun getApiFile(rootDir: File, refVersion: Version, forceRelease: Boolean = false): File {
+    val apiDir = File(rootDir, "api")
+
+    if (!refVersion.isSnapshot || forceRelease) {
+        // Release API file is always X.Y.0.txt.
+        return File(apiDir, "${refVersion.major}.${refVersion.minor}.0.txt")
+    }
+
+    // Non-release API file is always current.txt.
+    return File(apiDir, "current.txt")
+}
+
+private fun createVerifyUpdateApiAllowedTask(project: Project) =
+        project.tasks.createWithConfig("verifyUpdateApiAllowed") {
+            // This could be moved to doFirst inside updateApi, but using it as a
+            // dependency with no inputs forces it to run even when updateApi is a
+            // no-op.
+            doLast {
+                val rootFolder = project.projectDir
+                val version = Version(project.version as String)
+
+                if (version.isPatch) {
+                    throw GradleException("Public APIs may not be modified in patch releases.")
+                } else if (version.isSnapshot && getApiFile(rootFolder,
+                        version,
+                        true).exists()) {
+                    throw GradleException("Inconsistent version. Public API file already exists.")
+                } else if (!version.isSnapshot && getApiFile(rootFolder, version).exists()
+                        && !project.hasProperty("force")) {
+                    throw GradleException("Public APIs may not be modified in finalized releases.")
+                }
+            }
+        }
+
+// Generates API files
+private fun createGenerateApiTask(project: Project, docletpathParam: Collection<File>) =
+        project.tasks.createWithConfig("generateApi", DoclavaTask::class.java) {
+            setDocletpath(docletpathParam)
+            destinationDir = project.docsDir()
+            // Base classpath is Android SDK, sub-projects add their own.
+            classpath = project.androidJar()
+            apiFile = File(project.docsDir(), "release/${project.name}/current.txt")
+            generateDocs = false
+
+            coreJavadocOptions {
+                addBooleanOption("stubsourceonly", true)
+            }
+
+            exclude("**/BuildConfig.java")
+            exclude("**/R.java")
+        }
+
+private fun createCheckApiTask(
+        project: Project,
+        taskName: String,
+        docletpath: Collection<File>,
+        checkApiConfig: CheckApiConfig,
+        oldApi: File?,
+        newApi: File,
+        whitelist: File? = null) =
+        project.tasks.createWithConfig(taskName, CheckApiTask::class.java) {
+            doclavaClasspath = docletpath
+            onFailMessage = checkApiConfig.onFailMessage
+            checkApiErrors = checkApiConfig.errors
+            checkApiWarnings = checkApiConfig.warnings
+            checkApiHidden = checkApiConfig.hidden
+            newApiFile = newApi
+            oldApiFile = oldApi
+            whitelistErrorsFile = whitelist
+            doFirst {
+                logger.lifecycle("Verifying ${newApi.name} " +
+                        "against ${oldApi?.name ?: "nothing"}...")
+            }
+        }
+
+// configuration file for setting up api diffs and api docs
+private fun registerJavaProjectForDocsTask(task: Javadoc, javaCompileTask: JavaCompile) {
+    task.dependsOn(javaCompileTask)
+    task.source(javaCompileTask.source)
+    val project = task.project
+    task.classpath += project.files(javaCompileTask.classpath) +
+            project.files(javaCompileTask.destinationDir)
+}
+
+// configuration file for setting up api diffs and api docs
+private fun registerAndroidProjectForDocsTask(task: Javadoc, releaseVariant: LibraryVariant) {
+    task.dependsOn(releaseVariant.javaCompile)
+    val packageDir = releaseVariant.applicationId.replace('.', '/')
+    val sources = releaseVariant.javaCompile.source.filter { file ->
+        file.name != "R.java" || file.parent.endsWith(packageDir)
+    }
+    task.source(sources)
+    task.classpath += releaseVariant.getCompileClasspath(null) +
+            task.project.files(releaseVariant.javaCompile.destinationDir)
+}
+
+private fun createUpdateApiTask(project: Project, checkApiRelease: CheckApiTask) =
+        project.tasks.createWithConfig("updateApi", UpdateApiTask::class.java) {
+            group = JavaBasePlugin.VERIFICATION_GROUP
+            description = "Updates the candidate API file to incorporate valid changes."
+            newApiFile = checkApiRelease.newApiFile
+            oldApiFile = getApiFile(project.projectDir, project.version())
+            whitelistErrors = checkApiRelease.whitelistErrors
+            whitelistErrorsFile = checkApiRelease.whitelistErrorsFile
+
+            doFirst {
+                // Replace the expected whitelist with the detected whitelist.
+                whitelistErrors = checkApiRelease.detectedWhitelistErrors
+            }
+        }
+
+/**
+ * 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.
+ */
+private fun createOldApiXml(project: Project, doclavaConfig: Configuration) =
+        project.tasks.createWithConfig("oldApiXml", ApiXmlConversionTask::class.java) {
+            val regex = Regex("(\\d+\\.){2}\\d+")
+            val toApi = project.processProperty("toApi")
+            val fromApi = project.processProperty("fromApi")
+            classpath = project.files(doclavaConfig.resolve())
+            val rootFolder = project.projectDir
+            if (fromApi != null) {
+                // Use an explicit API file.
+                inputApiFile = File(rootFolder, "api/$fromApi.txt")
+            } else if (toApi != null && regex.matches(toApi)) {
+                // If toApi matches released API (X.Y.Z) format, use the most recently
+                // released API file prior to toApi.
+                inputApiFile = getLastReleasedApiFile(rootFolder, toApi)
+            } else {
+                // Use the most recently released API file.
+                inputApiFile = getApiFile(rootFolder, project.version())
+            }
+
+            outputApiXmlFile = File(project.docsDir(),
+                    "release/${stripExtension(inputApiFile.name)}.xml")
+
+            dependsOn(doclavaConfig)
+        }
+
+/**
+ * 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")
+
+            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)}.xml")
+        }
+
+/**
+ * Generates API diffs.
+ * <p>
+ * By default, diffs are generated for the delta between current.txt and the
+ * next most recent X.Y.Z.txt API file. Behavior may be changed by specifying
+ * one or both of -PtoApi and -PfromApi.
+ * <p>
+ * If both fromApi and toApi are specified, diffs will be generated for
+ * fromApi -> toApi. For example, 25.0.0 -> 26.0.0 diffs could be generated by
+ * using:
+ * <br><code>
+ *   ./gradlew generateDiffs -PfromApi=25.0.0 -PtoApi=26.0.0
+ * </code>
+ * <p>
+ * If only toApi is specified, it MUST be specified as X.Y.Z and diffs will be
+ * generated for (release before toApi) -> toApi. For example, 24.2.0 -> 25.0.0
+ * diffs could be generated by using:
+ * <br><code>
+ *   ./gradlew generateDiffs -PtoApi=25.0.0
+ * </code>
+ * <p>
+ * If only fromApi is specified, diffs will be generated for fromApi -> current.
+ * For example, lastApiReview -> current diffs could be generated by using:
+ * <br><code>
+ *   ./gradlew generateDiffs -PfromApi=lastApiReview
+ * </code>
+ * <p>
+ */
+private fun createGenerateDiffsTask(
+        project: Project,
+        oldApiTask: ApiXmlConversionTask,
+        newApiTask: ApiXmlConversionTask,
+        jdiffConfig: Configuration) =
+        project.tasks.createWithConfig("generateDiffs", JDiffTask::class.java) {
+            // Base classpath is Android SDK, sub-projects add their own.
+            classpath = project.androidJar()
+
+            // JDiff properties.
+            oldApiXmlFile = oldApiTask.outputApiXmlFile
+            newApiXmlFile = newApiTask.outputApiXmlFile
+
+            val newApi = newApiXmlFile.name.substringBeforeLast('.')
+            val docsDir = project.rootProject.docsDir()
+
+            newJavadocPrefix = "../../../../../reference/"
+            destinationDir = File(docsDir, "online/sdk/support_api_diff/${project.name}/$newApi")
+
+            // Javadoc properties.
+            docletpath = jdiffConfig.resolve()
+            title = "Support&nbsp;Library&nbsp;API&nbsp;Differences&nbsp;Report"
+
+            exclude("**/BuildConfig.java", "**/R.java")
+            dependsOn(oldApiTask, newApiTask, jdiffConfig)
+        }
+
+// Generates a distribution artifact for online docs.
+private fun createDistDocsTask(project: Project, generateDocs: DoclavaTask) =
+        project.tasks.createWithConfig("distDocs", Zip::class.java) {
+            dependsOn(generateDocs)
+            group = JavaBasePlugin.DOCUMENTATION_GROUP
+            description = "Generates distribution artifact for d.android.com-style documentation."
+            from(generateDocs.destinationDir)
+            baseName = "android-support-docs"
+            version = project.buildNumber()
+
+            doLast {
+                logger.lifecycle("'Wrote API reference to $archivePath")
+            }
+        }
+
+// Set up platform API files for federation.
+private fun createGenerateSdkApiTask(project: Project, doclavaConfig: Configuration): Task =
+        if (project.androidApiTxt() != null) {
+            project.tasks.createWithConfig("generateSdkApi", Copy::class.java) {
+                description = "Copies the API files for the current SDK."
+                // Export the API files so this looks like a DoclavaTask.
+                from(project.androidApiTxt()!!.absolutePath)
+                val apiFile = sdkApiFile(project)
+                into(apiFile.parent)
+                rename { apiFile.name }
+                // Register the fake removed file as an output.
+                val removedApiFile = removedSdkApiFile(project)
+                outputs.file(removedApiFile)
+                doLast { removedApiFile.createNewFile() }
+            }
+        } else {
+            project.tasks.createWithConfig("generateSdkApi", DoclavaTask::class.java) {
+                dependsOn(doclavaConfig)
+                description = "Generates API files for the current SDK."
+                setDocletpath(doclavaConfig.resolve())
+                destinationDir = project.docsDir()
+                classpath = project.androidJar()
+                source(project.zipTree(project.androidSrcJar()))
+                apiFile = sdkApiFile(project)
+                removedApiFile = removedSdkApiFile(project)
+                generateDocs = false
+                coreJavadocOptions {
+                    addStringOption("stubpackages", "android.*")
+                }
+            }
+        }
+
+private fun createGenerateDocsTask(
+        project: Project,
+        generateSdkApiTask: Task,
+        doclavaConfig: Configuration,
+        supportRootFolder: File) =
+        project.tasks.createWithConfig("generateDocs", GenerateDocsTask::class.java) {
+            dependsOn(generateSdkApiTask, doclavaConfig)
+            group = JavaBasePlugin.DOCUMENTATION_GROUP
+            description = "Generates d.android.com-style documentation. To generate offline docs " +
+                    "use \'-PofflineDocs=true\' parameter."
+
+            setDocletpath(doclavaConfig.resolve())
+            val offline = project.processProperty("offlineDocs") != null
+            destinationDir = File(project.docsDir(), if (offline) "offline" else "online")
+            classpath = project.androidJar()
+            val hidden = listOf<Int>(105, 106, 107, 111, 112, 113, 115, 116, 121)
+            doclavaErrors = ((101..122) - hidden).toSet()
+            doclavaWarnings = emptySet()
+            doclavaHidden += hidden
+
+            addSinceFilesFrom(supportRootFolder)
+
+            coreJavadocOptions {
+                addStringOption("templatedir",
+                        "$supportRootFolder/../../external/doclava/res/assets/templates-sdk")
+                addStringOption("samplesdir", "$supportRootFolder/samples")
+                addMultilineMultiValueOption("federate").value = listOf(
+                        listOf("Android", "https://developer.android.com")
+                )
+                addMultilineMultiValueOption("federationapi").value = listOf(
+                        listOf("Android", sdkApiFile(project).absolutePath)
+                )
+                addMultilineMultiValueOption("hdf").value = listOf(
+                        listOf("android.whichdoc", "online"),
+                        listOf("android.hasSamples", "true"),
+                        listOf("dac", "true")
+                )
+
+                // Specific to reference docs.
+                if (!offline) {
+                    addStringOption("toroot", "/")
+                    addBooleanOption("devsite", true)
+                    addStringOption("dac_libraryroot", project.docsDac().libraryroot)
+                    addStringOption("dac_dataname", project.docsDac().dataname)
+                }
+
+                exclude("**/BuildConfig.java")
+            }
+
+            addArtifactsAndSince()
+        }
+
+private fun initializeApiChecksForProject(
+        project: Project,
+        generateDocs: GenerateDocsTask,
+        createArchive: Task): Pair<DoclavaTask, JDiffTask> {
+    if (!project.hasProperty("docsDir")) {
+        project.extensions.add("docsDir", File(project.rootProject.docsDir(), project.name))
+    }
+    val artifact = "${project.group}:${project.name}:${project.version}"
+    val version = project.version()
+    val workingDir = project.projectDir
+
+    val doclavaConfiguration = project.rootProject.configurations.getByName("doclava")
+    val docletClasspath = doclavaConfiguration.resolve()
+    val generateApi = createGenerateApiTask(project, docletClasspath)
+    generateApi.dependsOn(doclavaConfiguration)
+    val verifyUpdateTask = createVerifyUpdateApiAllowedTask(project)
+
+    // Make sure the API surface has not broken since the last release.
+    val lastReleasedApiFile = getLastReleasedApiFile(workingDir, version.toString())
+
+    val whitelistFile = lastReleasedApiFile?.let { apiFile ->
+        File(lastReleasedApiFile.parentFile, stripExtension(apiFile.name) + ".ignore")
+    }
+    val checkApiRelease = createCheckApiTask(project,
+            "checkApiRelease",
+            docletClasspath,
+            CHECK_API_CONFIG_RELEASE,
+            lastReleasedApiFile,
+            generateApi.apiFile!!,
+            whitelistFile)
+    checkApiRelease.dependsOn(generateApi)
+
+    // Allow a comma-delimited list of whitelisted errors.
+    if (project.hasProperty("ignore")) {
+        checkApiRelease.whitelistErrors = (project.properties["ignore"] as String)
+                .split(',').toSet()
+    }
+
+    // Check whether the development API surface has changed.
+    val verifyConfig = if (version.isPatch) CHECK_API_CONFIG_PATCH else CHECK_API_CONFIG_DEVELOP
+    val currentApiFile = getApiFile(workingDir, version)
+    val checkApi = createCheckApiTask(project,
+            "checkApi",
+            docletClasspath,
+            verifyConfig,
+            currentApiFile,
+            generateApi.apiFile!!,
+            null)
+    checkApi.dependsOn(generateApi, checkApiRelease)
+
+    checkApi.group = JavaBasePlugin.VERIFICATION_GROUP
+    checkApi.description = "Verify the API surface."
+
+    val updateApiTask = createUpdateApiTask(project, checkApiRelease)
+    updateApiTask.dependsOn(checkApiRelease, verifyUpdateTask)
+    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)
+    generateDiffTask.dependsOn(generateDocs)
+
+    // Track API change history.
+    generateDocs.addSinceFilesFrom(project.projectDir)
+
+    // Associate current API surface with the Maven artifact.
+    generateDocs.addArtifact(generateApi.apiFile!!.absolutePath, artifact)
+    generateDocs.dependsOn(generateApi)
+    createArchive.dependsOn(checkApi)
+    return (generateApi to generateDiffTask)
+}
+
+private open class GenerateDocsTask : DoclavaTask() {
+
+    private data class Since(val path: String, val apiLevel: String)
+    private data class Artifact(val path: String, val artifact: String)
+
+    private val sinces = mutableListOf<Since>()
+    private val artifacts = mutableListOf<Artifact>()
+
+    fun addArtifactsAndSince() {
+        doFirst {
+            coreJavadocOptions {
+                if (sinces.isNotEmpty()) {
+                    addMultilineMultiValueOption("since").value = sinces.map { (path, apiLevel) ->
+                        listOf(path, apiLevel)
+                    }
+                }
+
+                if (artifacts.isNotEmpty()) {
+                    addMultilineMultiValueOption("artifact").value = artifacts.map { artifact ->
+                        listOf(artifact.path, artifact.artifact)
+                    }
+                }
+            }
+        }
+    }
+
+    fun addSinceFilesFrom(dir: File) {
+        val regex = Regex("(\\d+\\.\\d+\\.\\d).txt")
+        val apiDir = File(dir, "api")
+        apiDir.listFiles { file ->
+            file.isFile && regex.matches(file.name)
+        }.forEach { apiFile ->
+            val matchResult = regex.matchEntire(apiFile.name)!!
+            sinces.add(Since(apiFile.absolutePath, matchResult.groups[1]!!.value))
+        }
+    }
+
+    fun addArtifact(path: String, artifact: String) = artifacts.add(Artifact(path, artifact))
+}
+
+private fun configure(root: Project, createArchiveTask: Task, supportRootFolder: File) {
+    val doclavaConfiguration = root.configurations.getByName("doclava")
+    val generateSdkApiTask = createGenerateSdkApiTask(root, doclavaConfiguration)
+
+    val generateDocsTask = createGenerateDocsTask(root, generateSdkApiTask,
+            doclavaConfiguration, supportRootFolder)
+    createDistDocsTask(root, generateDocsTask)
+
+    root.subprojects { subProject ->
+        subProject.afterEvaluate { project ->
+            val extension = if (project.hasProperty("supportLibrary")) {
+                project.properties["supportLibrary"] as SupportLibraryExtension
+            } else {
+                null
+            }
+            if (extension == null || !extension.publish) {
+                project.logger.info("Project ${project.name} is not published, ignoring API tasks.")
+                return@afterEvaluate
+            }
+
+            if (!extension.generateDocs) {
+                project.logger.info("Project ${project.name} specified generateDocs = false, " +
+                        "ignoring API tasks.")
+                return@afterEvaluate
+            }
+
+            val library = project.extensions.findByType(LibraryExtension::class.java)
+            if (library != null) {
+                library.libraryVariants.all { variant ->
+                    if (variant.name == "release") {
+                        registerAndroidProjectForDocsTask(generateDocsTask, variant)
+                        if (!hasJavaSources(variant)) {
+                            return@all
+                        }
+                        if (!hasApiFolder(project)) {
+                            project.logger.info("Project ${project.name} doesn't have " +
+                                    "an api folder, ignoring API tasks.")
+                            return@all
+                        }
+                        val (generateApi, generateDiffs) = initializeApiChecksForProject(project,
+                                generateDocsTask, createArchiveTask)
+                        registerAndroidProjectForDocsTask(generateApi, variant)
+                        registerAndroidProjectForDocsTask(generateDiffs, variant)
+                    }
+                }
+            } else if (project.hasProperty("compileJava")) {
+                val compileJava = project.properties["compileJava"] as JavaCompile
+                registerJavaProjectForDocsTask(generateDocsTask, compileJava)
+                if (!hasApiFolder(project)) {
+                    project.logger.info("Project ${project.name} doesn't have an api folder, " +
+                            "ignoring API tasks.")
+                    return@afterEvaluate
+                }
+                project.afterEvaluate { proj ->
+                    val (generateApi, generateDiffs) = initializeApiChecksForProject(proj,
+                            generateDocsTask,
+                            createArchiveTask)
+                    registerJavaProjectForDocsTask(generateApi, compileJava)
+                    registerJavaProjectForDocsTask(generateDiffs, compileJava)
+                }
+            }
+        }
+    }
+}
+
+private fun sdkApiFile(project: Project) = File(project.docsDir(), "release/sdk_current.txt")
+private fun removedSdkApiFile(project: Project) = File(project.docsDir(), "release/sdk_removed.txt")
+
+private fun TaskContainer.createWithConfig(name: String, config: Task.() -> Unit) =
+        create(name) { task -> task.config() }
+
+private fun <T : Task> TaskContainer.createWithConfig(
+        name: String, taskClass: Class<T>,
+        config: T.() -> Unit) =
+        create(name, taskClass) { task -> task.config() }
+
+// Nasty part. Get rid of that eventually!
+private fun Project.docsDir(): File = properties["docsDir"] as File
+
+private fun Project.androidJar() = rootProject.properties["androidJar"] as FileCollection
+
+private fun Project.androidSrcJar() = rootProject.properties["androidSrcJar"] as File
+
+private fun Project.version() = Version(project.properties["version"] as String)
+
+private fun Project.buildNumber() = properties["buildNumber"] as String
+
+private fun Project.androidApiTxt() = properties["androidApiTxt"] as? File
+
+private fun Project.docsDac() = properties["docsDac"] as DacOptions
+
+private fun Project.processProperty(name: String) =
+        if (hasProperty(name)) {
+            properties[name] as String
+        } else {
+            null
+        }
diff --git a/buildSrc/src/main/kotlin/android/support/SupportAndroidLibraryPlugin.kt b/buildSrc/src/main/kotlin/android/support/SupportAndroidLibraryPlugin.kt
index b347415..5eaa7dd 100644
--- a/buildSrc/src/main/kotlin/android/support/SupportAndroidLibraryPlugin.kt
+++ b/buildSrc/src/main/kotlin/android/support/SupportAndroidLibraryPlugin.kt
@@ -24,7 +24,7 @@
 import org.gradle.api.Plugin
 import org.gradle.api.Project
 import java.io.File
-import java.util.*
+import java.util.Properties
 
 /**
  * Support library specific com.android.library plugin that sets common configurations needed for
@@ -37,6 +37,8 @@
                 SupportLibraryExtension::class.java, project)
         apply(project, supportLibraryExtension)
 
+        val isCoreSupportLibrary = project.rootProject.name == "support"
+
         project.afterEvaluate {
             val library = project.extensions.findByType(LibraryExtension::class.java)
                     ?: return@afterEvaluate
@@ -55,11 +57,11 @@
 
             // Java 8 is only fully supported on API 24+ and not all Java 8 features are binary
             // compatible with API < 24, so use Java 7 for both source AND target.
-            val javaVersion: JavaVersion;
+            val javaVersion: JavaVersion
             if (supportLibraryExtension.java8Library) {
                 if (library.defaultConfig.minSdkVersion.apiLevel < 24) {
                     throw IllegalArgumentException("Libraries can only support Java 8 if "
-                            + "minSdkVersion is 24 or higher");
+                            + "minSdkVersion is 24 or higher")
                 }
                 javaVersion = JavaVersion.VERSION_1_8
             } else {
@@ -75,6 +77,21 @@
         project.apply(mapOf("plugin" to "com.android.library"))
         project.apply(mapOf("plugin" to ErrorProneBasePlugin::class.java))
 
+        project.configurations.all { configuration ->
+            if (isCoreSupportLibrary) {
+                // In projects which compile as part of the "core" support libraries (which include
+                // the annotations), replace any transitive pointer to the deployed Maven
+                // coordinate version of annotations with a reference to the local project. These
+                // usually originate from test dependencies and otherwise cause multiple copies on
+                // the classpath. We do not do this for non-"core" projects as they need to
+                // depend on the Maven coordinate variant.
+                configuration.resolutionStrategy.dependencySubstitution.apply {
+                    substitute(module("com.android.support:support-annotations"))
+                            .with(project(":support-annotations"))
+                }
+            }
+        }
+
         val library = project.extensions.findByType(LibraryExtension::class.java)
                 ?: throw Exception("Failed to find Android extension")
 
@@ -111,7 +128,7 @@
         library.libraryVariants.all { libraryVariant ->
             if (libraryVariant.getBuildType().getName().equals("errorProne")) {
                 @Suppress("DEPRECATION")
-                libraryVariant.getJavaCompile().setToolChain(toolChain);
+                libraryVariant.getJavaCompile().setToolChain(toolChain)
 
                 @Suppress("DEPRECATION")
                 val compilerArgs = libraryVariant.getJavaCompile().options.compilerArgs
@@ -119,12 +136,16 @@
                         "-XDcompilePolicy=simple", // Workaround for b/36098770
 
                         // Enforce the following checks.
+                        "-Xep:RestrictTo:OFF",
+                        "-Xep:ParameterNotNullable:ERROR",
                         "-Xep:MissingOverride:ERROR",
+                        "-Xep:JdkObsolete:ERROR",
                         "-Xep:NarrowingCompoundAssignment:ERROR",
                         "-Xep:ClassNewInstance:ERROR",
                         "-Xep:ClassCanBeStatic:ERROR",
                         "-Xep:SynchronizeOnNonFinalField:ERROR",
-                        "-Xep:OperatorPrecedence:ERROR"
+                        "-Xep:OperatorPrecedence:ERROR",
+                        "-Xep:IntLongMath:ERROR"
                 )
             }
         }
@@ -155,7 +176,7 @@
     // Set baseline file for all legacy lint warnings.
     if (System.getenv("GRADLE_PLUGIN_VERSION") != null) {
         lintOptions.check("NewApi")
-    } else {
+    } else if (baseline.exists()) {
         lintOptions.baseline(baseline)
     }
 }
\ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/android/support/SupportLibraryExtension.kt b/buildSrc/src/main/kotlin/android/support/SupportLibraryExtension.kt
index 088e169..d5519c7 100644
--- a/buildSrc/src/main/kotlin/android/support/SupportLibraryExtension.kt
+++ b/buildSrc/src/main/kotlin/android/support/SupportLibraryExtension.kt
@@ -34,6 +34,13 @@
     var java8Library = false
     var legacySourceLocation = false
     var publish = false
+    /**
+     * This flag works only if publish flag is "true".
+     * It is useful for modules that are used for tooling. For example room annotation
+     * processor module is published, but we don't want to expose any docs, because we don't
+     * support using it as a library.
+     */
+    var generateDocs = true
 
     fun license(closure: Closure<*>): License {
         val license = project.configure(License(), closure) as License
@@ -47,7 +54,8 @@
 
     companion object {
         @JvmField
-        val ARCHITECTURE_URL = "https://developer.android.com/topic/libraries/architecture/index.html"
+        val ARCHITECTURE_URL
+                = "https://developer.android.com/topic/libraries/architecture/index.html"
         @JvmField
         val SUPPORT_URL = "http://developer.android.com/tools/extras/support-library.html"
     }
diff --git a/buildSrc/src/main/kotlin/android/support/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/android/support/dependencies/Dependencies.kt
new file mode 100644
index 0000000..e32cacd
--- /dev/null
+++ b/buildSrc/src/main/kotlin/android/support/dependencies/Dependencies.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.dependencies
+
+const val AUTO_COMMON = "com.google.auto:auto-common:0.6"
+const val ANTLR = "org.antlr:antlr4:4.5.3"
+const val APACHE_COMMONS_CODEC = "commons-codec:commons-codec:1.10"
+const val DEXMAKER_MOCKITO = "com.linkedin.dexmaker:dexmaker-mockito:2.2.0"
+const val ESPRESSO_CONTRIB = "com.android.support.test.espresso:espresso-contrib:3.0.1"
+const val ESPRESSO_CORE = "com.android.support.test.espresso:espresso-core:3.0.1"
+const val GOOGLE_COMPILE_TESTING = "com.google.testing.compile:compile-testing:0.11"
+const val GSON = "com.google.code.gson:gson:2.8.0"
+const val GUAVA = "com.google.guava:guava:21.0"
+const val INTELLIJ_ANNOTATIONS = "com.intellij:annotations:12.0"
+const val JAVAPOET = "com.squareup:javapoet:1.8.0"
+const val JSR250 = "javax.annotation:javax.annotation-api:1.2"
+const val JUNIT = "junit:junit:4.12"
+const val KOTLIN_STDLIB = "org.jetbrains.kotlin:kotlin-stdlib:1.2.0"
+const val MOCKITO_CORE = "org.mockito:mockito-core:2.7.6"
+const val REACTIVE_STREAMS = "org.reactivestreams:reactive-streams:1.0.0"
+const val RX_JAVA = "io.reactivex.rxjava2:rxjava:2.0.6"
+const val TEST_RUNNER = "com.android.support.test:runner:1.0.1"
+const val TEST_RULES = "com.android.support.test:rules:1.0.1"
+/**
+ * this Xerial version is newer than we want but we need it to fix
+ * https://github.com/xerial/sqlite-jdbc/issues/97
+ * https://github.com/xerial/sqlite-jdbc/issues/267
+ */
+const val XERIAL = "org.xerial:sqlite-jdbc:3.20.1"
\ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/android/support/doclava/DoclavaJavadocOptionFileOption.kt b/buildSrc/src/main/kotlin/android/support/doclava/DoclavaJavadocOptionFileOption.kt
new file mode 100644
index 0000000..828fb25
--- /dev/null
+++ b/buildSrc/src/main/kotlin/android/support/doclava/DoclavaJavadocOptionFileOption.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.doclava
+
+import org.gradle.external.javadoc.internal.AbstractJavadocOptionFileOption
+import org.gradle.external.javadoc.internal.JavadocOptionFileWriterContext
+import java.io.IOException
+import java.util.ArrayList
+
+//TODO: remove this once https://github.com/gradle/gradle/issues/2354 is fixed
+class DoclavaJavadocOptionFileOption : AbstractJavadocOptionFileOption<Iterable<String>> {
+
+    constructor(option: String) : super(option, null)
+
+    constructor(option: String, value: Iterable<String>?) : super(option, value)
+
+    @Throws(IOException::class)
+    override fun write(writerContext: JavadocOptionFileWriterContext) {
+        writerContext.writeOptionHeader(getOption())
+        val args = getValue()
+        if (args != null) {
+            val iter = args.iterator()
+            while (true) {
+                writerContext.writeValue(iter.next())
+                if (!iter.hasNext()) {
+                    break
+                }
+                writerContext.write(" ")
+            }
+        }
+        writerContext.newLine()
+    }
+    /**
+     * @return a deep copy of the option
+     */
+    override fun duplicate(): DoclavaJavadocOptionFileOption {
+        val value = getValue()
+        val valueCopy: ArrayList<String>?
+        if (value != null) {
+            valueCopy = ArrayList()
+            valueCopy += value
+        } else {
+            valueCopy = null
+        }
+        return DoclavaJavadocOptionFileOption(getOption(), valueCopy)
+    }
+}
diff --git a/buildSrc/src/main/kotlin/android/support/doclava/DoclavaTask.kt b/buildSrc/src/main/kotlin/android/support/doclava/DoclavaTask.kt
new file mode 100644
index 0000000..48a98f9
--- /dev/null
+++ b/buildSrc/src/main/kotlin/android/support/doclava/DoclavaTask.kt
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.doclava
+
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.Optional
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.javadoc.Javadoc
+import org.gradle.external.javadoc.CoreJavadocOptions
+import java.io.File
+
+// external/doclava/src/com/google/doclava/Errors.java
+private val DEFAULT_DOCLAVA_ERRORS = setOf<Int>(
+        101,  // unresolved link
+        103,  // unknown tag
+        104   // unknown param name
+)
+
+private val DEFAULT_DOCLAVA_WARNINGS = setOf<Int>(121 /* hidden type param */)
+
+private val DEFAULT_DOCLAVA_HIDDEN = setOf<Int>(
+        111,  // hidden super class
+        113   // @deprecation mismatch
+)
+
+private fun <E> CoreJavadocOptions.addMultilineMultiValueOption(
+        name: String, values: Collection<E>) {
+    addMultilineMultiValueOption(name).setValue(values.map { listOf(it.toString()) })
+}
+
+open class DoclavaTask : Javadoc() {
+
+    // All lowercase name to match MinimalJavadocOptions#docletpath
+    private var docletpath: List<File> = emptyList()
+
+    // doclava error types which will cause the build to fail
+    @Input
+    var doclavaErrors = DEFAULT_DOCLAVA_ERRORS
+
+    @Input
+    var doclavaWarnings = DEFAULT_DOCLAVA_WARNINGS
+
+    // spammy doclava warnings which we want to hide
+    @Input
+    var doclavaHidden = DEFAULT_DOCLAVA_HIDDEN
+
+    /**
+     * If non-null, the list of packages that will be treated as if they were
+     * marked with {@literal @hide}.<br>
+     * Packages names will be matched exactly; sub-packages are not automatically recognized.
+     */
+    @Optional
+    @Input
+    var hiddenPackages: Collection<String>? = null
+
+    /**
+     * If non-null and not-empty, the whitelist of packages that will be present in the generated
+     * stubs; if null or empty, then all packages have stubs generated.<br>
+     * Wildcards are accepted.
+     */
+    @Optional
+    @Input
+    var stubPackages: Set<String>? = null
+
+    @Input
+    var generateDocs = true
+
+    /**
+     * If non-null, the location of where to place the generated api file.
+     * If this is non-null, then {@link #removedApiFile} must be non-null as well.
+     */
+    @Optional
+    @OutputFile
+    var apiFile: File? = null
+
+    /**
+     * If non-null, the location of where to place the generated removed api file.
+     * If this is non-null, then {@link #apiFile} must be non-null as well.
+     */
+    @Optional
+    @OutputFile
+    var removedApiFile: File? = null
+
+    /**
+     * If non-null, the location of the generated keep list.
+     */
+    @Optional
+    @OutputFile
+    var keepListFile: File? = null
+
+    /**
+     * If non-null, the location to put the generated stub sources.
+     */
+    @Optional
+    @OutputDirectory
+    var stubsDir: File? = null
+
+    init {
+        setFailOnError(true)
+        options.doclet = "com.google.doclava.Doclava"
+        options.encoding("UTF-8")
+        options.quiet()
+        // doclava doesn't understand '-doctitle'
+        title = null
+        maxMemory = "1280m"
+        // If none of generateDocs, apiFile, keepListFile, or stubJarsDir are true, then there is
+        // no work to do.
+        onlyIf({ generateDocs || apiFile != null || keepListFile != null || stubsDir != null })
+    }
+
+    /**
+     * The doclet path which has the {@code com.gogole.doclava.Doclava} class.
+     * This option will override any doclet path set in this instance's {@link #options JavadocOptions}.
+     * @see MinimalJavadocOptions#getDocletpath()
+     */
+    @InputFiles
+    fun getDocletpath(): List<File> {
+        return docletpath
+    }
+
+    /**
+     * Sets the doclet path which has the {@code com.gogole.doclava.Doclava} class.
+     * This option will override any doclet path set in this instance's {@link #options JavadocOptions}.
+     * @see MinimalJavadocOptions#setDocletpath(java.util.List)
+     */
+    fun setDocletpath(docletpath: Collection<File>) {
+        this.docletpath = docletpath.toList()
+        // Go ahead and keep the docletpath in our JavadocOptions object in sync.
+        options.docletpath = docletpath.toList()
+    }
+
+    fun setDoclavaErrors(errors: List<Int> ) {
+        // Make it serializable.
+        doclavaErrors = errors.toSet()
+    }
+
+    fun setDoclavaWarnings(warnings: List<Int>) {
+        // Make it serializable.
+        doclavaWarnings = warnings.toSet()
+    }
+
+    fun setDoclavaHidden(hidden: List<Int>) {
+        // Make it serializable.
+        doclavaHidden = hidden.toSet()
+    }
+
+    /**
+     * "Configures" this DoclavaTask with parameters that might not be at their final values
+     * until this task is run.
+     */
+    private fun configureDoclava() = (options as CoreJavadocOptions).apply {
+
+        docletpath = this@DoclavaTask.docletpath
+
+        // configure doclava error/warning/hide levels
+        addMultilineMultiValueOption("hide", doclavaHidden)
+        addMultilineMultiValueOption("warning", doclavaWarnings)
+        addMultilineMultiValueOption("error", doclavaErrors)
+
+        if (hiddenPackages != null) {
+            addMultilineMultiValueOption("hidePackage", hiddenPackages!!)
+        }
+
+        if (!generateDocs) {
+            addOption(DoclavaJavadocOptionFileOption("nodocs"))
+        }
+
+        // If requested, generate the API files.
+        if (apiFile != null) {
+            addFileOption("api", apiFile)
+            addFileOption("removedApi", removedApiFile)
+        }
+
+        // If requested, generate the keep list.
+        addFileOption("proguard", keepListFile)
+
+        // If requested, generate stubs.
+        if (stubsDir != null) {
+            addFileOption("stubs", stubsDir)
+            val stubs = stubPackages
+            if (stubs != null) {
+                addStringOption("stubpackages", stubs.joinToString(":"))
+            }
+        }
+        // Always treat this as an Android docs task.
+        addOption(DoclavaJavadocOptionFileOption("android"))
+    }
+
+    fun coreJavadocOptions(configure: CoreJavadocOptions.() -> Unit) =
+            (options as CoreJavadocOptions).configure()
+
+    override fun generate() {
+        configureDoclava()
+        super.generate()
+    }
+}
+
diff --git a/car/AndroidManifest.xml b/car/AndroidManifest.xml
index 4e6d80f..854e097 100644
--- a/car/AndroidManifest.xml
+++ b/car/AndroidManifest.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.support.car">
+          package="androidx.car">
 </manifest>
diff --git a/car/build.gradle b/car/build.gradle
index c1be3a3..3970df9 100644
--- a/car/build.gradle
+++ b/car/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 
 plugins {
@@ -11,11 +12,11 @@
     api project(':support-v4')
     api project(':recyclerview-v7')
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_contrib, { exclude group: 'com.android.support' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(ESPRESSO_CONTRIB, libs.exclude_support)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
 }
 
 android {
diff --git a/car/lint-baseline.xml b/car/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/car/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/car/res/drawable/car_borderless_button_text_color.xml b/car/res/drawable/car_borderless_button_text_color.xml
new file mode 100644
index 0000000..ff27db5
--- /dev/null
+++ b/car/res/drawable/car_borderless_button_text_color.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2017 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<!-- Default text colors for car buttons when enabled/disabled. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/car_grey_700" android:state_enabled="false"/>
+    <item android:color="?android:attr/colorPrimary"/>
+</selector>
diff --git a/car/res/drawable/car_button_background.xml b/car/res/drawable/car_button_background.xml
index 3b139d9..1a8995c 100644
--- a/car/res/drawable/car_button_background.xml
+++ b/car/res/drawable/car_button_background.xml
@@ -18,14 +18,14 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false">
         <shape android:shape="rectangle">
-            <corners android:radius="@dimen/car_button_radius" />
+            <corners android:radius="@dimen/car_button_radius"/>
             <solid android:color="@color/car_grey_300"/>
         </shape>
     </item>
     <item>
         <shape android:shape="rectangle">
-            <corners android:radius="@dimen/car_button_radius" />
-            <solid android:color="@color/car_highlight"/>
+            <corners android:radius="@dimen/car_button_radius"/>
+            <solid android:color="?android:attr/colorPrimary"/>
         </shape>
     </item>
 </selector>
diff --git a/car/res/drawable/car_button_text_color.xml b/car/res/drawable/car_button_text_color.xml
index b14ec68..bb8c681 100644
--- a/car/res/drawable/car_button_text_color.xml
+++ b/car/res/drawable/car_button_text_color.xml
@@ -16,6 +16,6 @@
 -->
 <!-- Default text colors for car buttons when enabled/disabled. -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:color="@color/car_grey_700" />
+    <item android:color="@color/car_grey_700" android:state_enabled="false"/>
     <item android:color="@color/car_action1"/>
 </selector>
diff --git a/car/res/layout/car_drawer.xml b/car/res/layout/car_drawer.xml
index 812acb4..c4ce405 100644
--- a/car/res/layout/car_drawer.xml
+++ b/car/res/layout/car_drawer.xml
@@ -23,7 +23,7 @@
     android:background="@color/car_card"
     android:paddingTop="@dimen/car_app_bar_height" >
 
-  <android.support.car.widget.PagedListView
+  <androidx.car.widget.PagedListView
       android:id="@+id/drawer_list"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
diff --git a/car/res/layout/car_paged_list_card.xml b/car/res/layout/car_paged_list_card.xml
new file mode 100644
index 0000000..fe5de89
--- /dev/null
+++ b/car/res/layout/car_paged_list_card.xml
@@ -0,0 +1,28 @@
+<?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.
+  -->
+<android.support.v7.widget.CardView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:layout_marginBottom="@dimen/car_padding_1"
+    app:cardCornerRadius="@dimen/car_radius_1"
+    app:cardBackgroundColor="@color/car_card">
+
+    <include layout="@layout/car_paged_list_item_content" />
+
+</android.support.v7.widget.CardView>
diff --git a/v14/preference/res/values-v21/styles.xml b/car/res/layout/car_paged_list_item.xml
similarity index 66%
rename from v14/preference/res/values-v21/styles.xml
rename to car/res/layout/car_paged_list_item.xml
index 9a85987..c0861d9 100644
--- a/v14/preference/res/values-v21/styles.xml
+++ b/car/res/layout/car_paged_list_item.xml
@@ -12,9 +12,14 @@
   ~ distributed under the License is distributed on an "AS IS" BASIS,
   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
+  ~ limitations under the License.
   -->
-<resources>
-    <dimen name="preference_no_icon_padding_start">72dp</dimen>
-</resources>
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:background="@color/car_card">
 
+    <include layout="@layout/car_paged_list_item_content" />
+
+</FrameLayout>
diff --git a/car/res/layout/car_paged_list_item_content.xml b/car/res/layout/car_paged_list_item_content.xml
new file mode 100644
index 0000000..0e6b809
--- /dev/null
+++ b/car/res/layout/car_paged_list_item_content.xml
@@ -0,0 +1,102 @@
+<?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.
+  -->
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent">
+
+    <!-- Primary Action. -->
+    <ImageView
+        android:id="@+id/primary_icon"
+        android:layout_width="@dimen/car_single_line_list_item_height"
+        android:layout_height="@dimen/car_single_line_list_item_height"
+        android:layout_centerVertical="true"/>
+
+    <!-- Text. -->
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_toStartOf="@id/supplemental_actions"
+        android:singleLine="true"
+        android:ellipsize="end"/>
+    <TextView
+        android:id="@+id/body"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_toStartOf="@id/supplemental_actions"/>
+
+    <!-- Supplemental action(s) - supports either 1 supplemental icon or up to 2 action buttons. -->
+    <LinearLayout
+        android:id="@+id/supplemental_actions"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentEnd="true"
+        android:layout_marginEnd="@dimen/car_keyline_1"
+        android:layout_centerVertical="true"
+        android:gravity="center_vertical"
+        android:orientation="horizontal">
+        <!-- End icon with divider. -->
+        <View
+            android:id="@+id/supplemental_icon_divider"
+            android:layout_width="@dimen/car_vertical_line_divider_width"
+            android:layout_height="@dimen/car_vertical_line_divider_height"
+            android:layout_marginStart="@dimen/car_padding_4"
+            android:background="@color/car_list_divider"/>
+        <ImageView
+            android:id="@+id/supplemental_icon"
+            android:layout_width="@dimen/car_primary_icon_size"
+            android:layout_height="@dimen/car_primary_icon_size"
+            android:layout_marginStart="@dimen/car_padding_4"
+            android:scaleType="fitCenter"/>
+
+        <!-- Up to 2 action buttons with dividers. -->
+        <View
+            android:id="@+id/action2_divider"
+            android:layout_width="@dimen/car_vertical_line_divider_width"
+            android:layout_height="@dimen/car_vertical_line_divider_height"
+            android:layout_marginStart="@dimen/car_padding_4"
+            android:background="@color/car_list_divider"/>
+        <Button
+            android:id="@+id/action2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/car_padding_4"
+            android:ellipsize="end"
+            android:maxLength="@integer/car_borderless_button_text_length_limit"
+            android:maxLines="1"
+            android:background="@color/car_card"
+            style="@style/CarButton.Borderless"/>
+        <View
+            android:id="@+id/action1_divider"
+            android:layout_width="@dimen/car_vertical_line_divider_width"
+            android:layout_height="@dimen/car_vertical_line_divider_height"
+            android:layout_marginStart="@dimen/car_padding_4"
+            android:background="@color/car_list_divider"/>
+        <Button
+            android:id="@+id/action1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/car_padding_4"
+            android:ellipsize="end"
+            android:maxLength="@integer/car_borderless_button_text_length_limit"
+            android:maxLines="1"
+            android:background="@color/car_card"
+            style="@style/CarButton.Borderless"/>
+    </LinearLayout>
+</RelativeLayout>
diff --git a/car/res/layout/car_paged_recycler_view.xml b/car/res/layout/car_paged_recycler_view.xml
index 47a82ff..d3ca4a3 100644
--- a/car/res/layout/car_paged_recycler_view.xml
+++ b/car/res/layout/car_paged_recycler_view.xml
@@ -19,14 +19,14 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <android.support.car.widget.CarRecyclerView
+    <androidx.car.widget.CarRecyclerView
         android:id="@+id/recycler_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
     <!-- Putting this as the last child so that it can intercept any touch events on the
          scroll buttons. -->
-    <android.support.car.widget.PagedScrollBarView
+    <androidx.car.widget.PagedScrollBarView
         android:id="@+id/paged_scroll_view"
         android:layout_width="@dimen/car_margin"
         android:layout_height="match_parent"
diff --git a/car/res/layout/car_paged_scrollbar_buttons.xml b/car/res/layout/car_paged_scrollbar_buttons.xml
index 7dd213a..75d9414 100644
--- a/car/res/layout/car_paged_scrollbar_buttons.xml
+++ b/car/res/layout/car_paged_scrollbar_buttons.xml
@@ -29,7 +29,6 @@
         android:background="@drawable/car_pagination_background"
         android:focusable="false"
         android:hapticFeedbackEnabled="false"
-        android:scaleType="center"
         android:src="@drawable/ic_up" />
 
     <FrameLayout
@@ -37,8 +36,8 @@
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
-        android:layout_marginBottom="@dimen/car_paged_list_view_scrollbar_thumb_margin"
-        android:layout_marginTop="@dimen/car_paged_list_view_scrollbar_thumb_margin" >
+        android:layout_marginBottom="@dimen/car_scroll_bar_thumb_margin"
+        android:layout_marginTop="@dimen/car_scroll_bar_thumb_margin" >
 
         <ImageView
             android:id="@+id/scrollbar_thumb"
@@ -55,6 +54,5 @@
         android:background="@drawable/car_pagination_background"
         android:focusable="false"
         android:hapticFeedbackEnabled="false"
-        android:scaleType="center"
         android:src="@drawable/ic_down" />
 </LinearLayout>
diff --git a/car/res/values-h1752dp/dimens.xml b/car/res/values-h1752dp/dimens.xml
index 93aa85f..4b6a23d 100644
--- a/car/res/values-h1752dp/dimens.xml
+++ b/car/res/values-h1752dp/dimens.xml
@@ -14,8 +14,8 @@
 limitations under the License.
 -->
 <resources>
+    <!-- Car Component Dimensions -->
     <!-- Type Sizings -->
-    <dimen name="car_title_size">32sp</dimen>
     <dimen name="car_title2_size">40sp</dimen>
     <dimen name="car_headline1_size">56sp</dimen>
     <dimen name="car_headline2_size">50sp</dimen>
@@ -23,16 +23,31 @@
     <dimen name="car_body2_size">32sp</dimen>
     <dimen name="car_action1_size">32sp</dimen>
 
-    <!-- Car Component Dimensions -->
-    <!-- Application Bar Height -->
-    <dimen name="car_app_bar_height">112dp</dimen>
-
-    <dimen name="car_touch_target">96dp</dimen>
-
-    <!-- Icon dimensions -->
+    <!-- Icons and Buttons -->
+    <!-- Icons -->
     <dimen name="car_primary_icon_size">56dp</dimen>
     <dimen name="car_secondary_icon_size">36dp</dimen>
 
-    <!-- Line heights -->
+    <!-- Avatars -->
+    <dimen name="car_avatar_size">96dp</dimen>
+
+    <!-- Minimum touch target size. -->
+    <dimen name="car_touch_target_size">96dp</dimen>
+
+    <!-- Application Bar -->
+    <dimen name="car_app_bar_height">112dp</dimen>
+
+    <!-- List Items -->
+    <dimen name="car_single_line_list_item_height">128dp</dimen>
     <dimen name="car_double_line_list_item_height">128dp</dimen>
+
+    <!-- Cards -->
+    <dimen name="car_card_header_height">96dp</dimen>
+    <dimen name="car_card_action_bar_height">96dp</dimen>
+
+    <!-- Slide Up Menu -->
+    <dimen name="car_slide_up_menu_initial_height">128dp</dimen>
+
+    <!-- Sub Header -->
+    <dimen name="car_sub_header_height">96dp</dimen>
 </resources>
diff --git a/car/res/values-h684dp/dimens.xml b/car/res/values-h684dp/dimens.xml
index 72b04f2..039d377 100644
--- a/car/res/values-h684dp/dimens.xml
+++ b/car/res/values-h684dp/dimens.xml
@@ -15,13 +15,27 @@
 -->
 <resources>
     <!-- Car Component Dimensions -->
+    <!-- Application Bar -->
     <dimen name="car_app_bar_height">96dp</dimen>
 
-    <!-- List and Drawer Dimensions -->
+    <!-- List Items -->
+    <dimen name="car_single_line_list_item_height">116dp</dimen>
+    <dimen name="car_double_line_list_item_height">116dp</dimen>
+
+    <!-- Slide Up Menu -->
+    <dimen name="car_slide_up_menu_initial_height">116dp</dimen>
+
+    <!-- Scroll Bar -->
+    <dimen name="car_scroll_bar_padding">@dimen/car_padding_4</dimen>
+
+    <!-- Scroll Bar Thumb -->
+    <dimen name="car_scroll_bar_thumb_margin">@dimen/car_padding_2</dimen>
+
+    <!-- Scroll Bar Buttons -->
+    <dimen name="car_scroll_bar_button_size">76dp</dimen>
+
+    <!-- Drawer Dimensions -->
     <dimen name="car_drawer_list_item_icon_size">108dp</dimen>
     <dimen name="car_drawer_list_item_small_icon_size">56dp</dimen>
     <dimen name="car_drawer_list_item_end_icon_size">56dp</dimen>
-
-    <!-- Line heights -->
-    <dimen name="car_double_line_list_item_height">116dp</dimen>
 </resources>
diff --git a/car/res/values-night/colors.xml b/car/res/values-night/colors.xml
index 2ca5b02..12eb594 100644
--- a/car/res/values-night/colors.xml
+++ b/car/res/values-night/colors.xml
@@ -16,6 +16,7 @@
   -->
 <resources>
     <color name="car_title">@color/car_title_light</color>
+    <color name="car_title2">@color/car_title2_light</color>
     <color name="car_body1">@color/car_body1_light</color>
     <color name="car_body2">@color/car_body2_light</color>
 
diff --git a/car/res/values-w1280dp/dimens.xml b/car/res/values-w1280dp/dimens.xml
index ea46dcf..418e51f 100644
--- a/car/res/values-w1280dp/dimens.xml
+++ b/car/res/values-w1280dp/dimens.xml
@@ -14,14 +14,11 @@
 limitations under the License.
 -->
 <resources>
-    <dimen name="car_screen_margin_size">148dp</dimen>
-    <dimen name="car_scroll_bar_button_size">76dp</dimen>
-    
-    <dimen name="car_keyline_1">32dp</dimen>
-    <dimen name="car_keyline_2">108dp</dimen>
-    <dimen name="car_keyline_3">128dp</dimen>
-    <dimen name="car_keyline_4">168dp</dimen>
-    <dimen name="car_keyline_1_neg">32dp</dimen>
-    <dimen name="car_keyline_2_neg">108dp</dimen>
-    <dimen name="car_keyline_3_neg">128dp</dimen>
+    <!-- Framework -->
+    <!-- Margin -->
+    <dimen name="car_margin">148dp</dimen>
+
+    <!-- Keylines -->
+    <dimen name="car_keyline_4">182dp</dimen>
+    <dimen name="car_keyline_4_neg">-182dp</dimen>
 </resources>
diff --git a/car/res/values-w840dp/integers.xml b/car/res/values-w1280dp/integers.xml
similarity index 84%
rename from car/res/values-w840dp/integers.xml
rename to car/res/values-w1280dp/integers.xml
index 38c0440..62fcf37 100644
--- a/car/res/values-w840dp/integers.xml
+++ b/car/res/values-w1280dp/integers.xml
@@ -14,6 +14,10 @@
 limitations under the License.
 -->
 <resources>
-    <integer name="car_screen_num_of_columns">12</integer>
+    <!-- Application Components -->
+    <!-- Cards -->
     <integer name="column_card_default_column_span">8</integer>
+
+    <!-- Dialogs -->
+    <integer name="car_dialog_column_number">8</integer>
 </resources>
diff --git a/car/res/values-w1920dp/dimens.xml b/car/res/values-w1920dp/dimens.xml
index 9914613..b02ec00 100644
--- a/car/res/values-w1920dp/dimens.xml
+++ b/car/res/values-w1920dp/dimens.xml
@@ -14,5 +14,16 @@
 limitations under the License.
 -->
 <resources>
-    <dimen name="car_keyline_4">184dp</dimen>
+    <!-- Framework -->
+    <!-- Margin -->
+    <dimen name="car_margin">192dp</dimen>
+
+    <!-- Gutters -->
+    <dimen name="car_gutter_size">32dp</dimen>
+
+    <!-- Keylines -->
+    <dimen name="car_keyline_1">48dp</dimen>
+    <dimen name="car_keyline_3">152dp</dimen>
+    <dimen name="car_keyline_1_neg">-48dp</dimen>
+    <dimen name="car_keyline_3_neg">-152dp</dimen>
 </resources>
diff --git a/car/res/values-w1024dp/dimens.xml b/car/res/values-w1920dp/integers.xml
similarity index 86%
rename from car/res/values-w1024dp/dimens.xml
rename to car/res/values-w1920dp/integers.xml
index b1ae5ba..6519af5 100644
--- a/car/res/values-w1024dp/dimens.xml
+++ b/car/res/values-w1920dp/integers.xml
@@ -14,5 +14,7 @@
 limitations under the License.
 -->
 <resources>
-    <dimen name="car_screen_margin_size">112dp</dimen>
+    <!-- Framework -->
+    <!-- Columns -->
+    <integer name="car_column_number">16</integer>
 </resources>
diff --git a/car/res/values-w480dp/dimens.xml b/car/res/values-w480dp/dimens.xml
deleted file mode 100644
index 4077e0d..0000000
--- a/car/res/values-w480dp/dimens.xml
+++ /dev/null
@@ -1,18 +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>
-    <dimen name="car_screen_margin_size">24dp</dimen>
-</resources>
diff --git a/car/res/values-w600dp/integers.xml b/car/res/values-w600dp/integers.xml
deleted file mode 100644
index 5dcd8df..0000000
--- a/car/res/values-w600dp/integers.xml
+++ /dev/null
@@ -1,19 +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>
-    <integer name="car_screen_num_of_columns">8</integer>
-    <integer name="column_card_default_column_span">6</integer>
-</resources>
diff --git a/car/res/values-w690dp/dimens.xml b/car/res/values-w690dp/dimens.xml
index edf6c59..2d43ac8 100644
--- a/car/res/values-w690dp/dimens.xml
+++ b/car/res/values-w690dp/dimens.xml
@@ -14,11 +14,7 @@
 limitations under the License.
 -->
 <resources>
-    <dimen name="car_keyline_1">24dp</dimen>
-    <dimen name="car_keyline_2">96dp</dimen>
-    <dimen name="car_keyline_3">112dp</dimen>
-    <dimen name="car_keyline_4">148dp</dimen>
-    <dimen name="car_keyline_1_neg">-24dp</dimen>
-    <dimen name="car_keyline_2_neg">-96dp</dimen>
-    <dimen name="car_keyline_3_neg">-112dp</dimen>
+    <!-- Framework -->
+    <!-- Margin -->
+    <dimen name="car_margin">112dp</dimen>
 </resources>
diff --git a/car/res/values-w1024dp/dimens.xml b/car/res/values-w690dp/integers.xml
similarity index 62%
copy from car/res/values-w1024dp/dimens.xml
copy to car/res/values-w690dp/integers.xml
index b1ae5ba..0eb5837 100644
--- a/car/res/values-w1024dp/dimens.xml
+++ b/car/res/values-w690dp/integers.xml
@@ -14,5 +14,17 @@
 limitations under the License.
 -->
 <resources>
-    <dimen name="car_screen_margin_size">112dp</dimen>
+    <!-- Framework -->
+    <!-- Columns -->
+    <integer name="car_column_number">12</integer>
+
+    <!-- Application Components -->
+    <!-- Cards -->
+    <integer name="column_card_default_column_span">12</integer>
+
+    <!-- Dialogs -->
+    <integer name="car_dialog_column_number">10</integer>
+
+    <!-- Slide Up Menu -->
+    <integer name="car_slide_up_menu_column_number">12</integer>
 </resources>
diff --git a/car/res/values-w720dp/dimens.xml b/car/res/values-w720dp/dimens.xml
deleted file mode 100644
index b1ae5ba..0000000
--- a/car/res/values-w720dp/dimens.xml
+++ /dev/null
@@ -1,18 +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>
-    <dimen name="car_screen_margin_size">112dp</dimen>
-</resources>
diff --git a/car/res/values-w840dp/dimens.xml b/car/res/values-w930dp/dimens.xml
similarity index 68%
rename from car/res/values-w840dp/dimens.xml
rename to car/res/values-w930dp/dimens.xml
index 8b4d992..6d7714e 100644
--- a/car/res/values-w840dp/dimens.xml
+++ b/car/res/values-w930dp/dimens.xml
@@ -14,8 +14,17 @@
 limitations under the License.
 -->
 <resources>
+    <!-- Framework -->
+    <!-- Gutters -->
+    <dimen name="car_gutter_size">24dp</dimen>
+
+    <!-- Keylines -->
     <dimen name="car_keyline_1">32dp</dimen>
     <dimen name="car_keyline_2">108dp</dimen>
     <dimen name="car_keyline_3">128dp</dimen>
-    <dimen name="car_screen_gutter_size">24dp</dimen>
+    <dimen name="car_keyline_4">168dp</dimen>
+    <dimen name="car_keyline_1_neg">-32dp</dimen>
+    <dimen name="car_keyline_2_neg">-108dp</dimen>
+    <dimen name="car_keyline_3_neg">-128dp</dimen>
+    <dimen name="car_keyline_4_neg">-168dp</dimen>
 </resources>
diff --git a/car/res/values-w1024dp/dimens.xml b/car/res/values-w930dp/integers.xml
similarity index 76%
copy from car/res/values-w1024dp/dimens.xml
copy to car/res/values-w930dp/integers.xml
index b1ae5ba..60ddfa1 100644
--- a/car/res/values-w1024dp/dimens.xml
+++ b/car/res/values-w930dp/integers.xml
@@ -14,5 +14,10 @@
 limitations under the License.
 -->
 <resources>
-    <dimen name="car_screen_margin_size">112dp</dimen>
+    <!-- Application Components -->
+    <!-- Cards -->
+    <integer name="column_card_default_column_span">10</integer>
+
+    <!-- Dialogs -->
+    <integer name="car_dialog_column_number">10</integer>
 </resources>
diff --git a/car/res/values/attrs.xml b/car/res/values/attrs.xml
index 0ba8f55..01ed95f 100644
--- a/car/res/values/attrs.xml
+++ b/car/res/values/attrs.xml
@@ -28,8 +28,24 @@
         <!-- Set to true/false to offset rows as they slide off screen. Defaults to true -->
         <attr name="offsetRows" format="boolean" />
         <!-- Whether or not to offset the list view by the width of scroll bar. Setting this to
-             true will ensure that any views within the list will not overlap the scroll bar. -->
+             true will ensure that any views within the list will not overlap the scroll bar.
+             Deprecated: use gutter instead. If gutter is specified, this value is ignored.-->
         <attr name="offsetScrollBar" format="boolean" />
+        <!-- Whether to include a gutter to the start, end or both sides of the list view items.
+             The gutter width will be the width of the scrollbar, and by default will be set to
+             both. -->
+        <attr name="gutter" format="enum">
+            <!-- No gutter on either side, the list view items will extend the full width of the
+                 PagedListView. -->
+            <enum name="none" value="0" />
+            <!-- Include a gutter on the start side only (i.e. the side with the scrollbar). -->
+            <enum name="start" value="1" />
+            <!-- Include a gutter on the end side only (i.e. the opposite side to the
+                 scrollbar). -->
+            <enum name="end" value="2" />
+            <!-- Include a gutter on both sides of the list view items. -->
+            <enum name="both" value="3" />
+        </attr>
         <!-- Whether to display the scrollbar or not. Defaults to true. -->
         <attr name="scrollBarEnabled" format="boolean" />
         <!-- Whether or not to show a diving line between each item of the list. -->
@@ -43,7 +59,8 @@
         <!-- A starting margin before the drawing of the dividing line. This margin will be an
              offset from the view specified by "alignDividerStartTo" if given. -->
         <attr name="dividerStartMargin" format="dimension" />
-        <!-- The width of the margin on the right side of the list -->
+        <!-- The width of the margin on the right side of the list.
+             Deprecated: use gutter instead. If gutter is specified, this value is ignored.-->
         <attr name="listEndMargin" format="dimension" />
         <!-- An optional spacing between items in the list -->
         <attr name="itemSpacing" format="dimension" />
diff --git a/car/res/values/colors.xml b/car/res/values/colors.xml
index 00c6cf9..5b90125 100644
--- a/car/res/values/colors.xml
+++ b/car/res/values/colors.xml
@@ -63,6 +63,10 @@
     <color name="car_title_dark">@color/car_grey_900</color>
     <color name="car_title">@color/car_title_dark</color>
 
+    <color name="car_title2_light">@color/car_grey_100</color>
+    <color name="car_title2_dark">@color/car_grey_900</color>
+    <color name="car_title2">@color/car_title2_dark</color>
+
     <color name="car_headline1_light">@color/car_grey_100</color>
     <color name="car_headline1_dark">@color/car_grey_800</color>
     <color name="car_headline1">@color/car_headline1_dark</color>
diff --git a/car/res/values/dimens.xml b/car/res/values/dimens.xml
index c42437d..8e8621c 100644
--- a/car/res/values/dimens.xml
+++ b/car/res/values/dimens.xml
@@ -14,28 +14,22 @@
 limitations under the License.
 -->
 <resources>
-    <!-- Keylines for content. -->
-    <dimen name="car_keyline_1">48dp</dimen>
-    <dimen name="car_keyline_2">108dp</dimen>
-    <dimen name="car_keyline_3">152dp</dimen>
-    <dimen name="car_keyline_4">182dp</dimen>
-    <dimen name="car_keyline_1_neg">-48dp</dimen>
-    <dimen name="car_keyline_2_neg">-108dp</dimen>
-    <dimen name="car_keyline_3_neg">-152dp</dimen>
+    <!-- Framework -->
+    <!-- Margin -->
+    <dimen name="car_margin">20dp</dimen>
 
-    <!-- Type Sizings -->
-    <dimen name="car_title_size">26sp</dimen>
-    <dimen name="car_title2_size">32sp</dimen>
-    <dimen name="car_headline1_size">45sp</dimen>
-    <dimen name="car_headline2_size">36sp</dimen>
-    <dimen name="car_headline3_size">24sp</dimen>
-    <dimen name="car_headline4_size">20sp</dimen>
-    <dimen name="car_body1_size">32sp</dimen>
-    <dimen name="car_body2_size">26sp</dimen>
-    <dimen name="car_body3_size">16sp</dimen>
-    <dimen name="car_body4_size">14sp</dimen>
-    <dimen name="car_body5_size">18sp</dimen>
-    <dimen name="car_action1_size">26sp</dimen>
+    <!-- Gutters -->
+    <dimen name="car_gutter_size">16dp</dimen>
+
+    <!-- Keylines -->
+    <dimen name="car_keyline_1">24dp</dimen>
+    <dimen name="car_keyline_2">96dp</dimen>
+    <dimen name="car_keyline_3">112dp</dimen>
+    <dimen name="car_keyline_4">148dp</dimen>
+    <dimen name="car_keyline_1_neg">-24dp</dimen>
+    <dimen name="car_keyline_2_neg">-96dp</dimen>
+    <dimen name="car_keyline_3_neg">-112dp</dimen>
+    <dimen name="car_keyline_4_neg">-148dp</dimen>
 
     <!-- Paddings -->
     <dimen name="car_padding_1">4dp</dimen>
@@ -50,71 +44,106 @@
     <dimen name="car_radius_3">16dp</dimen>
     <dimen name="car_radius_5">100dp</dimen>
 
-    <!-- Margin -->
-    <dimen name="car_margin">112dp</dimen>
-
     <!-- Car Component Dimensions -->
-    <!-- Application Bar Height -->
-    <dimen name="car_app_bar_height">80dp</dimen>
+    <!-- Type Sizings -->
+    <dimen name="car_title_size">32sp</dimen>
+    <dimen name="car_title2_size">32sp</dimen>
+    <dimen name="car_headline1_size">45sp</dimen>
+    <dimen name="car_headline2_size">36sp</dimen>
+    <dimen name="car_headline3_size">24sp</dimen>
+    <dimen name="car_headline4_size">20sp</dimen>
+    <dimen name="car_body1_size">32sp</dimen>
+    <dimen name="car_body2_size">26sp</dimen>
+    <dimen name="car_body3_size">16sp</dimen>
+    <dimen name="car_body4_size">14sp</dimen>
+    <dimen name="car_body5_size">18sp</dimen>
+    <dimen name="car_action1_size">26sp</dimen>
 
-    <!-- The height of the bar that contains an applications action buttons. -->
-    <dimen name="car_action_bar_height">128dp</dimen>
-
-    <!-- Minimum touch target size. -->
-    <dimen name="car_touch_target">76dp</dimen>
-
-    <!-- Button Dimensions -->
-    <dimen name="car_button_height">64dp</dimen>
-    <dimen name="car_button_min_width">158dp</dimen>
-    <dimen name="car_button_horizontal_padding">@dimen/car_padding_4</dimen>
-    <dimen name="car_button_radius">@dimen/car_radius_1</dimen>
-
-    <!-- Icon dimensions -->
+    <!-- Icons and Buttons -->
+    <!-- Icons -->
     <dimen name="car_primary_icon_size">44dp</dimen>
     <dimen name="car_secondary_icon_size">24dp</dimen>
 
-    <!-- Line heights -->
+    <!-- Avatars -->
+    <dimen name="car_avatar_size">56dp</dimen>
+
+    <!-- Minimum touch target size. -->
+    <dimen name="car_touch_target_size">76dp</dimen>
+
+    <!-- Buttons -->
+    <dimen name="car_button_height">64dp</dimen>
+    <dimen name="car_button_min_width">158dp</dimen>
+    <dimen name="car_button_horizontal_padding">@dimen/car_padding_4</dimen>
+    <dimen name="car_borderless_button_horizontal_padding">0dp</dimen>
+    <dimen name="car_button_radius">@dimen/car_radius_1</dimen>
+
+    <!-- Application Bar -->
+    <dimen name="car_app_bar_height">80dp</dimen>
+
+    <!-- Action Bars -->
+    <dimen name="car_action_bar_height">128dp</dimen>
+    <dimen name="car_secondary_single_action_bar_height">@dimen/car_action_bar_height</dimen>
+    <dimen name="car_secondary_double_action_bar_height">256dp</dimen>
+
+    <!-- Lists -->
     <dimen name="car_single_line_list_item_height">76dp</dimen>
     <dimen name="car_double_line_list_item_height">96dp</dimen>
+    <dimen name="car_list_divider_height">1dp</dimen>
+    <!-- The height of a vertical line divider. -->
+    <dimen name="car_vertical_line_divider_height">60dp</dimen>
+    <dimen name="car_vertical_line_divider_width">1dp</dimen>
 
-    <!-- List and Drawer Dimensions -->
-    <!-- The margin on both sides of the screen before the contents of the PagedListView. -->
-    <dimen name="car_card_margin">96dp</dimen>
+    <!-- Cards -->
+    <dimen name="car_card_header_height">76dp</dimen>
+    <dimen name="car_card_action_bar_height">76dp</dimen>
 
-    <!-- The height of the dividers in the list. -->
-    <dimen name="car_divider_height">1dp</dimen>
+    <!-- Dialogs -->
+    <dimen name="car_dialog_header_height">@dimen/car_card_header_height</dimen>
+    <dimen name="car_dialog_action_bar_height">@dimen/car_card_action_bar_height</dimen>
 
+    <!-- Slide Up Menu -->
+    <dimen name="car_slide_up_menu_initial_height">76dp</dimen>
+
+    <!-- Slide Down Menu -->
+    <dimen name="car_slide_down_menu_initial_height">@dimen/car_slide_up_menu_initial_height</dimen>
+
+    <!-- Sub Header -->
+    <dimen name="car_sub_header_height">76dp</dimen>
+
+    <!-- Slider -->
+    <dimen name="car_slider_height">6dp</dimen>
+    <dimen name="car_slider_knob_size">20dp</dimen>
+
+    <!-- Scroll Bar -->
+    <dimen name="car_scroll_bar_padding">@dimen/car_padding_2</dimen>
+
+    <!-- Scroll Bar Thumb -->
+    <dimen name="car_scroll_bar_thumb_width">@dimen/car_slider_height</dimen>
+    <dimen name="car_min_scroll_bar_thumb_height">48dp</dimen>
+    <dimen name="car_max_scroll_bar_thumb_height">128dp</dimen>
+    <dimen name="car_scroll_bar_thumb_margin">@dimen/car_padding_1</dimen>
+
+    <!-- Scroll Bar and Alpha Jump Buttons -->
+    <dimen name="car_scroll_bar_button_size">56dp</dimen>
+    <dimen name="car_alpha_jump_button_size">@dimen/car_scroll_bar_button_size</dimen>
+
+    <!-- Progress Bar -->
+    <dimen name="car_progress_bar_height">@dimen/car_slider_height</dimen>
+
+    <!-- Text Input -->
+    <dimen name="car_text_input_line_height">2dp</dimen>
+
+    <!-- PagedListView Dimensions -->
     <!-- Sample row height used for scroll bar calculations in the off chance that a view hasn't
-         been measured. It's highly unlikely that this value will actually be used for more than
-         a frame max. The sample row is a 96dp card + 16dp margin on either side. -->
+        been measured. It's highly unlikely that this value will actually be used for more than
+        a frame max. The sample row is a 96dp card + 16dp margin on either side. -->
     <dimen name="car_sample_row_height">128dp</dimen>
 
     <!-- The amount of space the LayoutManager will make sure the last item on the screen is
          peeking before scrolling down -->
     <dimen name="car_last_card_peek_amount">16dp</dimen>
 
-    <!-- The spacing between each column that fits on the screen. The number of columns is
-         determined by integer/car_screen_num_of_columns. -->
-    <dimen name="car_screen_gutter_size">16dp</dimen>
-
-    <!-- The margin on both sizes of the scroll bar thumb. -->
-    <dimen name="car_paged_list_view_scrollbar_thumb_margin">8dp</dimen>
-
-    <!-- The size of the scroll bar up and down arrows. -->
-    <dimen name="car_scroll_bar_button_size">44dp</dimen>
-
-    <!-- The padding around the scroll bar. -->
-    <dimen name="car_scroll_bar_padding">16dp</dimen>
-
-    <!-- The width of the scroll bar thumb. -->
-    <dimen name="car_scroll_bar_thumb_width">6dp</dimen>
-
-    <!-- The minimum the scrollbar thumb can shrink to -->
-    <dimen name="min_thumb_height">48dp</dimen>
-
-    <!-- The maximum the scrollbar thumb can grow to -->
-    <dimen name="max_thumb_height">128dp</dimen>
-
+    <!-- Drawer Dimensions -->
     <!-- Size of progress-bar in Drawer -->
     <dimen name="car_drawer_progress_bar_size">48dp</dimen>
 
diff --git a/car/res/values/integers.xml b/car/res/values/integers.xml
index 575d646..6352d7c 100644
--- a/car/res/values/integers.xml
+++ b/car/res/values/integers.xml
@@ -14,10 +14,28 @@
 limitations under the License.
 -->
 <resources>
-    <!-- The number of columns that appear on-screen. -->
-    <integer name="car_screen_num_of_columns">4</integer>
+    <!-- Framework -->
+    <!-- Columns -->
+    <integer name="car_column_number">4</integer>
 
-    <!-- The default number of columns that a ColumnCardView will span if columnSpan is not
-         specified.-->
+    <!-- Application Components -->
+    <!-- Action Bar -->
+    <integer name="action_bar_column_number">@integer/car_column_number</integer>
+
+    <!-- Cards -->
     <integer name="column_card_default_column_span">4</integer>
+
+    <!-- Dialogs -->
+    <integer name="car_dialog_column_number">10</integer>
+
+    <!-- Slide Up Menu -->
+    <integer name="car_slide_up_menu_column_number">4</integer>
+
+    <!-- The length limit of body text in a paged list item. String longer than this limit should be
+         truncated. -->
+    <integer name="car_list_item_text_length_limit">120</integer>
+
+    <!-- The length limit of text in a borderless button. String longer than this limit should be
+         truncated. -->
+    <integer name="car_borderless_button_text_length_limit">20</integer>
 </resources>
diff --git a/car/res/values/strings.xml b/car/res/values/strings.xml
index 65f08b6..1fb4cf4 100644
--- a/car/res/values/strings.xml
+++ b/car/res/values/strings.xml
@@ -21,4 +21,5 @@
          -->
     <string name="car_drawer_open" translatable="false">Open drawer</string>
     <string name="car_drawer_close" translatable="false">Close drawer</string>
+    <string name="ellipsis" translatable="false">&#8230;</string>
 </resources>
diff --git a/car/res/values/styles.xml b/car/res/values/styles.xml
index 61e089b..606bdc5 100644
--- a/car/res/values/styles.xml
+++ b/car/res/values/styles.xml
@@ -15,25 +15,42 @@
 -->
 <resources>
     <!-- The styling for title text. The color of this text changes based on day/night mode. -->
-    <style name="CarTitle" >
+    <style name="CarTitle">
         <item name="android:textStyle">normal</item>
         <item name="android:textSize">@dimen/car_title_size</item>
         <item name="android:textColor">@color/car_title</item>
     </style>
 
     <!-- Title text that is permanently a dark color. -->
-    <style name="CarTitle.Dark" >
+    <style name="CarTitle.Dark">
         <item name="android:textColor">@color/car_title_dark</item>
     </style>
 
     <!-- Title text that is permanently a light color. -->
-    <style name="CarTitle.Light" >
+    <style name="CarTitle.Light">
         <item name="android:textColor">@color/car_title_light</item>
     </style>
 
+    <!-- The styling for title2 text. The color of this text changes based on day/night mode. -->
+    <style name="CarTitle2">
+        <item name="android:textStyle">normal</item>
+        <item name="android:textSize">@dimen/car_title2_size</item>
+        <item name="android:textColor">@color/car_title2</item>
+    </style>
+
+    <!-- Title2 text that is permanently a dark color. -->
+    <style name="CarTitle2.Dark">
+        <item name="android:textColor">@color/car_title2_dark</item>
+    </style>
+
+    <!-- Title2 text that is permanently a light color. -->
+    <style name="CarTitle2.Light">
+        <item name="android:textColor">@color/car_title2_light</item>
+    </style>
+
     <!-- The styling for the main headline text. The color of this text changes based on the
          day/night mode. -->
-    <style name="CarHeadline1" >
+    <style name="CarHeadline1">
         <item name="android:textStyle">normal</item>
         <item name="android:textSize">@dimen/car_headline1_size</item>
         <item name="android:textColor">@color/car_headline1</item>
@@ -41,7 +58,7 @@
 
     <!-- The styling for a sub-headline text. The color of this text changes based on the
          day/night mode. -->
-    <style name="CarHeadline2" >
+    <style name="CarHeadline2">
         <item name="android:textStyle">normal</item>
         <item name="android:textSize">@dimen/car_headline2_size</item>
         <item name="android:textColor">@color/car_headline2</item>
@@ -49,7 +66,7 @@
 
     <!-- The styling for a smaller alternate headline text. The color of this text changes based on
          the day/night mode. -->
-    <style name="CarHeadline3" >
+    <style name="CarHeadline3">
         <item name="android:textStyle">normal</item>
         <item name="android:textSize">@dimen/car_headline3_size</item>
         <item name="android:textColor">@color/car_headline3</item>
@@ -57,14 +74,14 @@
 
     <!-- The styling for the smallest headline text. The color of this text changes based on the
          day/night mode. -->
-    <style name="CarHeadline4" >
+    <style name="CarHeadline4">
         <item name="android:textStyle">normal</item>
         <item name="android:textSize">@dimen/car_headline4_size</item>
         <item name="android:textColor">@color/car_headline4</item>
     </style>
 
     <!-- The styling for body text. The color of this text changes based on the day/night mode. -->
-    <style name="CarBody1" >
+    <style name="CarBody1">
         <item name="android:textStyle">normal</item>
         <item name="android:textSize">@dimen/car_body1_size</item>
         <item name="android:textColor">@color/car_body1</item>
@@ -72,7 +89,7 @@
 
     <!-- An alternate styling for body text that is both a different color and size than
          CarBody1. -->
-    <style name="CarBody2" >
+    <style name="CarBody2">
         <item name="android:textStyle">normal</item>
         <item name="android:textSize">@dimen/car_body2_size</item>
         <item name="android:textColor">@color/car_body2</item>
@@ -80,7 +97,7 @@
 
     <!-- A smaller styling for body text. The color of this text changes based on the day/night
          mode. -->
-    <style name="CarBody3" >
+    <style name="CarBody3">
         <item name="android:textStyle">normal</item>
         <item name="android:textSize">@dimen/car_body3_size</item>
         <item name="android:textColor">@color/car_body3</item>
@@ -88,7 +105,7 @@
 
     <!-- The smallest styling for body text. The color of this text changes based on the day/night
          mode. -->
-    <style name="CarBody4" >
+    <style name="CarBody4">
         <item name="android:textStyle">normal</item>
         <item name="android:textSize">@dimen/car_body4_size</item>
         <item name="android:textColor">@color/car_body4</item>
@@ -119,14 +136,17 @@
         <item name="android:background">@drawable/car_button_background</item>
     </style>
 
-    <style name="CarBorderlessButton" parent="android:Widget.Material.Button.Borderless">
+    <style name="CarButton.Borderless" parent="android:Widget.Material.Button.Borderless">
         <item name="android:layout_height">@dimen/car_button_height</item>
-        <item name="android:minWidth">@dimen/car_button_min_width</item>
-        <item name="android:paddingStart">@dimen/car_button_horizontal_padding</item>
-        <item name="android:paddingEnd">@dimen/car_button_horizontal_padding</item>
+        <item name="android:paddingStart">@dimen/car_borderless_button_horizontal_padding</item>
+        <item name="android:paddingEnd">@dimen/car_borderless_button_horizontal_padding</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textSize">@dimen/car_action1_size</item>
-        <item name="android:textColor">@drawable/car_button_text_color</item>
+        <item name="android:textColor">@drawable/car_borderless_button_text_color</item>
         <item name="android:textAllCaps">true</item>
     </style>
+
+    <!-- Style for the progress bars -->
+    <style name="CarProgressBar.Horizontal"
+           parent="android:Widget.Material.ProgressBar.Horizontal"/>
 </resources>
diff --git a/car/src/main/java/android/support/car/drawer/CarDrawerActivity.java b/car/src/main/java/androidx/car/drawer/CarDrawerActivity.java
similarity index 98%
rename from car/src/main/java/android/support/car/drawer/CarDrawerActivity.java
rename to car/src/main/java/androidx/car/drawer/CarDrawerActivity.java
index f46c652..55bb23c 100644
--- a/car/src/main/java/android/support/car/drawer/CarDrawerActivity.java
+++ b/car/src/main/java/androidx/car/drawer/CarDrawerActivity.java
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-package android.support.car.drawer;
+package androidx.car.drawer;
 
 import android.content.res.Configuration;
 import android.os.Bundle;
 import android.support.annotation.LayoutRes;
 import android.support.annotation.Nullable;
-import android.support.car.R;
 import android.support.v4.widget.DrawerLayout;
 import android.support.v7.app.ActionBarDrawerToggle;
 import android.support.v7.app.AppCompatActivity;
@@ -30,6 +29,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.car.R;
+
 /**
  * Common base Activity for car apps that need to present a Drawer.
  *
diff --git a/car/src/main/java/android/support/car/drawer/CarDrawerAdapter.java b/car/src/main/java/androidx/car/drawer/CarDrawerAdapter.java
similarity index 98%
rename from car/src/main/java/android/support/car/drawer/CarDrawerAdapter.java
rename to car/src/main/java/androidx/car/drawer/CarDrawerAdapter.java
index b0fd965..ca16413 100644
--- a/car/src/main/java/android/support/car/drawer/CarDrawerAdapter.java
+++ b/car/src/main/java/androidx/car/drawer/CarDrawerAdapter.java
@@ -14,20 +14,21 @@
  * limitations under the License.
  */
 
-package android.support.car.drawer;
+package androidx.car.drawer;
 
 import android.content.Context;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.car.R;
-import android.support.car.widget.PagedListView;
 import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.car.R;
+import androidx.car.widget.PagedListView;
+
 /**
  * Base adapter for displaying items in the car navigation drawer, which uses a
  * {@link PagedListView}.
diff --git a/car/src/main/java/android/support/car/drawer/CarDrawerController.java b/car/src/main/java/androidx/car/drawer/CarDrawerController.java
similarity index 97%
rename from car/src/main/java/android/support/car/drawer/CarDrawerController.java
rename to car/src/main/java/androidx/car/drawer/CarDrawerController.java
index 7b23714..e26054f 100644
--- a/car/src/main/java/android/support/car/drawer/CarDrawerController.java
+++ b/car/src/main/java/androidx/car/drawer/CarDrawerController.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.car.drawer;
+package androidx.car.drawer;
 
 import android.content.Context;
 import android.content.res.Configuration;
@@ -22,8 +22,6 @@
 import android.support.annotation.AnimRes;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.car.R;
-import android.support.car.widget.PagedListView;
 import android.support.v4.widget.DrawerLayout;
 import android.support.v7.app.ActionBarDrawerToggle;
 import android.support.v7.widget.RecyclerView;
@@ -34,7 +32,10 @@
 import android.view.animation.AnimationUtils;
 import android.widget.ProgressBar;
 
-import java.util.Stack;
+import java.util.ArrayDeque;
+
+import androidx.car.R;
+import androidx.car.widget.PagedListView;
 
 /**
  * A controller that will handle the set up of the navigation drawer. It will hook up the
@@ -58,7 +59,7 @@
      * this stack is the order that the user has visited each level. When the user navigates up,
      * the adapters are popped from this list.
      */
-    private final Stack<CarDrawerAdapter> mAdapterStack = new Stack<>();
+    private final ArrayDeque<CarDrawerAdapter> mAdapterStack = new ArrayDeque<>();
 
     private final Context mContext;
 
@@ -114,11 +115,10 @@
         }
 
         // The root adapter is always the last item in the stack.
-        if (mAdapterStack.size() > 0) {
-            mAdapterStack.set(0, rootAdapter);
-        } else {
-            mAdapterStack.push(rootAdapter);
+        if (!mAdapterStack.isEmpty()) {
+            mAdapterStack.removeLast();
         }
+        mAdapterStack.addLast(rootAdapter);
 
         setToolbarTitleFrom(rootAdapter);
         mDrawerList.setAdapter(rootAdapter);
diff --git a/car/src/main/java/android/support/car/drawer/DrawerItemClickListener.java b/car/src/main/java/androidx/car/drawer/DrawerItemClickListener.java
similarity index 95%
rename from car/src/main/java/android/support/car/drawer/DrawerItemClickListener.java
rename to car/src/main/java/androidx/car/drawer/DrawerItemClickListener.java
index d707dbd..4c0c7a2 100644
--- a/car/src/main/java/android/support/car/drawer/DrawerItemClickListener.java
+++ b/car/src/main/java/androidx/car/drawer/DrawerItemClickListener.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.car.drawer;
+package androidx.car.drawer;
 
 /**
  * Listener for handling clicks on items/views managed by {@link DrawerItemViewHolder}.
diff --git a/car/src/main/java/android/support/car/drawer/DrawerItemViewHolder.java b/car/src/main/java/androidx/car/drawer/DrawerItemViewHolder.java
similarity index 95%
rename from car/src/main/java/android/support/car/drawer/DrawerItemViewHolder.java
rename to car/src/main/java/androidx/car/drawer/DrawerItemViewHolder.java
index d016b2d..8bbded9 100644
--- a/car/src/main/java/android/support/car/drawer/DrawerItemViewHolder.java
+++ b/car/src/main/java/androidx/car/drawer/DrawerItemViewHolder.java
@@ -14,19 +14,20 @@
  * limitations under the License.
  */
 
-package android.support.car.drawer;
+package androidx.car.drawer;
 
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.car.R;
 import android.support.v7.widget.RecyclerView;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.car.R;
+
 /**
  * Re-usable {@link RecyclerView.ViewHolder} for displaying items in the
- * {@link android.support.car.drawer.CarDrawerAdapter}.
+ * {@link androidx.car.drawer.CarDrawerAdapter}.
  */
 public class DrawerItemViewHolder extends RecyclerView.ViewHolder {
     private final ImageView mIcon;
diff --git a/car/src/main/java/android/support/car/utils/ColumnCalculator.java b/car/src/main/java/androidx/car/utils/ColumnCalculator.java
similarity index 95%
rename from car/src/main/java/android/support/car/utils/ColumnCalculator.java
rename to car/src/main/java/androidx/car/utils/ColumnCalculator.java
index fa5dd43..35b1a91 100644
--- a/car/src/main/java/android/support/car/utils/ColumnCalculator.java
+++ b/car/src/main/java/androidx/car/utils/ColumnCalculator.java
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-package android.support.car.utils;
+package androidx.car.utils;
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.support.car.R;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.WindowManager;
 
+import androidx.car.R;
+
 /**
  * Utility class that calculates the size of the columns that will fit on the screen. A column's
  * width is determined by the size of the margins and gutters (space between the columns) that fit
@@ -66,8 +67,8 @@
     private ColumnCalculator(Context context) {
         Resources res = context.getResources();
         int marginSize = res.getDimensionPixelSize(R.dimen.car_margin);
-        mGutterSize = res.getDimensionPixelSize(R.dimen.car_screen_gutter_size);
-        mNumOfColumns = res.getInteger(R.integer.car_screen_num_of_columns);
+        mGutterSize = res.getDimensionPixelSize(R.dimen.car_gutter_size);
+        mNumOfColumns = res.getInteger(R.integer.car_column_number);
 
         if (Log.isLoggable(TAG, Log.DEBUG)) {
             Log.d(TAG, String.format("marginSize: %d; numOfColumns: %d; gutterSize: %d",
diff --git a/car/src/main/java/android/support/car/widget/CarItemAnimator.java b/car/src/main/java/androidx/car/widget/CarItemAnimator.java
similarity index 98%
rename from car/src/main/java/android/support/car/widget/CarItemAnimator.java
rename to car/src/main/java/androidx/car/widget/CarItemAnimator.java
index ef22c48..e6bfd05 100644
--- a/car/src/main/java/android/support/car/widget/CarItemAnimator.java
+++ b/car/src/main/java/androidx/car/widget/CarItemAnimator.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import android.support.v7.widget.DefaultItemAnimator;
 import android.support.v7.widget.RecyclerView;
diff --git a/car/src/main/java/android/support/car/widget/CarRecyclerView.java b/car/src/main/java/androidx/car/widget/CarRecyclerView.java
similarity index 98%
rename from car/src/main/java/android/support/car/widget/CarRecyclerView.java
rename to car/src/main/java/androidx/car/widget/CarRecyclerView.java
index bb9cb71..1d89ed1 100644
--- a/car/src/main/java/android/support/car/widget/CarRecyclerView.java
+++ b/car/src/main/java/androidx/car/widget/CarRecyclerView.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import android.content.Context;
 import android.graphics.Canvas;
diff --git a/car/src/main/java/android/support/car/widget/ColumnCardView.java b/car/src/main/java/androidx/car/widget/ColumnCardView.java
similarity index 95%
rename from car/src/main/java/android/support/car/widget/ColumnCardView.java
rename to car/src/main/java/androidx/car/widget/ColumnCardView.java
index 06f8553..9ec2bb6 100644
--- a/car/src/main/java/android/support/car/widget/ColumnCardView.java
+++ b/car/src/main/java/androidx/car/widget/ColumnCardView.java
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.support.car.R;
-import android.support.car.utils.ColumnCalculator;
 import android.support.v7.widget.CardView;
 import android.util.AttributeSet;
 import android.util.Log;
 
+import androidx.car.R;
+import androidx.car.utils.ColumnCalculator;
+
 /**
  * A {@link CardView} whose width can be specified by the number of columns that it will span.
  *
@@ -34,7 +35,7 @@
  * a default span value that it uses.
  *
  * <pre>
- * &lt;android.support.car.widget.ColumnCardView
+ * &lt;androidx.car.widget.ColumnCardView
  *     android:layout_width="wrap_content"
  *     android:layout_height="wrap_content"
  *     app:columnSpan="4" /&gt;
diff --git a/car/src/main/java/android/support/car/widget/DayNightStyle.java b/car/src/main/java/androidx/car/widget/DayNightStyle.java
similarity index 98%
rename from car/src/main/java/android/support/car/widget/DayNightStyle.java
rename to car/src/main/java/androidx/car/widget/DayNightStyle.java
index ff5a1b3..6e3ecbe 100644
--- a/car/src/main/java/android/support/car/widget/DayNightStyle.java
+++ b/car/src/main/java/androidx/car/widget/DayNightStyle.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import android.support.annotation.IntDef;
 
diff --git a/car/src/main/java/androidx/car/widget/ListItem.java b/car/src/main/java/androidx/car/widget/ListItem.java
new file mode 100644
index 0000000..ad1e3b8
--- /dev/null
+++ b/car/src/main/java/androidx/car/widget/ListItem.java
@@ -0,0 +1,720 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.car.widget;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.IntDef;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+import java.lang.annotation.Retention;
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.car.R;
+
+/**
+ * Class to build a list item.
+ *
+ * <p>An item supports primary action and supplemental action(s).
+ *
+ * <p>An item visually composes of 3 parts; each part may contain multiple views.
+ * <ul>
+ *     <li>{@code Primary Action}: represented by an icon of following types.
+ *     <ul>
+ *         <li>Primary Icon - icon size could be large or small.
+ *         <li>No Icon
+ *         <li>Empty Icon - different from No Icon by how much margin {@code Text} offsets
+ *     </ul>
+ *     <li>{@code Text}: supports any combination of the follow text views.
+ *     <ul>
+ *         <li>Title
+ *         <li>Body
+ *     </ul>
+ *     <li>{@code Supplemental Action(s)}: represented by one of the following types; aligned toward
+ *     the end of item.
+ *     <ul>
+ *         <li>Supplemental Icon
+ *         <li>One Action Button
+ *         <li>Two Action Buttons
+ *     </ul>
+ * </ul>
+ *
+ * {@link ListItem} can be built through its {@link ListItem.Builder}. It binds data
+ * to {@link ListItemAdapter.ViewHolder} based on components selected.
+ */
+public class ListItem {
+
+    private Builder mBuilder;
+
+    private ListItem(Builder builder) {
+        mBuilder = builder;
+    }
+
+    /**
+     * Applies all {@link ViewBinder} to {@code viewHolder}.
+     */
+    void bind(ListItemAdapter.ViewHolder viewHolder) {
+        setAllSubViewsGone(viewHolder);
+        for (ViewBinder binder : mBuilder.mBinders) {
+            binder.bind(viewHolder);
+        }
+    }
+
+    void setAllSubViewsGone(ListItemAdapter.ViewHolder vh) {
+        View[] subviews = new View[] {
+                vh.getPrimaryIcon(),
+                vh.getTitle(), vh.getBody(),
+                vh.getSupplementalIcon(), vh.getSupplementalIconDivider(),
+                vh.getAction1(), vh.getAction1Divider(), vh.getAction2(), vh.getAction2Divider()};
+        for (View v : subviews) {
+            v.setVisibility(View.GONE);
+        }
+    }
+
+    /**
+     * Used by {@link ListItemAdapter} to choose layout to inflate for view holder.
+     * New view type needs support in {@link ListItemAdapter}.
+     */
+    protected int getViewType() {
+        return mBuilder.mIsCard
+                ? ListItemAdapter.CAR_PAGED_LIST_CARD
+                : ListItemAdapter.CAR_PAGED_LIST_ITEM;
+    }
+
+    /**
+     * Functional interface to provide a way to interact with views in
+     * {@link ListItemAdapter.ViewHolder}. {@code ViewBinder}s added to a
+     * {@code ListItem} will be called when {@code ListItem} {@code bind}s to
+     * {@link ListItemAdapter.ViewHolder}.
+     */
+    public interface ViewBinder {
+        /**
+         * Provides a way to interact with views in view holder.
+         */
+        void bind(ListItemAdapter.ViewHolder viewHolder);
+    }
+
+    /**
+     * Builds a {@link ListItem}.
+     *
+     * <p>With conflicting methods are called, e.g. setting primary action to both primary icon and
+     * no icon, the last called method wins.
+     */
+    public static class Builder {
+
+        @Retention(SOURCE)
+        @IntDef({
+                PRIMARY_ACTION_TYPE_NO_ICON, PRIMARY_ACTION_TYPE_EMPTY_ICON,
+                PRIMARY_ACTION_TYPE_LARGE_ICON, PRIMARY_ACTION_TYPE_SMALL_ICON})
+        private @interface PrimaryActionType {}
+
+        private static final int PRIMARY_ACTION_TYPE_NO_ICON = 0;
+        private static final int PRIMARY_ACTION_TYPE_EMPTY_ICON = 1;
+        private static final int PRIMARY_ACTION_TYPE_LARGE_ICON = 2;
+        private static final int PRIMARY_ACTION_TYPE_SMALL_ICON = 3;
+
+        @Retention(SOURCE)
+        @IntDef({SUPPLEMENTAL_ACTION_NO_ACTION, SUPPLEMENTAL_ACTION_SUPPLEMENTAL_ICON,
+                SUPPLEMENTAL_ACTION_ONE_ACTION, SUPPLEMENTAL_ACTION_TWO_ACTIONS})
+        private @interface SupplementalActionType {}
+
+        private static final int SUPPLEMENTAL_ACTION_NO_ACTION = 0;
+        private static final int SUPPLEMENTAL_ACTION_SUPPLEMENTAL_ICON = 1;
+        private static final int SUPPLEMENTAL_ACTION_ONE_ACTION = 2;
+        private static final int SUPPLEMENTAL_ACTION_TWO_ACTIONS = 3;
+
+        private final Context mContext;
+        private final List<ViewBinder> mBinders = new ArrayList<>();
+        // Store custom binders separately so they will bind after binders are created in build().
+        private final List<ViewBinder> mCustomBinders = new ArrayList<>();
+
+        private boolean mIsCard;
+
+        private View.OnClickListener mOnClickListener;
+
+        @PrimaryActionType private int mPrimaryActionType = PRIMARY_ACTION_TYPE_NO_ICON;
+        private int mPrimaryActionIconResId;
+        private Drawable mPrimaryActionIconDrawable;
+
+        private String mTitle;
+        private String mBody;
+        private boolean mIsBodyPrimary;
+
+        @SupplementalActionType private int mSupplementalActionType = SUPPLEMENTAL_ACTION_NO_ACTION;
+        private int mSupplementalIconResId;
+        private View.OnClickListener mSupplementalIconOnClickListener;
+        private boolean mShowSupplementalIconDivider;
+
+        private String mAction1Text;
+        private View.OnClickListener mAction1OnClickListener;
+        private boolean mShowAction1Divider;
+        private String mAction2Text;
+        private View.OnClickListener mAction2OnClickListener;
+        private boolean mShowAction2Divider;
+
+        public Builder(Context context) {
+            mContext = context;
+        }
+
+        /**
+         * Builds a {@link ListItem}. Adds {@link ViewBinder}s that will adjust layout in
+         * {@link ListItemAdapter.ViewHolder} depending on sub-views used.
+         */
+        public ListItem build() {
+            setItemLayoutHeight();
+            setPrimaryAction();
+            setText();
+            setSupplementalActions();
+            setOnClickListener();
+
+            mBinders.addAll(mCustomBinders);
+
+            return new ListItem(this);
+        }
+
+        /**
+         * Sets the height of item depending on which text field is set.
+         */
+        private void setItemLayoutHeight() {
+            if (TextUtils.isEmpty(mBody)) {
+                // If the item only has title or no text, it uses fixed-height as single line.
+                int height = (int) mContext.getResources().getDimension(
+                        R.dimen.car_single_line_list_item_height);
+                mBinders.add((vh) -> {
+                    RecyclerView.LayoutParams layoutParams =
+                            (RecyclerView.LayoutParams) vh.itemView.getLayoutParams();
+                    layoutParams.height = height;
+                    vh.itemView.setLayoutParams(layoutParams);
+                });
+            } else {
+                // If body is present, the item should be at least as tall as min height, and wraps
+                // content.
+                int minHeight = (int) mContext.getResources().getDimension(
+                        R.dimen.car_double_line_list_item_height);
+                mBinders.add((vh) -> {
+                    vh.itemView.setMinimumHeight(minHeight);
+                    vh.getContainerLayout().setMinimumHeight(minHeight);
+
+                    RecyclerView.LayoutParams layoutParams =
+                            (RecyclerView.LayoutParams) vh.itemView.getLayoutParams();
+                    layoutParams.height = RecyclerView.LayoutParams.WRAP_CONTENT;
+                    vh.itemView.setLayoutParams(layoutParams);
+                });
+            }
+        }
+
+        private void setPrimaryAction() {
+            setPrimaryIconContent();
+            setPrimaryIconLayout();
+        }
+
+        private void setText() {
+            setTextContent();
+            setTextVerticalMargin();
+            // Only setting start margin because text end is relative to the start of supplemental
+            // actions.
+            setTextStartMargin();
+        }
+
+        private void setOnClickListener() {
+            if (mOnClickListener != null) {
+                mBinders.add(vh -> vh.itemView.setOnClickListener(mOnClickListener));
+            }
+        }
+
+        private void setPrimaryIconContent() {
+            switch (mPrimaryActionType) {
+                case PRIMARY_ACTION_TYPE_SMALL_ICON:
+                case PRIMARY_ACTION_TYPE_LARGE_ICON:
+                    mBinders.add((vh) -> {
+                        vh.getPrimaryIcon().setVisibility(View.VISIBLE);
+
+                        if (mPrimaryActionIconDrawable != null) {
+                            vh.getPrimaryIcon().setImageDrawable(mPrimaryActionIconDrawable);
+                        } else if (mPrimaryActionIconResId != 0) {
+                            vh.getPrimaryIcon().setImageResource(mPrimaryActionIconResId);
+                        }
+                    });
+                    break;
+                case PRIMARY_ACTION_TYPE_EMPTY_ICON:
+                case PRIMARY_ACTION_TYPE_NO_ICON:
+                    // Do nothing.
+                    break;
+                default:
+                    throw new IllegalStateException("Unrecognizable primary action type.");
+            }
+        }
+
+        /**
+         * Sets layout params of primary icon.
+         *
+         * <p>Large icon will have no start margin, and always align center vertically.
+         *
+         * <p>Small icon will have start margin. When body text is present small icon uses a top
+         * margin otherwise align center vertically.
+         */
+        private void setPrimaryIconLayout() {
+            // Set all relevant fields in layout params to avoid carried over params when the item
+            // gets bound to a recycled view holder.
+            switch (mPrimaryActionType) {
+                case PRIMARY_ACTION_TYPE_SMALL_ICON:
+                    mBinders.add(vh -> {
+                        int iconSize = mContext.getResources().getDimensionPixelSize(
+                                R.dimen.car_primary_icon_size);
+                        // Icon size.
+                        RelativeLayout.LayoutParams layoutParams =
+                                (RelativeLayout.LayoutParams) vh.getPrimaryIcon().getLayoutParams();
+                        layoutParams.height = iconSize;
+                        layoutParams.width = iconSize;
+
+                        // Start margin.
+                        layoutParams.setMarginStart(mContext.getResources().getDimensionPixelSize(
+                                R.dimen.car_keyline_1));
+
+                        if (!TextUtils.isEmpty(mBody)) {
+                            // Set top margin.
+                            layoutParams.removeRule(RelativeLayout.CENTER_VERTICAL);
+                            layoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
+                                    R.dimen.car_padding_4);
+                        } else {
+                            // Centered vertically.
+                            layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
+                            layoutParams.topMargin = 0;
+                        }
+                        vh.getPrimaryIcon().setLayoutParams(layoutParams);
+                    });
+                    break;
+                case PRIMARY_ACTION_TYPE_LARGE_ICON:
+                    mBinders.add(vh -> {
+                        int iconSize = mContext.getResources().getDimensionPixelSize(
+                                R.dimen.car_single_line_list_item_height);
+                        // Icon size.
+                        RelativeLayout.LayoutParams layoutParams =
+                                (RelativeLayout.LayoutParams) vh.getPrimaryIcon().getLayoutParams();
+                        layoutParams.height = iconSize;
+                        layoutParams.width = iconSize;
+
+                        // No start margin.
+                        layoutParams.setMarginStart(0);
+
+                        // Always centered vertically.
+                        layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
+                        layoutParams.topMargin = 0;
+
+                        vh.getPrimaryIcon().setLayoutParams(layoutParams);
+                    });
+                    break;
+                case PRIMARY_ACTION_TYPE_EMPTY_ICON:
+                case PRIMARY_ACTION_TYPE_NO_ICON:
+                    // Do nothing.
+                    break;
+                default:
+                    throw new IllegalStateException("Unrecognizable primary action type.");
+            }
+        }
+
+        private void setTextContent() {
+            if (!TextUtils.isEmpty(mTitle)) {
+                mBinders.add(vh -> {
+                    vh.getTitle().setVisibility(View.VISIBLE);
+                    vh.getTitle().setText(mTitle);
+                });
+            }
+            if (!TextUtils.isEmpty(mBody)) {
+                mBinders.add(vh -> {
+                    vh.getBody().setVisibility(View.VISIBLE);
+                    vh.getBody().setText(mBody);
+                });
+            }
+
+            if (mIsBodyPrimary) {
+                mBinders.add((vh) -> {
+                    vh.getTitle().setTextAppearance(R.style.CarBody2);
+                    vh.getBody().setTextAppearance(R.style.CarBody1);
+                });
+            } else {
+                mBinders.add((vh) -> {
+                    vh.getTitle().setTextAppearance(R.style.CarBody1);
+                    vh.getBody().setTextAppearance(R.style.CarBody2);
+                });
+            }
+        }
+
+        /**
+         * Sets start margin of text view depending on icon type.
+         */
+        private void setTextStartMargin() {
+            final int startMarginResId;
+            switch (mPrimaryActionType) {
+                case PRIMARY_ACTION_TYPE_NO_ICON:
+                    startMarginResId = R.dimen.car_keyline_1;
+                    break;
+                case PRIMARY_ACTION_TYPE_EMPTY_ICON:
+                    startMarginResId = R.dimen.car_keyline_3;
+                    break;
+                case PRIMARY_ACTION_TYPE_SMALL_ICON:
+                    startMarginResId = R.dimen.car_keyline_3;
+                    break;
+                case PRIMARY_ACTION_TYPE_LARGE_ICON:
+                    startMarginResId = R.dimen.car_keyline_4;
+                    break;
+                default:
+                    throw new IllegalStateException("Unrecognizable primary action type.");
+            }
+            int startMargin = mContext.getResources().getDimensionPixelSize(startMarginResId);
+            mBinders.add(vh -> {
+                RelativeLayout.LayoutParams titleLayoutParams =
+                        (RelativeLayout.LayoutParams) vh.getTitle().getLayoutParams();
+                titleLayoutParams.setMarginStart(startMargin);
+                vh.getTitle().setLayoutParams(titleLayoutParams);
+
+                RelativeLayout.LayoutParams bodyLayoutParams =
+                        (RelativeLayout.LayoutParams) vh.getBody().getLayoutParams();
+                bodyLayoutParams.setMarginStart(startMargin);
+                vh.getBody().setLayoutParams(bodyLayoutParams);
+            });
+        }
+
+        /**
+         * Sets top/bottom margins of {@code Title} and {@code Body}.
+         */
+        private void setTextVerticalMargin() {
+            // Set all relevant fields in layout params to avoid carried over params when the item
+            // gets bound to a recycled view holder.
+            if (!TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mBody)) {
+                // Title only - view is aligned center vertically by itself.
+                mBinders.add(vh -> {
+                    RelativeLayout.LayoutParams layoutParams =
+                            (RelativeLayout.LayoutParams) vh.getTitle().getLayoutParams();
+                    layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
+                    layoutParams.topMargin = 0;
+                    vh.getTitle().setLayoutParams(layoutParams);
+                });
+            } else if (TextUtils.isEmpty(mTitle) && !TextUtils.isEmpty(mBody)) {
+                mBinders.add(vh -> {
+                    // Body uses top and bottom margin.
+                    int margin = mContext.getResources().getDimensionPixelSize(
+                            R.dimen.car_padding_3);
+                    RelativeLayout.LayoutParams layoutParams =
+                            (RelativeLayout.LayoutParams) vh.getBody().getLayoutParams();
+                    layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
+                    layoutParams.removeRule(RelativeLayout.BELOW);
+                    layoutParams.topMargin = margin;
+                    layoutParams.bottomMargin = margin;
+                    vh.getBody().setLayoutParams(layoutParams);
+                });
+            } else {
+                mBinders.add(vh -> {
+                    // Title has a top margin
+                    Resources resources = mContext.getResources();
+                    int padding1 = resources.getDimensionPixelSize(R.dimen.car_padding_1);
+                    int padding3 = resources.getDimensionPixelSize(R.dimen.car_padding_3);
+
+                    RelativeLayout.LayoutParams titleLayoutParams =
+                            (RelativeLayout.LayoutParams) vh.getTitle().getLayoutParams();
+                    titleLayoutParams.removeRule(RelativeLayout.CENTER_VERTICAL);
+                    titleLayoutParams.topMargin = padding3;
+                    vh.getTitle().setLayoutParams(titleLayoutParams);
+                    // Body is below title with a margin, and has bottom margin.
+                    RelativeLayout.LayoutParams bodyLayoutParams =
+                            (RelativeLayout.LayoutParams) vh.getBody().getLayoutParams();
+                    bodyLayoutParams.removeRule(RelativeLayout.CENTER_VERTICAL);
+                    bodyLayoutParams.addRule(RelativeLayout.BELOW, R.id.title);
+                    bodyLayoutParams.topMargin = padding1;
+                    bodyLayoutParams.bottomMargin = padding3;
+                    vh.getBody().setLayoutParams(bodyLayoutParams);
+                });
+            }
+        }
+
+        /**
+         * Sets up view(s) for supplemental action.
+         */
+        private void setSupplementalActions() {
+            switch (mSupplementalActionType) {
+                case SUPPLEMENTAL_ACTION_SUPPLEMENTAL_ICON:
+                    mBinders.add((vh) -> {
+                        vh.getSupplementalIcon().setVisibility(View.VISIBLE);
+                        if (mShowSupplementalIconDivider) {
+                            vh.getSupplementalIconDivider().setVisibility(View.VISIBLE);
+                        }
+
+                        vh.getSupplementalIcon().setImageResource(mSupplementalIconResId);
+                        vh.getSupplementalIcon().setOnClickListener(
+                                mSupplementalIconOnClickListener);
+                    });
+                    break;
+                case SUPPLEMENTAL_ACTION_TWO_ACTIONS:
+                    mBinders.add((vh) -> {
+                        vh.getAction2().setVisibility(View.VISIBLE);
+                        if (mShowAction2Divider) {
+                            vh.getAction2Divider().setVisibility(View.VISIBLE);
+                        }
+
+                        vh.getAction2().setText(mAction2Text);
+                        vh.getAction2().setOnClickListener(mAction2OnClickListener);
+                    });
+                    // Fall through
+                case SUPPLEMENTAL_ACTION_ONE_ACTION:
+                    mBinders.add((vh) -> {
+                        vh.getAction1().setVisibility(View.VISIBLE);
+                        if (mShowAction1Divider) {
+                            vh.getAction1Divider().setVisibility(View.VISIBLE);
+                        }
+
+                        vh.getAction1().setText(mAction1Text);
+                        vh.getAction1().setOnClickListener(mAction1OnClickListener);
+                    });
+                    break;
+                case SUPPLEMENTAL_ACTION_NO_ACTION:
+                    // Do nothing
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unrecognized supplemental action type.");
+            }
+        }
+
+        /**
+         * Builds the item in a {@link android.support.v7.widget.CardView}.
+         *
+         * <p>Each item will have rounded corner, margin between items, and elevation.
+         *
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withCardLook() {
+            mIsCard = true;
+            return this;
+        }
+
+        /**
+         * Sets {@link View.OnClickListener} of {@code ListItem}.
+         *
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withOnClickListener(View.OnClickListener listener) {
+            mOnClickListener = listener;
+            return this;
+        }
+
+        /**
+         * Sets {@code Primary Action} to be represented by an icon.
+         *
+         * @param iconResId the resource identifier of the drawable.
+         * @param useLargeIcon the size of primary icon. Large Icon is a square as tall as an item
+         *                     with only title set; useful for album cover art.
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withPrimaryActionIcon(@DrawableRes int iconResId, boolean useLargeIcon) {
+            return withPrimaryActionIcon(null, iconResId, useLargeIcon);
+        }
+
+        /**
+         * Sets {@code Primary Action} to be represented by an icon.
+         *
+         * @param drawable the Drawable to set, or null to clear the content.
+         * @param useLargeIcon the size of primary icon. Large Icon is a square as tall as an item
+         *                     with only title set; useful for album cover art.
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withPrimaryActionIcon(Drawable drawable, boolean useLargeIcon) {
+            return withPrimaryActionIcon(drawable, 0, useLargeIcon);
+        }
+
+        private Builder withPrimaryActionIcon(Drawable drawable, @DrawableRes int iconResId,
+                boolean useLargeIcon) {
+            mPrimaryActionType = useLargeIcon
+                    ? PRIMARY_ACTION_TYPE_LARGE_ICON
+                    : PRIMARY_ACTION_TYPE_SMALL_ICON;
+            mPrimaryActionIconResId = iconResId;
+            mPrimaryActionIconDrawable = drawable;
+            return this;
+        }
+
+        /**
+         * Sets {@code Primary Action} to be empty icon.
+         *
+         * {@code Text} would have a start margin as if {@code Primary Action} were set to
+         * primary icon.
+         *
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withPrimaryActionEmptyIcon() {
+            mPrimaryActionType = PRIMARY_ACTION_TYPE_EMPTY_ICON;
+            return this;
+        }
+
+        /**
+         * Sets {@code Primary Action} to have no icon. Text would align to the start of item.
+         *
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withPrimaryActionNoIcon() {
+            mPrimaryActionType = PRIMARY_ACTION_TYPE_NO_ICON;
+            return this;
+        }
+
+        /**
+         * Sets the title of item.
+         *
+         * <p>Primary text is {@code title} by default. It can be set by
+         * {@link #withBody(String, boolean)}
+         *
+         * @param title text to display as title.
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withTitle(String title) {
+            mTitle = title;
+            return this;
+        }
+
+        /**
+         * Sets the body text of item.
+         *
+         * <p>Text beyond length required by regulation will be truncated. Defaults {@code Title}
+         * text as the primary.
+         *
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withBody(String body) {
+            return withBody(body, false);
+        }
+
+        /**
+         * Sets the body text of item.
+         *
+         * <p>Text beyond length required by regulation will be truncated.
+         *
+         * @param asPrimary sets {@code Body Text} as primary text of item.
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withBody(String body, boolean asPrimary) {
+            int limit = mContext.getResources().getInteger(
+                    R.integer.car_list_item_text_length_limit);
+            if (body.length() < limit) {
+                mBody = body;
+            } else {
+                mBody = body.substring(0, limit) + mContext.getString(R.string.ellipsis);
+            }
+            mIsBodyPrimary = asPrimary;
+            return this;
+        }
+
+        /**
+         * Sets {@code Supplemental Action} to be represented by an {@code Supplemental Icon}.
+         *
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withSupplementalIcon(int iconResId, boolean showDivider) {
+            return withSupplementalIcon(iconResId, showDivider, null);
+        }
+
+        /**
+         * Sets {@code Supplemental Action} to be represented by an {@code Supplemental Icon}.
+         *
+         * @param iconResId drawable resource id.
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withSupplementalIcon(int iconResId, boolean showDivider,
+                View.OnClickListener listener) {
+            mSupplementalActionType = SUPPLEMENTAL_ACTION_SUPPLEMENTAL_ICON;
+
+            mSupplementalIconResId = iconResId;
+            mSupplementalIconOnClickListener = listener;
+            mShowSupplementalIconDivider = showDivider;
+            return this;
+        }
+
+        /**
+         * Sets {@code Supplemental Action} to be represented by an {@code Action Button}.
+         *
+         * @param text button text to display.
+         * @return This Builder object to allow for chaining calls to set methods.
+         */
+        public Builder withAction(String text, boolean showDivider, View.OnClickListener listener) {
+            if (TextUtils.isEmpty(text)) {
+                throw new IllegalArgumentException("Action text cannot be empty.");
+            }
+            mSupplementalActionType = SUPPLEMENTAL_ACTION_ONE_ACTION;
+
+            mAction1Text = text;
+            mAction1OnClickListener = listener;
+            mShowAction1Divider = showDivider;
+            return this;
+        }
+
+        /**
+         * Sets {@code Supplemental Action} to be represented by two {@code Action Button}s.
+         *
+         * <p>These two action buttons will be aligned towards item end.
+         *
+         * @param action1Text button text to display - this button will be closer to item end.
+         * @param action2Text button text to display.
+         */
+        public Builder withActions(String action1Text, boolean showAction1Divider,
+                View.OnClickListener action1OnClickListener,
+                String action2Text, boolean showAction2Divider,
+                View.OnClickListener action2OnClickListener) {
+            if (TextUtils.isEmpty(action1Text)) {
+                throw new IllegalArgumentException("Action1 text cannot be empty.");
+            }
+            if (TextUtils.isEmpty(action2Text)) {
+                throw new IllegalArgumentException("Action2 text cannot be empty.");
+            }
+            mSupplementalActionType = SUPPLEMENTAL_ACTION_TWO_ACTIONS;
+
+            mAction1Text = action1Text;
+            mAction1OnClickListener = action1OnClickListener;
+            mShowAction1Divider = showAction1Divider;
+            mAction2Text = action2Text;
+            mAction2OnClickListener = action2OnClickListener;
+            mShowAction2Divider = showAction2Divider;
+            return this;
+        }
+
+        /**
+         * Adds {@link ViewBinder} to interact with sub-views in
+         * {@link ListItemAdapter.ViewHolder}. These ViewBinders will always bind after
+         * other {@link Builder} methods have bond.
+         *
+         * <p>Make sure to call with...() method on the intended sub-view first.
+         *
+         * <p>Example:
+         * <pre>
+         * {@code
+         * new Builder()
+         *     .withTitle("title")
+         *     .withViewBinder((viewHolder) -> {
+         *         viewHolder.getTitle().doMoreStuff();
+         *     })
+         *     .build();
+         * }
+         * </pre>
+         */
+        public Builder withViewBinder(ViewBinder binder) {
+            mCustomBinders.add(binder);
+            return this;
+        }
+    }
+}
diff --git a/car/src/main/java/androidx/car/widget/ListItemAdapter.java b/car/src/main/java/androidx/car/widget/ListItemAdapter.java
new file mode 100644
index 0000000..2bdfae6
--- /dev/null
+++ b/car/src/main/java/androidx/car/widget/ListItemAdapter.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.car.widget;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.content.Context;
+import android.support.annotation.IntDef;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import java.lang.annotation.Retention;
+
+import androidx.car.R;
+
+/**
+ * Adapter for {@link PagedListView} to display {@link ListItem}.
+ *
+ * Implements {@link PagedListView.ItemCap} - defaults to unlimited item count.
+ */
+public class ListItemAdapter extends
+        RecyclerView.Adapter<ListItemAdapter.ViewHolder> implements PagedListView.ItemCap {
+    @Retention(SOURCE)
+    @IntDef({CAR_PAGED_LIST_ITEM, CAR_PAGED_LIST_CARD})
+    public @interface PagedListItemType {}
+    public static final int CAR_PAGED_LIST_ITEM = 0;
+    public static final int CAR_PAGED_LIST_CARD = 1;
+
+    private final Context mContext;
+    private final ListItemProvider mItemProvider;
+
+    private int mMaxItems = PagedListView.ItemCap.UNLIMITED;
+
+    public ListItemAdapter(Context context, ListItemProvider itemProvider) {
+        mContext = context;
+        mItemProvider = itemProvider;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return mItemProvider.get(position).getViewType();
+    }
+
+    @Override
+    public ViewHolder onCreateViewHolder(ViewGroup parent, @PagedListItemType int viewType) {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        int layoutId;
+        switch (viewType) {
+            case CAR_PAGED_LIST_ITEM:
+                layoutId = R.layout.car_paged_list_item;
+                break;
+            case CAR_PAGED_LIST_CARD:
+                layoutId = R.layout.car_paged_list_card;
+                break;
+            default:
+                throw new IllegalArgumentException("Unrecognizable view type: " + viewType);
+        }
+        View itemView = inflater.inflate(layoutId, parent, false);
+        return new ViewHolder(itemView);
+    }
+
+    @Override
+    public void onBindViewHolder(ViewHolder holder, int position) {
+        ListItem item = mItemProvider.get(position);
+        item.bind(holder);
+    }
+
+    @Override
+    public int getItemCount() {
+        return mMaxItems == PagedListView.ItemCap.UNLIMITED
+                ? mItemProvider.size()
+                : Math.min(mItemProvider.size(), mMaxItems);
+    }
+
+    @Override
+    public void setMaxItems(int maxItems) {
+        mMaxItems = maxItems;
+    }
+
+    /**
+     * Holds views of an item in PagedListView.
+     *
+     * <p>This ViewHolder maps to views in layout car_paged_list_item_content.xml.
+     */
+    public static class ViewHolder extends RecyclerView.ViewHolder {
+
+        private RelativeLayout mContainerLayout;
+
+        private ImageView mPrimaryIcon;
+
+        private TextView mTitle;
+        private TextView mBody;
+
+        private View mSupplementalIconDivider;
+        private ImageView mSupplementalIcon;
+
+        private Button mAction1;
+        private View mAction1Divider;
+
+        private Button mAction2;
+        private View mAction2Divider;
+
+        public ViewHolder(View itemView) {
+            super(itemView);
+
+            mContainerLayout = itemView.findViewById(R.id.container);
+
+            mPrimaryIcon = itemView.findViewById(R.id.primary_icon);
+
+            mTitle = itemView.findViewById(R.id.title);
+            mBody = itemView.findViewById(R.id.body);
+
+            mSupplementalIcon = itemView.findViewById(R.id.supplemental_icon);
+            mSupplementalIconDivider = itemView.findViewById(R.id.supplemental_icon_divider);
+
+            mAction1 = itemView.findViewById(R.id.action1);
+            mAction1Divider = itemView.findViewById(R.id.action1_divider);
+            mAction2 = itemView.findViewById(R.id.action2);
+            mAction2Divider = itemView.findViewById(R.id.action2_divider);
+        }
+
+        public RelativeLayout getContainerLayout() {
+            return mContainerLayout;
+        }
+
+        public ImageView getPrimaryIcon() {
+            return mPrimaryIcon;
+        }
+
+        public TextView getTitle() {
+            return mTitle;
+        }
+
+        public TextView getBody() {
+            return mBody;
+        }
+
+        public ImageView getSupplementalIcon() {
+            return mSupplementalIcon;
+        }
+
+        public View getSupplementalIconDivider() {
+            return mSupplementalIconDivider;
+        }
+
+        public Button getAction1() {
+            return mAction1;
+        }
+
+        public View getAction1Divider() {
+            return mAction1Divider;
+        }
+
+        public Button getAction2() {
+            return mAction2;
+        }
+
+        public View getAction2Divider() {
+            return mAction2Divider;
+        }
+    }
+}
diff --git a/car/src/main/java/androidx/car/widget/ListItemProvider.java b/car/src/main/java/androidx/car/widget/ListItemProvider.java
new file mode 100644
index 0000000..5a3edbd
--- /dev/null
+++ b/car/src/main/java/androidx/car/widget/ListItemProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.car.widget;
+
+import java.util.List;
+
+/**
+ * Supplies data as {@link ListItem}.
+ */
+public abstract class ListItemProvider {
+
+    /**
+     * Returns {@link ListItem} at requested position.
+     */
+    public abstract ListItem get(int position);
+
+    /**
+     * @return number of total items.
+     */
+    public abstract int size();
+
+    /**
+     * A simple provider that wraps around a list.
+     */
+    public static class ListProvider extends ListItemProvider {
+        private final List<ListItem> mItems;
+
+        public ListProvider(List<ListItem> items) {
+            mItems = items;
+        }
+
+        @Override
+        public ListItem get(int position) {
+            return mItems.get(position);
+        }
+
+        @Override
+        public int size() {
+            return mItems.size();
+        }
+    }
+}
diff --git a/car/src/main/java/android/support/car/widget/PagedLayoutManager.java b/car/src/main/java/androidx/car/widget/PagedLayoutManager.java
similarity index 99%
rename from car/src/main/java/android/support/car/widget/PagedLayoutManager.java
rename to car/src/main/java/androidx/car/widget/PagedLayoutManager.java
index c4f469a..cf3b75d 100644
--- a/car/src/main/java/android/support/car/widget/PagedLayoutManager.java
+++ b/car/src/main/java/androidx/car/widget/PagedLayoutManager.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import android.content.Context;
 import android.graphics.PointF;
@@ -23,7 +23,6 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
-import android.support.car.R;
 import android.support.v7.widget.LinearSmoothScroller;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.Recycler;
@@ -42,6 +41,8 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 
+import androidx.car.R;
+
 /**
  * Custom {@link RecyclerView.LayoutManager} that behaves similar to LinearLayoutManager except that
  * it has a few tricks up its sleeve.
diff --git a/car/src/main/java/android/support/car/widget/PagedListView.java b/car/src/main/java/androidx/car/widget/PagedListView.java
similarity index 90%
rename from car/src/main/java/android/support/car/widget/PagedListView.java
rename to car/src/main/java/androidx/car/widget/PagedListView.java
index 67a6247..88a59dc 100644
--- a/car/src/main/java/android/support/car/widget/PagedListView.java
+++ b/car/src/main/java/androidx/car/widget/PagedListView.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
@@ -28,12 +28,14 @@
 import android.os.Handler;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.annotation.ColorRes;
 import android.support.annotation.IdRes;
+import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.support.annotation.UiThread;
-import android.support.car.R;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.widget.RecyclerView;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -43,6 +45,8 @@
 import android.view.View;
 import android.widget.FrameLayout;
 
+import androidx.car.R;
+
 /**
  * Custom {@link android.support.v7.widget.RecyclerView} that displays a list of items that
  * resembles a {@link android.widget.ListView} but also has page up and page down arrows on the
@@ -71,7 +75,8 @@
     protected final PagedLayoutManager mLayoutManager;
     protected final Handler mHandler = new Handler();
     private final boolean mScrollBarEnabled;
-    private final PagedScrollBarView mScrollBarView;
+    @VisibleForTesting
+    final PagedScrollBarView mScrollBarView;
 
     private int mRowsPerPage = -1;
     protected RecyclerView.Adapter<? extends RecyclerView.ViewHolder> mAdapter;
@@ -119,6 +124,39 @@
     }
 
     /**
+     * The possible values for @{link #setGutter}. The default value is actually
+     * {@link Gutter#BOTH}.
+     */
+    @IntDef({
+            Gutter.NONE,
+            Gutter.START,
+            Gutter.END,
+            Gutter.BOTH,
+    })
+    public @interface Gutter {
+        /**
+         * No gutter on either side of the list items. The items will span the full width of the
+         * {@link PagedListView}.
+         */
+        int NONE = 0;
+
+        /**
+         * Include a gutter only on the start side (that is, the same side as the scroll bar).
+         */
+        int START = 1;
+
+        /**
+         * Include a gutter only on the end side (that is, the opposite side of the scroll bar).
+         */
+        int END = 2;
+
+        /**
+         * Include a gutter on both sides of the list items. This is the default behaviour.
+         */
+        int BOTH = 3;
+    }
+
+    /**
      * Interface for a {@link android.support.v7.widget.RecyclerView.Adapter} to set the position
      * offset for the adapter to load the data.
      *
@@ -167,14 +205,17 @@
         mRecyclerView.getRecycledViewPool().setMaxRecycledViews(0, 12);
         mRecyclerView.setItemAnimator(new CarItemAnimator(mLayoutManager));
 
-        boolean offsetScrollBar = a.getBoolean(R.styleable.PagedListView_offsetScrollBar, false);
-        if (offsetScrollBar) {
-            MarginLayoutParams params = (MarginLayoutParams) mRecyclerView.getLayoutParams();
-            params.setMarginStart(getResources().getDimensionPixelSize(
-                    R.dimen.car_margin));
-            params.setMarginEnd(
-                    a.getDimensionPixelSize(R.styleable.PagedListView_listEndMargin, 0));
-            mRecyclerView.setLayoutParams(params);
+        if (a.hasValue(R.styleable.PagedListView_gutter)) {
+            int gutter = a.getInt(R.styleable.PagedListView_gutter, Gutter.BOTH);
+            setGutter(gutter);
+        } else if (a.hasValue(R.styleable.PagedListView_offsetScrollBar)) {
+            boolean offsetScrollBar =
+                    a.getBoolean(R.styleable.PagedListView_offsetScrollBar, false);
+            if (offsetScrollBar) {
+                setGutter(Gutter.START);
+            }
+        } else {
+            setGutter(Gutter.BOTH);
         }
 
         if (a.getBoolean(R.styleable.PagedListView_showPagedListViewDivider, true)) {
@@ -286,6 +327,31 @@
         return mLayoutManager.getPosition(v);
     }
 
+    /**
+     * Set the gutter to the specified value.
+     *
+     * The gutter is the space to the start/end of the list view items and will be equal in size
+     * to the scroll bars. By default, there is a gutter to both the left and right of the list
+     * view items, to account for the scroll bar.
+     *
+     * @param gutter A {@link Gutter} value that identifies which sides to apply the gutter to.
+     */
+    public void setGutter(@Gutter int gutter) {
+        int startPadding = 0;
+        int endPadding = 0;
+        if ((gutter & Gutter.START) != 0) {
+            startPadding = getResources().getDimensionPixelSize(R.dimen.car_margin);
+        }
+        if ((gutter & Gutter.END) != 0) {
+            endPadding = getResources().getDimensionPixelSize(R.dimen.car_margin);
+        }
+        mRecyclerView.setPaddingRelative(startPadding, 0, endPadding, 0);
+
+        // If there's a gutter, set ClipToPadding to false so that CardView's shadow will still
+        // appear outside of the padding.
+        mRecyclerView.setClipToPadding(startPadding == 0 && endPadding == 0);
+    }
+
     @NonNull
     public CarRecyclerView getRecyclerView() {
         return mRecyclerView;
@@ -451,6 +517,25 @@
     }
 
     /**
+     * Sets the color of scrollbar.
+     *
+     * <p>Custom color ignores {@link DayNightStyle}. Calling {@link #resetScrollbarColor} resets to
+     * default color.
+     *
+     * @param color Resource identifier of the color.
+     */
+    public void setScrollbarColor(@ColorRes int color) {
+        mScrollBarView.setThumbColor(color);
+    }
+
+    /**
+     * Resets the color of scrollbar to default.
+     */
+    public void resetScrollbarColor() {
+        mScrollBarView.resetThumbColor();
+    }
+
+    /**
      * Adds an {@link android.support.v7.widget.RecyclerView.OnItemTouchListener} to this
      * PagedListView.
      *
@@ -473,6 +558,7 @@
     public void removeOnItemTouchListener(@NonNull RecyclerView.OnItemTouchListener touchListener) {
         mRecyclerView.removeOnItemTouchListener(touchListener);
     }
+
     /**
      * Sets how this {@link PagedListView} responds to day/night configuration changes. By
      * default, the PagedListView is darker in the day and lighter at night.
@@ -940,7 +1026,7 @@
             Resources res = context.getResources();
             mPaint = new Paint();
             mPaint.setColor(res.getColor(R.color.car_list_divider));
-            mDividerHeight = res.getDimensionPixelSize(R.dimen.car_divider_height);
+            mDividerHeight = res.getDimensionPixelSize(R.dimen.car_list_divider_height);
         }
 
         /** Updates the list divider color which may have changed due to a day night transition. */
@@ -970,8 +1056,18 @@
                     continue;
                 }
 
-                int left = mDividerStartMargin + startChild.getLeft();
-                int right = endChild.getRight();
+                Rect containerRect = new Rect();
+                container.getGlobalVisibleRect(containerRect);
+
+                Rect startRect = new Rect();
+                startChild.getGlobalVisibleRect(startRect);
+
+                Rect endRect = new Rect();
+                endChild.getGlobalVisibleRect(endRect);
+
+                int left = container.getLeft() + mDividerStartMargin
+                        + (startRect.left - containerRect.left);
+                int right = container.getRight() - (endRect.right - containerRect.right);
                 int bottom = container.getBottom() + spacing / 2 + mDividerHeight / 2;
                 int top = bottom - mDividerHeight;
 
diff --git a/car/src/main/java/android/support/car/widget/PagedScrollBarView.java b/car/src/main/java/androidx/car/widget/PagedScrollBarView.java
similarity index 81%
rename from car/src/main/java/android/support/car/widget/PagedScrollBarView.java
rename to car/src/main/java/androidx/car/widget/PagedScrollBarView.java
index 1c46b5d..25f586c 100644
--- a/car/src/main/java/android/support/car/widget/PagedScrollBarView.java
+++ b/car/src/main/java/androidx/car/widget/PagedScrollBarView.java
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import android.content.Context;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
-import android.support.car.R;
+import android.support.annotation.ColorRes;
+import android.support.annotation.VisibleForTesting;
 import android.support.v4.content.ContextCompat;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -30,6 +31,8 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import androidx.car.R;
+
 /** A custom view to provide list scroll behaviour -- up/down buttons and scroll indicator. */
 public class PagedScrollBarView extends FrameLayout
         implements View.OnClickListener, View.OnLongClickListener {
@@ -48,13 +51,16 @@
 
     private final ImageView mUpButton;
     private final ImageView mDownButton;
-    private final ImageView mScrollThumb;
+    @VisibleForTesting
+    final ImageView mScrollThumb;
     /** The "filler" view between the up and down buttons */
     private final View mFiller;
 
     private final Interpolator mPaginationInterpolator = new AccelerateDecelerateInterpolator();
     private final int mMinThumbLength;
     private final int mMaxThumbLength;
+    private boolean mUseCustomThumbBackground;
+    @ColorRes private int mCustomThumbBackgroundResId;
     private PaginationListener mPaginationListener;
 
     public PagedScrollBarView(Context context, AttributeSet attrs) {
@@ -84,8 +90,10 @@
         mScrollThumb = (ImageView) findViewById(R.id.scrollbar_thumb);
         mFiller = findViewById(R.id.filler);
 
-        mMinThumbLength = getResources().getDimensionPixelSize(R.dimen.min_thumb_height);
-        mMaxThumbLength = getResources().getDimensionPixelSize(R.dimen.max_thumb_height);
+        mMinThumbLength = getResources()
+                .getDimensionPixelSize(R.dimen.car_min_scroll_bar_thumb_height);
+        mMaxThumbLength = getResources()
+                .getDimensionPixelSize(R.dimen.car_max_scroll_bar_thumb_height);
     }
 
     @Override
@@ -196,43 +204,65 @@
         return mDownButton.isEnabled();
     }
 
+    /**
+     * Sets the color of thumb.
+     *
+     * <p>Custom thumb color ignores {@link DayNightStyle}. Calling {@link #resetThumbColor} resets
+     * to default color.
+     *
+     * @param color Resource identifier of the color.
+     */
+    public void setThumbColor(@ColorRes int color) {
+        mUseCustomThumbBackground = true;
+        mCustomThumbBackgroundResId = color;
+        reloadColors();
+    }
+
+    /**
+     * Resets the color of thumb to default.
+     */
+    public void resetThumbColor() {
+        mUseCustomThumbBackground = false;
+        reloadColors();
+    }
+
     /** Reload the colors for the current {@link DayNightStyle}. */
     private void reloadColors() {
-        int tint;
-        int thumbBackground;
+        int tintResId;
+        int thumbBackgroundResId;
         int upDownBackgroundResId;
 
         switch (mDayNightStyle) {
             case DayNightStyle.AUTO:
-                tint = ContextCompat.getColor(getContext(), R.color.car_tint);
-                thumbBackground = ContextCompat.getColor(getContext(),
-                        R.color.car_scrollbar_thumb);
+                tintResId = R.color.car_tint;
+                thumbBackgroundResId = R.color.car_scrollbar_thumb;
                 upDownBackgroundResId = R.drawable.car_pagination_background;
                 break;
             case DayNightStyle.AUTO_INVERSE:
-                tint = ContextCompat.getColor(getContext(), R.color.car_tint_inverse);
-                thumbBackground = ContextCompat.getColor(getContext(),
-                        R.color.car_scrollbar_thumb_inverse);
+                tintResId = R.color.car_tint_inverse;
+                thumbBackgroundResId = R.color.car_scrollbar_thumb_inverse;
                 upDownBackgroundResId = R.drawable.car_pagination_background_inverse;
                 break;
             case DayNightStyle.FORCE_NIGHT:
-                tint = ContextCompat.getColor(getContext(), R.color.car_tint_light);
-                thumbBackground = ContextCompat.getColor(getContext(),
-                        R.color.car_scrollbar_thumb_light);
+                tintResId = R.color.car_tint_light;
+                thumbBackgroundResId = R.color.car_scrollbar_thumb_light;
                 upDownBackgroundResId = R.drawable.car_pagination_background_night;
                 break;
             case DayNightStyle.FORCE_DAY:
-                tint = ContextCompat.getColor(getContext(), R.color.car_tint_dark);
-                thumbBackground = ContextCompat.getColor(getContext(),
-                        R.color.car_scrollbar_thumb_dark);
+                tintResId =  R.color.car_tint_dark;
+                thumbBackgroundResId = R.color.car_scrollbar_thumb_dark;
                 upDownBackgroundResId = R.drawable.car_pagination_background_day;
                 break;
             default:
                 throw new IllegalArgumentException("Unknown DayNightStyle: " + mDayNightStyle);
         }
 
-        mScrollThumb.setBackgroundColor(thumbBackground);
+        if (mUseCustomThumbBackground) {
+            thumbBackgroundResId = mCustomThumbBackgroundResId;
+        }
+        mScrollThumb.setBackgroundColor(ContextCompat.getColor(getContext(), thumbBackgroundResId));
 
+        int tint = ContextCompat.getColor(getContext(), tintResId);
         mUpButton.setColorFilter(tint, PorterDuff.Mode.SRC_IN);
         mUpButton.setBackgroundResource(upDownBackgroundResId);
 
diff --git a/car/tests/AndroidManifest.xml b/car/tests/AndroidManifest.xml
index 949e85a..8e5422d 100644
--- a/car/tests/AndroidManifest.xml
+++ b/car/tests/AndroidManifest.xml
@@ -15,12 +15,12 @@
   ~ limitations under the License.
   -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.support.car.widget.test">
+          package="androidx.car.widget.test">
     <uses-sdk android:targetSdkVersion="${target-sdk-version}"/>
 
     <application android:supportsRtl="true">
-        <activity android:name="android.support.car.widget.ColumnCardViewTestActivity"/>
-        <activity android:name="android.support.car.widget.PagedListViewSavedStateActivity"/>
-        <activity android:name="android.support.car.widget.PagedListViewTestActivity"/>
+        <activity android:name="androidx.car.widget.ColumnCardViewTestActivity"/>
+        <activity android:name="androidx.car.widget.PagedListViewSavedStateActivity"/>
+        <activity android:name="androidx.car.widget.PagedListViewTestActivity"/>
     </application>
 </manifest>
diff --git a/car/tests/res/layout/activity_column_card_view.xml b/car/tests/res/layout/activity_column_card_view.xml
index ad9c5e1..a6acc57 100644
--- a/car/tests/res/layout/activity_column_card_view.xml
+++ b/car/tests/res/layout/activity_column_card_view.xml
@@ -21,13 +21,13 @@
     android:layout_height="match_parent"
     android:orientation="vertical">
 
-    <android.support.car.widget.ColumnCardView
+    <androidx.car.widget.ColumnCardView
         android:id="@+id/default_width_column_card"
         android:layout_gravity="center"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
-    <android.support.car.widget.ColumnCardView
+    <androidx.car.widget.ColumnCardView
         car:columnSpan="2"
         android:id="@+id/span_2_column_card"
         android:layout_gravity="center"
diff --git a/car/tests/res/layout/activity_paged_list_view.xml b/car/tests/res/layout/activity_paged_list_view.xml
index d14eb96..d7c8946 100644
--- a/car/tests/res/layout/activity_paged_list_view.xml
+++ b/car/tests/res/layout/activity_paged_list_view.xml
@@ -21,7 +21,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <android.support.car.widget.PagedListView
+    <androidx.car.widget.PagedListView
         android:id="@+id/paged_list_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/car/tests/res/layout/activity_two_paged_list_view.xml b/car/tests/res/layout/activity_two_paged_list_view.xml
index 588071f..457cb95 100644
--- a/car/tests/res/layout/activity_two_paged_list_view.xml
+++ b/car/tests/res/layout/activity_two_paged_list_view.xml
@@ -21,7 +21,7 @@
     android:layout_height="match_parent"
     android:orientation="horizontal">
 
-    <android.support.car.widget.PagedListView
+    <androidx.car.widget.PagedListView
         android:id="@+id/paged_list_view_1"
         android:layout_weight="1"
         android:layout_width="0dp"
@@ -29,7 +29,7 @@
         app:showPagedListViewDivider="false"
         app:offsetScrollBar="true"/>
 
-    <android.support.car.widget.PagedListView
+    <androidx.car.widget.PagedListView
         android:id="@+id/paged_list_view_2"
         android:layout_weight="1"
         android:layout_width="0dp"
diff --git a/car/tests/res/layout/paged_list_item_column_card.xml b/car/tests/res/layout/paged_list_item_column_card.xml
index 2bc5cd0..5028abf 100644
--- a/car/tests/res/layout/paged_list_item_column_card.xml
+++ b/car/tests/res/layout/paged_list_item_column_card.xml
@@ -20,7 +20,7 @@
     android:layout_height="wrap_content"
     android:orientation="vertical">
 
-    <android.support.car.widget.ColumnCardView
+    <androidx.car.widget.ColumnCardView
         android:id="@+id/column_card"
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
@@ -30,6 +30,6 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"/>
 
-    </android.support.car.widget.ColumnCardView>
+    </androidx.car.widget.ColumnCardView>
 
 </FrameLayout>
diff --git a/car/res/values-w1024dp/dimens.xml b/car/tests/res/values/strings.xml
similarity index 78%
copy from car/res/values-w1024dp/dimens.xml
copy to car/tests/res/values/strings.xml
index b1ae5ba..478abc4 100644
--- a/car/res/values-w1024dp/dimens.xml
+++ b/car/tests/res/values/strings.xml
@@ -14,5 +14,5 @@
 limitations under the License.
 -->
 <resources>
-    <dimen name="car_screen_margin_size">112dp</dimen>
+    <string name="over_120_chars">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</string>
 </resources>
diff --git a/car/tests/src/android/support/car/widget/ColumnCardViewTest.java b/car/tests/src/androidx/car/widget/ColumnCardViewTest.java
similarity index 96%
rename from car/tests/src/android/support/car/widget/ColumnCardViewTest.java
rename to car/tests/src/androidx/car/widget/ColumnCardViewTest.java
index cb61caf..1963629 100644
--- a/car/tests/src/android/support/car/widget/ColumnCardViewTest.java
+++ b/car/tests/src/androidx/car/widget/ColumnCardViewTest.java
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 
-import android.support.car.test.R;
-import android.support.car.utils.ColumnCalculator;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
@@ -32,6 +30,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import androidx.car.test.R;
+import androidx.car.utils.ColumnCalculator;
+
 /** Instrumentation unit tests for {@link ColumnCardView}. */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/car/tests/src/android/support/car/widget/ColumnCardViewTestActivity.java b/car/tests/src/androidx/car/widget/ColumnCardViewTestActivity.java
similarity index 92%
rename from car/tests/src/android/support/car/widget/ColumnCardViewTestActivity.java
rename to car/tests/src/androidx/car/widget/ColumnCardViewTestActivity.java
index 693e4a1..3f42d62 100644
--- a/car/tests/src/android/support/car/widget/ColumnCardViewTestActivity.java
+++ b/car/tests/src/androidx/car/widget/ColumnCardViewTestActivity.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.support.car.test.R;
+
+import androidx.car.test.R;
 
 public class ColumnCardViewTestActivity extends Activity {
     @Override
diff --git a/car/tests/src/androidx/car/widget/ListItemTest.java b/car/tests/src/androidx/car/widget/ListItemTest.java
new file mode 100644
index 0000000..64b9ede
--- /dev/null
+++ b/car/tests/src/androidx/car/widget/ListItemTest.java
@@ -0,0 +1,560 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.car.widget;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
+import static android.support.test.espresso.contrib.RecyclerViewActions.scrollToPosition;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+import static junit.framework.TestCase.assertFalse;
+
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.number.IsCloseTo.closeTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.drawable.Drawable;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.widget.CardView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import androidx.car.test.R;
+
+/**
+* Tests the layout configuration in {@link ListItem}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ListItemTest {
+
+    @Rule
+    public ActivityTestRule<PagedListViewTestActivity> mActivityRule =
+            new ActivityTestRule<>(PagedListViewTestActivity.class);
+
+    private PagedListViewTestActivity mActivity;
+    private PagedListView mPagedListView;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+        mPagedListView = mActivity.findViewById(R.id.paged_list_view);
+    }
+
+    private void setupPagedListView(List<ListItem> items) {
+        ListItemProvider provider = new ListItemProvider.ListProvider(
+                new ArrayList<>(items));
+        try {
+            mActivityRule.runOnUiThread(() -> {
+                mPagedListView.setAdapter(new ListItemAdapter(mActivity, provider));
+            });
+        } catch (Throwable throwable) {
+            throwable.printStackTrace();
+            throw new RuntimeException(throwable);
+        }
+        // Wait for paged list view to layout by using espresso to scroll to a position.
+        onView(withId(R.id.recycler_view)).perform(scrollToPosition(0));
+    }
+
+    private static void verifyViewIsHidden(View view) {
+        if (view instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) view;
+            final int childCount = viewGroup.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                verifyViewIsHidden(viewGroup.getChildAt(i));
+            }
+        } else {
+            assertThat(view.getVisibility(), is(equalTo(View.GONE)));
+        }
+    }
+
+    private ListItemAdapter.ViewHolder getViewHolderAtPosition(int position) {
+        return (ListItemAdapter.ViewHolder) mPagedListView.getRecyclerView()
+                .findViewHolderForAdapterPosition(
+                position);
+    }
+
+    @Test
+    public void testEmptyItemHidesAllViews() {
+        ListItem item = new ListItem.Builder(mActivity).build();
+        setupPagedListView(Arrays.asList(item));
+        verifyViewIsHidden(mPagedListView.findViewByPosition(0));
+    }
+
+    @Test
+    public void testPrimaryActionVisible() {
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true)
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                        .build());
+        setupPagedListView(items);
+
+        assertThat(getViewHolderAtPosition(0).getPrimaryIcon().getVisibility(),
+                is(equalTo(View.VISIBLE)));
+        assertThat(getViewHolderAtPosition(1).getPrimaryIcon().getVisibility(),
+                is(equalTo(View.VISIBLE)));
+    }
+
+    @Test
+    public void testTextVisible() {
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withTitle("title")
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withBody("body")
+                        .build());
+        setupPagedListView(items);
+
+        assertThat(getViewHolderAtPosition(0).getTitle().getVisibility(),
+                is(equalTo(View.VISIBLE)));
+        assertThat(getViewHolderAtPosition(1).getBody().getVisibility(),
+                is(equalTo(View.VISIBLE)));
+    }
+
+    @Test
+    public void testSupplementalActionVisible() {
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withSupplementalIcon(android.R.drawable.sym_def_app_icon, true)
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withAction("text", true, null)
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withActions("text", true, null,
+                                 "text", true, null)
+                        .build());
+        setupPagedListView(items);
+
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        assertThat(viewHolder.getSupplementalIcon().getVisibility(), is(equalTo(View.VISIBLE)));
+        assertThat(viewHolder.getSupplementalIconDivider().getVisibility(),
+                is(equalTo(View.VISIBLE)));
+
+        viewHolder = getViewHolderAtPosition(1);
+        assertThat(viewHolder.getAction1().getVisibility(), is(equalTo(View.VISIBLE)));
+        assertThat(viewHolder.getAction1Divider().getVisibility(), is(equalTo(View.VISIBLE)));
+
+        viewHolder = getViewHolderAtPosition(2);
+        assertThat(viewHolder.getAction1().getVisibility(), is(equalTo(View.VISIBLE)));
+        assertThat(viewHolder.getAction1Divider().getVisibility(), is(equalTo(View.VISIBLE)));
+        assertThat(viewHolder.getAction2().getVisibility(), is(equalTo(View.VISIBLE)));
+        assertThat(viewHolder.getAction2Divider().getVisibility(), is(equalTo(View.VISIBLE)));
+    }
+
+    @Test
+    public void testDividersAreOptional() {
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withSupplementalIcon(android.R.drawable.sym_def_app_icon, false)
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withAction("text", false, null)
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withActions("text", false, null,
+                                "text", false, null)
+                        .build());
+        setupPagedListView(items);
+
+        setupPagedListView(items);
+
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        assertThat(viewHolder.getSupplementalIcon().getVisibility(), is(equalTo(View.VISIBLE)));
+        assertThat(viewHolder.getSupplementalIconDivider().getVisibility(),
+                is(equalTo(View.GONE)));
+
+        viewHolder = getViewHolderAtPosition(1);
+        assertThat(viewHolder.getAction1().getVisibility(), is(equalTo(View.VISIBLE)));
+        assertThat(viewHolder.getAction1Divider().getVisibility(), is(equalTo(View.GONE)));
+
+        viewHolder = getViewHolderAtPosition(2);
+        assertThat(viewHolder.getAction1().getVisibility(), is(equalTo(View.VISIBLE)));
+        assertThat(viewHolder.getAction1Divider().getVisibility(), is(equalTo(View.GONE)));
+        assertThat(viewHolder.getAction2().getVisibility(), is(equalTo(View.VISIBLE)));
+        assertThat(viewHolder.getAction2Divider().getVisibility(), is(equalTo(View.GONE)));
+    }
+
+    @Test
+    public void testTextStartMarginMatchesPrimaryActionType() {
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true)
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionEmptyIcon()
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionNoIcon()
+                        .build());
+        List<Integer> expectedStartMargin = Arrays.asList(R.dimen.car_keyline_4,
+                R.dimen.car_keyline_3, R.dimen.car_keyline_3, R.dimen.car_keyline_1);
+        setupPagedListView(items);
+
+        for (int i = 0; i < items.size(); i++) {
+            ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(i);
+
+            int expected = InstrumentationRegistry.getContext().getResources()
+                    .getDimensionPixelSize(expectedStartMargin.get(i));
+            assertThat(((ViewGroup.MarginLayoutParams) viewHolder.getTitle().getLayoutParams())
+                    .getMarginStart(), is(equalTo(expected)));
+            assertThat(((ViewGroup.MarginLayoutParams) viewHolder.getBody().getLayoutParams())
+                    .getMarginStart(), is(equalTo(expected)));
+        }
+    }
+
+    @Test
+    public void testItemWithOnlyTitleIsSingleLine() {
+        List<ListItem> items = Arrays.asList(
+                // Only space
+                new ListItem.Builder(mActivity)
+                        .withTitle(" ")
+                        .build(),
+                // Underscore
+                new ListItem.Builder(mActivity)
+                        .withTitle("______")
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withTitle("ALL UPPER CASE")
+                        .build(),
+                // String wouldn't fit in one line
+                new ListItem.Builder(mActivity)
+                        .withTitle(InstrumentationRegistry.getContext().getResources().getString(
+                                R.string.over_120_chars))
+                        .build());
+        setupPagedListView(items);
+
+        double singleLineHeight = InstrumentationRegistry.getContext().getResources().getDimension(
+                R.dimen.car_single_line_list_item_height);
+
+        for (int i = 0; i < items.size(); i++) {
+            assertThat((double) mPagedListView.findViewByPosition(i).getHeight(),
+                    is(closeTo(singleLineHeight, 1.0d)));
+        }
+    }
+
+    @Test
+    public void testItemWithBodyTextIsAtLeastDoubleLine() {
+        List<ListItem> items = Arrays.asList(
+                // Only space
+                new ListItem.Builder(mActivity)
+                        .withBody(" ")
+                        .build(),
+                // Underscore
+                new ListItem.Builder(mActivity)
+                        .withBody("____")
+                        .build(),
+                // String wouldn't fit in one line
+                new ListItem.Builder(mActivity)
+                        .withBody(InstrumentationRegistry.getContext().getResources().getString(
+                                R.string.over_120_chars))
+                        .build());
+        setupPagedListView(items);
+
+        final int doubleLineHeight =
+                (int) InstrumentationRegistry.getContext().getResources().getDimension(
+                        R.dimen.car_double_line_list_item_height);
+
+        for (int i = 0; i < items.size(); i++) {
+            assertThat(mPagedListView.findViewByPosition(i).getHeight(),
+                    is(greaterThanOrEqualTo(doubleLineHeight)));
+        }
+    }
+
+    @Test
+    public void testBodyTextLengthLimit() {
+        final String longText = InstrumentationRegistry.getContext().getResources().getString(
+                R.string.over_120_chars);
+        final int limit = InstrumentationRegistry.getContext().getResources().getInteger(
+                R.integer.car_list_item_text_length_limit);
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withBody(longText)
+                        .build());
+        setupPagedListView(items);
+
+        // + 1 for appended ellipsis.
+        assertThat(getViewHolderAtPosition(0).getBody().getText().length(),
+                is(equalTo(limit + 1)));
+    }
+
+    @Test
+    public void testPrimaryIconDrawable() {
+        Drawable drawable = InstrumentationRegistry.getContext().getResources().getDrawable(
+                android.R.drawable.sym_def_app_icon, null);
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(drawable, true)
+                        .build());
+        setupPagedListView(items);
+
+        assertTrue(getViewHolderAtPosition(0).getPrimaryIcon().getDrawable().getConstantState()
+                .equals(drawable.getConstantState()));
+    }
+
+    @Test
+    public void testLargePrimaryIconHasNoStartMargin() {
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true)
+                        .build());
+        setupPagedListView(items);
+
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        assertThat(((ViewGroup.MarginLayoutParams) viewHolder.getPrimaryIcon().getLayoutParams())
+                .getMarginStart(), is(equalTo(0)));
+    }
+
+    @Test
+    public void testSmallPrimaryIconStartMargin() {
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                        .build());
+        setupPagedListView(items);
+
+        int expected = InstrumentationRegistry.getContext().getResources().getDimensionPixelSize(
+                R.dimen.car_keyline_1);
+
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        assertThat(((ViewGroup.MarginLayoutParams) viewHolder.getPrimaryIcon().getLayoutParams())
+                .getMarginStart(), is(equalTo(expected)));
+    }
+
+    @Test
+    public void testClickingPrimaryActionIsSeparateFromSupplementalAction() {
+        final boolean[] clicked = {false, false};
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withOnClickListener((v) -> clicked[0] = true)
+                        .withSupplementalIcon(android.R.drawable.sym_def_app_icon, true,
+                                (v) -> clicked[1] = true)
+                        .build());
+        setupPagedListView(items);
+
+        onView(withId(R.id.recycler_view)).perform(actionOnItemAtPosition(0, click()));
+        assertTrue(clicked[0]);
+        assertFalse(clicked[1]);
+
+        onView(withId(R.id.recycler_view)).perform(
+                actionOnItemAtPosition(0, clickChildViewWithId(R.id.supplemental_icon)));
+        assertTrue(clicked[1]);
+    }
+
+    @Test
+    public void testClickingSupplementalIcon() {
+        final boolean[] clicked = {false};
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withSupplementalIcon(android.R.drawable.sym_def_app_icon, true,
+                                (v) -> clicked[0] = true)
+                        .build());
+        setupPagedListView(items);
+
+        onView(withId(R.id.recycler_view)).perform(
+                actionOnItemAtPosition(0, clickChildViewWithId(R.id.supplemental_icon)));
+        assertTrue(clicked[0]);
+    }
+
+    @Test
+    public void testClickingSupplementalAction() {
+        final boolean[] clicked = {false};
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withAction("action", true, (v) -> clicked[0] = true)
+                        .build());
+        setupPagedListView(items);
+
+        onView(withId(R.id.recycler_view)).perform(
+                actionOnItemAtPosition(0, clickChildViewWithId(R.id.action1)));
+        assertTrue(clicked[0]);
+    }
+
+    @Test
+    public void testClickingBothSupplementalActions() {
+        final boolean[] clicked = {false, false};
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withActions("action 1", true, (v) -> clicked[0] = true,
+                                "action 2", true, (v) -> clicked[1] = true)
+                        .build());
+        setupPagedListView(items);
+
+        onView(withId(R.id.recycler_view)).perform(
+                actionOnItemAtPosition(0, clickChildViewWithId(R.id.action1)));
+        assertTrue(clicked[0]);
+        assertFalse(clicked[1]);
+
+        onView(withId(R.id.recycler_view)).perform(
+                actionOnItemAtPosition(0, clickChildViewWithId(R.id.action2)));
+        assertTrue(clicked[1]);
+    }
+
+    @Test
+    public void testCustomViewBinderAreCalledLast() {
+        final String updatedTitle = "updated title";
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withTitle("original title")
+                        .withViewBinder((viewHolder) -> viewHolder.getTitle().setText(updatedTitle))
+                        .build());
+        setupPagedListView(items);
+
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        assertThat(viewHolder.getTitle().getText(), is(equalTo(updatedTitle)));
+    }
+
+    @Test
+    public void testCustomViewBinderOnUnusedViewsHasNoEffect() {
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withViewBinder((viewHolder) -> viewHolder.getBody().setText("text"))
+                        .build());
+        setupPagedListView(items);
+
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        assertThat(viewHolder.getBody().getVisibility(), is(equalTo(View.GONE)));
+        // Custom binder interacts with body but has no effect.
+        // Expect card height to remain single line.
+        assertThat((double) viewHolder.itemView.getHeight(), is(closeTo(
+                InstrumentationRegistry.getContext().getResources().getDimension(
+                        R.dimen.car_single_line_list_item_height), 1.0d)));
+    }
+
+    @Test
+    public void testCardLookUsesCardView() {
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withCardLook()
+                        .build());
+        setupPagedListView(items);
+
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        assertThat(viewHolder.itemView, is(instanceOf(CardView.class)));
+    }
+
+    @Test
+    public void testSettingTitleOrBodyAsPrimaryText() {
+        // Create 2 items, one with Title as primary (default) and one with Body.
+        // The primary text, regardless of view, should have consistent look (as primary).
+        List<ListItem> items = Arrays.asList(
+                new ListItem.Builder(mActivity)
+                        .withTitle("title")
+                        .withBody("body")
+                        .build(),
+                new ListItem.Builder(mActivity)
+                        .withTitle("title")
+                        .withBody("body", true)
+                        .build());
+        setupPagedListView(items);
+
+        ListItemAdapter.ViewHolder titlePrimary = getViewHolderAtPosition(0);
+        ListItemAdapter.ViewHolder bodyPrimary = getViewHolderAtPosition(1);
+        assertThat(titlePrimary.getTitle().getTextSize(),
+                is(equalTo(bodyPrimary.getBody().getTextSize())));
+        assertThat(titlePrimary.getTitle().getTextColors(),
+                is(equalTo(bodyPrimary.getBody().getTextColors())));
+    }
+
+    @Test
+    public void testNoCarriedOverLayoutParamsForTextView() throws Throwable {
+        ListItem singleLine = new ListItem.Builder(mActivity).withTitle("t").build();
+        setupPagedListView(Arrays.asList(singleLine));
+
+        // Manually rebind the view holder of a single line item to a double line item.
+        ListItem doubleLine = new ListItem.Builder(mActivity).withTitle("t").withBody("b").build();
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        mActivityRule.runOnUiThread(() -> doubleLine.bind(viewHolder));
+
+        RelativeLayout.LayoutParams titleLayoutParams =
+                (RelativeLayout.LayoutParams) viewHolder.getTitle().getLayoutParams();
+        RelativeLayout.LayoutParams bodyLayoutParams =
+                (RelativeLayout.LayoutParams) viewHolder.getTitle().getLayoutParams();
+        assertThat(titleLayoutParams.getRule(RelativeLayout.CENTER_VERTICAL), is(equalTo(0)));
+        assertThat(bodyLayoutParams.getRule(RelativeLayout.CENTER_VERTICAL), is(equalTo(0)));
+    }
+
+    @Test
+    public void testNoCarriedOverLayoutParamsForPrimaryIcon() throws Throwable {
+        ListItem smallIcon = new ListItem.Builder(mActivity)
+                .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                .withBody("body")  // Small icon of items with body text should use top margin.
+                .build();
+        setupPagedListView(Arrays.asList(smallIcon));
+
+        // Manually rebind the view holder.
+        ListItem largeIcon = new ListItem.Builder(mActivity)
+                .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true)
+                .build();
+        ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
+        mActivityRule.runOnUiThread(() -> largeIcon.bind(viewHolder));
+
+        RelativeLayout.LayoutParams iconLayoutParams =
+                (RelativeLayout.LayoutParams) viewHolder.getPrimaryIcon().getLayoutParams();
+        assertThat(iconLayoutParams.getRule(RelativeLayout.CENTER_VERTICAL),
+                is(equalTo(RelativeLayout.TRUE)));
+        assertThat(iconLayoutParams.topMargin, is(equalTo(0)));
+    }
+
+    private static ViewAction clickChildViewWithId(final int id) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return null;
+            }
+
+            @Override
+            public String getDescription() {
+                return "Click on a child view with specific id.";
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                View v = view.findViewById(id);
+                v.performClick();
+            }
+        };
+    }
+}
diff --git a/car/tests/src/android/support/car/widget/PagedListViewSavedStateActivity.java b/car/tests/src/androidx/car/widget/PagedListViewSavedStateActivity.java
similarity index 93%
rename from car/tests/src/android/support/car/widget/PagedListViewSavedStateActivity.java
rename to car/tests/src/androidx/car/widget/PagedListViewSavedStateActivity.java
index 8cb976c..d9eecd5 100644
--- a/car/tests/src/android/support/car/widget/PagedListViewSavedStateActivity.java
+++ b/car/tests/src/androidx/car/widget/PagedListViewSavedStateActivity.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.support.car.test.R;
+
+import androidx.car.test.R;
 
 /**
  * Test Activity for testing the saving of state for the {@link PagedListView}. It will inflate
diff --git a/car/tests/src/android/support/car/widget/PagedListViewSavedStateTest.java b/car/tests/src/androidx/car/widget/PagedListViewSavedStateTest.java
similarity index 99%
rename from car/tests/src/android/support/car/widget/PagedListViewSavedStateTest.java
rename to car/tests/src/androidx/car/widget/PagedListViewSavedStateTest.java
index 9b871b3..b134e10 100644
--- a/car/tests/src/android/support/car/widget/PagedListViewSavedStateTest.java
+++ b/car/tests/src/androidx/car/widget/PagedListViewSavedStateTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import static android.support.test.espresso.Espresso.onView;
 import static android.support.test.espresso.action.ViewActions.click;
@@ -26,7 +26,6 @@
 
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
-import android.support.car.test.R;
 import android.support.test.espresso.IdlingRegistry;
 import android.support.test.espresso.IdlingResource;
 import android.support.test.filters.SmallTest;
@@ -50,6 +49,8 @@
 import java.util.List;
 import java.util.Random;
 
+import androidx.car.test.R;
+
 /** Unit tests for the ability of the {@link PagedListView} to save state. */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/car/tests/src/android/support/car/widget/PagedListViewTest.java b/car/tests/src/androidx/car/widget/PagedListViewTest.java
similarity index 91%
rename from car/tests/src/android/support/car/widget/PagedListViewTest.java
rename to car/tests/src/androidx/car/widget/PagedListViewTest.java
index 0d07fbd..c977a6e 100644
--- a/car/tests/src/android/support/car/widget/PagedListViewTest.java
+++ b/car/tests/src/androidx/car/widget/PagedListViewTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import static android.support.test.espresso.Espresso.onView;
 import static android.support.test.espresso.action.ViewActions.click;
@@ -35,8 +35,9 @@
 import static org.junit.Assert.assertThat;
 
 import android.content.pm.PackageManager;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.support.car.test.R;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.espresso.Espresso;
 import android.support.test.espresso.IdlingResource;
@@ -61,6 +62,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import androidx.car.test.R;
+
 /** Unit tests for {@link PagedListView}. */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -366,6 +369,43 @@
                 is(equalTo(downDrawable.getConstantState())));
     }
 
+    @Test
+    public void testSettingAndResettingScrollbarColor() {
+        setUpPagedListView(0);
+
+        final int color = R.color.car_teal_700;
+
+        // Setting non-zero res ID changes color.
+        mPagedListView.setScrollbarColor(color);
+        assertThat(((ColorDrawable)
+                        mPagedListView.mScrollBarView.mScrollThumb.getBackground()).getColor(),
+                is(equalTo(InstrumentationRegistry.getContext().getColor(color))));
+
+        // Resets to default color.
+        mPagedListView.resetScrollbarColor();
+        assertThat(((ColorDrawable)
+                        mPagedListView.mScrollBarView.mScrollThumb.getBackground()).getColor(),
+                is(equalTo(InstrumentationRegistry.getContext().getColor(
+                        R.color.car_scrollbar_thumb))));
+    }
+
+    @Test
+    public void testSettingScrollbarColorIgnoresDayNightStyle() {
+        setUpPagedListView(0);
+
+        final int color = R.color.car_teal_700;
+        mPagedListView.setScrollbarColor(color);
+
+        for (int style : new int[] {DayNightStyle.AUTO, DayNightStyle.AUTO_INVERSE,
+                DayNightStyle.FORCE_NIGHT, DayNightStyle.FORCE_DAY}) {
+            mPagedListView.setDayNightStyle(style);
+
+            assertThat(((ColorDrawable)
+                            mPagedListView.mScrollBarView.mScrollThumb.getBackground()).getColor(),
+                    is(equalTo(InstrumentationRegistry.getContext().getColor(color))));
+        }
+    }
+
     private static String itemText(int index) {
         return "Data " + index;
     }
diff --git a/car/tests/src/android/support/car/widget/PagedListViewTestActivity.java b/car/tests/src/androidx/car/widget/PagedListViewTestActivity.java
similarity index 93%
rename from car/tests/src/android/support/car/widget/PagedListViewTestActivity.java
rename to car/tests/src/androidx/car/widget/PagedListViewTestActivity.java
index 6371374..741cadd 100644
--- a/car/tests/src/android/support/car/widget/PagedListViewTestActivity.java
+++ b/car/tests/src/androidx/car/widget/PagedListViewTestActivity.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package android.support.car.widget;
+package androidx.car.widget;
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.support.car.test.R;
+
+import androidx.car.test.R;
 
 /**
  * Simple test activity for {@link PagedListView} class.
diff --git a/compat/api/27.0.0.ignore b/compat/api/27.0.0.ignore
new file mode 100644
index 0000000..b49088f
--- /dev/null
+++ b/compat/api/27.0.0.ignore
@@ -0,0 +1 @@
+8227953
diff --git a/compat/api/current.txt b/compat/api/current.txt
index 5a87c03..66525e2 100644
--- a/compat/api/current.txt
+++ b/compat/api/current.txt
@@ -495,7 +495,7 @@
     field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
   }
 
-  public final class RemoteInput extends android.support.v4.app.RemoteInputCompatBase.RemoteInput {
+  public final class RemoteInput {
     method public static void addDataResultToIntent(android.support.v4.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String, android.net.Uri>);
     method public static void addResultsToIntent(android.support.v4.app.RemoteInput[], android.content.Intent, android.os.Bundle);
     method public boolean getAllowFreeFormInput();
@@ -522,19 +522,6 @@
     method public android.support.v4.app.RemoteInput.Builder setLabel(java.lang.CharSequence);
   }
 
-   deprecated class RemoteInputCompatBase {
-  }
-
-  public static abstract deprecated class RemoteInputCompatBase.RemoteInput {
-    ctor public deprecated RemoteInputCompatBase.RemoteInput();
-    method protected abstract deprecated boolean getAllowFreeFormInput();
-    method protected abstract deprecated java.util.Set<java.lang.String> getAllowedDataTypes();
-    method protected abstract deprecated java.lang.CharSequence[] getChoices();
-    method protected abstract deprecated android.os.Bundle getExtras();
-    method protected abstract deprecated java.lang.CharSequence getLabel();
-    method protected abstract deprecated java.lang.String getResultKey();
-  }
-
   public final class ServiceCompat {
     method public static void stopForeground(android.app.Service, int);
     field public static final int START_STICKY = 1; // 0x1
@@ -937,7 +924,7 @@
     method public static void requestFont(android.content.Context, android.support.v4.provider.FontRequest, android.support.v4.provider.FontsContractCompat.FontRequestCallback, android.os.Handler);
   }
 
-  public static final class FontsContractCompat.Columns {
+  public static final class FontsContractCompat.Columns implements android.provider.BaseColumns {
     ctor public FontsContractCompat.Columns();
     field public static final java.lang.String FILE_ID = "file_id";
     field public static final java.lang.String ITALIC = "font_italic";
@@ -1136,7 +1123,7 @@
     method public int size();
   }
 
-  public class LongSparseArray<E> {
+  public class LongSparseArray<E> implements java.lang.Cloneable {
     ctor public LongSparseArray();
     ctor public LongSparseArray(int);
     method public void append(long, E);
@@ -1235,7 +1222,7 @@
     method public V valueAt(int);
   }
 
-  public class SparseArrayCompat<E> {
+  public class SparseArrayCompat<E> implements java.lang.Cloneable {
     ctor public SparseArrayCompat();
     ctor public SparseArrayCompat(int);
     method public void append(int, E);
diff --git a/compat/build.gradle b/compat/build.gradle
index b8ea13b..a26eac8 100644
--- a/compat/build.gradle
+++ b/compat/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,16 +7,16 @@
 }
 
 dependencies {
-    api project(':support-annotations')
+    api(project(":support-annotations"))
     api (libs.arch_lifecycle_runtime)  {
         exclude module: 'support-annotations'
         transitive = true
     }
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
     androidTestImplementation project(':support-testutils'), {
         exclude group: 'com.android.support', module: 'support-compat'
     }
diff --git a/compat/lint-baseline.xml b/compat/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/compat/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/compat/src/main/java/android/support/v4/accessibilityservice/package.html b/compat/src/main/java/android/support/v4/accessibilityservice/package.html
deleted file mode 100755
index 3d017b0..0000000
--- a/compat/src/main/java/android/support/v4/accessibilityservice/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<body>
-
-Support android.accessibilityservice classes to assist with development of applications for
-android API level 4 or later.
-
-</body>
diff --git a/compat/src/main/java/android/support/v4/app/NotificationCompat.java b/compat/src/main/java/android/support/v4/app/NotificationCompat.java
index 1077b1f..80c7757 100644
--- a/compat/src/main/java/android/support/v4/app/NotificationCompat.java
+++ b/compat/src/main/java/android/support/v4/app/NotificationCompat.java
@@ -32,6 +32,7 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Build;
@@ -116,7 +117,6 @@
      * default stream type is {@link AudioManager#STREAM_NOTIFICATION}.
      */
     public static final int STREAM_DEFAULT = -1;
-
     /**
      * Bit set in the Notification flags field when LEDs should be turned on
      * for this notification.
@@ -439,6 +439,14 @@
     public static final int COLOR_DEFAULT = Color.TRANSPARENT;
 
     /** @hide */
+    @RestrictTo(LIBRARY_GROUP)
+    @IntDef({AudioManager.STREAM_VOICE_CALL, AudioManager.STREAM_SYSTEM, AudioManager.STREAM_RING,
+            AudioManager.STREAM_MUSIC, AudioManager.STREAM_ALARM, AudioManager.STREAM_NOTIFICATION,
+            AudioManager.STREAM_DTMF, AudioManager.STREAM_ACCESSIBILITY})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface StreamType {}
+
+    /** @hide */
     @Retention(SOURCE)
     @IntDef({VISIBILITY_PUBLIC, VISIBILITY_PRIVATE, VISIBILITY_SECRET})
     public @interface NotificationVisibility {}
@@ -957,6 +965,12 @@
         public Builder setSound(Uri sound) {
             mNotification.sound = sound;
             mNotification.audioStreamType = Notification.STREAM_DEFAULT;
+            if (Build.VERSION.SDK_INT >= 21) {
+                mNotification.audioAttributes = new AudioAttributes.Builder()
+                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                        .setUsage(AudioAttributes.USAGE_NOTIFICATION)
+                        .build();
+            }
             return this;
         }
 
@@ -971,9 +985,15 @@
          * @see Notification#STREAM_DEFAULT
          * @see AudioManager for the <code>STREAM_</code> constants.
          */
-        public Builder setSound(Uri sound, int streamType) {
+        public Builder setSound(Uri sound, @StreamType int streamType) {
             mNotification.sound = sound;
             mNotification.audioStreamType = streamType;
+            if (Build.VERSION.SDK_INT >= 21) {
+                mNotification.audioAttributes = new AudioAttributes.Builder()
+                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                        .setLegacyStreamType(streamType)
+                        .build();
+            }
             return this;
         }
 
diff --git a/compat/src/main/java/android/support/v4/app/NotificationCompatBuilder.java b/compat/src/main/java/android/support/v4/app/NotificationCompatBuilder.java
index 71f4160..db775a5 100644
--- a/compat/src/main/java/android/support/v4/app/NotificationCompatBuilder.java
+++ b/compat/src/main/java/android/support/v4/app/NotificationCompatBuilder.java
@@ -28,6 +28,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.RestrictTo;
+import android.text.TextUtils;
 import android.util.SparseArray;
 import android.widget.RemoteViews;
 
@@ -69,7 +70,6 @@
                 .setSmallIcon(n.icon, n.iconLevel)
                 .setContent(n.contentView)
                 .setTicker(n.tickerText, b.mTickerView)
-                .setSound(n.sound, n.audioStreamType)
                 .setVibrate(n.vibrate)
                 .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS)
                 .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0)
@@ -86,6 +86,9 @@
                 .setLargeIcon(b.mLargeIcon)
                 .setNumber(b.mNumber)
                 .setProgress(b.mProgressMax, b.mProgress, b.mProgressIndeterminate);
+        if (Build.VERSION.SDK_INT < 21) {
+            mBuilder.setSound(n.sound, n.audioStreamType);
+        }
         if (Build.VERSION.SDK_INT >= 16) {
             mBuilder.setSubText(b.mSubText)
                     .setUsesChronometer(b.mUseChronometer)
@@ -141,7 +144,8 @@
             mBuilder.setCategory(b.mCategory)
                     .setColor(b.mColor)
                     .setVisibility(b.mVisibility)
-                    .setPublicVersion(b.mPublicVersion);
+                    .setPublicVersion(b.mPublicVersion)
+                    .setSound(n.sound, n.audioAttributes);
 
             for (String person: b.mPeople) {
                 mBuilder.addPerson(person);
@@ -169,6 +173,13 @@
             if (b.mColorizedSet) {
                 mBuilder.setColorized(b.mColorized);
             }
+
+            if (!TextUtils.isEmpty(b.mChannelId)) {
+                mBuilder.setSound(null)
+                        .setDefaults(0)
+                        .setLights(0, 0, 0)
+                        .setVibrate(null);
+            }
         }
     }
 
diff --git a/compat/src/main/java/android/support/v4/app/NotificationManagerCompat.java b/compat/src/main/java/android/support/v4/app/NotificationManagerCompat.java
index 1a0f1bc..07fcb6c 100644
--- a/compat/src/main/java/android/support/v4/app/NotificationManagerCompat.java
+++ b/compat/src/main/java/android/support/v4/app/NotificationManagerCompat.java
@@ -43,10 +43,10 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.ArrayDeque;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -560,7 +560,7 @@
             /** The service stub provided by onServiceConnected */
             public INotificationSideChannel service;
             /** Queue of pending tasks to send to this listener service */
-            public LinkedList<Task> taskQueue = new LinkedList<Task>();
+            public ArrayDeque<Task> taskQueue = new ArrayDeque<>();
             /** Number of retries attempted while connecting to this listener service */
             public int retryCount = 0;
 
diff --git a/compat/src/main/java/android/support/v4/app/package.html b/compat/src/main/java/android/support/v4/app/package.html
deleted file mode 100755
index 02d1b79..0000000
--- a/compat/src/main/java/android/support/v4/app/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<body>
-
-Support android.app classes to assist with development of applications for
-android API level 4 or later.  The main features here are backwards-compatible
-versions of {@link android.support.v4.app.FragmentManager} and
-{@link android.support.v4.app.LoaderManager}.
-
-</body>
diff --git a/compat/src/main/java/android/support/v4/content/package.html b/compat/src/main/java/android/support/v4/content/package.html
deleted file mode 100755
index 33bf4b5..0000000
--- a/compat/src/main/java/android/support/v4/content/package.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<body>
-
-Support android.content classes to assist with development of applications for
-android API level 4 or later.  The main features here are
-{@link android.support.v4.content.Loader} and related classes and
-{@link android.support.v4.content.LocalBroadcastManager} to
-provide a cleaner implementation of broadcasts that don't need to go outside
-of an app.
-
-</body>
diff --git a/compat/src/main/java/android/support/v4/content/pm/package.html b/compat/src/main/java/android/support/v4/content/pm/package.html
deleted file mode 100755
index da850bd..0000000
--- a/compat/src/main/java/android/support/v4/content/pm/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<body>
-
-Support android.content.pm classes to assist with development of applications for
-android API level 4 or later.
-
-</body>
diff --git a/compat/src/main/java/android/support/v4/database/package.html b/compat/src/main/java/android/support/v4/database/package.html
deleted file mode 100755
index 25ac59a..0000000
--- a/compat/src/main/java/android/support/v4/database/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<body>
-
-Support android.database classes to assist with development of applications for
-android API level 4 or later.
-
-</body>
diff --git a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java
index 1b55a2e..28ab3ed 100644
--- a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java
+++ b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java
@@ -196,10 +196,9 @@
     /**
      * Call FontFamily#abortCreation()
      */
-    private static boolean abortCreation(Object family) {
+    private static void abortCreation(Object family) {
         try {
-            Boolean result = (Boolean) sAbortCreation.invoke(family);
-            return result.booleanValue();
+            sAbortCreation.invoke(family);
         } catch (IllegalAccessException | InvocationTargetException e) {
             throw new RuntimeException(e);
         }
@@ -241,6 +240,9 @@
             final ContentResolver resolver = context.getContentResolver();
             try (ParcelFileDescriptor pfd =
                     resolver.openFileDescriptor(bestFont.getUri(), "r", cancellationSignal)) {
+                if (pfd == null) {
+                    return null;
+                }
                 return new Typeface.Builder(pfd.getFileDescriptor())
                         .setWeight(bestFont.getWeight())
                         .setItalic(bestFont.isItalic())
diff --git a/compat/src/main/java/android/support/v4/os/package.html b/compat/src/main/java/android/support/v4/os/package.html
deleted file mode 100755
index 929c967..0000000
--- a/compat/src/main/java/android/support/v4/os/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<body>
-
-Support android.os classes to assist with development of applications for
-android API level 4 or later.
-
-</body>
diff --git a/compat/src/main/java/android/support/v4/provider/FontsContractCompat.java b/compat/src/main/java/android/support/v4/provider/FontsContractCompat.java
index 0926186..39acf68 100644
--- a/compat/src/main/java/android/support/v4/provider/FontsContractCompat.java
+++ b/compat/src/main/java/android/support/v4/provider/FontsContractCompat.java
@@ -274,7 +274,10 @@
                     : new ReplyCallback<TypefaceResult>() {
                         @Override
                         public void onReply(final TypefaceResult typeface) {
-                            if (typeface.mResult == FontFamilyResult.STATUS_OK) {
+                            if (typeface == null) {
+                                fontCallback.callbackFailAsync(
+                                        FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND, handler);
+                            } else if (typeface.mResult == FontFamilyResult.STATUS_OK) {
                                 fontCallback.callbackSuccessAsync(typeface.mTypeface, handler);
                             } else {
                                 fontCallback.callbackFailAsync(typeface.mResult, handler);
diff --git a/compat/src/main/java/android/support/v4/util/ArraySet.java b/compat/src/main/java/android/support/v4/util/ArraySet.java
index ab080fa..a9a8806 100644
--- a/compat/src/main/java/android/support/v4/util/ArraySet.java
+++ b/compat/src/main/java/android/support/v4/util/ArraySet.java
@@ -16,9 +16,6 @@
 
 package android.support.v4.util;
 
-import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.support.annotation.RestrictTo;
 import android.util.Log;
 
 import java.lang.reflect.Array;
@@ -74,7 +71,6 @@
     static Object[] sTwiceBaseCache;
     static int sTwiceBaseCacheSize;
 
-    final boolean mIdentityHashCode;
     int[] mHashes;
     Object[] mArray;
     int mSize;
@@ -238,19 +234,13 @@
      * will grow once items are added to it.
      */
     public ArraySet() {
-        this(0, false);
+        this(0);
     }
 
     /**
      * Create a new ArraySet with a given initial capacity.
      */
     public ArraySet(int capacity) {
-        this(capacity, false);
-    }
-
-    /** {@hide} */
-    public ArraySet(int capacity, boolean identityHashCode) {
-        mIdentityHashCode = identityHashCode;
         if (capacity == 0) {
             mHashes = INT;
             mArray = OBJECT;
@@ -270,14 +260,6 @@
         }
     }
 
-    /** {@hide} */
-    public ArraySet(Collection<E> set) {
-        this();
-        if (set != null) {
-            addAll(set);
-        }
-    }
-
     /**
      * Make the array map empty.  All storage is released.
      */
@@ -326,8 +308,7 @@
      * @return Returns the index of the value if it exists, else a negative integer.
      */
     public int indexOf(Object key) {
-        return key == null ? indexOfNull()
-                : indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
+        return key == null ? indexOfNull() : indexOf(key, key.hashCode());
     }
 
     /**
@@ -364,7 +345,7 @@
             hash = 0;
             index = indexOfNull();
         } else {
-            hash = mIdentityHashCode ? System.identityHashCode(value) : value.hashCode();
+            hash = value.hashCode();
             index = indexOf(value, hash);
         }
         if (index >= 0) {
@@ -406,36 +387,6 @@
     }
 
     /**
-     * Special fast path for appending items to the end of the array without validation.
-     * The array must already be large enough to contain the item.
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    public void append(E value) {
-        final int index = mSize;
-        final int hash = value == null ? 0
-                : (mIdentityHashCode ? System.identityHashCode(value) : value.hashCode());
-        if (index >= mHashes.length) {
-            throw new IllegalStateException("Array is full");
-        }
-        if (index > 0 && mHashes[index - 1] > hash) {
-            // Cannot optimize since it would break the sorted order - fallback to add()
-            if (DEBUG) {
-                RuntimeException e = new RuntimeException("here");
-                e.fillInStackTrace();
-                Log.w(TAG, "New hash " + hash
-                        + " is before end of array hash " + mHashes[index - 1]
-                        + " at index " + index, e);
-            }
-            add(value);
-            return;
-        }
-        mSize = index + 1;
-        mHashes[index] = hash;
-        mArray[index] = value;
-    }
-
-    /**
      * Perform a {@link #add(Object)} of all values in <var>array</var>
      * @param array The array whose contents are to be retrieved.
      */
diff --git a/compat/src/main/java/android/support/v4/util/package.html b/compat/src/main/java/android/support/v4/util/package.html
deleted file mode 100644
index afde9b7..0000000
--- a/compat/src/main/java/android/support/v4/util/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<body>
-
-Support android.util classes to assist with development of applications for
-android API level 4 or later.
-
-</body>
diff --git a/compat/src/main/java/android/support/v4/view/accessibility/package.html b/compat/src/main/java/android/support/v4/view/accessibility/package.html
deleted file mode 100755
index 57b084f..0000000
--- a/compat/src/main/java/android/support/v4/view/accessibility/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-Support classes to access some of the android.view.accessibility package features introduced after API level 4 in a backwards compatible fashion.
-
-</body>
diff --git a/compat/src/main/java/android/support/v4/view/package.html b/compat/src/main/java/android/support/v4/view/package.html
deleted file mode 100755
index d80ef70..0000000
--- a/compat/src/main/java/android/support/v4/view/package.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<body>
-
-Support android.util classes to assist with development of applications for
-android API level 4 or later.  The main features here are a variety of classes
-for handling backwards compatibility with views (for example
-{@link android.support.v4.view.MotionEventCompat} allows retrieving multi-touch
-data if available), and a new
-{@link android.support.v4.view.ViewPager} widget (which at some point should be moved over
-to the widget package).
-
-</body>
diff --git a/compat/src/main/java/android/support/v4/widget/package.html b/compat/src/main/java/android/support/v4/widget/package.html
deleted file mode 100755
index e2c636d..0000000
--- a/compat/src/main/java/android/support/v4/widget/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<body>
-
-Support android.widget classes to assist with development of applications for
-android API level 4 or later.  This includes a complete modern implementation
-of {@link android.support.v4.widget.CursorAdapter} and related classes, which
-is needed for use with {@link android.support.v4.content.CursorLoader}.
-
-</body>
diff --git a/compat/tests/java/android/support/v4/app/NotificationCompatTest.java b/compat/tests/java/android/support/v4/app/NotificationCompatTest.java
index dd870dd..7a5a57f 100644
--- a/compat/tests/java/android/support/v4/app/NotificationCompatTest.java
+++ b/compat/tests/java/android/support/v4/app/NotificationCompatTest.java
@@ -34,6 +34,9 @@
 import android.annotation.TargetApi;
 import android.app.Notification;
 import android.content.Context;
+import android.graphics.Color;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
@@ -424,6 +427,71 @@
         }
     }
 
+    @Test
+    @SdkSuppress(minSdkVersion = 21)
+    public void testHasAudioAttributesFrom21() throws Throwable {
+        Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity())
+                .setSound(Uri.EMPTY)
+                .build();
+        assertNotNull(n.audioAttributes);
+        assertEquals(-1, n.audioStreamType);
+        assertEquals(Uri.EMPTY, n.sound);
+
+        n = new NotificationCompat.Builder(mActivityTestRule.getActivity())
+                .setSound(Uri.EMPTY, AudioManager.STREAM_RING)
+                .build();
+        assertNotNull(n.audioAttributes);
+        assertEquals(AudioAttributes.CONTENT_TYPE_SONIFICATION,
+                n.audioAttributes.getContentType());
+        assertEquals(-1, n.audioStreamType);
+        assertEquals(Uri.EMPTY, n.sound);
+    }
+
+    @Test
+    @SdkSuppress(maxSdkVersion = 20)
+    public void testHasStreamTypePre21() throws Throwable {
+        Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity())
+                .setSound(Uri.EMPTY, 34)
+                .build();
+        assertEquals(34, n.audioStreamType);
+        assertEquals(Uri.EMPTY, n.sound);
+    }
+
+    @SdkSuppress(minSdkVersion = 26)
+    @Test
+    public void testClearAlertingFieldsIfUsingChannels() throws Throwable {
+        long[] vibration = new long[]{100};
+
+        // stripped if using channels
+        Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity(), "test")
+                .setSound(Uri.EMPTY)
+                .setDefaults(Notification.DEFAULT_ALL)
+                .setVibrate(vibration)
+                .setLights(Color.BLUE, 100, 100)
+                .build();
+        assertNull(n.sound);
+        assertEquals(0, n.defaults);
+        assertNull(n.vibrate);
+        assertEquals(0, n.ledARGB);
+        assertEquals(0, n.ledOnMS);
+        assertEquals(0, n.ledOffMS);
+
+        // left intact if not using channels
+        n = new NotificationCompat.Builder(mActivityTestRule.getActivity())
+                .setSound(Uri.EMPTY)
+                .setDefaults(Notification.DEFAULT_ALL)
+                .setVibrate(vibration)
+                .setLights(Color.BLUE, 100, 100)
+                .build();
+        assertEquals(Uri.EMPTY, n.sound);
+        assertNotNull(n.audioAttributes);
+        assertEquals(Notification.DEFAULT_ALL, n.defaults);
+        assertEquals(vibration, n.vibrate);
+        assertEquals(Color.BLUE, n.ledARGB);
+        assertEquals(100, n.ledOnMS);
+        assertEquals(100, n.ledOffMS);
+    }
+
     private static RemoteInput newDataOnlyRemoteInput() {
         return new RemoteInput.Builder(DATA_RESULT_KEY)
             .setAllowFreeFormInput(false)
diff --git a/compat/tests/java/android/support/v4/provider/FontsContractCompatTest.java b/compat/tests/java/android/support/v4/provider/FontsContractCompatTest.java
index 66bdd50..4edab02 100644
--- a/compat/tests/java/android/support/v4/provider/FontsContractCompatTest.java
+++ b/compat/tests/java/android/support/v4/provider/FontsContractCompatTest.java
@@ -40,9 +40,11 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.Signature;
 import android.graphics.Typeface;
+import android.support.annotation.NonNull;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.content.res.ResourcesCompat;
 import android.support.v4.provider.FontsContractCompat.FontFamilyResult;
 import android.support.v4.provider.FontsContractCompat.FontInfo;
 import android.util.Base64;
@@ -56,6 +58,8 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Unit tests for {@link FontsContractCompat}.
@@ -111,34 +115,6 @@
                 InstrumentationRegistry.getInstrumentation().getTargetContext());
     }
 
-    private static class TestCallback extends FontsContractCompat.FontRequestCallback {
-        private Typeface mTypeface;
-
-        private int mSuccessCallCount;
-        private int mFailedCallCount;
-
-        public void onTypefaceRetrieved(Typeface typeface) {
-            mTypeface = typeface;
-            mSuccessCallCount++;
-        }
-
-        public void onTypefaceRequestFailed(int reason) {
-            mFailedCallCount++;
-        }
-
-        public Typeface getTypeface() {
-            return mTypeface;
-        }
-
-        public int getSuccessCallCount() {
-            return mSuccessCallCount;
-        }
-
-        public int getFailedCallCount() {
-            return mFailedCallCount;
-        }
-    }
-
     @Test
     public void typefaceNotCacheTest() throws NameNotFoundException {
         FontRequest request = new FontRequest(
@@ -413,4 +389,43 @@
         when(packageManager.getPackageInfo(anyString(), anyInt())).thenReturn(packageInfo);
         return info;
     }
+
+    @Test
+    public void testGetFontSync_invalidUri() throws InterruptedException {
+        final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+        final FontRequest request = new FontRequest(
+                AUTHORITY, PACKAGE, MockFontProvider.INVALID_URI, SIGNATURE);
+        final CountDownLatch latch = new CountDownLatch(1);
+        final FontCallback callback = new FontCallback(latch);
+
+        inst.runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                FontsContractCompat.getFontSync(mContext, request, callback, null,
+                        false /* isBlockingFetch */, 300 /* timeout */, Typeface.NORMAL);
+            }
+        });
+        assertTrue(latch.await(5L, TimeUnit.SECONDS));
+        assertNull(callback.mTypeface);
+    }
+
+    public static class FontCallback extends ResourcesCompat.FontCallback {
+        private final CountDownLatch mLatch;
+        Typeface mTypeface;
+
+        FontCallback(CountDownLatch latch) {
+            mLatch = latch;
+        }
+
+        @Override
+        public void onFontRetrieved(@NonNull Typeface typeface) {
+            mTypeface = typeface;
+            mLatch.countDown();
+        }
+
+        @Override
+        public void onFontRetrievalFailed(int reason) {
+            mLatch.countDown();
+        }
+    }
 }
diff --git a/compat/tests/java/android/support/v4/provider/MockFontProvider.java b/compat/tests/java/android/support/v4/provider/MockFontProvider.java
index f07d92d..f584d68 100644
--- a/compat/tests/java/android/support/v4/provider/MockFontProvider.java
+++ b/compat/tests/java/android/support/v4/provider/MockFontProvider.java
@@ -43,6 +43,7 @@
     static final String[] FONT_FILES = {
             "samplefont.ttf", "large_a.ttf", "large_b.ttf", "large_c.ttf", "large_d.ttf"
     };
+    private static final int INVALID_FONT_FILE_ID = -1;
     private static final int SAMPLE_FONT_FILE_0_ID = 0;
     private static final int LARGE_A_FILE_ID = 1;
     private static final int LARGE_B_FILE_ID = 2;
@@ -59,6 +60,7 @@
     static final String NEGATIVE_ERROR_CODE_QUERY = "negativeCode";
     static final String MANDATORY_FIELDS_ONLY_QUERY = "mandatoryFields";
     static final String STYLE_TEST_QUERY = "styleTest";
+    static final String INVALID_URI = "invalidURI";
 
     static class Font {
         Font(int id, int fileId, int ttcIndex, String varSettings, int weight, int italic,
@@ -176,6 +178,11 @@
                         Columns.RESULT_CODE_OK, true),
         });
 
+        map.put(INVALID_URI, new Font[] {
+                new Font(id++, INVALID_FONT_FILE_ID, 0, null, 400, 0,
+                        Columns.RESULT_CODE_OK, true),
+        });
+
         QUERY_MAP = Collections.unmodifiableMap(map);
     }
 
@@ -260,6 +267,9 @@
     @Override
     public ParcelFileDescriptor openFile(Uri uri, String mode) {
         final int id = (int) ContentUris.parseId(uri);
+        if (id < 0) {
+            return null;
+        }
         final File targetFile = getCopiedFile(getContext(), FONT_FILES[id]);
         try {
             return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_READ_ONLY);
diff --git a/content/build.gradle b/content/build.gradle
index 3639301..9091053 100644
--- a/content/build.gradle
+++ b/content/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -22,12 +23,12 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-compat')
+    api(project(":support-annotations"))
+    api(project(":support-compat"))
 
-    androidTestImplementation libs.junit
-    androidTestImplementation libs.test_runner,   { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core, { exclude module: 'support-annotations' }
+    androidTestImplementation(JUNIT)
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
 }
 
 android {
diff --git a/content/lint-baseline.xml b/content/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/content/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/core-ui/api/27.0.0.ignore b/core-ui/api/27.0.0.ignore
new file mode 100644
index 0000000..8dbf04a
--- /dev/null
+++ b/core-ui/api/27.0.0.ignore
@@ -0,0 +1,9 @@
+46690b4
+1670c35
+cde6951
+21047f0
+1416521
+4f63fb9
+2337166
+9e34008
+7546756
diff --git a/core-ui/api/current.txt b/core-ui/api/current.txt
index 346ffc4..77e805d 100644
--- a/core-ui/api/current.txt
+++ b/core-ui/api/current.txt
@@ -1,6 +1,6 @@
 package android.support.design.widget {
 
-  public class CoordinatorLayout extends android.view.ViewGroup {
+  public class CoordinatorLayout extends android.view.ViewGroup implements android.support.v4.view.NestedScrollingParent2 {
     ctor public CoordinatorLayout(android.content.Context);
     ctor public CoordinatorLayout(android.content.Context, android.util.AttributeSet);
     ctor public CoordinatorLayout(android.content.Context, android.util.AttributeSet, int);
@@ -16,7 +16,6 @@
     method public void onAttachedToWindow();
     method public void onDetachedFromWindow();
     method public void onDraw(android.graphics.Canvas);
-    method protected void onLayout(boolean, int, int, int, int);
     method public void onLayoutChild(android.view.View, int);
     method public void onMeasureChild(android.view.View, int, int, int, int);
     method public void onNestedPreScroll(android.view.View, int, int, int[], int);
@@ -214,7 +213,6 @@
     ctor public PagerTitleStrip(android.content.Context);
     ctor public PagerTitleStrip(android.content.Context, android.util.AttributeSet);
     method public int getTextSpacing();
-    method protected void onLayout(boolean, int, int, int, int);
     method public void setGravity(int);
     method public void setNonPrimaryAlpha(float);
     method public void setTextColor(int);
@@ -239,7 +237,6 @@
     method public int getOffscreenPageLimit();
     method public int getPageMargin();
     method public boolean isFakeDragging();
-    method protected void onLayout(boolean, int, int, int, int);
     method protected void onPageScrolled(int, float, int);
     method public void onRestoreInstanceState(android.os.Parcelable);
     method public android.os.Parcelable onSaveInstanceState();
@@ -300,23 +297,18 @@
 
 package android.support.v4.view.animation {
 
-  public class FastOutLinearInInterpolator extends android.support.v4.view.animation.LookupTableInterpolator {
+  public class FastOutLinearInInterpolator implements android.view.animation.Interpolator {
     ctor public FastOutLinearInInterpolator();
   }
 
-  public class FastOutSlowInInterpolator extends android.support.v4.view.animation.LookupTableInterpolator {
+  public class FastOutSlowInInterpolator implements android.view.animation.Interpolator {
     ctor public FastOutSlowInInterpolator();
   }
 
-  public class LinearOutSlowInInterpolator extends android.support.v4.view.animation.LookupTableInterpolator {
+  public class LinearOutSlowInInterpolator implements android.view.animation.Interpolator {
     ctor public LinearOutSlowInInterpolator();
   }
 
-   abstract class LookupTableInterpolator implements android.view.animation.Interpolator {
-    ctor public LookupTableInterpolator(float[]);
-    method public float getInterpolation(float);
-  }
-
 }
 
 package android.support.v4.widget {
@@ -348,7 +340,7 @@
     field public static final float RELATIVE_UNSPECIFIED = 0.0f;
   }
 
-  public class CircularProgressDrawable extends android.graphics.drawable.Drawable {
+  public class CircularProgressDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
     ctor public CircularProgressDrawable(android.content.Context);
     method public void draw(android.graphics.Canvas);
     method public boolean getArrowEnabled();
@@ -393,7 +385,7 @@
     method public void show();
   }
 
-  public abstract class CursorAdapter extends android.widget.BaseAdapter {
+  public abstract class CursorAdapter extends android.widget.BaseAdapter implements android.widget.Filterable {
     ctor public deprecated CursorAdapter(android.content.Context, android.database.Cursor);
     ctor public CursorAdapter(android.content.Context, android.database.Cursor, boolean);
     ctor public CursorAdapter(android.content.Context, android.database.Cursor, int);
@@ -438,7 +430,6 @@
     method public boolean isDrawerVisible(android.view.View);
     method public boolean isDrawerVisible(int);
     method public void onDraw(android.graphics.Canvas);
-    method protected void onLayout(boolean, int, int, int, int);
     method public void openDrawer(android.view.View);
     method public void openDrawer(android.view.View, boolean);
     method public void openDrawer(int);
@@ -529,12 +520,18 @@
     method public void scrollTargetBy(int, int);
   }
 
-  public class NestedScrollView extends android.widget.FrameLayout {
+  public class NestedScrollView extends android.widget.FrameLayout implements android.support.v4.view.NestedScrollingChild2 android.support.v4.view.NestedScrollingParent android.support.v4.view.ScrollingView {
     ctor public NestedScrollView(android.content.Context);
     ctor public NestedScrollView(android.content.Context, android.util.AttributeSet);
     ctor public NestedScrollView(android.content.Context, android.util.AttributeSet, int);
     method public boolean arrowScroll(int);
+    method public int computeHorizontalScrollExtent();
+    method public int computeHorizontalScrollOffset();
+    method public int computeHorizontalScrollRange();
     method protected int computeScrollDeltaToGetChildRectOnScreen(android.graphics.Rect);
+    method public int computeVerticalScrollExtent();
+    method public int computeVerticalScrollOffset();
+    method public int computeVerticalScrollRange();
     method public boolean dispatchNestedPreScroll(int, int, int[], int[], int);
     method public boolean dispatchNestedScroll(int, int, int, int, int[], int);
     method public boolean executeKeyEvent(android.view.KeyEvent);
@@ -603,7 +600,6 @@
     method public int getSliderFadeColor();
     method public boolean isOpen();
     method public boolean isSlideable();
-    method protected void onLayout(boolean, int, int, int, int);
     method public boolean openPane();
     method public void setCoveredFadeColor(int);
     method public void setPanelSlideListener(android.support.v4.widget.SlidingPaneLayout.PanelSlideListener);
@@ -648,7 +644,7 @@
     ctor public Space(android.content.Context);
   }
 
-  public class SwipeRefreshLayout extends android.view.ViewGroup {
+  public class SwipeRefreshLayout extends android.view.ViewGroup implements android.support.v4.view.NestedScrollingChild android.support.v4.view.NestedScrollingParent {
     ctor public SwipeRefreshLayout(android.content.Context);
     ctor public SwipeRefreshLayout(android.content.Context, android.util.AttributeSet);
     method public boolean canChildScrollUp();
@@ -656,7 +652,6 @@
     method public int getProgressViewEndOffset();
     method public int getProgressViewStartOffset();
     method public boolean isRefreshing();
-    method protected void onLayout(boolean, int, int, int, int);
     method public void onMeasure(int, int);
     method public deprecated void setColorScheme(int...);
     method public void setColorSchemeColors(int...);
diff --git a/core-ui/build.gradle b/core-ui/build.gradle
index 098440d..f7cd2d7 100644
--- a/core-ui/build.gradle
+++ b/core-ui/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,20 +7,19 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-compat')
+    api(project(":support-annotations"))
+    api(project(":support-compat"))
     api project(':support-core-utils')
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_contrib, { exclude group: 'com.android.support' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(ESPRESSO_CONTRIB, libs.exclude_support)
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
     androidTestImplementation project(':support-testutils'), {
         exclude group: 'com.android.support', module: 'support-core-ui'
     }
 
-    testImplementation libs.junit
+    testImplementation(JUNIT)
 }
 
 android {
diff --git a/core-ui/src/main/java/android/support/design/widget/CoordinatorLayout.java b/core-ui/src/main/java/android/support/design/widget/CoordinatorLayout.java
index c45810e..03cce02 100644
--- a/core-ui/src/main/java/android/support/design/widget/CoordinatorLayout.java
+++ b/core-ui/src/main/java/android/support/design/widget/CoordinatorLayout.java
@@ -400,6 +400,7 @@
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
             lp.resetTouchBehaviorTracking();
         }
+        mBehaviorTouchView = null;
         mDisallowInterceptReset = false;
     }
 
diff --git a/core-ui/src/main/java/android/support/v4/app/package.html b/core-ui/src/main/java/android/support/v4/app/package.html
deleted file mode 100755
index 02d1b79..0000000
--- a/core-ui/src/main/java/android/support/v4/app/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<body>
-
-Support android.app classes to assist with development of applications for
-android API level 4 or later.  The main features here are backwards-compatible
-versions of {@link android.support.v4.app.FragmentManager} and
-{@link android.support.v4.app.LoaderManager}.
-
-</body>
diff --git a/core-ui/src/main/java/android/support/v4/view/PagerAdapter.java b/core-ui/src/main/java/android/support/v4/view/PagerAdapter.java
index a8fb099..af8e076 100644
--- a/core-ui/src/main/java/android/support/v4/view/PagerAdapter.java
+++ b/core-ui/src/main/java/android/support/v4/view/PagerAdapter.java
@@ -131,6 +131,7 @@
     /**
      * Called to inform the adapter of which item is currently considered to
      * be the "primary", that is the one show to the user as the current page.
+     * This method will not be invoked when the adapter contains no items.
      *
      * @param container The containing View from which the page will be removed.
      * @param position The page position that is now the primary.
diff --git a/core-ui/src/main/java/android/support/v4/view/ViewPager.java b/core-ui/src/main/java/android/support/v4/view/ViewPager.java
index 36d8696..350fe95 100644
--- a/core-ui/src/main/java/android/support/v4/view/ViewPager.java
+++ b/core-ui/src/main/java/android/support/v4/view/ViewPager.java
@@ -1224,6 +1224,8 @@
             }
 
             calculatePageOffsets(curItem, curIndex, oldCurInfo);
+
+            mAdapter.setPrimaryItem(this, mCurItem, curItem.object);
         }
 
         if (DEBUG) {
@@ -1233,8 +1235,6 @@
             }
         }
 
-        mAdapter.setPrimaryItem(this, mCurItem, curItem != null ? curItem.object : null);
-
         mAdapter.finishUpdate(this);
 
         // Check width measurement of current pages and drawing sort order.
diff --git a/core-ui/src/main/java/android/support/v4/view/package.html b/core-ui/src/main/java/android/support/v4/view/package.html
deleted file mode 100755
index d80ef70..0000000
--- a/core-ui/src/main/java/android/support/v4/view/package.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<body>
-
-Support android.util classes to assist with development of applications for
-android API level 4 or later.  The main features here are a variety of classes
-for handling backwards compatibility with views (for example
-{@link android.support.v4.view.MotionEventCompat} allows retrieving multi-touch
-data if available), and a new
-{@link android.support.v4.view.ViewPager} widget (which at some point should be moved over
-to the widget package).
-
-</body>
diff --git a/core-ui/src/main/java/android/support/v4/widget/NestedScrollView.java b/core-ui/src/main/java/android/support/v4/widget/NestedScrollView.java
index 73ff084..6fe1928 100644
--- a/core-ui/src/main/java/android/support/v4/widget/NestedScrollView.java
+++ b/core-ui/src/main/java/android/support/v4/widget/NestedScrollView.java
@@ -23,6 +23,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -1820,10 +1821,20 @@
             final int scrollY = getScrollY();
             if (!mEdgeGlowTop.isFinished()) {
                 final int restoreCount = canvas.save();
-                final int width = getWidth() - getPaddingLeft() - getPaddingRight();
-
-                canvas.translate(getPaddingLeft(), Math.min(0, scrollY));
-                mEdgeGlowTop.setSize(width, getHeight());
+                int width = getWidth();
+                int height = getHeight();
+                int xTranslation = 0;
+                int yTranslation = Math.min(0, scrollY);
+                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || getClipToPadding()) {
+                    width -= getPaddingLeft() + getPaddingRight();
+                    xTranslation += getPaddingLeft();
+                }
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && getClipToPadding()) {
+                    height -= getPaddingTop() + getPaddingBottom();
+                    yTranslation += getPaddingTop();
+                }
+                canvas.translate(xTranslation, yTranslation);
+                mEdgeGlowTop.setSize(width, height);
                 if (mEdgeGlowTop.draw(canvas)) {
                     ViewCompat.postInvalidateOnAnimation(this);
                 }
@@ -1831,11 +1842,19 @@
             }
             if (!mEdgeGlowBottom.isFinished()) {
                 final int restoreCount = canvas.save();
-                final int width = getWidth() - getPaddingLeft() - getPaddingRight();
-                final int height = getHeight();
-
-                canvas.translate(-width + getPaddingLeft(),
-                        Math.max(getScrollRange(), scrollY) + height);
+                int width = getWidth();
+                int height = getHeight();
+                int xTranslation = 0;
+                int yTranslation = Math.max(getScrollRange(), scrollY) + height;
+                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || getClipToPadding()) {
+                    width -= getPaddingLeft() + getPaddingRight();
+                    xTranslation += getPaddingLeft();
+                }
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && getClipToPadding()) {
+                    height -= getPaddingTop() + getPaddingBottom();
+                    yTranslation -= getPaddingBottom();
+                }
+                canvas.translate(xTranslation - width, yTranslation);
                 canvas.rotate(180, width, 0);
                 mEdgeGlowBottom.setSize(width, height);
                 if (mEdgeGlowBottom.draw(canvas)) {
diff --git a/core-ui/src/main/java/android/support/v4/widget/package.html b/core-ui/src/main/java/android/support/v4/widget/package.html
deleted file mode 100755
index e2c636d..0000000
--- a/core-ui/src/main/java/android/support/v4/widget/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<body>
-
-Support android.widget classes to assist with development of applications for
-android API level 4 or later.  This includes a complete modern implementation
-of {@link android.support.v4.widget.CursorAdapter} and related classes, which
-is needed for use with {@link android.support.v4.content.CursorLoader}.
-
-</body>
diff --git a/core-ui/tests/AndroidManifest.xml b/core-ui/tests/AndroidManifest.xml
index c1b1a75..904111e 100644
--- a/core-ui/tests/AndroidManifest.xml
+++ b/core-ui/tests/AndroidManifest.xml
@@ -36,6 +36,10 @@
 
         <activity android:name="android.support.v4.view.ViewPagerWithTabStripActivity"/>
 
+        <activity android:name="android.support.v4.view.ViewPagerTest$ViewPagerActivity"/>
+
+        <activity android:name="android.support.design.widget.CoordinatorLayoutActivity"/>
+
     </application>
 
 </manifest>
diff --git a/design/tests/src/android/support/design/testutils/CoordinatorLayoutUtils.java b/core-ui/tests/java/android/support/design/testutils/CoordinatorLayoutUtils.java
similarity index 100%
rename from design/tests/src/android/support/design/testutils/CoordinatorLayoutUtils.java
rename to core-ui/tests/java/android/support/design/testutils/CoordinatorLayoutUtils.java
diff --git a/core-ui/tests/java/android/support/design/widget/CoordinatorLayoutActivity.java b/core-ui/tests/java/android/support/design/widget/CoordinatorLayoutActivity.java
new file mode 100644
index 0000000..b7fe740
--- /dev/null
+++ b/core-ui/tests/java/android/support/design/widget/CoordinatorLayoutActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.design.widget;
+
+import android.support.coreui.test.R;
+import android.support.v4.BaseTestActivity;
+import android.widget.FrameLayout;
+
+public class CoordinatorLayoutActivity extends BaseTestActivity {
+
+    FrameLayout mContainer;
+    CoordinatorLayout mCoordinatorLayout;
+
+    @Override
+    protected int getContentViewLayoutResId() {
+        return R.layout.activity_coordinator_layout;
+    }
+
+    @Override
+    protected void onContentViewSet() {
+        mContainer = findViewById(R.id.container);
+        mCoordinatorLayout = findViewById(R.id.coordinator);
+    }
+
+}
diff --git a/design/tests/src/android/support/design/widget/CoordinatorLayoutSortTest.java b/core-ui/tests/java/android/support/design/widget/CoordinatorLayoutSortTest.java
similarity index 91%
rename from design/tests/src/android/support/design/widget/CoordinatorLayoutSortTest.java
rename to core-ui/tests/java/android/support/design/widget/CoordinatorLayoutSortTest.java
index 0a407b7..4e0ccfc 100644
--- a/design/tests/src/android/support/design/widget/CoordinatorLayoutSortTest.java
+++ b/core-ui/tests/java/android/support/design/widget/CoordinatorLayoutSortTest.java
@@ -22,8 +22,10 @@
 import android.support.design.testutils.CoordinatorLayoutUtils;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
 import android.view.View;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -35,8 +37,9 @@
 
 @RunWith(Parameterized.class)
 @MediumTest
-public class CoordinatorLayoutSortTest
-        extends BaseInstrumentationTestCase<CoordinatorLayoutActivity> {
+public class CoordinatorLayoutSortTest {
+    @Rule
+    public final ActivityTestRule<CoordinatorLayoutActivity> mActivityTestRule;
 
     private static final int NUMBER_VIEWS_DEPENDENCY_SORT = 4;
 
@@ -60,7 +63,7 @@
 
     public CoordinatorLayoutSortTest(int firstIndex, int secondIndex, int thirdIndex,
             int fourthIndex) {
-        super(CoordinatorLayoutActivity.class);
+        mActivityTestRule = new ActivityTestRule<>(CoordinatorLayoutActivity.class);
         mFirstAddIndex = firstIndex;
         mSecondAddIndex = secondIndex;
         mThirdAddIndex = thirdIndex;
@@ -86,8 +89,8 @@
 
             // Create a Behavior which depends on the previously added view
             View dependency = i > 0 ? views.get(i - 1) : null;
-            final CoordinatorLayout.Behavior<View> behavior
-                    = new CoordinatorLayoutUtils.DependentBehavior(dependency);
+            final CoordinatorLayout.Behavior<View> behavior =
+                    new CoordinatorLayoutUtils.DependentBehavior(dependency);
 
             // And set its LayoutParams to use the Behavior
             CoordinatorLayout.LayoutParams lp = col.generateDefaultLayoutParams();
diff --git a/design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java b/core-ui/tests/java/android/support/design/widget/CoordinatorLayoutTest.java
similarity index 97%
rename from design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java
rename to core-ui/tests/java/android/support/design/widget/CoordinatorLayoutTest.java
index 3588043..4062efb 100644
--- a/design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java
+++ b/core-ui/tests/java/android/support/design/widget/CoordinatorLayoutTest.java
@@ -42,13 +42,15 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.support.annotation.NonNull;
-import android.support.design.test.R;
+import android.support.coreui.test.R;
 import android.support.design.testutils.CoordinatorLayoutUtils;
 import android.support.design.testutils.CoordinatorLayoutUtils.DependentBehavior;
 import android.support.design.widget.CoordinatorLayout.Behavior;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.MediumTest;
 import android.support.test.filters.SdkSuppress;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.view.ViewCompat;
 import android.support.v4.view.WindowInsetsCompat;
@@ -59,19 +61,24 @@
 import android.widget.ImageView;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
 @MediumTest
-public class CoordinatorLayoutTest extends BaseInstrumentationTestCase<CoordinatorLayoutActivity> {
+@RunWith(AndroidJUnit4.class)
+public class CoordinatorLayoutTest {
+    @Rule
+    public final ActivityTestRule<CoordinatorLayoutActivity> mActivityTestRule;
 
     private Instrumentation mInstrumentation;
 
     public CoordinatorLayoutTest() {
-        super(CoordinatorLayoutActivity.class);
+        mActivityTestRule = new ActivityTestRule<>(CoordinatorLayoutActivity.class);
     }
 
     @Before
@@ -383,14 +390,14 @@
         final View viewA = new View(col.getContext());
         final View viewB = new View(col.getContext());
         final CoordinatorLayout.LayoutParams lpB = col.generateDefaultLayoutParams();
-        final CoordinatorLayout.Behavior behavior
-                = new CoordinatorLayoutUtils.DependentBehavior(viewA) {
-            @Override
-            public void onDependentViewRemoved(CoordinatorLayout parent, View child,
-                    View dependency) {
-                parent.getDependencies(child);
-            }
-        };
+        final CoordinatorLayout.Behavior behavior =
+                new CoordinatorLayoutUtils.DependentBehavior(viewA) {
+                    @Override
+                    public void onDependentViewRemoved(
+                            CoordinatorLayout parent, View child, View dependency) {
+                        parent.getDependencies(child);
+                    }
+                };
         lpB.setBehavior(behavior);
 
         // Now add views
diff --git a/core-ui/tests/java/android/support/v4/view/ViewPagerTest.java b/core-ui/tests/java/android/support/v4/view/ViewPagerTest.java
new file mode 100644
index 0000000..070a052
--- /dev/null
+++ b/core-ui/tests/java/android/support/v4/view/ViewPagerTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.view;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@MediumTest
+public final class ViewPagerTest {
+    @Rule
+    public final ActivityTestRule<ViewPagerActivity> activityRule = new ActivityTestRule<>(
+            ViewPagerActivity.class);
+
+    public static final class ViewPagerActivity extends Activity {
+        public ViewPager pager;
+
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            pager = new ViewPager(this);
+            setContentView(pager);
+        }
+    }
+
+    @Test
+    public void setPrimaryItemNotCalledWhenAdapterIsEmpty() {
+        ViewPager pager = activityRule.getActivity().pager;
+        final PrimaryItemPagerAdapter adapter = new PrimaryItemPagerAdapter();
+        pager.setAdapter(adapter);
+
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+        assertFalse(adapter.primaryCalled);
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                adapter.count = 1;
+                adapter.notifyDataSetChanged();
+            }
+        });
+
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+        assertTrue(adapter.primaryCalled);
+    }
+
+    static final class PrimaryItemPagerAdapter extends PagerAdapter {
+        public volatile int count;
+        public volatile boolean primaryCalled;
+
+        @Override
+        public int getCount() {
+            return count;
+        }
+
+        @Override
+        public void setPrimaryItem(@NonNull ViewGroup container, int position,
+                @NonNull Object object) {
+            primaryCalled = true;
+        }
+
+        @Override
+        public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
+            return view == object;
+        }
+
+        @NonNull
+        @Override
+        public Object instantiateItem(@NonNull ViewGroup container, int position) {
+            View view = new View(container.getContext());
+            container.addView(view);
+            return view;
+        }
+
+        @Override
+        public void destroyItem(@NonNull ViewGroup container, int position,
+                @NonNull Object object) {
+            container.removeView((View) object);
+        }
+    }
+}
diff --git a/core-ui/tests/res/layout/activity_coordinator_layout.xml b/core-ui/tests/res/layout/activity_coordinator_layout.xml
new file mode 100644
index 0000000..93bf947
--- /dev/null
+++ b/core-ui/tests/res/layout/activity_coordinator_layout.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:id="@+id/container"
+             android:layout_width="match_parent"
+             android:layout_height="match_parent">
+
+    <android.support.design.widget.CoordinatorLayout
+        android:id="@+id/coordinator"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/design/tests/res/layout/include_nestedscrollview.xml b/core-ui/tests/res/layout/include_nestedscrollview.xml
similarity index 100%
rename from design/tests/res/layout/include_nestedscrollview.xml
rename to core-ui/tests/res/layout/include_nestedscrollview.xml
diff --git a/core-ui/tests/res/values/ids.xml b/core-ui/tests/res/values/ids.xml
index e5fcf63..f3ac9b4 100644
--- a/core-ui/tests/res/values/ids.xml
+++ b/core-ui/tests/res/values/ids.xml
@@ -24,4 +24,5 @@
     <item name="page_7" type="id"/>
     <item name="page_8" type="id"/>
     <item name="page_9" type="id"/>
+    <item name="anchor" type="id"/>
 </resources>
\ No newline at end of file
diff --git a/core-utils/build.gradle b/core-utils/build.gradle
index 64c9ff8..3f1efa1 100644
--- a/core-utils/build.gradle
+++ b/core-utils/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,13 +7,13 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-compat')
+    api(project(":support-annotations"))
+    api(project(":support-compat"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
 }
 
 android {
diff --git a/core-utils/java/android/support/v4/app/package.html b/core-utils/java/android/support/v4/app/package.html
deleted file mode 100755
index 02d1b79..0000000
--- a/core-utils/java/android/support/v4/app/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<body>
-
-Support android.app classes to assist with development of applications for
-android API level 4 or later.  The main features here are backwards-compatible
-versions of {@link android.support.v4.app.FragmentManager} and
-{@link android.support.v4.app.LoaderManager}.
-
-</body>
diff --git a/core-utils/java/android/support/v4/content/package.html b/core-utils/java/android/support/v4/content/package.html
deleted file mode 100755
index 33bf4b5..0000000
--- a/core-utils/java/android/support/v4/content/package.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<body>
-
-Support android.content classes to assist with development of applications for
-android API level 4 or later.  The main features here are
-{@link android.support.v4.content.Loader} and related classes and
-{@link android.support.v4.content.LocalBroadcastManager} to
-provide a cleaner implementation of broadcasts that don't need to go outside
-of an app.
-
-</body>
diff --git a/core-utils/lint-baseline.xml b/core-utils/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/core-utils/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/customtabs/build.gradle b/customtabs/build.gradle
index 28b5f99..75e28f7 100644
--- a/customtabs/build.gradle
+++ b/customtabs/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,21 +7,21 @@
 }
 
 dependencies {
-    api project(':support-compat')
-    api project(':support-annotations')
+    api(project(":support-compat"))
+    api(project(":support-annotations"))
 
-    androidTestImplementation libs.test_runner,   { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core, { exclude module: 'support-annotations' }
-    androidTestImplementation project(':support-testutils')
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(project(":support-testutils"))
 }
 
 android {
     defaultConfig {
-        minSdkVersion 15
+        minSdkVersion(15)
     }
 
     sourceSets {
-        main.aidl.srcDirs = ['src/main/java']
+        main.aidl.srcDirs = ["src/main/java"]
     }
 }
 
diff --git a/customtabs/lint-baseline.xml b/customtabs/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/customtabs/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/design/api/27.0.0.ignore b/design/api/27.0.0.ignore
index 533cc49..d982dc1 100644
--- a/design/api/27.0.0.ignore
+++ b/design/api/27.0.0.ignore
@@ -1,5 +1,14 @@
+a1fc27e
 197ce1d
 88bc57e
 9761c3e
 86b38bf
 c6abd5e
+cea5c29
+8bac7c2
+f02de9f
+1d50e39
+fb2d5b2
+4c9b1f0
+7da565d
+33c90df
diff --git a/design/api/current.txt b/design/api/current.txt
index b15eca1..71de20a 100644
--- a/design/api/current.txt
+++ b/design/api/current.txt
@@ -15,7 +15,7 @@
     method public deprecated void setTargetElevation(float);
   }
 
-  public static class AppBarLayout.Behavior extends android.support.design.widget.HeaderBehavior {
+  public static class AppBarLayout.Behavior extends android.support.design.widget.CoordinatorLayout.Behavior {
     ctor public AppBarLayout.Behavior();
     ctor public AppBarLayout.Behavior(android.content.Context, android.util.AttributeSet);
     method public boolean onLayoutChild(android.support.design.widget.CoordinatorLayout, android.support.design.widget.AppBarLayout, int);
@@ -63,7 +63,7 @@
     method public abstract void onOffsetChanged(android.support.design.widget.AppBarLayout, int);
   }
 
-  public static class AppBarLayout.ScrollingViewBehavior extends android.support.design.widget.HeaderScrollingViewBehavior {
+  public static class AppBarLayout.ScrollingViewBehavior extends android.support.design.widget.CoordinatorLayout.Behavior {
     ctor public AppBarLayout.ScrollingViewBehavior();
     ctor public AppBarLayout.ScrollingViewBehavior(android.content.Context, android.util.AttributeSet);
     method public boolean layoutDependsOn(android.support.design.widget.CoordinatorLayout, android.view.View, android.view.View);
@@ -183,7 +183,6 @@
     ctor public CollapsingToolbarLayout(android.content.Context, android.util.AttributeSet);
     ctor public CollapsingToolbarLayout(android.content.Context, android.util.AttributeSet, int);
     method protected android.support.design.widget.CollapsingToolbarLayout.LayoutParams generateDefaultLayoutParams();
-    method public android.widget.FrameLayout.LayoutParams generateLayoutParams(android.util.AttributeSet);
     method protected android.widget.FrameLayout.LayoutParams generateLayoutParams(android.view.ViewGroup.LayoutParams);
     method public int getCollapsedTitleGravity();
     method public android.graphics.Typeface getCollapsedTitleTypeface();
@@ -244,13 +243,14 @@
     field public static final int COLLAPSE_MODE_PIN = 1; // 0x1
   }
 
-  public class FloatingActionButton extends android.support.design.widget.VisibilityAwareImageButton {
+  public class FloatingActionButton extends android.widget.ImageButton {
     ctor public FloatingActionButton(android.content.Context);
     ctor public FloatingActionButton(android.content.Context, android.util.AttributeSet);
     ctor public FloatingActionButton(android.content.Context, android.util.AttributeSet, int);
     method public float getCompatElevation();
     method public android.graphics.drawable.Drawable getContentBackground();
     method public boolean getContentRect(android.graphics.Rect);
+    method public int getCustomSize();
     method public int getRippleColor();
     method public int getSize();
     method public boolean getUseCompatPadding();
@@ -258,11 +258,13 @@
     method public void hide(android.support.design.widget.FloatingActionButton.OnVisibilityChangedListener);
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
     method public void setCompatElevation(float);
+    method public void setCustomSize(int);
     method public void setRippleColor(int);
     method public void setSize(int);
     method public void setUseCompatPadding(boolean);
     method public void show();
     method public void show(android.support.design.widget.FloatingActionButton.OnVisibilityChangedListener);
+    field public static final int NO_CUSTOM_SIZE = 0; // 0x0
     field public static final int SIZE_AUTO = -1; // 0xffffffff
     field public static final int SIZE_MINI = 1; // 0x1
     field public static final int SIZE_NORMAL = 0; // 0x0
@@ -284,20 +286,6 @@
     method public void onShown(android.support.design.widget.FloatingActionButton);
   }
 
-   abstract class HeaderBehavior<V extends android.view.View> extends android.support.design.widget.ViewOffsetBehavior {
-    ctor public HeaderBehavior();
-    ctor public HeaderBehavior(android.content.Context, android.util.AttributeSet);
-  }
-
-   abstract class HeaderScrollingViewBehavior extends android.support.design.widget.ViewOffsetBehavior {
-    ctor public HeaderScrollingViewBehavior();
-    ctor public HeaderScrollingViewBehavior(android.content.Context, android.util.AttributeSet);
-    method public final int getOverlayTop();
-    method protected void layoutChild(android.support.design.widget.CoordinatorLayout, android.view.View, int);
-    method public boolean onMeasureChild(android.support.design.widget.CoordinatorLayout, android.view.View, int, int, int, int);
-    method public final void setOverlayTop(int);
-  }
-
   public class NavigationView extends android.widget.FrameLayout {
     ctor public NavigationView(android.content.Context);
     ctor public NavigationView(android.content.Context, android.util.AttributeSet);
@@ -396,7 +384,6 @@
     method public void addTab(android.support.design.widget.TabLayout.Tab, boolean);
     method public void addTab(android.support.design.widget.TabLayout.Tab, int, boolean);
     method public void clearOnTabSelectedListeners();
-    method public android.widget.FrameLayout.LayoutParams generateLayoutParams(android.util.AttributeSet);
     method public int getSelectedTabPosition();
     method public android.support.design.widget.TabLayout.Tab getTabAt(int);
     method public int getTabCount();
@@ -472,7 +459,7 @@
     ctor public TextInputEditText(android.content.Context, android.util.AttributeSet, int);
   }
 
-  public class TextInputLayout extends android.widget.LinearLayout {
+  public class TextInputLayout extends android.widget.LinearLayout implements android.support.v7.widget.WithHint {
     ctor public TextInputLayout(android.content.Context);
     ctor public TextInputLayout(android.content.Context, android.util.AttributeSet);
     ctor public TextInputLayout(android.content.Context, android.util.AttributeSet, int);
@@ -508,21 +495,5 @@
     method public void setTypeface(android.graphics.Typeface);
   }
 
-   class ViewOffsetBehavior<V extends android.view.View> extends android.support.design.widget.CoordinatorLayout.Behavior {
-    ctor public ViewOffsetBehavior();
-    ctor public ViewOffsetBehavior(android.content.Context, android.util.AttributeSet);
-    method public int getLeftAndRightOffset();
-    method public int getTopAndBottomOffset();
-    method protected void layoutChild(android.support.design.widget.CoordinatorLayout, V, int);
-    method public boolean setLeftAndRightOffset(int);
-    method public boolean setTopAndBottomOffset(int);
-  }
-
-   class VisibilityAwareImageButton extends android.widget.ImageButton {
-    ctor public VisibilityAwareImageButton(android.content.Context);
-    ctor public VisibilityAwareImageButton(android.content.Context, android.util.AttributeSet);
-    ctor public VisibilityAwareImageButton(android.content.Context, android.util.AttributeSet, int);
-  }
-
 }
 
diff --git a/design/build.gradle b/design/build.gradle
index 06a5a55..e7ebc91 100644
--- a/design/build.gradle
+++ b/design/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,16 +7,16 @@
 }
 
 dependencies {
-    api project(':support-v4')
-    api project(':appcompat-v7')
-    api project(':recyclerview-v7')
-    api project(':transition')
+    api(project(":support-v4"))
+    api(project(":appcompat-v7"))
+    api(project(":recyclerview-v7"))
+    api(project(":transition"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_contrib, { exclude group: 'com.android.support' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(ESPRESSO_CONTRIB, libs.exclude_support)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
     androidTestImplementation project(':support-testutils')
 }
 
diff --git a/design/lint-baseline.xml b/design/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/design/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/design/res/values/attrs.xml b/design/res/values/attrs.xml
index 6cdb22c..8c3536f 100644
--- a/design/res/values/attrs.xml
+++ b/design/res/values/attrs.xml
@@ -23,7 +23,7 @@
 
         <!-- Ripple color for the FAB. -->
         <attr name="rippleColor" format="color"/>
-        <!-- Size for the FAB. -->
+        <!-- Size for the FAB. If fabCustomSize is set, this will be ignored. -->
         <attr name="fabSize">
             <!-- A size which will change based on the window size. -->
             <enum name="auto" value="-1"/>
@@ -32,6 +32,8 @@
             <!-- The mini sized button. -->
             <enum name="mini" value="1"/>
         </attr>
+        <!-- Custom size for the FAB. If this is set, fabSize will be ignored. -->
+        <attr name="fabCustomSize" format="dimension"/>
         <!-- Elevation value for the FAB -->
         <attr name="elevation"/>
         <!-- TranslationZ value for the FAB when pressed-->
diff --git a/design/src/android/support/design/widget/FloatingActionButton.java b/design/src/android/support/design/widget/FloatingActionButton.java
index a53096e..f37b379 100644
--- a/design/src/android/support/design/widget/FloatingActionButton.java
+++ b/design/src/android/support/design/widget/FloatingActionButton.java
@@ -117,6 +117,11 @@
     public static final int SIZE_AUTO = -1;
 
     /**
+     * Indicates that FloatingActionButton should not have a custom size.
+     */
+    public static final int NO_CUSTOM_SIZE = 0;
+
+    /**
      * The switch point for the largest screen edge where SIZE_AUTO switches from mini to normal.
      */
     private static final int AUTO_MINI_LARGEST_SCREEN_WIDTH = 470;
@@ -133,6 +138,7 @@
     private int mBorderWidth;
     private int mRippleColor;
     private int mSize;
+    private int mCustomSize;
     int mImagePadding;
     private int mMaxImageSize;
 
@@ -165,6 +171,8 @@
                 R.styleable.FloatingActionButton_backgroundTintMode, -1), null);
         mRippleColor = a.getColor(R.styleable.FloatingActionButton_rippleColor, 0);
         mSize = a.getInt(R.styleable.FloatingActionButton_fabSize, SIZE_AUTO);
+        mCustomSize = a.getDimensionPixelSize(R.styleable.FloatingActionButton_fabCustomSize,
+                    0);
         mBorderWidth = a.getDimensionPixelSize(R.styleable.FloatingActionButton_borderWidth, 0);
         final float elevation = a.getDimension(R.styleable.FloatingActionButton_elevation, 0f);
         final float pressedTranslationZ = a.getDimension(
@@ -431,12 +439,41 @@
         };
     }
 
+    /**
+     * Sets the size of the button to be a custom value in pixels. If set to
+     * {@link #NO_CUSTOM_SIZE}, custom size will not be used and size will be calculated according
+     * to {@link #setSize(int)} method.
+     *
+     * @param size preferred size in pixels, or zero
+     *
+     * @attr ref android.support.design.R.styleable#FloatingActionButton_fabCustomSize
+     */
+    public void setCustomSize(int size) {
+        if (size < 0) {
+            throw new IllegalArgumentException("Custom size should be non-negative.");
+        }
+        mCustomSize = size;
+    }
+
+    /**
+     * Returns the custom size for this button.
+     *
+     * @return size in pixels, or {@link #NO_CUSTOM_SIZE}
+     */
+    public int getCustomSize() {
+        return mCustomSize;
+    }
+
     int getSizeDimension() {
         return getSizeDimension(mSize);
     }
 
     private int getSizeDimension(@Size final int size) {
         final Resources res = getResources();
+        // If custom size is set, return it
+        if (mCustomSize != NO_CUSTOM_SIZE) {
+            return mCustomSize;
+        }
         switch (size) {
             case SIZE_AUTO:
                 // If we're set to auto, grab the size from resources and refresh
diff --git a/design/tests/res/values/ids.xml b/design/tests/res/values/ids.xml
index 73540b7..52b8356 100644
--- a/design/tests/res/values/ids.xml
+++ b/design/tests/res/values/ids.xml
@@ -26,5 +26,4 @@
     <item name="page_9" type="id"/>
     <item name="textinputlayout" type="id"/>
     <item name="textinputedittext" type="id"/>
-    <item name="anchor" type="id"/>
 </resources>
\ No newline at end of file
diff --git a/design/tests/src/android/support/design/testutils/FloatingActionButtonActions.java b/design/tests/src/android/support/design/testutils/FloatingActionButtonActions.java
index 97949e6..a166f6b 100644
--- a/design/tests/src/android/support/design/testutils/FloatingActionButtonActions.java
+++ b/design/tests/src/android/support/design/testutils/FloatingActionButtonActions.java
@@ -107,6 +107,30 @@
         };
     }
 
+    public static ViewAction setCustomSize(final int size) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isAssignableFrom(FloatingActionButton.class);
+            }
+
+            @Override
+            public String getDescription() {
+                return "Sets FloatingActionButton custom size";
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                uiController.loopMainThreadUntilIdle();
+
+                final FloatingActionButton fab = (FloatingActionButton) view;
+                fab.setCustomSize(size);
+
+                uiController.loopMainThreadUntilIdle();
+            }
+        };
+    }
+
     public static ViewAction setCompatElevation(final float size) {
         return new ViewAction() {
             @Override
diff --git a/design/tests/src/android/support/design/testutils/TestUtilsMatchers.java b/design/tests/src/android/support/design/testutils/TestUtilsMatchers.java
index 36cdee6..46bb982 100644
--- a/design/tests/src/android/support/design/testutils/TestUtilsMatchers.java
+++ b/design/tests/src/android/support/design/testutils/TestUtilsMatchers.java
@@ -268,6 +268,36 @@
     }
 
     /**
+     * Returns a matcher that matches FloatingActionButtons with the specified custom size.
+     */
+    public static Matcher withFabCustomSize(final int customSize) {
+        return new BoundedMatcher<View, View>(View.class) {
+            private String mFailedCheckDescription;
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText(mFailedCheckDescription);
+            }
+
+            @Override
+            public boolean matchesSafely(final View view) {
+                if (!(view instanceof FloatingActionButton)) {
+                    return false;
+                }
+
+                final FloatingActionButton fab = (FloatingActionButton) view;
+                if (Math.abs(fab.getCustomSize() - customSize) > 1.0f) {
+                    mFailedCheckDescription =
+                            "Custom size " + fab.getCustomSize() + " is different than expected "
+                                    + customSize;
+                    return false;
+                }
+                return true;
+            }
+        };
+    }
+
+    /**
      * Returns a matcher that matches FloatingActionButtons with the specified background
      * fill color.
      */
diff --git a/design/tests/src/android/support/design/widget/FloatingActionButtonTest.java b/design/tests/src/android/support/design/widget/FloatingActionButtonTest.java
index 1037235..f7e9286 100644
--- a/design/tests/src/android/support/design/widget/FloatingActionButtonTest.java
+++ b/design/tests/src/android/support/design/widget/FloatingActionButtonTest.java
@@ -20,6 +20,7 @@
 import static android.support.design.testutils.FloatingActionButtonActions.setBackgroundTintColor;
 import static android.support.design.testutils.FloatingActionButtonActions.setBackgroundTintList;
 import static android.support.design.testutils.FloatingActionButtonActions.setCompatElevation;
+import static android.support.design.testutils.FloatingActionButtonActions.setCustomSize;
 import static android.support.design.testutils.FloatingActionButtonActions.setImageResource;
 import static android.support.design.testutils.FloatingActionButtonActions.setLayoutGravity;
 import static android.support.design.testutils.FloatingActionButtonActions.setSize;
@@ -31,6 +32,7 @@
 import static android.support.design.testutils.TestUtilsMatchers.withFabBackgroundFill;
 import static android.support.design.testutils.TestUtilsMatchers.withFabContentAreaOnMargins;
 import static android.support.design.testutils.TestUtilsMatchers.withFabContentHeight;
+import static android.support.design.testutils.TestUtilsMatchers.withFabCustomSize;
 import static android.support.design.widget.DesignViewActions.setVisibility;
 import static android.support.test.espresso.Espresso.onView;
 import static android.support.test.espresso.action.ViewActions.click;
@@ -271,4 +273,16 @@
                 .perform(setEnabled(true))
                 .perform(setCompatElevation(8));
     }
+
+    @SmallTest
+    @Test
+    public void testSetCustomSize() {
+        onView(withId(R.id.fab_standard))
+                .perform(setCustomSize(10))
+                .check(matches(withFabCustomSize(10)));
+
+        onView(withId(R.id.fab_standard))
+                .perform(setCustomSize(20))
+                .check(matches(withFabCustomSize(20)));
+    }
 }
diff --git a/dynamic-animation/build.gradle b/dynamic-animation/build.gradle
index 5069a73..ac5623d 100644
--- a/dynamic-animation/build.gradle
+++ b/dynamic-animation/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,12 +7,12 @@
 }
 
 dependencies {
-    api project(':support-core-utils')
+    api(project(":support-core-utils"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
 }
 
 android {
diff --git a/dynamic-animation/lint-baseline.xml b/dynamic-animation/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/dynamic-animation/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/emoji/appcompat/build.gradle b/emoji/appcompat/build.gradle
index 7912c52..3fe04d8 100644
--- a/emoji/appcompat/build.gradle
+++ b/emoji/appcompat/build.gradle
@@ -23,8 +23,8 @@
 
 dependencies {
     api fileTree(include: ['*.jar'], dir: 'libs')
-    api project(':support-emoji')
-    api project(':appcompat-v7')
+    api(project(":support-emoji"))
+    api(project(":appcompat-v7"))
 }
 
 android {
diff --git a/emoji/appcompat/lint-baseline.xml b/emoji/appcompat/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/emoji/appcompat/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/emoji/bundled/build.gradle b/emoji/bundled/build.gradle
index c0613f2..013ab85 100644
--- a/emoji/bundled/build.gradle
+++ b/emoji/bundled/build.gradle
@@ -20,7 +20,7 @@
 }
 
 dependencies {
-    api project(':support-emoji')
+    api(project(":support-emoji"))
 }
 
 supportLibrary {
diff --git a/emoji/bundled/lint-baseline.xml b/emoji/bundled/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/emoji/bundled/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/emoji/core/build.gradle b/emoji/core/build.gradle
index f07c277..a311f25 100644
--- a/emoji/core/build.gradle
+++ b/emoji/core/build.gradle
@@ -1,5 +1,8 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
+import java.util.zip.ZipException
+import java.util.zip.ZipFile
 
 plugins {
     id("SupportAndroidLibraryPlugin")
@@ -19,12 +22,12 @@
     // treats this as local jar and package it inside the aar.
     api files(configurations.repackage)
 
-    api project(':support-compat')
+    api(project(":support-compat"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
     androidTestImplementation project(':support-testutils')
 }
 
@@ -76,3 +79,53 @@
         url = "http://www.unicode.org/copyright.html#License"
     }
 }
+
+import org.gradle.api.Task
+import org.gradle.api.tasks.TaskAction
+
+class ValidateJarInput extends DefaultTask {
+    Task syncTask
+
+    @TaskAction
+    void validate() {
+        for (File f : syncTask.inputs.files.files) {
+            if (f.name.endsWith(".jar")) {
+                ZipFile zip = null
+                for (def i : 0..3) {
+                    try {
+                        zip = new ZipFile(f)
+                        if (i > 0) {
+                            // If we get here, we know this is some timing issues.  The jar file is
+                            // properly created, but only if we wait.
+                            logger.error("Succeeded in opening jar file '$f' after $i retries.  Failing build.")
+                            throw new RuntimeException("Failed opening zip file earlier.")
+                        }
+                        break
+                    } catch (ZipException e) {
+                        logger.error("Error opening jar file '$f' (attempt: $i): $e.message")
+                        sleep(1000)
+                    } finally {
+                        if (zip != null) {
+                            zip.close()
+                        }
+                    }
+                    if (i == 3) {
+                        // We failed after 3 retries, this means the generated file is not a proper
+                        // jar file.
+                        throw new RuntimeException("Failed opening zip file after 3 retries.")
+                    }
+                }
+            }
+        }
+    }
+}
+
+afterEvaluate {
+    def syncJniTask = tasks.getByName("transformNativeLibsWithSyncJniLibsForRelease")
+    println "found $syncJniTask.name"
+    def validateTask = tasks.create("validateJarInputsForRelease", ValidateJarInput.class) { t ->
+        t.syncTask = syncJniTask
+    }
+    validateTask.dependsOn(syncJniTask.getDependsOn().collect())
+    syncJniTask.dependsOn(validateTask)
+}
diff --git a/emoji/core/lint-baseline.xml b/emoji/core/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/emoji/core/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java
index f258c12..5436aa2 100644
--- a/emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java
+++ b/emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java
@@ -221,6 +221,7 @@
      *
      * @see EmojiCompat.Config
      */
+    @SuppressWarnings("GuardedBy")
     public static EmojiCompat init(@NonNull final Config config) {
         if (sInstance == null) {
             synchronized (sInstanceLock) {
@@ -238,6 +239,7 @@
      *
      * @hide
      */
+    @SuppressWarnings("GuardedBy")
     @RestrictTo(LIBRARY_GROUP)
     @VisibleForTesting
     public static EmojiCompat reset(@NonNull final Config config) {
@@ -252,6 +254,7 @@
      *
      * @hide
      */
+    @SuppressWarnings("GuardedBy")
     @RestrictTo(LIBRARY_GROUP)
     @VisibleForTesting
     public static EmojiCompat reset(final EmojiCompat emojiCompat) {
diff --git a/emoji/core/src/main/java/android/support/text/emoji/EmojiMetadata.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiMetadata.java
index 488dcf9..7d495ed 100644
--- a/emoji/core/src/main/java/android/support/text/emoji/EmojiMetadata.java
+++ b/emoji/core/src/main/java/android/support/text/emoji/EmojiMetadata.java
@@ -26,12 +26,13 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
-import android.support.text.emoji.flatbuffer.MetadataItem;
-import android.support.text.emoji.flatbuffer.MetadataList;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
+import androidx.text.emoji.flatbuffer.MetadataItem;
+import androidx.text.emoji.flatbuffer.MetadataList;
+
 /**
  * Information about a single emoji.
  *
diff --git a/emoji/core/src/main/java/android/support/text/emoji/MetadataListReader.java b/emoji/core/src/main/java/android/support/text/emoji/MetadataListReader.java
index 6034726..02856cb 100644
--- a/emoji/core/src/main/java/android/support/text/emoji/MetadataListReader.java
+++ b/emoji/core/src/main/java/android/support/text/emoji/MetadataListReader.java
@@ -22,13 +22,14 @@
 import android.support.annotation.IntRange;
 import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
-import android.support.text.emoji.flatbuffer.MetadataList;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
+import androidx.text.emoji.flatbuffer.MetadataList;
+
 /**
  * Reads the emoji metadata from a given InputStream or ByteBuffer.
  *
@@ -275,7 +276,7 @@
         @Override
         public void skip(int numOfBytes) throws IOException {
             while (numOfBytes > 0) {
-                long skipped = mInputStream.skip(numOfBytes);
+                int skipped = (int) mInputStream.skip(numOfBytes);
                 if (skipped < 1) {
                     throw new IOException("Skip didn't move at least 1 byte forward");
                 }
diff --git a/emoji/core/src/main/java/android/support/text/emoji/MetadataRepo.java b/emoji/core/src/main/java/android/support/text/emoji/MetadataRepo.java
index e86277e..f5afec8 100644
--- a/emoji/core/src/main/java/android/support/text/emoji/MetadataRepo.java
+++ b/emoji/core/src/main/java/android/support/text/emoji/MetadataRepo.java
@@ -24,7 +24,6 @@
 import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
 import android.support.annotation.VisibleForTesting;
-import android.support.text.emoji.flatbuffer.MetadataList;
 import android.support.v4.util.Preconditions;
 import android.util.SparseArray;
 
@@ -32,6 +31,8 @@
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 
+import androidx.text.emoji.flatbuffer.MetadataList;
+
 /**
  * Class to hold the emoji metadata required to process and draw emojis.
  */
diff --git a/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditableFactory.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditableFactory.java
index 9793c9d..20cde4f 100644
--- a/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditableFactory.java
+++ b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditableFactory.java
@@ -55,6 +55,7 @@
         }
     }
 
+    @SuppressWarnings("GuardedBy")
     public static Editable.Factory getInstance() {
         if (sInstance == null) {
             synchronized (sInstanceLock) {
diff --git a/exifinterface/build.gradle b/exifinterface/build.gradle
index b7218f9..fa4d7b4 100644
--- a/exifinterface/build.gradle
+++ b/exifinterface/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,9 +7,9 @@
 }
 
 dependencies {
-    api project(':support-annotations')
+    api(project(":support-annotations"))
 
-    androidTestImplementation libs.test_runner,   { exclude module: 'support-annotations' }
+    androidTestImplementation(TEST_RUNNER)
 }
 
 android {
diff --git a/exifinterface/lint-baseline.xml b/exifinterface/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/exifinterface/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/exifinterface/src/main/java/android/support/media/ExifInterface.java b/exifinterface/src/main/java/android/support/media/ExifInterface.java
index 72b61cb..eea69ab 100644
--- a/exifinterface/src/main/java/android/support/media/ExifInterface.java
+++ b/exifinterface/src/main/java/android/support/media/ExifInterface.java
@@ -4678,9 +4678,7 @@
     private int getMimeType(BufferedInputStream in) throws IOException {
         in.mark(SIGNATURE_CHECK_SIZE);
         byte[] signatureCheckBytes = new byte[SIGNATURE_CHECK_SIZE];
-        if (in.read(signatureCheckBytes) != SIGNATURE_CHECK_SIZE) {
-            throw new EOFException();
-        }
+        in.read(signatureCheckBytes);
         in.reset();
         if (isJpegFormat(signatureCheckBytes)) {
             return IMAGE_TYPE_JPEG;
@@ -5333,7 +5331,7 @@
             int dataFormat = dataInputStream.readUnsignedShort();
             int numberOfComponents = dataInputStream.readInt();
             // Next four bytes is for data offset or value.
-            long nextEntryOffset = dataInputStream.peek() + 4;
+            long nextEntryOffset = dataInputStream.peek() + 4L;
 
             // Look up a corresponding tag from tag number
             ExifTag tag = (ExifTag) sExifTagMapsForReading[ifdType].get(tagNumber);
diff --git a/fragment/api/current.txt b/fragment/api/current.txt
index ccd6f4f..df78c30 100644
--- a/fragment/api/current.txt
+++ b/fragment/api/current.txt
@@ -22,7 +22,7 @@
     field public static final int STYLE_NO_TITLE = 1; // 0x1
   }
 
-  public class Fragment implements android.content.ComponentCallbacks android.view.View.OnCreateContextMenuListener {
+  public class Fragment implements android.content.ComponentCallbacks android.arch.lifecycle.LifecycleOwner android.view.View.OnCreateContextMenuListener {
     ctor public Fragment();
     method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public final boolean equals(java.lang.Object);
@@ -141,7 +141,7 @@
     field public static final android.os.Parcelable.Creator<android.support.v4.app.Fragment.SavedState> CREATOR;
   }
 
-  public class FragmentActivity extends android.support.v4.app.SupportActivity {
+  public class FragmentActivity extends android.support.v4.app.SupportActivity implements android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback android.support.v4.app.ActivityCompat.RequestPermissionsRequestCodeValidator {
     ctor public FragmentActivity();
     method public java.lang.Object getLastCustomNonConfigurationInstance();
     method public android.support.v4.app.FragmentManager getSupportFragmentManager();
diff --git a/fragment/build.gradle b/fragment/build.gradle
index 73977c2..b1cc47e 100644
--- a/fragment/build.gradle
+++ b/fragment/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,15 +7,15 @@
 }
 
 dependencies {
-    api project(':support-compat')
-    api project(':support-core-ui')
-    api project(':support-core-utils')
-    api project(':support-annotations')
+    api(project(":support-compat"))
+    api(project(":support-core-ui"))
+    api(project(":support-core-utils"))
+    api(project(":support-annotations"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has its own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has its own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
     androidTestImplementation project(':support-testutils'), {
         exclude group: 'com.android.support', module: 'support-fragment'
     }
diff --git a/fragment/lint-baseline.xml b/fragment/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/fragment/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/fragment/src/main/java/android/support/v4/app/Fragment.java b/fragment/src/main/java/android/support/v4/app/Fragment.java
index e734a27..5b560cd 100644
--- a/fragment/src/main/java/android/support/v4/app/Fragment.java
+++ b/fragment/src/main/java/android/support/v4/app/Fragment.java
@@ -1816,8 +1816,9 @@
      * use the same value as set in {@link #setEnterTransition(Object)}.
      *
      * @param transition The Transition to use to move Views out of the Scene when the Fragment
-     *                   is preparing to close. <code>transition</code> must be an
-     *                   android.transition.Transition.
+     *         is preparing to close. <code>transition</code> must be an
+     *         {@link android.transition.Transition android.transition.Transition} or
+     *         {@link android.support.transition.Transition android.support.transition.Transition}.
      */
     public void setReturnTransition(@Nullable Object transition) {
         ensureAnimationInfo().mReturnTransition = transition;
@@ -1854,8 +1855,10 @@
      * remain unaffected.
      *
      * @param transition The Transition to use to move Views out of the Scene when the Fragment
-     *                   is being closed not due to popping the back stack. <code>transition</code>
-     *                   must be an android.transition.Transition.
+     *          is being closed not due to popping the back stack. <code>transition</code>
+     *          must be an
+     *          {@link android.transition.Transition android.transition.Transition} or
+     *          {@link android.support.transition.Transition android.support.transition.Transition}.
      */
     public void setExitTransition(@Nullable Object transition) {
         ensureAnimationInfo().mExitTransition = transition;
@@ -1891,8 +1894,10 @@
      * transition as {@link #setExitTransition(Object)}.
      *
      * @param transition The Transition to use to move Views into the scene when reentering from a
-     *                   previously-started Activity. <code>transition</code>
-     *                   must be an android.transition.Transition.
+     *          previously-started Activity. <code>transition</code>
+     *          must be an
+     *          {@link android.transition.Transition android.transition.Transition} or
+     *          {@link android.support.transition.Transition android.support.transition.Transition}.
      */
     public void setReenterTransition(@Nullable Object transition) {
         ensureAnimationInfo().mReenterTransition = transition;
@@ -1925,7 +1930,9 @@
      * value will cause transferred shared elements to blink to the final position.
      *
      * @param transition The Transition to use for shared elements transferred into the content
-     *                   Scene.  <code>transition</code> must be an android.transition.Transition.
+     *          Scene.  <code>transition</code> must be an
+     *          {@link android.transition.Transition android.transition.Transition} or
+     *          {@link android.support.transition.Transition android.support.transition.Transition}.
      */
     public void setSharedElementEnterTransition(@Nullable Object transition) {
         ensureAnimationInfo().mSharedElementEnterTransition = transition;
@@ -1958,7 +1965,9 @@
      * {@link #setSharedElementEnterTransition(Object)}.
      *
      * @param transition The Transition to use for shared elements transferred out of the content
-     *                   Scene. <code>transition</code> must be an android.transition.Transition.
+     *          Scene. <code>transition</code> must be an
+     *          {@link android.transition.Transition android.transition.Transition} or
+     *          {@link android.support.transition.Transition android.support.transition.Transition}.
      */
     public void setSharedElementReturnTransition(@Nullable Object transition) {
         ensureAnimationInfo().mSharedElementReturnTransition = transition;
diff --git a/fragment/src/main/java/android/support/v4/app/package.html b/fragment/src/main/java/android/support/v4/app/package.html
deleted file mode 100755
index 02d1b79..0000000
--- a/fragment/src/main/java/android/support/v4/app/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<body>
-
-Support android.app classes to assist with development of applications for
-android API level 4 or later.  The main features here are backwards-compatible
-versions of {@link android.support.v4.app.FragmentManager} and
-{@link android.support.v4.app.LoaderManager}.
-
-</body>
diff --git a/graphics/drawable/animated/api/27.0.0.ignore b/graphics/drawable/animated/api/27.0.0.ignore
new file mode 100644
index 0000000..34748c7
--- /dev/null
+++ b/graphics/drawable/animated/api/27.0.0.ignore
@@ -0,0 +1 @@
+da32427
diff --git a/graphics/drawable/animated/api/current.txt b/graphics/drawable/animated/api/current.txt
index f2601de..ebdc90b 100644
--- a/graphics/drawable/animated/api/current.txt
+++ b/graphics/drawable/animated/api/current.txt
@@ -1,6 +1,6 @@
 package android.support.graphics.drawable {
 
-  public abstract interface Animatable2Compat {
+  public abstract interface Animatable2Compat implements android.graphics.drawable.Animatable {
     method public abstract void clearAnimationCallbacks();
     method public abstract void registerAnimationCallback(android.support.graphics.drawable.Animatable2Compat.AnimationCallback);
     method public abstract boolean unregisterAnimationCallback(android.support.graphics.drawable.Animatable2Compat.AnimationCallback);
@@ -12,7 +12,7 @@
     method public void onAnimationStart(android.graphics.drawable.Drawable);
   }
 
-  public class AnimatedVectorDrawableCompat extends android.support.graphics.drawable.VectorDrawableCommon implements android.support.graphics.drawable.Animatable2Compat {
+  public class AnimatedVectorDrawableCompat extends android.graphics.drawable.Drawable implements android.support.graphics.drawable.Animatable2Compat android.support.v4.graphics.drawable.TintAwareDrawable {
     method public void clearAnimationCallbacks();
     method public static void clearAnimationCallbacks(android.graphics.drawable.Drawable);
     method public static android.support.graphics.drawable.AnimatedVectorDrawableCompat create(android.content.Context, int);
diff --git a/graphics/drawable/animated/build.gradle b/graphics/drawable/animated/build.gradle
index bfe405f..e76f846 100644
--- a/graphics/drawable/animated/build.gradle
+++ b/graphics/drawable/animated/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,26 +7,26 @@
 }
 
 dependencies {
-    api project(':support-vector-drawable')
-    api project(':support-core-ui')
+    api(project(":support-vector-drawable"))
+    api(project(":support-core-ui"))
 
-    androidTestImplementation libs.test_runner,   { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core, { exclude module: 'support-annotations' }
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
 }
 
 android {
     defaultConfig {
-        minSdkVersion 14
+        minSdkVersion(14)
         // This disables the builds tools automatic vector -> PNG generation
         generatedDensities = []
     }
 
     aaptOptions {
-        additionalParameters "--no-version-vectors"
+        additionalParameters("--no-version-vectors")
     }
 
     buildTypes.all {
-        consumerProguardFiles 'proguard-rules.pro'
+        consumerProguardFiles("proguard-rules.pro")
     }
 }
 
diff --git a/graphics/drawable/static/api/27.0.0.ignore b/graphics/drawable/static/api/27.0.0.ignore
new file mode 100644
index 0000000..dc31648
--- /dev/null
+++ b/graphics/drawable/static/api/27.0.0.ignore
@@ -0,0 +1,2 @@
+57adc08
+4aae3d4
diff --git a/graphics/drawable/static/api/current.txt b/graphics/drawable/static/api/current.txt
index db07bf2..2fe60b8 100644
--- a/graphics/drawable/static/api/current.txt
+++ b/graphics/drawable/static/api/current.txt
@@ -1,9 +1,6 @@
 package android.support.graphics.drawable {
 
-   abstract class VectorDrawableCommon extends android.graphics.drawable.Drawable {
-  }
-
-  public class VectorDrawableCompat extends android.support.graphics.drawable.VectorDrawableCommon {
+  public class VectorDrawableCompat extends android.graphics.drawable.Drawable implements android.support.v4.graphics.drawable.TintAwareDrawable {
     method public static android.support.graphics.drawable.VectorDrawableCompat create(android.content.res.Resources, int, android.content.res.Resources.Theme);
     method public static android.support.graphics.drawable.VectorDrawableCompat createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void draw(android.graphics.Canvas);
diff --git a/graphics/drawable/static/build.gradle b/graphics/drawable/static/build.gradle
index b8ab699..8575d6a 100644
--- a/graphics/drawable/static/build.gradle
+++ b/graphics/drawable/static/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,10 +7,10 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-compat')
+    api(project(":support-annotations"))
+    api(project(":support-compat"))
 
-    androidTestImplementation libs.test_runner, { exclude module: 'support-annotations' }
+    androidTestImplementation(TEST_RUNNER)
 }
 
 android {
diff --git a/graphics/drawable/static/lint-baseline.xml b/graphics/drawable/static/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/graphics/drawable/static/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/graphics/drawable/static/src/main/java/android/support/graphics/drawable/VectorDrawableCompat.java b/graphics/drawable/static/src/main/java/android/support/graphics/drawable/VectorDrawableCompat.java
index 2c7ae41..943f1aa 100644
--- a/graphics/drawable/static/src/main/java/android/support/graphics/drawable/VectorDrawableCompat.java
+++ b/graphics/drawable/static/src/main/java/android/support/graphics/drawable/VectorDrawableCompat.java
@@ -56,8 +56,8 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
-import java.util.Stack;
 
 /**
  * For API 24 and above, this class is delegating to the framework's {@link VectorDrawable}.
@@ -173,6 +173,10 @@
  * <dd>Sets the lineJoin for a stroked path: miter,round,bevel. Default is miter.</dd>
  * <dt><code>android:strokeMiterLimit</code></dt>
  * <dd>Sets the Miter limit for a stroked path. Default is 4.</dd>
+ * <dt><code>android:fillType</code></dt>
+ * <dd>Sets the fillType for a path. The types can be either "evenOdd" or "nonZero". They behave the
+ * same as SVG's "fill-rule" properties. Default is nonZero. For more details, see
+ * <a href="https://www.w3.org/TR/SVG/painting.html#FillRuleProperty">FillRuleProperty</a></dd>
  * </dl></dd>
  * </dl>
  *
@@ -726,7 +730,7 @@
 
         // Use a stack to help to build the group tree.
         // The top of the stack is always the current group.
-        final Stack<VGroup> groupStack = new Stack<VGroup>();
+        final ArrayDeque<VGroup> groupStack = new ArrayDeque<>();
         groupStack.push(pathRenderer.mRootGroup);
 
         int eventType = parser.getEventType();
@@ -781,14 +785,7 @@
         }
 
         if (noPathTag) {
-            final StringBuffer tag = new StringBuffer();
-
-            if (tag.length() > 0) {
-                tag.append(" or ");
-            }
-            tag.append(SHAPE_PATH);
-
-            throw new XmlPullParserException("no " + tag + " defined");
+            throw new XmlPullParserException("no " + SHAPE_PATH + " defined");
         }
     }
 
diff --git a/jetifier/.gitignore b/jetifier/.gitignore
new file mode 100644
index 0000000..4469528
--- /dev/null
+++ b/jetifier/.gitignore
@@ -0,0 +1 @@
+**/build
diff --git a/jetifier/jetifier/build.gradle b/jetifier/jetifier/build.gradle
new file mode 100644
index 0000000..c817220
--- /dev/null
+++ b/jetifier/jetifier/build.gradle
@@ -0,0 +1,96 @@
+/*
+ * 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
+ */
+
+buildscript {
+    ext.supportRootFolder = "${project.projectDir}/../../"
+    apply from: "$supportRootFolder/buildSrc/repos.gradle"
+
+    ext.kotlin_version = '1.2.0'
+
+    repos.addMavenRepositories(repositories)
+
+    dependencies {
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+    }
+}
+
+subprojects {
+    group 'android.support.tools.jetifier'
+
+    ext.supportRootFolder = "${project.projectDir}/../../.."
+
+    apply plugin: 'kotlin'
+    apply from: "$supportRootFolder/buildSrc/repos.gradle"
+
+    compileKotlin {
+        kotlinOptions.jvmTarget = "1.8"
+    }
+    compileTestKotlin {
+        kotlinOptions.jvmTarget = "1.8"
+    }
+
+    repos.addMavenRepositories(repositories)
+
+    dependencies {
+        compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+    }
+}
+
+ext.runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null
+def setupOutDirs() {
+    /*
+     * With the build server you are given two env variables.
+     * The OUT_DIR is a temporary directory you can use to put things during the build.
+     * The DIST_DIR is where you want to save things from the build.
+     *
+     * The build server will copy the contents of DIST_DIR to somewhere and make it available.
+     */
+    if (ext.runningInBuildServer) {
+        buildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/support/build')
+                .getCanonicalFile()
+        project.ext.distDir = new File(System.env.DIST_DIR).getCanonicalFile()
+
+        // the build server should always print out full stack traces for any failures.
+        gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS
+    } else {
+        buildDir = file("${ext.supportRootFolder}/../../out/host/gradle/frameworks/support/jetifier/build")
+        project.ext.distDir = new File("${ext.supportRootFolder}/../../out/dist")
+    }
+    subprojects {
+        // Change buildDir so that all plugins pick up the new value.
+        project.buildDir = new File("$project.parent.buildDir/../$project.name/build")
+        project.ext.distDir = new File("${ext.supportRootFolder}/../../out/dist")
+    }
+}
+
+def configureBuildOnServer() {
+    def buildOnServerTask = rootProject.tasks.create("buildOnServer")
+    rootProject.tasks.whenTaskAdded { task ->
+        if ("build".equals(task.name)) {
+            buildOnServerTask.dependsOn task
+        }
+    }
+    subprojects {
+        project.tasks.whenTaskAdded { task ->
+            if ("fatJar".equals(task.name)) {
+                buildOnServerTask.dependsOn task
+            }
+        }
+    }
+}
+
+setupOutDirs()
+configureBuildOnServer()
diff --git a/jetifier/jetifier/core/build.gradle b/jetifier/jetifier/core/build.gradle
new file mode 100644
index 0000000..1ac3f36
--- /dev/null
+++ b/jetifier/jetifier/core/build.gradle
@@ -0,0 +1,26 @@
+/*
+ * 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
+ */
+
+version '1.0'
+
+dependencies {
+    compile group: 'org.ow2.asm', name: 'asm', version: '5.2'
+    compile group: 'org.ow2.asm', name: 'asm-commons', version: '5.2'
+    compile group: 'com.google.code.gson', name: 'gson', version: '2.8.0'
+    compile group: 'org.jdom', name: 'jdom2', version: '2.0.6'
+    testCompile group: 'junit', name: 'junit', version: '4.12'
+    testCompile group: 'com.google.truth', name: 'truth', version: '0.31'
+}
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/Processor.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/Processor.kt
new file mode 100644
index 0000000..5af8fb2
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/Processor.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core
+
+import android.support.tools.jetifier.core.archive.Archive
+import android.support.tools.jetifier.core.archive.ArchiveFile
+import android.support.tools.jetifier.core.archive.ArchiveItemVisitor
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.transform.TransformationContext
+import android.support.tools.jetifier.core.transform.Transformer
+import android.support.tools.jetifier.core.transform.bytecode.ByteCodeTransformer
+import android.support.tools.jetifier.core.transform.pom.PomDocument
+import android.support.tools.jetifier.core.transform.pom.PomScanner
+import android.support.tools.jetifier.core.transform.proguard.ProGuardTransformer
+import android.support.tools.jetifier.core.transform.resource.XmlResourcesTransformer
+import android.support.tools.jetifier.core.utils.Log
+import java.io.File
+import java.io.FileNotFoundException
+import java.nio.file.Files
+import java.nio.file.Path
+
+/**
+ * The main entry point to the library. Extracts any given archive recursively and runs all
+ * the registered [Transformer]s over the set and creates new archives that will contain the
+ * transformed files.
+ */
+class Processor(private val config : Config) : ArchiveItemVisitor {
+
+    companion object {
+        private const val TAG = "Processor"
+    }
+
+    private val context = TransformationContext(config)
+
+    private val transformers = listOf(
+            // Register your transformers here
+            ByteCodeTransformer(context),
+            XmlResourcesTransformer(context),
+            ProGuardTransformer(context)
+    )
+
+    /**
+     * Transforms the input libraries given in [inputLibraries] using all the registered
+     * [Transformer]s and returns new libraries stored in [outputPath].
+     *
+     * Currently we have the following transformers:
+     * - [ByteCodeTransformer] for java native code
+     * - [XmlResourcesTransformer] for java native code
+     * - [ProGuardTransformer] for PorGuard files
+     */
+    fun transform(inputLibraries: Set<File>, outputPath: Path) : TransformationResult {
+        // 1) Extract and load all libraries
+        val libraries = loadLibraries(inputLibraries)
+
+        // 2) Search for POM files
+        val pomFiles = scanPomFiles(libraries)
+
+        // 3) Transform all the libraries
+        libraries.forEach{ transformLibrary(it) }
+
+        if (context.wasErrorFound()) {
+            throw IllegalArgumentException("There were ${context.mappingNotFoundFailuresCount}" +
+                " errors found during the remapping. Check the logs for more details.")
+        }
+
+        // TODO: Here we might need to modify the POM files if they point at a library that we have
+        // just refactored.
+
+        // 4) Transform the previously discovered POM files
+        transformPomFiles(pomFiles)
+
+        // 5) Repackage the libraries back to archives
+        val outputLibraries = libraries.map{ it.writeSelfToDir(outputPath) }.toSet()
+
+        // TODO: Filter out only the libraries that have been really changed
+        return TransformationResult(
+            filesToRemove = inputLibraries,
+            filesToAdd = outputLibraries)
+    }
+
+    private fun loadLibraries(inputLibraries : Iterable<File>) : List<Archive> {
+        val libraries = mutableListOf<Archive>()
+        for (library in inputLibraries) {
+            if (!library.canRead()) {
+                throw FileNotFoundException("Cannot open a library at '$library'")
+            }
+
+            libraries.add(Archive.Builder.extract(library))
+        }
+        return libraries.toList()
+    }
+
+    private fun scanPomFiles(libraries: List<Archive>) : List<PomDocument> {
+        val scanner = PomScanner(config)
+
+        libraries.forEach { scanner.scanArchiveForPomFile(it) }
+        if (scanner.wasErrorFound()) {
+            throw IllegalArgumentException("At least one of the libraries depends on an older" +
+                " version of support library. Check the logs for more details.")
+        }
+
+        return scanner.pomFiles
+    }
+
+    private fun transformPomFiles(files: List<PomDocument>) {
+        files.forEach {
+            it.applyRules(config.pomRewriteRules)
+            it.saveBackToFileIfNeeded()
+        }
+    }
+
+    private fun transformLibrary(archive: Archive) {
+        Log.i(TAG, "Started new transformation")
+        Log.i(TAG, "- Input file: %s", archive.relativePath)
+
+        archive.accept(this)
+    }
+
+    override fun visit(archive: Archive) {
+        archive.files.forEach{ it.accept(this) }
+    }
+
+    override fun visit(archiveFile: ArchiveFile) {
+        val transformer = transformers.firstOrNull { it.canTransform(archiveFile) }
+
+        if (transformer == null) {
+            Log.i(TAG, "[Skipped] %s", archiveFile.relativePath)
+            return
+        }
+
+        Log.i(TAG, "[Applied: %s] %s", transformer.javaClass.simpleName, archiveFile.relativePath)
+        transformer.runTransform(archiveFile)
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/TransformationResult.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/TransformationResult.kt
new file mode 100644
index 0000000..3e90483
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/TransformationResult.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core
+
+import java.io.File
+
+/**
+ * Result of the transformation done by the [Processor]
+ *
+ * @param filesToRemove files to be removed from project's dependencies
+ * @param filesToAdd files generated by Jetifier to be added to project's dependencies
+ */
+data class TransformationResult(val filesToRemove: Set<File>, val filesToAdd: Set<File>)
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/Archive.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/Archive.kt
new file mode 100644
index 0000000..70ea68c
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/Archive.kt
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.archive
+
+import android.support.tools.jetifier.core.utils.Log
+import java.io.BufferedOutputStream
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.Paths
+import java.util.zip.ZipEntry
+import java.util.zip.ZipInputStream
+import java.util.zip.ZipOutputStream
+
+/**
+ * Represents an archive (zip, jar, aar ...)
+ */
+class Archive(
+        override val relativePath: Path,
+        val files: List<ArchiveItem>)
+    : ArchiveItem {
+
+    companion object {
+        /** Defines file extensions that are recognized as archives */
+        val ARCHIVE_EXTENSIONS = listOf(".jar", ".zip", ".aar")
+
+        const val TAG = "Archive"
+    }
+
+    override val fileName: String = relativePath.fileName.toString()
+
+    override fun accept(visitor: ArchiveItemVisitor) {
+        visitor.visit(this)
+    }
+
+    @Throws(IOException::class)
+    fun writeSelfToDir(outputDirPath: Path) : File {
+        val outputPath = Paths.get(outputDirPath.toString(), fileName)
+
+        if (Files.exists(outputPath)) {
+            Log.i(TAG, "Deleting old output file")
+            Files.delete(outputPath)
+        }
+
+        // Create directories if they don't exist yet
+        Files.createDirectories(outputDirPath)
+
+        Log.i(TAG, "Writing archive: %s", outputPath.toUri())
+        val file = outputPath.toFile()
+        Files.createFile(outputPath)
+        val stream = BufferedOutputStream(FileOutputStream(file))
+        writeSelfTo(stream)
+        stream.close()
+        return file
+    }
+
+    @Throws(IOException::class)
+    override fun writeSelfTo(outputStream: OutputStream) {
+        val out = ZipOutputStream(outputStream)
+
+        for (file in files) {
+            Log.d(TAG, "Writing file: %s", file.relativePath)
+
+            val entry = ZipEntry(file.relativePath.toString())
+            out.putNextEntry(entry)
+            file.writeSelfTo(out)
+            out.closeEntry()
+        }
+        out.finish()
+    }
+
+
+    object Builder {
+
+        @Throws(IOException::class)
+        fun extract(archiveFile: File): Archive {
+            Log.i(TAG, "Extracting: %s", archiveFile.absolutePath)
+
+            val inputStream = FileInputStream(archiveFile)
+            inputStream.use {
+                return extractArchive(it, archiveFile.toPath())
+            }
+        }
+
+        @Throws(IOException::class)
+        private fun extractArchive(inputStream: InputStream, relativePath: Path)
+                : Archive {
+            val zipIn = ZipInputStream(inputStream)
+            val files = mutableListOf<ArchiveItem>()
+
+            var entry: ZipEntry? = zipIn.nextEntry
+            // iterates over entries in the zip file
+            while (entry != null) {
+                if (!entry.isDirectory) {
+                    val entryPath = Paths.get(entry.name)
+                    if (isArchive(entry)) {
+                        Log.i(TAG, "Extracting nested: %s", entryPath)
+                        files.add(extractArchive(zipIn, entryPath))
+                    } else {
+                        files.add(extractFile(zipIn, entryPath))
+                    }
+                }
+                zipIn.closeEntry()
+                entry = zipIn.nextEntry
+            }
+            // Cannot close the zip stream at this moment as that would close also any parent zip
+            // streams in case we are processing a nested archive.
+
+            return Archive(relativePath, files.toList())
+        }
+
+        @Throws(IOException::class)
+        private fun extractFile(zipIn: ZipInputStream, relativePath: Path): ArchiveFile {
+            Log.d(TAG, "Extracting archive: %s", relativePath)
+
+            val data = zipIn.readBytes()
+            return ArchiveFile(relativePath, data)
+        }
+
+        private fun isArchive(zipEntry: ZipEntry) : Boolean {
+            return ARCHIVE_EXTENSIONS.any { zipEntry.name.endsWith(it, ignoreCase = true) }
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/ArchiveFile.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/ArchiveFile.kt
new file mode 100644
index 0000000..3054b71
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/ArchiveFile.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.archive
+
+import java.io.IOException
+import java.io.OutputStream
+import java.nio.file.Path
+
+/**
+ * Represents a file in the archive that is not an archive.
+ */
+class ArchiveFile(override val relativePath: Path, var data: ByteArray) : ArchiveItem {
+
+    override val fileName: String = relativePath.fileName.toString()
+
+    override fun accept(visitor: ArchiveItemVisitor) {
+        visitor.visit(this)
+    }
+
+    @Throws(IOException::class)
+    override fun writeSelfTo(outputStream: OutputStream) {
+        outputStream.write(data)
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/ArchiveItem.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/ArchiveItem.kt
new file mode 100644
index 0000000..2d35e13
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/ArchiveItem.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.archive
+
+import java.io.OutputStream
+import java.nio.file.Path
+
+/**
+ * Abstraction to represent archive and its files as a one thing.
+ */
+interface ArchiveItem {
+
+    /**
+     * Relative path of the item according to its location in the archive.
+     *
+     * Files in a nested archive have a path relative to that archive not to the parent of
+     * the archive. The root archive has the file system path set as its relative path.
+     */
+    val relativePath : Path
+
+    /**
+     * Name of the file.
+     */
+    val fileName : String
+
+    /**
+     * Accepts visitor.
+     */
+    fun accept(visitor: ArchiveItemVisitor)
+
+    /**
+     * Writes its internal data (or other nested files) into the given output stream.
+     */
+    fun writeSelfTo(outputStream: OutputStream)
+
+
+    fun isPomFile() = fileName.equals("pom.xml", ignoreCase = true)
+
+    fun isClassFile() = fileName.endsWith(".class", ignoreCase = true)
+
+    fun isXmlFile() = fileName.endsWith(".xml", ignoreCase = true)
+
+    fun isProGuardFile () = fileName.equals("proguard.txt", ignoreCase = true)
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/ArchiveItemVisitor.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/ArchiveItemVisitor.kt
new file mode 100644
index 0000000..7c99fd9
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/archive/ArchiveItemVisitor.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.archive
+
+/**
+ * Visitor for [ArchiveItem]
+ */
+interface ArchiveItemVisitor {
+
+    fun visit(archive: Archive)
+
+    fun visit(archiveFile: ArchiveFile)
+
+}
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/config/Config.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/config/Config.kt
new file mode 100644
index 0000000..8d70d87
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/config/Config.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.config
+
+import android.support.tools.jetifier.core.rules.RewriteRule
+import android.support.tools.jetifier.core.transform.pom.PomRewriteRule
+import android.support.tools.jetifier.core.map.TypesMap
+import android.support.tools.jetifier.core.transform.proguard.ProGuardTypesMap
+import com.google.gson.annotations.SerializedName
+
+/**
+ * The main and only one configuration that is used by the tool and all its transformers.
+ *
+ * [restrictToPackagePrefixes] Package prefixes that limit the scope of the rewriting
+ * [rewriteRules] Rules to scan support libraries to generate [TypesMap]
+ * [pomRewriteRules] Rules to rewrite POM files
+ * [typesMap] Map of all java types and fields to be used to rewrite libraries.
+ */
+data class Config(
+        val restrictToPackagePrefixes: List<String>,
+        val rewriteRules: List<RewriteRule>,
+        val pomRewriteRules: List<PomRewriteRule>,
+        val typesMap: TypesMap,
+        val proGuardMap: ProGuardTypesMap) {
+
+    companion object {
+        /** Path to the default config file located within the jar file. */
+        const val DEFAULT_CONFIG_RES_PATH = "/default.generated.config"
+    }
+
+    fun setNewMap(mappings: TypesMap) : Config {
+        return Config(
+            restrictToPackagePrefixes, rewriteRules, pomRewriteRules, mappings, proGuardMap)
+    }
+
+    /** Returns JSON data model of this class */
+    fun toJson() : JsonData {
+        return JsonData(
+            restrictToPackagePrefixes,
+            rewriteRules.map { it.toJson() }.toList(),
+            pomRewriteRules.map { it.toJson() }.toList(),
+            typesMap.toJson(),
+            proGuardMap.toJson()
+        )
+    }
+
+
+    /**
+     * JSON data model for [Config].
+     */
+    data class JsonData(
+            @SerializedName("restrictToPackagePrefixes")
+            val restrictToPackages: List<String?>,
+
+            @SerializedName("rules")
+            val rules: List<RewriteRule.JsonData?>,
+
+            @SerializedName("pomRules")
+            val pomRules: List<PomRewriteRule.JsonData?>,
+
+            @SerializedName("map")
+            val mappings: TypesMap.JsonData? = null,
+
+            @SerializedName("proGuardMap")
+            val proGuardMap: ProGuardTypesMap.JsonData? = null) {
+
+        /** Creates instance of [Config] */
+        fun toConfig() : Config {
+            return Config(
+                restrictToPackages.filterNotNull(),
+                rules.filterNotNull().map { it.toRule() },
+                pomRules.filterNotNull().map { it.toRule() },
+                mappings?.toMappings() ?: TypesMap.EMPTY,
+                proGuardMap?.toMappings() ?: ProGuardTypesMap.EMPTY
+            )
+        }
+    }
+
+}
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/config/ConfigParser.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/config/ConfigParser.kt
new file mode 100644
index 0000000..50d510c
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/config/ConfigParser.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.config
+
+import android.support.tools.jetifier.core.utils.Log
+import com.google.gson.GsonBuilder
+import java.io.FileNotFoundException
+import java.io.FileWriter
+import java.nio.file.Files
+import java.nio.file.Path
+
+object ConfigParser {
+
+    private const val TAG : String = "Config"
+
+    private val gson = GsonBuilder().setPrettyPrinting().create()
+
+    fun writeToString(config: Config) : String {
+        return gson.toJson(config.toJson())
+    }
+
+    fun writeToFile(config: Config, outputPath: Path) {
+        FileWriter(outputPath.toFile()).use {
+            gson.toJson(config.toJson(), it)
+        }
+    }
+
+    fun parseFromString(inputText: String) : Config? {
+        return gson.fromJson(inputText, Config.JsonData::class.java).toConfig()
+    }
+
+    fun loadFromFile(configPath: Path) : Config? {
+        return loadConfigFileInternal(configPath)
+    }
+
+    fun loadDefaultConfig() : Config? {
+        Log.v(TAG, "Using the default config '%s'", Config.DEFAULT_CONFIG_RES_PATH)
+
+        val inputStream = javaClass.getResourceAsStream(Config.DEFAULT_CONFIG_RES_PATH)
+        return parseFromString(inputStream.reader().readText())
+    }
+
+    fun loadConfigOrFail(configPath: Path?) : Config {
+        if (configPath != null) {
+            val config = loadConfigFileInternal(configPath)
+            if (config != null) {
+                return config
+            }
+            throw FileNotFoundException("Config file was not found at '$configPath'")
+        }
+
+        val config = loadDefaultConfig()
+        if (config != null) {
+            return config
+        }
+        throw AssertionError("The default config could not be found!")
+    }
+
+    private fun loadConfigFileInternal(configPath: Path) : Config? {
+        if (!Files.isReadable(configPath)) {
+            Log.e(TAG, "Cannot access the config file: '%s'", configPath)
+            return null
+        }
+
+        Log.i(TAG, "Parsing config file: '%s'", configPath.toUri())
+        val config = parseFromString(configPath.toFile().readText())
+
+        if (config == null) {
+            Log.e(TAG, "Failed to parseFromString the config file")
+            return null
+        }
+
+        return config
+    }
+}
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/map/LibraryMapGenerator.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/map/LibraryMapGenerator.kt
new file mode 100644
index 0000000..de5a17f
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/map/LibraryMapGenerator.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.map
+
+import android.support.tools.jetifier.core.archive.Archive
+import android.support.tools.jetifier.core.archive.ArchiveFile
+import android.support.tools.jetifier.core.archive.ArchiveItemVisitor
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.transform.Transformer
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassWriter
+
+/**
+ * Scans a library java files using [MapGeneratorRemapper] to create [TypesMap].
+ */
+class LibraryMapGenerator constructor(config: Config) : ArchiveItemVisitor {
+
+    val remapper = MapGeneratorRemapper(config)
+
+    /**
+     * Scans the given [library] to extend the types map meta-data. The final map can be retrieved
+     * using [generateMap].
+     */
+    fun scanLibrary(library: Archive) {
+        library.accept(this)
+    }
+
+    /**
+     * Creates the [TypesMap] based on the meta-data aggregated via previous [scanFile] calls
+     */
+    fun generateMap() : TypesMap {
+        return remapper.createTypesMap()
+    }
+
+    override fun visit(archive: Archive) {
+        archive.files.forEach{ it.accept(this) }
+    }
+
+    override fun visit(archiveFile: ArchiveFile) {
+        if (archiveFile.isClassFile()) {
+            scanFile(archiveFile)
+        }
+    }
+
+    private fun scanFile(file: ArchiveFile) {
+        val reader = ClassReader(file.data)
+        val writer = ClassWriter(0 /* flags */)
+
+        val visitor = remapper.createClassRemapper(writer)
+
+        reader.accept(visitor, 0 /* flags */)
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/map/MapGeneratorRemapper.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/map/MapGeneratorRemapper.kt
new file mode 100644
index 0000000..374e213
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/map/MapGeneratorRemapper.kt
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.map
+
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.rules.JavaField
+import android.support.tools.jetifier.core.rules.JavaType
+import android.support.tools.jetifier.core.transform.bytecode.CoreRemapper
+import android.support.tools.jetifier.core.transform.bytecode.asm.CustomClassRemapper
+import android.support.tools.jetifier.core.transform.bytecode.asm.CustomRemapper
+import android.support.tools.jetifier.core.utils.Log
+import org.objectweb.asm.ClassVisitor
+import java.util.regex.Pattern
+
+/**
+ * Hooks to asm remapping to collect data for [TypesMap] by applying all the [RewriteRule]s from the
+ * given [config] on all discovered and eligible types and fields.
+ */
+class MapGeneratorRemapper(private val config: Config) : CoreRemapper {
+
+    companion object {
+        private const val TAG : String = "MapGeneratorRemapper"
+    }
+
+    private val typesRewritesMap = hashMapOf<JavaType, JavaType>()
+    private val fieldsRewritesMap = hashMapOf<JavaField, JavaField>()
+
+    var isMapNotComplete = false
+        private set
+
+    /**
+     * Ignore mPrefix types and anything that contains $ as these are internal fields that won't be
+     * ever referenced.
+     */
+    private val ignoredFields = Pattern.compile("(^m[A-Z]+.*$)|(.*\\$.*)")
+
+    /**
+     * Ignores types ending with '$digit' as these are private inner classes and won't be ever
+     * referenced.
+     */
+    private val ignoredTypes = Pattern.compile("^(.*)\\$[0-9]+$")
+
+    fun createClassRemapper(visitor: ClassVisitor): CustomClassRemapper {
+        return CustomClassRemapper(visitor, CustomRemapper(this))
+    }
+
+    override fun rewriteType(type: JavaType): JavaType {
+        if (!isTypeSupported(type)) {
+            return type
+        }
+
+        if (typesRewritesMap.contains(type)) {
+            return type
+        }
+
+        if (isTypeIgnored(type)) {
+            return type
+        }
+
+        // Try to find a rule
+        for (rule in config.rewriteRules) {
+            val mappedTypeName = rule.apply(type) ?: continue
+            typesRewritesMap.put(type, mappedTypeName)
+
+            Log.i(TAG, "  map: %s -> %s", type, mappedTypeName)
+            return mappedTypeName
+        }
+
+        isMapNotComplete = true
+        Log.e(TAG, "No rule for: " + type)
+        typesRewritesMap.put(type, type) // Identity
+        return type
+    }
+
+    override fun rewriteField(field : JavaField): JavaField {
+        if (!isTypeSupported(field.owner)) {
+            return field
+        }
+
+        if (isTypeIgnored(field.owner) || isFieldIgnored(field)) {
+            return field
+        }
+
+        if (fieldsRewritesMap.contains(field)) {
+            return field
+        }
+
+        // Try to find a rule
+        for (rule in config.rewriteRules) {
+            val mappedFieldName = rule.apply(field) ?: continue
+            fieldsRewritesMap.put(field, mappedFieldName)
+
+            Log.i(TAG, "  map: %s -> %s", field, mappedFieldName)
+            return mappedFieldName
+        }
+
+        isMapNotComplete = true
+        Log.e(TAG, "No rule for: " + field)
+        fieldsRewritesMap.put(field, field) // Identity
+        return field
+    }
+
+    fun createTypesMap() : TypesMap {
+        return TypesMap(typesRewritesMap, fieldsRewritesMap)
+    }
+
+    private fun isTypeSupported(type: JavaType) : Boolean {
+        return config.restrictToPackagePrefixes.any{ type.fullName.startsWith(it) }
+    }
+
+    private fun isTypeIgnored(type: JavaType) : Boolean {
+        return ignoredTypes.matcher(type.fullName).matches()
+    }
+
+    private fun isFieldIgnored(field: JavaField) : Boolean {
+        return ignoredFields.matcher(field.name).matches()
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/map/TypesMap.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/map/TypesMap.kt
new file mode 100644
index 0000000..ce02026
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/map/TypesMap.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.map
+
+import android.support.tools.jetifier.core.rules.JavaField
+import android.support.tools.jetifier.core.rules.JavaType
+import android.support.tools.jetifier.core.rules.RewriteRule
+
+/**
+ * Contains all the mappings needed to rewrite java types and fields.
+ *
+ * These mappings are generated by the preprocessor from existing support libraries and by applying
+ * the given [RewriteRule]s.
+ */
+data class TypesMap(
+        val types: Map<JavaType, JavaType>,
+        val fields: Map<JavaField, JavaField>) {
+
+    companion object {
+        val EMPTY = TypesMap(emptyMap(), emptyMap())
+    }
+
+    /** Returns JSON data model of this class */
+    fun toJson() : JsonData {
+        return JsonData(
+                types = types.map { it.key.fullName to it.value.fullName }
+                        .toMap(),
+                fields = mapFields())
+    }
+
+    private fun mapFields() : Map<String, Map<String, List<String>>> {
+        val rawMap = mutableMapOf<String, MutableMap<String, MutableList<String>>>()
+
+        fields.forEach{
+            rawMap
+                .getOrPut(it.key.owner.fullName, { mutableMapOf<String, MutableList<String>>()} )
+                .getOrPut(it.value.owner.fullName, { mutableListOf() })
+                .add(it.key.name)
+        }
+        return rawMap
+    }
+
+    /**
+     * JSON data model for [TypesMap].
+     */
+    data class JsonData(
+            val types: Map<String, String>,
+            val fields: Map<String, Map<String, List<String>>>)  {
+
+        /** Creates instance of [TypesMap] */
+        fun toMappings() : TypesMap {
+            return TypesMap(
+                types = types
+                    .orEmpty()
+                    .map { JavaType(it.key) to JavaType(it.value) }
+                    .toMap(),
+                fields = fields
+                    .orEmpty().entries
+                    .flatMap {
+                        top ->
+                        top.value.flatMap {
+                            mid ->
+                            mid.value.map {
+                                JavaField(top.key, it) to JavaField(mid.key, it)
+                            }
+                        }
+                    }
+                    .toMap())
+        }
+    }
+}
+
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/JavaField.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/JavaField.kt
new file mode 100644
index 0000000..c423f0a
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/JavaField.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.rules
+
+/**
+ * Wrapper for Java field declaration.
+ */
+data class JavaField(val owner : JavaType, val name : String) {
+
+    constructor(owner : String, name : String) : this(JavaType(owner), name)
+
+
+    fun renameOwner(newOwner: JavaType) = JavaField(newOwner, name)
+
+    override fun toString() = owner.toString() + "." + name
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/JavaType.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/JavaType.kt
new file mode 100644
index 0000000..d7a077b
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/JavaType.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.rules
+
+/**
+ * Wrapper for Java type declaration.
+ */
+data class JavaType(val fullName: String) {
+
+    init {
+        if (fullName.contains('.')) {
+            throw IllegalArgumentException("The type does not support '.' as package separator!")
+        }
+    }
+
+    companion object {
+        /** Creates the type from notation where packages are separated using '.' */
+        fun fromDotVersion(fullName: String) : JavaType {
+            return JavaType(fullName.replace('.', '/'))
+        }
+    }
+
+    /** Returns the type as a string where packages are separated using '.' */
+    fun toDotNotation() : String {
+        return fullName.replace('/', '.')
+    }
+
+
+    override fun toString() = fullName
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/JavaTypeXmlRef.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/JavaTypeXmlRef.kt
new file mode 100644
index 0000000..9d58046
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/JavaTypeXmlRef.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.rules
+
+/**
+ * Wrapper for Java type reference used in XML.
+ *
+ * In XML we use '.' as a package separator.
+ */
+data class JavaTypeXmlRef(val fullName : String) {
+
+    constructor(type: JavaType)
+        : this(type.fullName.replace('/', '.'))
+
+    fun toJavaType() : JavaType {
+        return JavaType(fullName.replace('.', '/'))
+    }
+
+    override fun toString() = fullName
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/RewriteRule.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/RewriteRule.kt
new file mode 100644
index 0000000..700e757
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/rules/RewriteRule.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.rules
+
+import com.google.gson.annotations.SerializedName
+import java.util.regex.Pattern
+
+/**
+ * Rule that rewrites a Java type or field based on the given arguments.
+ *
+ * Used in the preprocessor when generating [TypesMap].
+ *
+ * @param from Regular expression where packages are separated via '/' and inner class separator
+ * is "$". Used to match the input type.
+ * @param to A string to be used as a replacement if the 'from' pattern is matched. It can also
+ * apply groups matched from the original pattern using {x} annotation, e.g. {0}.
+ * @param fieldSelectors Collection of regular expressions that are used to match fields. If the
+ * type is matched (using 'from') and the field is matched (or the list of fields selectors is
+ * empty) the field's type gets rewritten according to the 'to' parameter.
+ */
+class RewriteRule(
+        private val from: String,
+        private val to: String,
+        private val fieldSelectors: List<String> = emptyList()) {
+
+    // We escape '$' so we don't conflict with regular expression symbols.
+    private val inputPattern = Pattern.compile("^${from.replace("$", "\\$")}$")
+    private val outputPattern = to.replace("$", "\$")
+
+    private val fields = fieldSelectors.map { Pattern.compile("^$it$") }
+
+    /**
+     * Rewrites the given java type. Returns null if this rule is not applicable for the given type.
+     */
+    fun apply(input: JavaType): JavaType? {
+        if (fields.isNotEmpty()) {
+            return null
+        }
+
+        return applyInternal(input)
+    }
+
+    /**
+     * Rewrites the given field type. Returns null if this rule is not applicable for the given
+     * type.
+     */
+    fun apply(inputField: JavaField) : JavaField? {
+        val typeRewriteResult = applyInternal(inputField.owner) ?: return null
+
+        val isFieldInTheFilter = fields.isEmpty()
+                || fields.any { it.matcher(inputField.name).matches() }
+        if (isFieldInTheFilter) {
+            return inputField.renameOwner(typeRewriteResult)
+        }
+
+        return null
+    }
+
+    private fun applyInternal(input: JavaType): JavaType? {
+        val matcher = inputPattern.matcher(input.fullName)
+        if (!matcher.matches()) {
+            return null
+        }
+
+        var result = outputPattern
+        for (i in 0..matcher.groupCount() - 1) {
+            result = result.replace("{$i}", matcher.group(i + 1))
+        }
+
+        return JavaType(result)
+    }
+
+    override fun toString() : String {
+        return "$inputPattern -> $outputPattern " + fields.joinToString { it.toString() }
+    }
+
+    /** Returns JSON data model of this class */
+    fun toJson() : JsonData {
+        return JsonData(from, to, fieldSelectors)
+    }
+
+
+    /**
+     * JSON data model for [RewriteRule].
+     */
+    data class JsonData(
+            @SerializedName("from")
+            val from: String,
+
+            @SerializedName("to")
+            val to: String,
+
+            @SerializedName("fieldSelectors")
+            val fieldSelectors: List<String>? = null)  {
+
+        /** Creates instance of [RewriteRule] */
+        fun toRule() : RewriteRule {
+            return RewriteRule(from, to, fieldSelectors.orEmpty())
+        }
+    }
+
+}
+
+
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/TransformationContext.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/TransformationContext.kt
new file mode 100644
index 0000000..3f8af95
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/TransformationContext.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform
+
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.rules.JavaType
+import android.support.tools.jetifier.core.transform.proguard.ProGuardType
+import java.util.regex.Pattern
+
+/**
+ * Context to share the transformation state between individual [Transformer]s.
+ */
+class TransformationContext(val config: Config) {
+
+    // Merges all packages prefixes into one regEx pattern
+    private val packagePrefixPattern = Pattern.compile(
+        "^(" + config.restrictToPackagePrefixes.map { "($it)" }.joinToString("|") + ").*$")
+
+    /** Counter for [reportNoMappingFoundFailure] calls. */
+    var mappingNotFoundFailuresCount = 0
+        private set
+
+    /** Counter for [reportNoProGuardMappingFoundFailure] calls. */
+    var proGuardMappingNotFoundFailuresCount = 0
+        private set
+
+    /** Returns whether any errors were found during the transformation process */
+    fun wasErrorFound() = mappingNotFoundFailuresCount > 0
+
+    /**
+     * Returns whether the given type is eligible for rewrite.
+     *
+     * If not, the transformers should ignore it.
+     */
+    fun isEligibleForRewrite(type: JavaType) : Boolean {
+        if (config.restrictToPackagePrefixes.isEmpty()) {
+            return false
+        }
+        return packagePrefixPattern.matcher(type.fullName).matches()
+    }
+
+    /**
+     * Returns whether the given ProGuard type reference is eligible for rewrite.
+     *
+     * Keep in mind that his has limited capabilities - mainly when * is used as a prefix. Rules
+     * like *.v7 are not matched by prefix support.v7. So don't rely on it and use
+     * the [ProGuardTypesMap] as first.
+     */
+    fun isEligibleForRewrite(type: ProGuardType) : Boolean {
+        if (config.restrictToPackagePrefixes.isEmpty()) {
+            return false
+        }
+        return packagePrefixPattern.matcher(type.value).matches()
+    }
+
+    /**
+     * Used to report that there was a reference found that satisfies [isEligibleForRewrite] but no
+     * mapping was found to rewrite it.
+     */
+    fun reportNoMappingFoundFailure() {
+        mappingNotFoundFailuresCount++
+    }
+
+    /**
+     * Used to report that there was a reference found in the ProGuard file that satisfies
+     * [isEligibleForRewrite] but no mapping was found to rewrite it.
+     */
+    fun reportNoProGuardMappingFoundFailure() {
+        proGuardMappingNotFoundFailuresCount++
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/Transformer.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/Transformer.kt
new file mode 100644
index 0000000..0c6c8aa
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/Transformer.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform
+
+import android.support.tools.jetifier.core.archive.ArchiveFile
+
+/**
+ * Interface to be implemented by any class that wants process files.
+ */
+interface Transformer {
+
+    /**
+     * Returns whether this instance can process the given file.
+     */
+    fun canTransform(file: ArchiveFile): Boolean
+
+    /**
+     * Runs transformation of the given file.
+     */
+    fun runTransform(file: ArchiveFile)
+
+}
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/ByteCodeTransformer.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/ByteCodeTransformer.kt
new file mode 100644
index 0000000..33235e0
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/ByteCodeTransformer.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.bytecode
+
+import android.support.tools.jetifier.core.archive.ArchiveFile
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.transform.TransformationContext
+import android.support.tools.jetifier.core.transform.Transformer
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassWriter
+
+/**
+ * The [Transformer] responsible for java byte code refactoring.
+ */
+class ByteCodeTransformer internal constructor(context: TransformationContext) : Transformer {
+
+    private val remapper: CoreRemapperImpl = CoreRemapperImpl(context)
+
+
+    override fun canTransform(file: ArchiveFile) = file.isClassFile()
+
+    override fun runTransform(file: ArchiveFile) {
+        val reader = ClassReader(file.data)
+        val writer = ClassWriter(0 /* flags */)
+
+        val visitor = remapper.createClassRemapper(writer)
+
+        reader.accept(visitor, 0 /* flags */)
+
+        file.data = writer.toByteArray()
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/CoreRemapper.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/CoreRemapper.kt
new file mode 100644
index 0000000..50f3b31
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/CoreRemapper.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.bytecode
+
+import android.support.tools.jetifier.core.rules.JavaField
+import android.support.tools.jetifier.core.rules.JavaType
+
+/**
+ * High-level re-mapping interface to provide only the refactorings needed by jetifier.
+ */
+interface CoreRemapper {
+    fun rewriteType(type: JavaType) : JavaType
+
+    fun rewriteField(field: JavaField) : JavaField
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/CoreRemapperImpl.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/CoreRemapperImpl.kt
new file mode 100644
index 0000000..486cc25
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/CoreRemapperImpl.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.bytecode
+
+import android.support.tools.jetifier.core.map.TypesMap
+import android.support.tools.jetifier.core.rules.JavaField
+import android.support.tools.jetifier.core.rules.JavaType
+import android.support.tools.jetifier.core.transform.TransformationContext
+import android.support.tools.jetifier.core.transform.bytecode.asm.CustomClassRemapper
+import android.support.tools.jetifier.core.transform.bytecode.asm.CustomRemapper
+import android.support.tools.jetifier.core.utils.Log
+import org.objectweb.asm.ClassVisitor
+
+/**
+ * Applies mappings defined in [TypesMap] during the remapping process.
+ */
+class CoreRemapperImpl(private val context: TransformationContext) : CoreRemapper {
+
+    companion object {
+        const val TAG = "CoreRemapperImpl"
+    }
+
+    private val typesMap = context.config.typesMap
+
+    fun createClassRemapper(visitor: ClassVisitor): CustomClassRemapper {
+        return CustomClassRemapper(visitor, CustomRemapper(this))
+    }
+
+    override fun rewriteType(type: JavaType): JavaType {
+        val result = typesMap.types[type]
+
+        if (!context.isEligibleForRewrite(type)) {
+            return type
+        }
+
+        if (result != null) {
+            Log.i(TAG, "  map: %s -> %s", type, result)
+            return result
+        }
+
+        context.reportNoMappingFoundFailure()
+        Log.e(TAG, "No mapping for: " + type)
+        return type
+    }
+
+    override fun rewriteField(field : JavaField): JavaField {
+        val result = typesMap.fields[field]
+
+        if (!context.isEligibleForRewrite(field.owner)) {
+            return field
+        }
+
+        if (result != null) {
+            Log.i(TAG, "  map: %s -> %s", field, result)
+            return result
+        }
+
+        context.reportNoMappingFoundFailure()
+        Log.e(TAG, "No mapping for: " + field)
+        return field
+    }
+
+}
+
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/asm/CustomClassRemapper.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/asm/CustomClassRemapper.kt
new file mode 100644
index 0000000..692e65d
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/asm/CustomClassRemapper.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.bytecode.asm
+
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.FieldVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.commons.ClassRemapper
+
+/**
+ * Currently only adds field context awareness into [ClassRemapper] and substitutes the default
+ * method remapper with [CustomMethodRemapper]
+ */
+class CustomClassRemapper(cv: ClassVisitor, private val customRemapper: CustomRemapper)
+    : ClassRemapper(Opcodes.ASM5, cv, customRemapper) {
+
+    override fun visitField(access: Int,
+                            name: String,
+                            desc: String?,
+                            signature: String?,
+                            value: Any?) : FieldVisitor? {
+        cv ?: return null
+
+        val field = customRemapper.mapField(className, name)
+        val fieldVisitor = cv.visitField(
+                access,
+                field.name,
+                remapper.mapDesc(desc),
+                remapper.mapSignature(signature, true),
+                remapper.mapValue(value))
+
+        fieldVisitor ?: return null
+
+        return createFieldRemapper(fieldVisitor)
+    }
+
+    override fun createMethodRemapper(mv: MethodVisitor) : MethodVisitor {
+        return CustomMethodRemapper(mv, customRemapper)
+    }
+}
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/asm/CustomMethodRemapper.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/asm/CustomMethodRemapper.kt
new file mode 100644
index 0000000..cc60cbf
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/asm/CustomMethodRemapper.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.bytecode.asm
+
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.commons.MethodRemapper
+
+/**
+ * Currently only adds field context awareness into [MethodRemapper]
+ */
+internal class CustomMethodRemapper(mv:MethodVisitor,
+                                    private val customRemapper: CustomRemapper)
+    : MethodRemapper(Opcodes.ASM5, mv, customRemapper) {
+
+    override fun visitFieldInsn(opcode: Int, owner: String, name: String, desc: String?) {
+        mv ?: return
+
+        val field = customRemapper.mapField(owner, name)
+        mv.visitFieldInsn(opcode, field.owner.fullName, field.name, remapper.mapDesc(desc))
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/asm/CustomRemapper.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/asm/CustomRemapper.kt
new file mode 100644
index 0000000..5debf70
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/bytecode/asm/CustomRemapper.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.bytecode.asm
+
+import android.support.tools.jetifier.core.rules.JavaField
+import android.support.tools.jetifier.core.rules.JavaType
+import android.support.tools.jetifier.core.transform.bytecode.CoreRemapper
+import org.objectweb.asm.commons.Remapper
+
+/**
+ * Extends [Remapper] with a capability to rewrite field names together with their owner.
+ */
+class CustomRemapper(val remapperImpl: CoreRemapper) : Remapper() {
+
+    override fun map(typeName: String): String {
+        return remapperImpl.rewriteType(JavaType(typeName)).fullName
+    }
+
+    fun mapField(ownerName: String, fieldName: String): JavaField {
+        return remapperImpl.rewriteField(JavaField(ownerName, fieldName))
+    }
+
+    override fun mapFieldName(owner: String?, name: String, desc: String?): String {
+        throw RuntimeException("This should not be called")
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomDependency.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomDependency.kt
new file mode 100644
index 0000000..1622fd7
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomDependency.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.pom
+
+import com.google.gson.annotations.SerializedName
+import org.jdom2.Document
+import org.jdom2.Element
+
+/**
+ * Represents a '<dependency>' XML node of a POM file.
+ *
+ * See documentation of the content at https://maven.apache.org/pom.html#Dependencies
+ */
+data class PomDependency(
+        @SerializedName("groupId")
+        val groupId: String? = null,
+
+        @SerializedName("artifactId")
+        val artifactId: String? = null,
+
+        @SerializedName("version")
+        var version: String? = null,
+
+        @SerializedName("classifier")
+        val classifier: String? = null,
+
+        @SerializedName("type")
+        val type: String? = null,
+
+        @SerializedName("scope")
+        val scope: String? = null,
+
+        @SerializedName("systemPath")
+        val systemPath: String? = null,
+
+        @SerializedName("optional")
+        val optional: String? = null) {
+
+    companion object {
+
+        /**
+         * Creates a new [PomDependency] from the given XML [Element].
+         */
+        fun fromXmlElement(node: Element, properties: Map<String, String>) : PomDependency {
+            var groupId : String? = null
+            var artifactId : String? = null
+            var version : String? = null
+            var classifier : String? = null
+            var type : String? = null
+            var scope : String? = null
+            var systemPath : String? = null
+            var optional : String? = null
+
+            for (childNode in node.children) {
+                when (childNode.name) {
+                    "groupId" -> groupId = XmlUtils.resolveValue(childNode.value, properties)
+                    "artifactId" -> artifactId = XmlUtils.resolveValue(childNode.value, properties)
+                    "version" -> version = XmlUtils.resolveValue(childNode.value, properties)
+                    "classifier" -> classifier = XmlUtils.resolveValue(childNode.value, properties)
+                    "type" -> type = XmlUtils.resolveValue(childNode.value, properties)
+                    "scope" -> scope = XmlUtils.resolveValue(childNode.value, properties)
+                    "systemPath" -> systemPath = XmlUtils.resolveValue(childNode.value, properties)
+                    "optional" -> optional = XmlUtils.resolveValue(childNode.value, properties)
+                }
+            }
+
+            return PomDependency(
+                    groupId = groupId,
+                    artifactId = artifactId,
+                    version = version,
+                    classifier = classifier,
+                    type = type,
+                    scope = scope,
+                    systemPath = systemPath,
+                    optional = optional)
+        }
+
+    }
+
+    init {
+        if (version != null) {
+            version = version!!.toLowerCase()
+        }
+    }
+
+    /**
+     * Whether this dependency should be skipped from the rewriting process
+     */
+    fun shouldSkipRewrite() : Boolean {
+        return scope != null && scope.toLowerCase() == "test"
+    }
+
+    /**
+     * Returns a new dependency created by taking all the items from the [input] dependency and then
+     * overwriting these with all of its non-null items.
+     */
+    fun rewrite(input: PomDependency) : PomDependency {
+        return PomDependency(
+            groupId = groupId ?: input.groupId,
+            artifactId = artifactId ?: input.artifactId,
+            version = version ?: input.version,
+            classifier = classifier ?: input.classifier,
+            type = type ?: input.type,
+            scope = scope ?: input.scope,
+            systemPath = systemPath ?: input.systemPath,
+            optional = optional ?: input.optional
+        )
+    }
+
+    /**
+     * Transforms the current data into XML '<dependency>' node.
+     */
+    fun toXmlElement(document: Document) : Element {
+        val node = Element("dependency")
+        node.namespace = document.rootElement.namespace
+
+        XmlUtils.addStringNodeToNode(node, "groupId", groupId)
+        XmlUtils.addStringNodeToNode(node, "artifactId", artifactId)
+        XmlUtils.addStringNodeToNode(node, "version", version)
+        XmlUtils.addStringNodeToNode(node, "classifier", classifier)
+        XmlUtils.addStringNodeToNode(node, "type", type)
+        XmlUtils.addStringNodeToNode(node, "scope", scope)
+        XmlUtils.addStringNodeToNode(node, "systemPath", systemPath)
+        XmlUtils.addStringNodeToNode(node, "optional", optional)
+
+        return node
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomDocument.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomDocument.kt
new file mode 100644
index 0000000..d5bdc3a
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomDocument.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.pom
+
+import android.support.tools.jetifier.core.archive.ArchiveFile
+import android.support.tools.jetifier.core.utils.Log
+import org.jdom2.Document
+import org.jdom2.Element
+
+/**
+ * Wraps a single POM XML [ArchiveFile] with parsed metadata about transformation related sections.
+ */
+class PomDocument(val file: ArchiveFile, private val document: Document) {
+
+    companion object {
+        private const val TAG = "Pom"
+
+        fun loadFrom(file: ArchiveFile) : PomDocument {
+            val document = XmlUtils.createDocumentFromByteArray(file.data)
+            val pomDoc = PomDocument(file, document)
+            pomDoc.initialize()
+            return pomDoc
+        }
+    }
+
+    val dependencies : MutableSet<PomDependency> = mutableSetOf()
+    private val properties : MutableMap<String, String> = mutableMapOf()
+    private var dependenciesGroup : Element? = null
+    private var hasChanged : Boolean = false
+
+    private fun initialize() {
+        val propertiesGroup = document.rootElement
+                .getChild("properties", document.rootElement.namespace)
+        if (propertiesGroup != null) {
+            propertiesGroup.children
+                .filterNot { it.value.isNullOrEmpty() }
+                .forEach { properties[it.name] = it.value }
+        }
+
+        dependenciesGroup = document.rootElement
+                .getChild("dependencies", document.rootElement.namespace) ?: return
+        dependenciesGroup!!.children.mapTo(dependencies) {
+            PomDependency.fromXmlElement(it, properties)
+        }
+    }
+
+    /**
+     * Validates that this document is consistent with the provided [rules].
+     *
+     * Currently it checks that all the dependencies that are going to be rewritten by the given
+     * rules satisfy the minimal version requirements defined by the rules.
+     */
+    fun validate(rules: List<PomRewriteRule>) : Boolean {
+        if (dependenciesGroup == null) {
+            // Nothing to validate as this file has no dependencies section
+            return true
+        }
+
+        return dependencies.all { dep -> rules.all { it.validateVersion(dep) } }
+    }
+
+    /**
+     * Applies the given [rules] to rewrite the POM file.
+     *
+     * Changes are not saved back until requested.
+     */
+    fun applyRules(rules: List<PomRewriteRule>) {
+        if (dependenciesGroup == null) {
+            // Nothing to transform as this file has no dependencies section
+            return
+        }
+
+        val newDependencies = mutableSetOf<PomDependency>()
+        for (dependency in dependencies) {
+            if (dependency.shouldSkipRewrite()) {
+                continue
+            }
+
+            val rule = rules.firstOrNull { it.matches(dependency) }
+            if (rule == null) {
+                // No rule to rewrite => keep it
+                newDependencies.add(dependency)
+            } else {
+                // Replace with new dependencies
+                newDependencies.addAll(rule.to.mapTo(newDependencies){ it.rewrite(dependency) })
+            }
+        }
+
+        if (newDependencies.isEmpty()) {
+            // No changes
+            return
+        }
+
+        dependenciesGroup!!.children.clear()
+        newDependencies.forEach { dependenciesGroup!!.addContent(it.toXmlElement(document)) }
+        hasChanged = true
+    }
+
+    /**
+     * Saves any current pending changes back to the file if needed.
+     */
+    fun saveBackToFileIfNeeded() {
+        if (!hasChanged) {
+            return
+        }
+
+        file.data =  XmlUtils.convertDocumentToByteArray(document)
+    }
+
+    /**
+     * Logs the information about the current file using info level.
+     */
+    fun logDocumentDetails() {
+        Log.i(TAG, "POM file at: '%s'", file.relativePath)
+        for ((groupId, artifactId, version) in dependencies) {
+            Log.i(TAG, "- Dep: %s:%s:%s", groupId, artifactId, version)
+        }
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomRewriteRule.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomRewriteRule.kt
new file mode 100644
index 0000000..070a640
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomRewriteRule.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.pom
+
+import android.support.tools.jetifier.core.utils.Log
+import com.google.gson.annotations.SerializedName
+
+/**
+ * Rule that defines how to rewrite a dependency element in a POM file.
+ *
+ * Any dependency that is matched against [from] should be rewritten to list of the dependencies
+ * defined in [to].
+ */
+data class PomRewriteRule(val from: PomDependency, val to: List<PomDependency>) {
+
+    companion object {
+        val TAG : String = "PomRule"
+    }
+
+    /**
+     * Validates that the given [input] dependency has a valid version.
+     */
+    fun validateVersion(input: PomDependency, document: PomDocument? = null) : Boolean {
+        if (from.version == null || input.version == null) {
+            return true
+        }
+
+        if (!matches(input)) {
+            return true
+        }
+
+        if (!areVersionsMatching(from.version!!, input.version!!)) {
+            Log.e(TAG, "Version mismatch! Expected version '%s' but found version '%s' for " +
+                    "'%s:%s' in '%s' file.", from.version, input.version, input.groupId,
+                    input.artifactId, document?.file?.relativePath)
+            return false
+        }
+
+        return true
+    }
+
+    /**
+     * Checks if the given [version] is supported to be rewritten with a rule having [ourVersion].
+     *
+     * Version entry can be actually quite complicated, see the full documentation at:
+     * https://maven.apache.org/pom.html#Dependencies
+     */
+    private fun areVersionsMatching(ourVersion: String, version: String) : Boolean {
+        if (version == "latest" || version == "release") {
+            return true
+        }
+
+        if (version.endsWith(",)") || version.endsWith(",]")) {
+            return true
+        }
+
+        if (version.endsWith("$ourVersion]")) {
+            return true
+        }
+
+        return ourVersion == version
+    }
+
+    fun matches(input: PomDependency) : Boolean {
+        return input.artifactId == from.artifactId && input.groupId == from.groupId
+    }
+
+    /** Returns JSON data model of this class */
+    fun toJson() : PomRewriteRule.JsonData {
+        return PomRewriteRule.JsonData(from, to)
+    }
+
+
+    /**
+     * JSON data model for [PomRewriteRule].
+     */
+    data class JsonData(
+            @SerializedName("from")
+            val from: PomDependency,
+            @SerializedName("to")
+            val to: List<PomDependency>)  {
+
+        /** Creates instance of [PomRewriteRule] */
+        fun toRule() : PomRewriteRule {
+            return PomRewriteRule(from, to.filterNotNull())
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomScanner.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomScanner.kt
new file mode 100644
index 0000000..e9cc511
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/PomScanner.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.pom
+
+import android.support.tools.jetifier.core.archive.Archive
+import android.support.tools.jetifier.core.archive.ArchiveFile
+import android.support.tools.jetifier.core.archive.ArchiveItemVisitor
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.utils.Log
+
+/**
+ * Helper to scan [Archive]s to find their POM files.
+ */
+class PomScanner(private val config: Config) {
+
+    companion object {
+        private const val TAG = "PomScanner"
+    }
+
+    private val pomFilesInternal = mutableListOf<PomDocument>()
+
+    private var validationFailuresCount = 0
+
+    val pomFiles : List<PomDocument> = pomFilesInternal
+
+    fun wasErrorFound() = validationFailuresCount > 0
+
+    /**
+     * Scans the given [archive] for a POM file
+     *
+     * @return null if POM file was not found
+     */
+    fun scanArchiveForPomFile(archive: Archive) : PomDocument? {
+        val session = PomScannerSession()
+        archive.accept(session)
+
+        if (session.pomFile == null) {
+            return null
+        }
+        val pomFile = session.pomFile!!
+
+        pomFile.logDocumentDetails()
+
+        if (!pomFile.validate(config.pomRewriteRules)) {
+            Log.e(TAG, "Version mismatch!")
+            validationFailuresCount++
+        }
+
+        pomFilesInternal.add(session.pomFile!!)
+
+        return session.pomFile
+    }
+
+
+    private class PomScannerSession : ArchiveItemVisitor {
+
+        var pomFile : PomDocument? = null
+
+        override fun visit(archive: Archive) {
+            for (archiveItem in archive.files) {
+                if (pomFile != null) {
+                    break
+                }
+                archiveItem.accept(this)
+            }
+        }
+
+        override fun visit(archiveFile: ArchiveFile) {
+            if (archiveFile.isPomFile()) {
+                pomFile = PomDocument.loadFrom(archiveFile)
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/XmlUtils.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/XmlUtils.kt
new file mode 100644
index 0000000..67b7a3d
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/pom/XmlUtils.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.pom
+
+import android.support.tools.jetifier.core.utils.Log
+import org.jdom2.Document
+import org.jdom2.Element
+import org.jdom2.input.SAXBuilder
+import org.jdom2.output.Format
+import org.jdom2.output.XMLOutputter
+import java.io.ByteArrayOutputStream
+import java.util.regex.Pattern
+
+/**
+ * Utilities for handling XML documents.
+ */
+class XmlUtils {
+
+    companion object {
+
+        private val variablePattern = Pattern.compile("\\$\\{([^}]*)}")
+
+        /** Saves the given [Document] to a new byte array */
+        fun convertDocumentToByteArray(document : Document) : ByteArray {
+            val xmlOutput = XMLOutputter()
+            ByteArrayOutputStream().use {
+                xmlOutput.format = Format.getPrettyFormat()
+                xmlOutput.output(document, it)
+                return it.toByteArray()
+            }
+        }
+
+        /** Creates a new [Document] from the given [ByteArray] */
+        fun createDocumentFromByteArray(data: ByteArray) : Document {
+            val builder = SAXBuilder()
+            data.inputStream().use {
+                return builder.build(it)
+            }
+        }
+
+        /**
+         * Creates a new XML element with the given [id] and text given in [value] and puts it under
+         * the given [parent]. Nothing is created if the [value] argument is null or empty.
+         */
+        fun addStringNodeToNode(parent: Element, id: String, value: String?) {
+            if (value.isNullOrEmpty()) {
+                return
+            }
+
+            val element = Element(id)
+            element.text = value
+            element.namespace = parent.namespace
+            parent.children.add(element)
+        }
+
+
+        fun resolveValue(value: String?, properties: Map<String, String>) : String? {
+            if (value == null) {
+                return null
+            }
+
+            val matcher = variablePattern.matcher(value)
+            if (matcher.matches()) {
+                val variableName = matcher.group(1)
+                val varValue = properties[variableName]
+                if (varValue == null) {
+                    Log.e("TAG", "Failed to resolve variable '%s'", value)
+                    return value
+                }
+                return varValue
+            }
+
+            return value
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardClassFilterParser.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardClassFilterParser.kt
new file mode 100644
index 0000000..c431572
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardClassFilterParser.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import android.support.tools.jetifier.core.transform.proguard.patterns.GroupsReplacer
+import android.support.tools.jetifier.core.transform.proguard.patterns.PatternHelper
+import java.util.regex.Pattern
+
+/**
+ * Parses and rewrites ProGuard rules that contain class filters. See ProGuard documentation
+ * https://www.guardsquare.com/en/proguard/manual/usage#filters
+ */
+class ProGuardClassFilterParser(private val mapper : ProGuardTypesMapper) {
+
+    companion object {
+        private const val RULES = "(adaptclassstrings|dontnote|dontwarn)"
+    }
+
+    val replacer = GroupsReplacer(
+        pattern = PatternHelper.build("^ *-$RULES ⦅[^-]+⦆ *$", Pattern.MULTILINE),
+        groupsMap = listOf(
+            { filter : String -> rewriteClassFilter(filter) }
+        )
+    )
+
+    private fun rewriteClassFilter(classFilter: String) : String {
+        return classFilter
+            .splitToSequence(",")
+            .filterNotNull()
+            .map { it.trim() }
+            .filter { it.isNotEmpty() }
+            .map { replaceTypeInClassFilter(it) }
+            .joinToString(separator = ", ")
+    }
+
+    private fun replaceTypeInClassFilter(type: String) : String {
+        if (!type.startsWith('!')) {
+            return mapper.replaceType(type)
+        }
+
+        val withoutNegation = type.substring(1, type.length)
+        return '!' + mapper.replaceType(withoutNegation)
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardClassSpecParser.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardClassSpecParser.kt
new file mode 100644
index 0000000..933ff08
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardClassSpecParser.kt
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import android.support.tools.jetifier.core.transform.proguard.patterns.GroupsReplacer
+import android.support.tools.jetifier.core.transform.proguard.patterns.PatternHelper
+
+/**
+ * Parses and rewrites ProGuard rules that contain class specification. See ProGuard documentation
+ * https://www.guardsquare.com/en/proguard/manual/usage#classspecification
+ */
+class ProGuardClassSpecParser(private val mapper : ProGuardTypesMapper) {
+
+    companion object {
+        private const val RULES = "(keep[a-z]*|whyareyoukeeping|assumenosideeffects)"
+        private const val RULES_MODIFIERS =
+            "(includedescriptorclasses|allowshrinking|allowoptimization|allowobfuscation)"
+
+        private const val CLASS_NAME = "[\\w.$?*_%]+"
+        private const val CLASS_MODIFIERS = "[!]?(public|final|abstract)"
+        private const val CLASS_TYPES = "[!]?(interface|class|enum)"
+
+        private const val ANNOTATION_TYPE = CLASS_NAME
+
+        private const val FIELD_NAME = "[\\w?*_%]+"
+        private const val FIELD_TYPE = CLASS_NAME
+        private const val FIELD_MODIFIERS =
+            "[!]?(public|private|protected|static|volatile|transient)"
+
+        private const val METHOD_MODIFIERS =
+            "[!]?(public|private|protected|static|synchronized|native|abstract|strictfp)"
+        private const val RETURN_TYPE_NAME = CLASS_NAME
+        private const val METHOD_NAME = "[\\w?*_]+"
+        private const val ARGS = "[^)]*"
+    }
+
+    val replacer = GroupsReplacer(
+        pattern = PatternHelper.build(
+            "-$RULES ($RULES_MODIFIERS )*(@⦅$ANNOTATION_TYPE⦆ )?($CLASS_MODIFIERS )*$CLASS_TYPES " +
+            "⦅$CLASS_NAME⦆( (extends|implements) ⦅$CLASS_NAME⦆)?+ *( *\\{⦅[^}]*⦆\\} *)?+"),
+        groupsMap = listOf(
+            { annotation : String -> mapper.replaceType(annotation) },
+            { className : String -> mapper.replaceType(className) },
+            { className2 : String -> mapper.replaceType(className2) },
+            { bodyGroup : String -> rewriteBodyGroup(bodyGroup) }
+        )
+    )
+
+    private val bodyReplacers = listOf(
+        // [@annotation] [[!]public|private|etc...] <fields>;
+        GroupsReplacer(
+            pattern = PatternHelper.build(
+                "^ *(@⦅$ANNOTATION_TYPE⦆ )?($FIELD_MODIFIERS )*<fields> *$"),
+            groupsMap = listOf(
+                { annotation : String -> mapper.replaceType(annotation) }
+        )),
+
+        // [@annotation] [[!]public|private|etc...] fieldType fieldName;
+        GroupsReplacer(
+            pattern = PatternHelper.build(
+                "^ *(@⦅$ANNOTATION_TYPE⦆ )?($FIELD_MODIFIERS )*(⦅$FIELD_TYPE⦆ $FIELD_NAME) *$"),
+            groupsMap = listOf(
+                { annotation : String -> mapper.replaceType(annotation) },
+                { fieldType : String -> mapper.replaceType(fieldType) }
+        )),
+
+        // [@annotation] [[!]public|private|etc...] <methods>;
+        GroupsReplacer(
+            pattern = PatternHelper.build(
+                "^ *(@⦅$ANNOTATION_TYPE⦆ )?($METHOD_MODIFIERS )*<methods> *$"),
+            groupsMap = listOf(
+                { annotation : String -> mapper.replaceType(annotation) }
+        )),
+
+        // [@annotation] [[!]public|private|etc...] className(argumentType,...));
+        GroupsReplacer(
+            pattern = PatternHelper.build(
+                "^ *(@⦅$ANNOTATION_TYPE⦆ )?($METHOD_MODIFIERS )*⦅$CLASS_NAME⦆ *\\(⦅$ARGS⦆\\) *$"),
+            groupsMap = listOf(
+                { annotation : String -> mapper.replaceType(annotation) },
+                { className : String -> mapper.replaceType(className) },
+                { argsType : String -> mapper.replaceMethodArgs(argsType) }
+            )
+        ),
+
+        // [@annotation] [[!]public|private|etc...] <init>(argumentType,...));
+        GroupsReplacer(
+            pattern = PatternHelper.build(
+                "^ *(@⦅$ANNOTATION_TYPE⦆ )?($METHOD_MODIFIERS )*<init> *\\(⦅$ARGS⦆\\) *$"),
+            groupsMap = listOf(
+                { annotation : String -> mapper.replaceType(annotation) },
+                { argsType : String -> mapper.replaceMethodArgs(argsType) }
+        )),
+
+        // [@annotation] [[!]public|private|etc...] returnType methodName(argumentType,...));
+        GroupsReplacer(
+            pattern = PatternHelper.build("^ *(@⦅$ANNOTATION_TYPE⦆ )?($METHOD_MODIFIERS )*" +
+                "⦅$RETURN_TYPE_NAME⦆ $METHOD_NAME *\\(⦅$ARGS⦆\\) *$"),
+            groupsMap = listOf(
+                { annotation : String -> mapper.replaceType(annotation) },
+                { returnType : String -> mapper.replaceType(returnType) },
+                { argsType : String -> mapper.replaceMethodArgs(argsType) }
+        ))
+    )
+
+    private fun rewriteBodyGroup(bodyGroup: String) : String {
+        if (bodyGroup == "*" || bodyGroup == "**") {
+            return bodyGroup
+        }
+
+        return bodyGroup
+            .split(';')
+            .map {
+                for (replacer in bodyReplacers) {
+                    val matcher = replacer.pattern.matcher(it)
+                    if (matcher.matches()) {
+                        return@map replacer.runReplacements(matcher)
+                    }
+                }
+                return@map it
+            }
+            .joinToString(";")
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTransformer.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTransformer.kt
new file mode 100644
index 0000000..423bf05
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTransformer.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import android.support.tools.jetifier.core.archive.ArchiveFile
+import android.support.tools.jetifier.core.transform.TransformationContext
+import android.support.tools.jetifier.core.transform.Transformer
+import android.support.tools.jetifier.core.transform.proguard.patterns.ReplacersRunner
+import java.nio.charset.StandardCharsets
+
+/**
+ * The [Transformer] responsible for ProGuard files refactoring.
+ */
+class ProGuardTransformer internal constructor(context: TransformationContext) : Transformer {
+
+    private val mapper = ProGuardTypesMapper(context)
+
+    val replacer = ReplacersRunner(listOf(
+        ProGuardClassSpecParser(mapper).replacer,
+        ProGuardClassFilterParser(mapper).replacer
+    ))
+
+    override fun canTransform(file: ArchiveFile): Boolean {
+        return file.isProGuardFile()
+    }
+
+    override fun runTransform(file: ArchiveFile) {
+        val sb = StringBuilder(file.data.toString(StandardCharsets.UTF_8))
+        val result = replacer.applyReplacers(sb.toString())
+        file.data = result.toByteArray()
+    }
+}
+
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardType.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardType.kt
new file mode 100644
index 0000000..be15fbf
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardType.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import android.support.tools.jetifier.core.rules.JavaType
+
+/**
+ * Represents a type reference in ProGuard file. This type is similar to the regular java type but
+ * can also contain wildcards (*,**,?).
+ */
+data class ProGuardType(val value: String) {
+
+    init {
+        if (value.contains('.')) {
+            throw IllegalArgumentException("The type does not support '.' as package separator!")
+        }
+    }
+
+    companion object {
+        /** Creates the type reference from notation where packages are separated using '.' */
+        fun fromDotNotation(type: String) : ProGuardType {
+            return ProGuardType(type.replace('.', '/'))
+        }
+    }
+
+    /**
+     * Whether the type reference is trivial such as "*".
+     */
+    fun isTrivial() = value == "*" || value == "**" || value == "***" || value == "%"
+
+    fun toJavaType() : JavaType? {
+        if (value.contains('*') || value.contains('?')) {
+            return null
+        }
+        return JavaType(value)
+    }
+
+    /** Returns the type reference as a string where packages are separated using '.' */
+    fun toDotNotation() : String {
+        return value.replace('/', '.')
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTypesMap.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTypesMap.kt
new file mode 100644
index 0000000..03d6282
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTypesMap.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+/**
+ * Contains custom mappings to map support library types referenced in ProGuard to new ones.
+ */
+data class ProGuardTypesMap(val rules: Map<ProGuardType, ProGuardType>) {
+
+    companion object {
+        val EMPTY = ProGuardTypesMap(emptyMap())
+    }
+
+    /** Returns JSON data model of this class */
+    fun toJson() : JsonData {
+        return JsonData(rules.map { it.key.value to it.value.value }.toMap())
+    }
+
+    /**
+     * JSON data model for [ProGuardTypesMap].
+     */
+    data class JsonData(val rules: Map<String, String>)  {
+
+        /** Creates instance of [ProGuardTypesMap] */
+        fun toMappings() : ProGuardTypesMap {
+            return ProGuardTypesMap(rules.map { ProGuardType(it.key) to ProGuardType(it.value) }.toMap())
+        }
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTypesMapper.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTypesMapper.kt
new file mode 100644
index 0000000..28195a3
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTypesMapper.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import android.support.tools.jetifier.core.transform.TransformationContext
+import android.support.tools.jetifier.core.utils.Log
+
+/**
+ * Maps ProGuard types using [TypesMap] and [ProGuardTypesMap].
+ */
+class ProGuardTypesMapper(private val context: TransformationContext) {
+
+    companion object {
+        const val TAG = "ProGuardTypesMapper"
+    }
+
+    private val config = context.config
+
+    /**
+     * Replaces the given ProGuard type that was parsed from the ProGuard file (thus having '.' as
+     * a separator.
+     */
+    fun replaceType(typeToReplace: String) : String {
+        val type = ProGuardType.fromDotNotation(typeToReplace)
+        if (type.isTrivial()) {
+            return typeToReplace
+        }
+
+        val javaType = type.toJavaType()
+        if (javaType != null) {
+            // We are dealing with an explicit type definition
+            if (!context.isEligibleForRewrite(javaType)) {
+                return typeToReplace
+            }
+
+            val result = config.typesMap.types[javaType]
+            if (result == null) {
+                context.reportNoProGuardMappingFoundFailure()
+                Log.e(TAG, "No mapping for: " + type)
+                return typeToReplace
+            }
+
+            Log.i(TAG, "  map: %s -> %s", type, result)
+            return result.toDotNotation()
+        }
+
+        // Type contains wildcards - try custom rules map
+        val result = config.proGuardMap.rules[type]
+        if (result != null) {
+            Log.i(TAG, "  map: %s -> %s", type, result)
+            return result.toDotNotation()
+        }
+
+        // Report error only when we are sure
+        if (context.isEligibleForRewrite(type)) {
+            context.reportNoProGuardMappingFoundFailure()
+            Log.e(TAG, "No mapping for: " + type)
+        }
+        return typeToReplace
+    }
+
+    /**
+     * Replaces the given arguments list used in a ProGuard method rule. Argument must be separated
+     * with ','. The method also accepts '...' symbol as defined in the spec.
+     */
+    fun replaceMethodArgs(argsTypes: String) : String {
+        if (argsTypes.isEmpty() || argsTypes == "...") {
+            return argsTypes
+        }
+
+        return argsTypes
+            .splitToSequence(",")
+            .filterNotNull()
+            .map { it.trim() }
+            .filter { it.isNotEmpty() }
+            .map { replaceType(it) }
+            .joinToString(separator = ", ")
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/patterns/GroupsReplacer.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/patterns/GroupsReplacer.kt
new file mode 100644
index 0000000..6213a55
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/patterns/GroupsReplacer.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard.patterns
+
+import java.util.regex.Matcher
+import java.util.regex.Pattern
+
+/**
+ * Applies replacements on a matched string using the given [pattern] and its groups. Each group is
+ * mapped using a lambda from [groupsMap].
+ */
+class GroupsReplacer(val pattern: Pattern,
+                     private val groupsMap: List<(String) -> String>) {
+
+    /**
+     * Takes the given [matcher] and replace its matched groups using mapping functions given in
+     * [groupsMap].
+     */
+    fun runReplacements(matcher: Matcher) : String {
+        var result = matcher.group(0)
+
+        // We go intentionally backwards to replace using indexes
+        for (i in groupsMap.size - 1 downTo 0) {
+            val groupVal = matcher.group(i + 1) ?: continue
+            val localStart = matcher.start(i + 1) - matcher.start()
+            val localEnd =  matcher.end(i + 1) - matcher.start()
+
+            result = result.replaceRange(
+                startIndex = localStart,
+                endIndex = localEnd,
+                replacement = groupsMap[i].invoke(groupVal))
+        }
+        return result
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/patterns/PatternHelper.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/patterns/PatternHelper.kt
new file mode 100644
index 0000000..3171185
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/patterns/PatternHelper.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard.patterns
+
+import java.util.regex.Pattern
+
+/**
+ * Helps to build regular expression [Pattern]s defined with less verbose syntax.
+ *
+ * You can use following shortcuts:
+ * '⦅⦆' - denotes a capturing group (normally '()' is capturing group)
+ * '()' - denotes non-capturing group (normally (?:) is non-capturing group)
+ * ' ' - denotes a whitespace characters (at least one)
+ * ' *' - denotes a whitespace characters (any)
+ * ';' - denotes ' *;'
+ */
+object PatternHelper {
+
+    private val rewrites = listOf(
+        " *" to "[\\s]*", // Optional space
+        " " to "[\\s]+", // Space
+        "⦅" to "(", // Capturing group start
+        "ï½ " to ")", // Capturing group end
+        ";" to "[\\s]*;" // Allow spaces in front of ';'
+    )
+
+    /**
+     * Transforms the given [toReplace] according to the rules defined in documentation of this
+     * class and compiles it to a [Pattern].
+     */
+    fun build(toReplace: String, flags : Int = 0) : Pattern {
+        var result = toReplace
+        result = result.replace("(?<!\\\\)\\(".toRegex(), "(?:")
+        rewrites.forEach { result = result.replace(it.first, it.second) }
+        return Pattern.compile(result, flags)
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/patterns/ReplacersRunner.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/patterns/ReplacersRunner.kt
new file mode 100644
index 0000000..54501f9
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/proguard/patterns/ReplacersRunner.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard.patterns
+
+/**
+ * Runs multiple [GroupsReplacer]s on given strings.
+ */
+class ReplacersRunner(val replacers: List<GroupsReplacer>) {
+
+    /**
+     * Runs all the [GroupsReplacer]s on the given [input].
+     *
+     * The replacers have to be distinct as this method can't guarantee that output of one replacer
+     * won't be matched by another replacer.
+     */
+    fun applyReplacers(input : String) : String {
+        val sb = StringBuilder()
+        var lastSeenChar = 0
+        var processedInput = input
+
+        for (replacer in replacers) {
+            val matcher = replacer.pattern.matcher(processedInput)
+
+            while (matcher.find()) {
+                if (lastSeenChar < matcher.start()) {
+                    sb.append(input, lastSeenChar, matcher.start())
+                }
+
+                val result = replacer.runReplacements(matcher)
+                sb.append(result)
+                lastSeenChar = matcher.end()
+            }
+
+            if (lastSeenChar == 0) {
+                continue
+            }
+
+            if (lastSeenChar <= processedInput.length - 1) {
+                sb.append(processedInput, lastSeenChar, processedInput.length)
+            }
+
+            lastSeenChar = 0
+            processedInput = sb.toString()
+            sb.setLength(0)
+        }
+
+        return processedInput
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/resource/XmlResourcesTransformer.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/resource/XmlResourcesTransformer.kt
new file mode 100644
index 0000000..0a29828
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/resource/XmlResourcesTransformer.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.resource
+
+import android.support.tools.jetifier.core.archive.ArchiveFile
+import android.support.tools.jetifier.core.map.TypesMap
+import android.support.tools.jetifier.core.rules.JavaTypeXmlRef
+import android.support.tools.jetifier.core.transform.TransformationContext
+import android.support.tools.jetifier.core.transform.Transformer
+import android.support.tools.jetifier.core.utils.Log
+import java.nio.charset.Charset
+import java.nio.charset.StandardCharsets
+import java.util.regex.Pattern
+import javax.xml.stream.XMLInputFactory
+
+/**
+ * Transformer for XML resource files.
+ *
+ * Searches for any java type reference that is pointing to the support library and rewrites it
+ * using the available mappings from [TypesMap].
+ */
+class XmlResourcesTransformer internal constructor(private val context: TransformationContext)
+        : Transformer {
+
+    companion object {
+        const val TAG = "XmlResourcesTransformer"
+
+        const val PATTERN_TYPE_GROUP = 1
+    }
+
+    /**
+     * List of regular expression patterns used to find support library references in XML files.
+     *
+     * Matches xml tags in form of:
+     * 1. '<(/)prefix(SOMETHING)'.
+     * 2. <view ... class="prefix(SOMETHING)" ...>
+     *
+     * Note that this can also rewrite commented blocks of XML. But on a library level we don't care
+     * much about comments.
+     */
+    private val patterns = listOf(
+        Pattern.compile("</?([a-zA-Z0-9.]+)"),
+        Pattern.compile("<view[^>]*class=\"([a-zA-Z0-9.\$_]+)\"[^>]*>")
+    )
+
+    private val typesMap = context.config.typesMap
+
+    override fun canTransform(file: ArchiveFile) = file.isXmlFile() && !file.isPomFile()
+
+    override fun runTransform(file: ArchiveFile) {
+        file.data = transform(file.data)
+    }
+
+    fun transform(data: ByteArray) : ByteArray {
+        var changesDone = false
+
+        val charset = getCharset(data)
+        val sb = StringBuilder(data.toString(charset))
+        for (pattern in patterns) {
+            var matcher = pattern.matcher(sb)
+            while (matcher.find()) {
+                val typeToReplace = JavaTypeXmlRef(matcher.group(PATTERN_TYPE_GROUP))
+                val result = rewriteType(typeToReplace)
+                if (result == typeToReplace) {
+                    continue
+                }
+                sb.replace(matcher.start(PATTERN_TYPE_GROUP), matcher.end(PATTERN_TYPE_GROUP),
+                    result.fullName)
+                changesDone = true
+                matcher = pattern.matcher(sb)
+            }
+        }
+
+        if (changesDone) {
+            return sb.toString().toByteArray(charset)
+        }
+
+        return data
+    }
+
+    fun getCharset(data: ByteArray) : Charset {
+        data.inputStream().use {
+            val xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(it)
+
+            xmlReader.encoding ?: return StandardCharsets.UTF_8 // Encoding was not detected
+
+            val result = Charset.forName(xmlReader.encoding)
+            if (result == null) {
+                Log.e(TAG, "Failed to find charset for encoding '%s'", xmlReader.encoding)
+                return StandardCharsets.UTF_8
+            }
+            return result
+        }
+    }
+
+    fun rewriteType(type: JavaTypeXmlRef): JavaTypeXmlRef {
+        val javaType = type.toJavaType()
+        if (!context.isEligibleForRewrite(javaType)) {
+            return type
+        }
+
+        val result = typesMap.types[javaType]
+        if (result != null) {
+            Log.i(TAG, "  map: %s -> %s", type, result)
+            return JavaTypeXmlRef(result)
+        }
+
+        context.reportNoMappingFoundFailure()
+        Log.e(TAG, "No mapping for: " + type)
+        return type
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/Log.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/Log.kt
new file mode 100644
index 0000000..902dea4
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/Log.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.utils
+
+object Log {
+
+    var currentLevel : LogLevel = LogLevel.INFO
+
+    var logConsumer : LogConsumer = StdOutLogConsumer()
+
+    fun setLevel(level: String?) {
+        currentLevel = when (level) {
+            "debug" -> LogLevel.DEBUG
+            "verbose" -> LogLevel.VERBOSE
+            else -> LogLevel.INFO
+        }
+
+    }
+
+    fun e(tag: String, message: String, vararg args: Any?) {
+        if (currentLevel >= LogLevel.ERROR) {
+            logConsumer.error("[$tag] $message".format(*args))
+        }
+    }
+
+    fun d(tag: String, message: String, vararg args: Any?) {
+        if (currentLevel >= LogLevel.DEBUG) {
+            logConsumer.debug("[$tag] $message".format(*args))
+        }
+    }
+
+    fun i(tag: String, message: String, vararg args: Any?) {
+        if (currentLevel >= LogLevel.INFO) {
+            logConsumer.info("[$tag] $message".format(*args))
+        }
+    }
+
+    fun v(tag: String, message: String, vararg args: Any?) {
+        if (currentLevel >= LogLevel.VERBOSE) {
+            logConsumer.verbose("[$tag] $message".format(*args))
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/LogConsumer.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/LogConsumer.kt
new file mode 100644
index 0000000..ddebd25
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/LogConsumer.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.utils
+
+/**
+ * Interface to plug custom logs consumers to [Log].
+ */
+interface LogConsumer {
+
+    fun error(message: String)
+
+    fun info(message: String)
+
+    fun verbose(message: String)
+
+    fun debug(message: String)
+
+}
+
diff --git a/buildSrc/src/main/kotlin/android/support/KotlinNoOp.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/LogLevel.kt
similarity index 62%
copy from buildSrc/src/main/kotlin/android/support/KotlinNoOp.kt
copy to jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/LogLevel.kt
index 968f6ca..f46b8f6 100644
--- a/buildSrc/src/main/kotlin/android/support/KotlinNoOp.kt
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/LogLevel.kt
@@ -1,24 +1,24 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *       http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
 
-package android.support
+package android.support.tools.jetifier.core.utils
 
-class KotlinNoOp {
-
-    fun noOp() {
-    }
-
+enum class LogLevel(val priority : Int) {
+    ERROR(0),
+    INFO(1),
+    VERBOSE(2),
+    DEBUG(3),
 }
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/StdOutLogConsumer.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/StdOutLogConsumer.kt
new file mode 100644
index 0000000..7cfd25e
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/utils/StdOutLogConsumer.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.utils
+
+/**
+ * Prints logs to the standard output.
+ */
+class StdOutLogConsumer : LogConsumer {
+
+    override fun error(message: String) {
+        println("ERROR: $message")
+    }
+
+    override fun info(message: String) {
+        println("INFO: $message")
+    }
+
+    override fun verbose(message: String) {
+        println("VERBOSE: $message")
+    }
+
+    override fun debug(message: String) {
+        println("DEBUG: $message")
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/resources/default.config b/jetifier/jetifier/core/src/main/resources/default.config
new file mode 100644
index 0000000..a95f7cb
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/resources/default.config
@@ -0,0 +1,251 @@
+# 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
+
+{
+    # Skip packages that don't match the following regex
+    restrictToPackagePrefixes: [
+        "android/support/"
+    ],
+    rules: [
+        {
+            from: "android/support/design/widget/CoordinatorLayout",
+            to: "androidx/widget/CoordinatorLayout"
+        },
+        {
+            from: "android/support/design/widget/DirectedAcyclicGraph",
+            to: "androidx/widget/DirectedAcyclicGraph"
+        },
+        {
+            from: "android/support/design/widget/ViewGroupUtils",
+            to: "androidx/widget/ViewGroupUtils"
+        },
+        {
+            from: "android/support/v4/view/ViewPager",
+            to: "androidx/widget/ViewPager"
+        },
+        {
+            from: "android/support/v4/view/PagerAdapter",
+            to: "androidx/widget/PagerAdapter"
+        },
+        {
+            from: "android/support/v4/view/PagerTabStrip",
+            to: "androidx/widget/PagerTabStrip"
+        },
+        {
+            from: "android/support/v4/view/PagerTitleStrip",
+            to: "androidx/widget/PagerTitleStrip"
+        },
+        {
+            from: "android/support/v17/preference/(.*)",
+            to: "androidx/leanback/preference/{0}"
+        },
+        {
+            from: "android/support/customtabs/(.*)",
+            to: "androidx/browser/customtabs/{0}"
+        },
+        {
+            from: "android/support/v4/(.*)",
+            to: "androidx/{0}"
+        },
+        {
+            from: "android/support/v7/graphics/ColorCutQuantizer",
+            to: "androidx/graphics/palette/ColorCutQuantizer"
+        },
+        {
+            from: "android/support/v7/graphics/Palette",
+            to: "androidx/graphics/palette/Palette"
+        },
+        {
+            from: "android/support/v7/graphics/Target",
+            to: "androidx/graphics/palette/Target"
+        },
+        {
+            from: "android/support/v7/(.*)",
+            to: "androidx/{0}"
+        },
+        {
+            from: "android/support/v13/(.*)",
+            to: "androidx/{0}"
+        },
+        {
+            from: "android/support/v14/(.*)",
+            to: "androidx/{0}"
+        },
+        {
+            from: "android/support/v17/(.*)",
+            to: "androidx/{0}"
+        },
+        {
+            from: "android/support/percent/(.*)",
+            to: "androidx/{0}"
+        },
+        {
+            from: "android/support/(.*)",
+            to: "androidx/{0}"
+        },
+        {
+            from: "android/arch/(.*)",
+            to: "androidx/{0}"
+        }
+    ],
+    pomRules: [
+        {
+            from: { groupId: "com.android.support", artifactId: "animated-vector-drawable", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "animated-vector-drawable", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "appcompat-v7", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "appcompat", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "cardview-v7", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "cardview", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "customtabs", version: "27.0.1" },
+            to: [{ groupId: "com.androidx.browser", artifactId: "customtabs", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "design", version: "27.0.1" },
+            to: [
+                    { groupId: "com.androidx", artifactId: "design", version: "28.0.0" },
+                    { groupId: "com.androidx", artifactId: "widget", version: "28.0.0" }
+                ]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "exifinterface", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "exifinterface", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "gridlayout-v7", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "gridlayout", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "instantvideo", version: "26.0.0-alpha1" },
+            to: [{ groupId: "com.androidx", artifactId: "instantvideo", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "leanback-v17", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "leanback", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "multidex", version: "1.0.2" },
+            to: [{ groupId: "com.androidx", artifactId: "multidex", version: "2.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "multidex-instrumentation", version: "1.0.2" },
+            to: [{ groupId: "com.androidx", artifactId: "multidex-instrumentation", version: "2.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "palette-v7", version: "27.0.1" },
+            to: [{ groupId: "com.androidx.graphics", artifactId: "palette", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "percent", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "widget", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "preference-leanback-v17", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "preference-leanback", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "preference-v14", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "preference", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "preference-v7", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "preference", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "recommendation", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "recommendation", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "recyclerview-v7", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "recyclerview", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-annotations", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "annotations", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-compat", version: "27.0.1" },
+            to: [{ groupId: "com.androidx.browser", artifactId: "compat", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-content", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "content", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-core-ui", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "core-ui", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-core-utils", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "core-utils", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-dynamic-animation", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "dynamic-animation", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-emoji", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "emoji", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-emoji-appcompat", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "emoji-appcompat", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-emoji-bundled", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "emoji-bundled", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-fragment", version: "27.0.1" },
+            to: [{ groupId: "com.androidx.browser", artifactId: "fragment", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-media-compat", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "media-compat", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-tv-provider", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "tv-provider", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-v13", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "androidx", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-v4", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "androidx", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "support-vector-drawable", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "vector-drawable", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "transition", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "transition", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "wear", version: "27.0.1" },
+            to: [{ groupId: "com.androidx", artifactId: "wear", version: "28.0.0" }]
+        },
+        {
+            from: { groupId: "com.android.support", artifactId: "wearable", version: "26.0.0-alpha1" },
+            to: [{ groupId: "com.androidx", artifactId: "wearable", version: "28.0.0" }]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/main/resources/default.generated.config b/jetifier/jetifier/core/src/main/resources/default.generated.config
new file mode 100644
index 0000000..3965e19
--- /dev/null
+++ b/jetifier/jetifier/core/src/main/resources/default.generated.config
@@ -0,0 +1,14526 @@
+# 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
+
+# DO NOT EDIT MANUALLY! This file was auto-generated using Jetifier preprocessor.
+# To make some changes in the configuration edit "default.config" and run
+# preprocessor/scripts/processDefaultConfig.sh script to update this file.
+
+{
+  "restrictToPackagePrefixes": [
+    "android/support/"
+  ],
+  "rules": [
+    {
+      "from": "android/support/design/widget/CoordinatorLayout",
+      "to": "androidx/widget/CoordinatorLayout",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/design/widget/DirectedAcyclicGraph",
+      "to": "androidx/widget/DirectedAcyclicGraph",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/design/widget/ViewGroupUtils",
+      "to": "androidx/widget/ViewGroupUtils",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v4/view/ViewPager",
+      "to": "androidx/widget/ViewPager",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v4/view/PagerAdapter",
+      "to": "androidx/widget/PagerAdapter",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v4/view/PagerTabStrip",
+      "to": "androidx/widget/PagerTabStrip",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v4/view/PagerTitleStrip",
+      "to": "androidx/widget/PagerTitleStrip",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v17/preference/(.*)",
+      "to": "androidx/leanback/preference/{0}",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/customtabs/(.*)",
+      "to": "androidx/browser/customtabs/{0}",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v4/(.*)",
+      "to": "androidx/{0}",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v7/graphics/ColorCutQuantizer",
+      "to": "androidx/graphics/palette/ColorCutQuantizer",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v7/graphics/Palette",
+      "to": "androidx/graphics/palette/Palette",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v7/graphics/Target",
+      "to": "androidx/graphics/palette/Target",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v7/(.*)",
+      "to": "androidx/{0}",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v13/(.*)",
+      "to": "androidx/{0}",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v14/(.*)",
+      "to": "androidx/{0}",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/v17/(.*)",
+      "to": "androidx/{0}",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/percent/(.*)",
+      "to": "androidx/{0}",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/support/(.*)",
+      "to": "androidx/{0}",
+      "fieldSelectors": []
+    },
+    {
+      "from": "android/arch/(.*)",
+      "to": "androidx/{0}",
+      "fieldSelectors": []
+    }
+  ],
+  "pomRules": [
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "animated-vector-drawable",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "animated-vector-drawable",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "appcompat-v7",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "appcompat",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "cardview-v7",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "cardview",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "customtabs",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx.browser",
+          "artifactId": "customtabs",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "design",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "design",
+          "version": "28.0.0"
+        },
+        {
+          "groupId": "com.androidx",
+          "artifactId": "widget",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "exifinterface",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "exifinterface",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "gridlayout-v7",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "gridlayout",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "instantvideo",
+        "version": "26.0.0-alpha1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "instantvideo",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "leanback-v17",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "leanback",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "multidex",
+        "version": "1.0.2"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "multidex",
+          "version": "2.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "multidex-instrumentation",
+        "version": "1.0.2"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "multidex-instrumentation",
+          "version": "2.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "palette-v7",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx.graphics",
+          "artifactId": "palette",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "percent",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "widget",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "preference-leanback-v17",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "preference-leanback",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "preference-v14",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "preference",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "preference-v7",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "preference",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "recommendation",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "recommendation",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "recyclerview-v7",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "recyclerview",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-annotations",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "annotations",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-compat",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx.browser",
+          "artifactId": "compat",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-content",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "content",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-core-ui",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "core-ui",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-core-utils",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "core-utils",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-dynamic-animation",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "dynamic-animation",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-emoji",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "emoji",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-emoji-appcompat",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "emoji-appcompat",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-emoji-bundled",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "emoji-bundled",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-fragment",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx.browser",
+          "artifactId": "fragment",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-media-compat",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "media-compat",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-tv-provider",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "tv-provider",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-v13",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "androidx",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-v4",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "androidx",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "support-vector-drawable",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "vector-drawable",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "transition",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "transition",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "wear",
+        "version": "27.0.1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "wear",
+          "version": "28.0.0"
+        }
+      ]
+    },
+    {
+      "from": {
+        "groupId": "com.android.support",
+        "artifactId": "wearable",
+        "version": "26.0.0-alpha1"
+      },
+      "to": [
+        {
+          "groupId": "com.androidx",
+          "artifactId": "wearable",
+          "version": "28.0.0"
+        }
+      ]
+    }
+  ],
+  "map": {
+    "types": {
+      "android/support/v4/provider/FontsContractCompat$Columns": "androidx/provider/FontsContractCompat$Columns",
+      "android/support/design/widget/AppBarLayout$Behavior$SavedState": "androidx/design/widget/AppBarLayout$Behavior$SavedState",
+      "android/support/v4/internal/view/SupportMenu": "androidx/internal/view/SupportMenu",
+      "android/support/v4/media/MediaDescriptionCompat": "androidx/media/MediaDescriptionCompat",
+      "android/support/transition/ChangeTransform$GhostListener": "androidx/transition/ChangeTransform$GhostListener",
+      "android/support/design/widget/BaseTransientBottomBar$BaseCallback": "androidx/design/widget/BaseTransientBottomBar$BaseCallback",
+      "android/support/v4/print/PrintHelper$ColorMode": "androidx/print/PrintHelper$ColorMode",
+      "android/support/annotation/RequiresPermission$Write": "androidx/annotation/RequiresPermission$Write",
+      "android/support/v7/widget/FastScroller$AnimatorUpdater": "androidx/widget/FastScroller$AnimatorUpdater",
+      "android/support/multidex/MultiDex$V14": "androidx/multidex/MultiDex$V14",
+      "android/support/v17/leanback/app/BrowseSupportFragment$MainFragmentAdapterRegistry": "androidx/leanback/app/BrowseSupportFragment$MainFragmentAdapterRegistry",
+      "android/support/v7/preference/PreferenceDataStore": "androidx/preference/PreferenceDataStore",
+      "android/support/v17/leanback/app/DetailsBackgroundVideoHelper$PlaybackControlStateCallback": "androidx/leanback/app/DetailsBackgroundVideoHelper$PlaybackControlStateCallback",
+      "android/support/v4/content/LocalBroadcastManager": "androidx/content/LocalBroadcastManager",
+      "android/support/v7/view/ActionBarPolicy": "androidx/view/ActionBarPolicy",
+      "android/support/v4/content/Loader$OnLoadCanceledListener": "androidx/content/Loader$OnLoadCanceledListener",
+      "android/support/v4/view/GestureDetectorCompat$GestureDetectorCompatImplBase": "androidx/view/GestureDetectorCompat$GestureDetectorCompatImplBase",
+      "android/support/v4/app/SharedElementCallback$OnSharedElementsReadyListener": "androidx/app/SharedElementCallback$OnSharedElementsReadyListener",
+      "android/support/v7/app/MediaRouteVolumeSlider": "androidx/app/MediaRouteVolumeSlider",
+      "android/support/multidex/MultiDex$V19": "androidx/multidex/MultiDex$V19",
+      "android/support/v17/leanback/widget/StaggeredGridDefault": "androidx/leanback/widget/StaggeredGridDefault",
+      "android/support/v17/leanback/widget/GuidedActionAdapter$ActionOnKeyListener": "androidx/leanback/widget/GuidedActionAdapter$ActionOnKeyListener",
+      "android/support/design/widget/BottomNavigationView$OnNavigationItemReselectedListener": "androidx/design/widget/BottomNavigationView$OnNavigationItemReselectedListener",
+      "android/support/app/recommendation/ContentRecommendation$ContentPricing": "androidx/app/recommendation/ContentRecommendation$ContentPricing",
+      "android/support/v17/leanback/widget/BaseCardView$LayoutParams": "androidx/leanback/widget/BaseCardView$LayoutParams",
+      "android/support/text/emoji/MetadataListReader": "androidx/text/emoji/MetadataListReader",
+      "android/support/v7/appcompat/R$drawable": "androidx/appcompat/R$drawable",
+      "android/support/design/widget/BaseTransientBottomBar$OnAttachStateChangeListener": "androidx/design/widget/BaseTransientBottomBar$OnAttachStateChangeListener",
+      "android/support/v4/view/GravityCompat": "androidx/view/GravityCompat",
+      "android/support/v7/view/menu/SubMenuWrapperICS": "androidx/view/menu/SubMenuWrapperICS",
+      "android/support/graphics/drawable/VectorDrawableCompat": "androidx/graphics/drawable/VectorDrawableCompat",
+      "android/support/v4/view/AsyncLayoutInflater$InflateRequest": "androidx/view/AsyncLayoutInflater$InflateRequest",
+      "android/support/v17/leanback/app/HeadersFragment$NoOverlappingFrameLayout": "androidx/leanback/app/HeadersFragment$NoOverlappingFrameLayout",
+      "android/support/v17/leanback/widget/ShadowHelperJbmr2": "androidx/leanback/widget/ShadowHelperJbmr2",
+      "android/support/design/internal/ScrimInsetsFrameLayout": "androidx/design/internal/ScrimInsetsFrameLayout",
+      "android/support/v17/leanback/widget/HorizontalHoverCardSwitcher": "androidx/leanback/widget/HorizontalHoverCardSwitcher",
+      "android/support/v7/widget/RecyclerView$Recycler": "androidx/widget/RecyclerView$Recycler",
+      "android/support/v7/widget/FastScroller$State": "androidx/widget/FastScroller$State",
+      "android/support/v7/media/SystemMediaRouteProvider$JellybeanMr2Impl": "androidx/media/SystemMediaRouteProvider$JellybeanMr2Impl",
+      "android/support/wear/R$id": "androidx/wear/R$id",
+      "android/support/v17/leanback/widget/FocusHighlight": "androidx/leanback/widget/FocusHighlight",
+      "android/support/v7/view/menu/ExpandedMenuView": "androidx/view/menu/ExpandedMenuView",
+      "android/support/graphics/drawable/PathInterpolatorCompat": "androidx/graphics/drawable/PathInterpolatorCompat",
+      "android/support/v17/leanback/widget/MediaItemActionPresenter": "androidx/leanback/widget/MediaItemActionPresenter",
+      "android/support/v4/content/Loader$OnLoadCompleteListener": "androidx/content/Loader$OnLoadCompleteListener",
+      "android/support/v17/leanback/widget/NonOverlappingLinearLayout": "androidx/leanback/widget/NonOverlappingLinearLayout",
+      "android/support/v7/view/menu/MenuItemWrapperICS$CollapsibleActionViewWrapper": "androidx/view/menu/MenuItemWrapperICS$CollapsibleActionViewWrapper",
+      "android/support/v4/widget/SlidingPaneLayout$SlidingPanelLayoutImplJB": "androidx/widget/SlidingPaneLayout$SlidingPanelLayoutImplJB",
+      "android/support/v17/leanback/app/ErrorFragment": "androidx/leanback/app/ErrorFragment",
+      "android/support/v7/view/menu/MenuItemWrapperICS$OnActionExpandListenerWrapper": "androidx/view/menu/MenuItemWrapperICS$OnActionExpandListenerWrapper",
+      "android/support/v7/app/AppCompatActivity": "androidx/app/AppCompatActivity",
+      "android/support/v17/preference/LeanbackSettingsFragment$DummyFragment": "androidx/leanback/preference/LeanbackSettingsFragment$DummyFragment",
+      "android/support/app/recommendation/ContentRecommendation$IntentType": "androidx/app/recommendation/ContentRecommendation$IntentType",
+      "android/support/v17/leanback/widget/PlaybackControlsRowView": "androidx/leanback/widget/PlaybackControlsRowView",
+      "android/support/v4/text/TextDirectionHeuristicsCompat$TextDirectionHeuristicLocale": "androidx/text/TextDirectionHeuristicsCompat$TextDirectionHeuristicLocale",
+      "android/support/v4/util/SparseArrayCompat": "androidx/util/SparseArrayCompat",
+      "android/support/v4/net/TrafficStatsCompat": "androidx/net/TrafficStatsCompat",
+      "android/support/design/widget/TabLayout$Tab": "androidx/design/widget/TabLayout$Tab",
+      "android/support/v7/view/CollapsibleActionView": "androidx/view/CollapsibleActionView",
+      "android/support/v17/leanback/R$id": "androidx/leanback/R$id",
+      "android/support/v4/content/MimeTypeFilter": "androidx/content/MimeTypeFilter",
+      "android/support/media/tv/TvContractCompat$WatchNextPrograms$WatchNextType": "androidx/media/tv/TvContractCompat$WatchNextPrograms$WatchNextType",
+      "android/support/transition/ViewUtilsImpl": "androidx/transition/ViewUtilsImpl",
+      "android/support/v17/leanback/app/DetailsFragment$SetSelectionRunnable": "androidx/leanback/app/DetailsFragment$SetSelectionRunnable",
+      "android/support/v7/app/MediaRouteControllerDialog$ClickListener": "androidx/app/MediaRouteControllerDialog$ClickListener",
+      "android/support/design/widget/VisibilityAwareImageButton": "androidx/design/widget/VisibilityAwareImageButton",
+      "android/support/transition/ViewGroupUtilsImpl": "androidx/transition/ViewGroupUtilsImpl",
+      "android/support/design/internal/package-info": "androidx/design/internal/package-info",
+      "android/support/v7/widget/SearchView$SearchAutoComplete": "androidx/widget/SearchView$SearchAutoComplete",
+      "android/support/v17/leanback/widget/GuidedActionAdapterGroup": "androidx/leanback/widget/GuidedActionAdapterGroup",
+      "android/support/v7/widget/AppCompatBackgroundHelper": "androidx/widget/AppCompatBackgroundHelper",
+      "android/support/v4/widget/EdgeEffectCompat$EdgeEffectApi21Impl": "androidx/widget/EdgeEffectCompat$EdgeEffectApi21Impl",
+      "android/support/v17/leanback/R$fraction": "androidx/leanback/R$fraction",
+      "android/support/wear/widget/drawer/WearableActionDrawerMenu": "androidx/wear/widget/drawer/WearableActionDrawerMenu",
+      "android/support/v4/content/IntentCompat": "androidx/content/IntentCompat",
+      "android/support/compat/R": "androidx/compat/R",
+      "android/support/v7/widget/RecyclerView$ViewCacheExtension": "androidx/widget/RecyclerView$ViewCacheExtension",
+      "android/support/v7/widget/DecorContentParent": "androidx/widget/DecorContentParent",
+      "android/support/design/widget/BaseTransientBottomBar$Behavior": "androidx/design/widget/BaseTransientBottomBar$Behavior",
+      "android/support/design/widget/TabLayout$ViewPagerOnTabSelectedListener": "androidx/design/widget/TabLayout$ViewPagerOnTabSelectedListener",
+      "android/support/v7/preference/EditTextPreference$SavedState": "androidx/preference/EditTextPreference$SavedState",
+      "android/support/design/widget/ShadowViewDelegate": "androidx/design/widget/ShadowViewDelegate",
+      "android/support/v7/cardview/BuildConfig": "androidx/cardview/BuildConfig",
+      "android/support/v7/app/AlertController$ButtonHandler": "androidx/app/AlertController$ButtonHandler",
+      "android/support/v4/widget/AutoScrollHelper$ScrollAnimationRunnable": "androidx/widget/AutoScrollHelper$ScrollAnimationRunnable",
+      "android/support/v7/view/menu/ShowableListMenu": "androidx/view/menu/ShowableListMenu",
+      "android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper": "androidx/leanback/widget/DetailsOverviewSharedElementHelper",
+      "android/support/v7/widget/MenuPopupWindow$MenuDropDownListView": "androidx/widget/MenuPopupWindow$MenuDropDownListView",
+      "android/support/v17/leanback/transition/LeanbackTransitionHelper": "androidx/leanback/transition/LeanbackTransitionHelper",
+      "android/support/design/widget/BottomSheetDialogFragment": "androidx/design/widget/BottomSheetDialogFragment",
+      "android/support/v4/app/NotificationCompat$Extender": "androidx/app/NotificationCompat$Extender",
+      "android/support/v4/text/TextDirectionHeuristicsCompat$TextDirectionHeuristicInternal": "androidx/text/TextDirectionHeuristicsCompat$TextDirectionHeuristicInternal",
+      "android/support/wear/widget/SwipeDismissLayout$OnPreSwipeListener": "androidx/wear/widget/SwipeDismissLayout$OnPreSwipeListener",
+      "android/support/v4/graphics/BitmapCompat$BitmapCompatApi18Impl": "androidx/graphics/BitmapCompat$BitmapCompatApi18Impl",
+      "android/support/v4/view/ViewCompat$AutofillImportance": "androidx/view/ViewCompat$AutofillImportance",
+      "android/support/v4/app/AppOpsManagerCompat": "androidx/app/AppOpsManagerCompat",
+      "android/support/annotation/FractionRes": "androidx/annotation/FractionRes",
+      "android/support/media/instantvideo/widget/InstantVideoView": "androidx/media/instantvideo/widget/InstantVideoView",
+      "android/support/design/internal/NavigationMenuPresenter$NormalViewHolder": "androidx/design/internal/NavigationMenuPresenter$NormalViewHolder",
+      "android/support/v4/view/accessibility/AccessibilityRecordCompat": "androidx/view/accessibility/AccessibilityRecordCompat",
+      "android/support/v7/view/menu/MenuWrapperFactory": "androidx/view/menu/MenuWrapperFactory",
+      "android/support/v17/leanback/app/HeadersSupportFragment$NoOverlappingFrameLayout": "androidx/leanback/app/HeadersSupportFragment$NoOverlappingFrameLayout",
+      "android/support/v7/widget/ScrollingTabContainerView$VisibilityAnimListener": "androidx/widget/ScrollingTabContainerView$VisibilityAnimListener",
+      "android/support/v7/internal/package-info": "androidx/internal/package-info",
+      "android/support/v4/media/MediaBrowserServiceCompatApi26$ResultWrapper": "androidx/media/MediaBrowserServiceCompatApi26$ResultWrapper",
+      "android/support/v4/media/MediaBrowserServiceCompat$ResultFlags": "androidx/media/MediaBrowserServiceCompat$ResultFlags",
+      "android/support/v4/media/session/MediaControllerCompat$MediaControllerImplApi21$ExtraBinderRequestResultReceiver": "androidx/media/session/MediaControllerCompat$MediaControllerImplApi21$ExtraBinderRequestResultReceiver",
+      "android/support/v17/leanback/widget/OnChildSelectedListener": "androidx/leanback/widget/OnChildSelectedListener",
+      "android/support/v7/mediarouter/BuildConfig": "androidx/mediarouter/BuildConfig",
+      "android/support/v4/os/LocaleListHelper": "androidx/os/LocaleListHelper",
+      "android/support/v7/widget/ChildHelper": "androidx/widget/ChildHelper",
+      "android/support/v17/leanback/widget/BaseOnItemViewClickedListener": "androidx/leanback/widget/BaseOnItemViewClickedListener",
+      "android/support/v17/leanback/widget/VerticalGridPresenter": "androidx/leanback/widget/VerticalGridPresenter",
+      "android/support/v7/widget/Toolbar$LayoutParams": "androidx/widget/Toolbar$LayoutParams",
+      "android/support/v4/provider/SelfDestructiveThread": "androidx/provider/SelfDestructiveThread",
+      "android/support/v17/leanback/widget/DetailsParallax": "androidx/leanback/widget/DetailsParallax",
+      "android/support/v4/content/pm/ActivityInfoCompat": "androidx/content/pm/ActivityInfoCompat",
+      "android/support/percent/PercentFrameLayout$LayoutParams": "androidx/PercentFrameLayout$LayoutParams",
+      "android/support/v7/widget/RecyclerView$ItemAnimator$ItemAnimatorFinishedListener": "androidx/widget/RecyclerView$ItemAnimator$ItemAnimatorFinishedListener",
+      "android/support/v4/media/MediaBrowserCompat$ConnectionCallback": "androidx/media/MediaBrowserCompat$ConnectionCallback",
+      "android/support/design/widget/ThemeUtils": "androidx/design/widget/ThemeUtils",
+      "android/support/wear/widget/drawer/RecyclerViewFlingWatcher": "androidx/wear/widget/drawer/RecyclerViewFlingWatcher",
+      "android/support/v4/app/SupportActivity": "androidx/app/SupportActivity",
+      "android/support/transition/TransitionUtils": "androidx/transition/TransitionUtils",
+      "android/support/v4/graphics/TypefaceCompatApi21Impl": "androidx/graphics/TypefaceCompatApi21Impl",
+      "android/support/v7/media/MediaRouter$CallbackRecord": "androidx/media/MediaRouter$CallbackRecord",
+      "android/support/wear/widget/drawer/NestedScrollViewFlingWatcher": "androidx/wear/widget/drawer/NestedScrollViewFlingWatcher",
+      "android/support/v4/graphics/drawable/TintAwareDrawable": "androidx/graphics/drawable/TintAwareDrawable",
+      "android/support/text/emoji/widget/EmojiTextViewHelper$HelperInternal": "androidx/text/emoji/widget/EmojiTextViewHelper$HelperInternal",
+      "android/support/transition/Styleable": "androidx/transition/Styleable",
+      "android/support/v17/leanback/widget/BaseCardView": "androidx/leanback/widget/BaseCardView",
+      "android/support/v17/leanback/app/DetailsSupportFragment": "androidx/leanback/app/DetailsSupportFragment",
+      "android/support/design/internal/NavigationMenuPresenter$NavigationMenuSeparatorItem": "androidx/design/internal/NavigationMenuPresenter$NavigationMenuSeparatorItem",
+      "android/support/app/recommendation/ContentRecommendation$IntentData": "androidx/app/recommendation/ContentRecommendation$IntentData",
+      "android/support/wear/widget/drawer/WearableDrawerLayout$DrawerStateCallback": "androidx/wear/widget/drawer/WearableDrawerLayout$DrawerStateCallback",
+      "android/support/wear/widget/CircularProgressLayoutController$CircularProgressTimer": "androidx/wear/widget/CircularProgressLayoutController$CircularProgressTimer",
+      "android/support/v4/widget/CircleImageView": "androidx/widget/CircleImageView",
+      "android/support/v17/leanback/app/BaseRowFragment": "androidx/leanback/app/BaseRowFragment",
+      "android/support/text/emoji/EmojiCompat$ReplaceStrategy": "androidx/text/emoji/EmojiCompat$ReplaceStrategy",
+      "android/support/v7/widget/ViewInfoStore$InfoRecord": "androidx/widget/ViewInfoStore$InfoRecord",
+      "android/support/transition/TransitionInflater": "androidx/transition/TransitionInflater",
+      "android/support/v17/leanback/media/PlaybackControlGlue$UpdatePlaybackStateHandler": "androidx/leanback/media/PlaybackControlGlue$UpdatePlaybackStateHandler",
+      "android/support/v7/widget/RecyclerView$State$LayoutState": "androidx/widget/RecyclerView$State$LayoutState",
+      "android/support/v17/leanback/widget/RoundedRectHelper": "androidx/leanback/widget/RoundedRectHelper",
+      "android/support/v4/app/ServiceCompat": "androidx/app/ServiceCompat",
+      "android/support/percent/PercentRelativeLayout$LayoutParams": "androidx/PercentRelativeLayout$LayoutParams",
+      "android/support/v17/leanback/widget/RowHeaderPresenter": "androidx/leanback/widget/RowHeaderPresenter",
+      "android/support/v7/widget/SearchView$UpdatableTouchDelegate": "androidx/widget/SearchView$UpdatableTouchDelegate",
+      "android/support/media/tv/TvContractCompat$PreviewProgramColumns$AspectRatio": "androidx/media/tv/TvContractCompat$PreviewProgramColumns$AspectRatio",
+      "android/support/text/emoji/EmojiMetadata$HasGlyph": "androidx/text/emoji/EmojiMetadata$HasGlyph",
+      "android/support/media/tv/BasePreviewProgram$Builder": "androidx/media/tv/BasePreviewProgram$Builder",
+      "android/support/multidex/ZipUtil$CentralDirectory": "androidx/multidex/ZipUtil$CentralDirectory",
+      "android/support/v7/widget/helper/ItemTouchUIUtil": "androidx/widget/helper/ItemTouchUIUtil",
+      "android/support/v4/widget/DrawerLayout$ChildAccessibilityDelegate": "androidx/widget/DrawerLayout$ChildAccessibilityDelegate",
+      "android/support/v7/media/SystemMediaRouteProvider": "androidx/media/SystemMediaRouteProvider",
+      "android/support/v4/app/LoaderManagerImpl": "androidx/app/LoaderManagerImpl",
+      "android/support/media/ExifInterface$IfdType": "androidx/media/ExifInterface$IfdType",
+      "android/support/v4/widget/CompoundButtonCompat$CompoundButtonCompatBaseImpl": "androidx/widget/CompoundButtonCompat$CompoundButtonCompatBaseImpl",
+      "android/support/v4/graphics/drawable/DrawableWrapperApi14": "androidx/graphics/drawable/DrawableWrapperApi14",
+      "android/support/wear/widget/drawer/WearableDrawerLayout$BottomDrawerDraggerCallback": "androidx/wear/widget/drawer/WearableDrawerLayout$BottomDrawerDraggerCallback",
+      "android/support/v4/view/TintableBackgroundView": "androidx/view/TintableBackgroundView",
+      "android/support/v17/leanback/graphics/BoundsRule": "androidx/leanback/graphics/BoundsRule",
+      "android/support/v17/leanback/widget/RecyclerViewParallax$ChildPositionProperty": "androidx/leanback/widget/RecyclerViewParallax$ChildPositionProperty",
+      "android/support/v4/text/TextDirectionHeuristicsCompat$TextDirectionHeuristicImpl": "androidx/text/TextDirectionHeuristicsCompat$TextDirectionHeuristicImpl",
+      "android/support/v17/leanback/widget/PlaybackControlsPresenter": "androidx/leanback/widget/PlaybackControlsPresenter",
+      "android/support/v7/app/ActionBarDrawerToggle": "androidx/app/ActionBarDrawerToggle",
+      "android/support/design/internal/BaselineLayout": "androidx/design/internal/BaselineLayout",
+      "android/support/v7/preference/PreferenceScreen": "androidx/preference/PreferenceScreen",
+      "android/support/v4/graphics/drawable/DrawableWrapperApi19": "androidx/graphics/drawable/DrawableWrapperApi19",
+      "android/support/v17/leanback/app/DetailsFragment": "androidx/leanback/app/DetailsFragment",
+      "android/support/annotation/ColorLong": "androidx/annotation/ColorLong",
+      "android/support/annotation/IntRange": "androidx/annotation/IntRange",
+      "android/support/v7/widget/LinearLayoutCompat$DividerMode": "androidx/widget/LinearLayoutCompat$DividerMode",
+      "android/support/annotation/RestrictTo": "androidx/annotation/RestrictTo",
+      "android/support/v4/media/session/PlaybackStateCompat": "androidx/media/session/PlaybackStateCompat",
+      "android/support/v17/leanback/widget/RecyclerViewParallax": "androidx/leanback/widget/RecyclerViewParallax",
+      "android/support/v7/widget/ChildHelper$Callback": "androidx/widget/ChildHelper$Callback",
+      "android/support/v17/leanback/widget/DetailsOverviewLogoPresenter": "androidx/leanback/widget/DetailsOverviewLogoPresenter",
+      "android/support/constraint/Guideline": "androidx/constraint/Guideline",
+      "android/support/design/widget/CircularBorderDrawable": "androidx/design/widget/CircularBorderDrawable",
+      "android/support/text/emoji/widget/EmojiInputConnection": "androidx/text/emoji/widget/EmojiInputConnection",
+      "android/support/v4/widget/ImageViewCompat$ImageViewCompatImpl": "androidx/widget/ImageViewCompat$ImageViewCompatImpl",
+      "android/support/v17/leanback/widget/ItemBridgeAdapterShadowOverlayWrapper": "androidx/leanback/widget/ItemBridgeAdapterShadowOverlayWrapper",
+      "android/support/v7/view/menu/MenuBuilder": "androidx/view/menu/MenuBuilder",
+      "android/support/v7/media/MediaRouteDiscoveryRequest": "androidx/media/MediaRouteDiscoveryRequest",
+      "android/support/design/widget/AppBarLayout$ScrollingViewBehavior": "androidx/design/widget/AppBarLayout$ScrollingViewBehavior",
+      "android/support/v17/leanback/widget/PersistentFocusWrapper$SavedState": "androidx/leanback/widget/PersistentFocusWrapper$SavedState",
+      "android/support/v7/widget/RecyclerView$ItemAnimator$ItemAnimatorListener": "androidx/widget/RecyclerView$ItemAnimator$ItemAnimatorListener",
+      "android/support/v17/leanback/media/PlaybackBannerControlGlue": "androidx/leanback/media/PlaybackBannerControlGlue",
+      "android/support/design/internal/NavigationMenuPresenter$ViewHolder": "androidx/design/internal/NavigationMenuPresenter$ViewHolder",
+      "android/support/v7/widget/AppCompatDrawableManager$VdcInflateDelegate": "androidx/widget/AppCompatDrawableManager$VdcInflateDelegate",
+      "android/support/graphics/drawable/AndroidResources": "androidx/graphics/drawable/AndroidResources",
+      "android/support/v7/widget/RecyclerView$RecyclerViewDataObserver": "androidx/widget/RecyclerView$RecyclerViewDataObserver",
+      "android/support/design/R$integer": "androidx/design/R$integer",
+      "android/support/v4/app/AppLaunchChecker": "androidx/app/AppLaunchChecker",
+      "android/support/design/BuildConfig": "androidx/design/BuildConfig",
+      "android/support/v17/leanback/transition/ParallaxTransition": "androidx/leanback/transition/ParallaxTransition",
+      "android/support/text/emoji/widget/SpannableBuilder": "androidx/text/emoji/widget/SpannableBuilder",
+      "android/support/text/emoji/widget/ExtractButtonCompat": "androidx/text/emoji/widget/ExtractButtonCompat",
+      "android/support/v17/leanback/app/ListRowDataAdapter$QueueBasedDataObserver": "androidx/leanback/app/ListRowDataAdapter$QueueBasedDataObserver",
+      "android/support/content/ContentPager$QueryRunner": "androidx/content/ContentPager$QueryRunner",
+      "android/support/v4/app/FragmentTabHost$SavedState": "androidx/app/FragmentTabHost$SavedState",
+      "android/support/v7/widget/OpReorderer$Callback": "androidx/widget/OpReorderer$Callback",
+      "android/support/multidex/MultiDexExtractor$ExtractedDex": "androidx/multidex/MultiDexExtractor$ExtractedDex",
+      "android/support/design/widget/SwipeDismissBehavior": "androidx/design/widget/SwipeDismissBehavior",
+      "android/support/v4/content/FileProvider": "androidx/content/FileProvider",
+      "android/support/v17/leanback/app/BrowseFragment$BrowseTransitionListener": "androidx/leanback/app/BrowseFragment$BrowseTransitionListener",
+      "android/support/design/widget/ViewOffsetBehavior": "androidx/design/widget/ViewOffsetBehavior",
+      "android/support/v17/leanback/app/ListRowDataAdapter$SimpleDataObserver": "androidx/leanback/app/ListRowDataAdapter$SimpleDataObserver",
+      "android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat": "androidx/accessibilityservice/AccessibilityServiceInfoCompat",
+      "android/support/v7/widget/ScrollbarHelper": "androidx/widget/ScrollbarHelper",
+      "android/support/v17/leanback/widget/BaseCardView$InfoAlphaAnimation": "androidx/leanback/widget/BaseCardView$InfoAlphaAnimation",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$RepeatAction": "androidx/leanback/widget/PlaybackControlsRow$RepeatAction",
+      "android/support/v7/widget/LinearSnapHelper": "androidx/widget/LinearSnapHelper",
+      "android/support/v7/view/menu/BaseWrapper": "androidx/view/menu/BaseWrapper",
+      "android/support/wear/utils/MetadataConstants": "androidx/wear/utils/MetadataConstants",
+      "android/support/v7/widget/RecyclerView$ItemAnimator": "androidx/widget/RecyclerView$ItemAnimator",
+      "android/support/v17/leanback/media/PlaybackGlueHost$HostCallback": "androidx/leanback/media/PlaybackGlueHost$HostCallback",
+      "android/support/v7/widget/ActionMenuPresenter$ActionMenuPopupCallback": "androidx/widget/ActionMenuPresenter$ActionMenuPopupCallback",
+      "android/support/v7/widget/GridLayout$Interval": "androidx/widget/GridLayout$Interval",
+      "android/support/v17/leanback/widget/GuidedActionsStylist$ViewHolder": "androidx/leanback/widget/GuidedActionsStylist$ViewHolder",
+      "android/support/v4/app/Fragment$InstantiationException": "androidx/app/Fragment$InstantiationException",
+      "android/support/v14/preference/EditTextPreferenceDialogFragment": "androidx/preference/EditTextPreferenceDialogFragment",
+      "android/support/text/emoji/EmojiCompat$CompatInternal": "androidx/text/emoji/EmojiCompat$CompatInternal",
+      "android/support/v14/preference/BuildConfig": "androidx/preference/BuildConfig",
+      "android/support/v4/app/FragmentManagerNonConfig": "androidx/app/FragmentManagerNonConfig",
+      "android/support/v7/media/MediaRouter$GlobalMediaRouter": "androidx/media/MediaRouter$GlobalMediaRouter",
+      "android/support/transition/Styleable$TransitionManager": "androidx/transition/Styleable$TransitionManager",
+      "android/support/v4/content/res/ConfigurationHelper": "androidx/content/res/ConfigurationHelper",
+      "android/support/v7/app/MediaRouteDiscoveryFragment": "androidx/app/MediaRouteDiscoveryFragment",
+      "android/support/v7/media/MediaRouteSelector": "androidx/media/MediaRouteSelector",
+      "android/support/v4/media/session/MediaControllerCompat$MediaControllerImplApi21": "androidx/media/session/MediaControllerCompat$MediaControllerImplApi21",
+      "android/support/v17/leanback/widget/ControlBar": "androidx/leanback/widget/ControlBar",
+      "android/support/v4/media/session/MediaControllerCompat$MediaControllerImplApi24": "androidx/media/session/MediaControllerCompat$MediaControllerImplApi24",
+      "android/support/app/recommendation/ContentRecommendation$ContentStatus": "androidx/app/recommendation/ContentRecommendation$ContentStatus",
+      "android/support/v4/media/session/MediaControllerCompat$MediaControllerImplApi23": "androidx/media/session/MediaControllerCompat$MediaControllerImplApi23",
+      "android/support/v4/media/MediaMetadataCompat": "androidx/media/MediaMetadataCompat",
+      "android/support/v4/util/CircularIntArray": "androidx/util/CircularIntArray",
+      "android/support/transition/Slide$CalculateSlide": "androidx/transition/Slide$CalculateSlide",
+      "android/support/transition/GhostViewUtils": "androidx/transition/GhostViewUtils",
+      "android/support/design/widget/NavigationView$OnNavigationItemSelectedListener": "androidx/design/widget/NavigationView$OnNavigationItemSelectedListener",
+      "android/support/v4/hardware/fingerprint/FingerprintManagerCompat$CryptoObject": "androidx/hardware/fingerprint/FingerprintManagerCompat$CryptoObject",
+      "android/support/media/tv/TvContractCompat$Programs": "androidx/media/tv/TvContractCompat$Programs",
+      "android/support/v4/provider/FontsContractCompat": "androidx/provider/FontsContractCompat",
+      "android/support/v4/content/res/FontResourcesParserCompat$ProviderResourceEntry": "androidx/content/res/FontResourcesParserCompat$ProviderResourceEntry",
+      "android/support/v17/leanback/widget/BaseGridView": "androidx/leanback/widget/BaseGridView",
+      "android/support/design/R": "androidx/design/R",
+      "android/support/annotation/GuardedBy": "androidx/annotation/GuardedBy",
+      "android/support/v17/leanback/widget/ListRowPresenter$ViewHolder": "androidx/leanback/widget/ListRowPresenter$ViewHolder",
+      "android/support/constraint/solver/widgets/ConstraintWidgetContainer": "androidx/constraint/solver/widgets/ConstraintWidgetContainer",
+      "android/support/wear/widget/drawer/WearableDrawerView$DrawerState": "androidx/wear/widget/drawer/WearableDrawerView$DrawerState",
+      "android/support/v7/widget/LinearLayoutManager$SavedState": "androidx/widget/LinearLayoutManager$SavedState",
+      "android/support/v4/util/LongSparseArray": "androidx/util/LongSparseArray",
+      "android/support/media/tv/TvContractCompat$ProgramColumns$ReviewRatingStyle": "androidx/media/tv/TvContractCompat$ProgramColumns$ReviewRatingStyle",
+      "android/support/v7/media/MediaRouter$GlobalMediaRouter$RemoteControlClientRecord": "androidx/media/MediaRouter$GlobalMediaRouter$RemoteControlClientRecord",
+      "android/support/v7/widget/TintResources": "androidx/widget/TintResources",
+      "android/support/v7/util/ThreadUtil$MainThreadCallback": "androidx/util/ThreadUtil$MainThreadCallback",
+      "android/support/animation/DynamicAnimation$MassState": "androidx/animation/DynamicAnimation$MassState",
+      "android/support/v4/widget/PopupWindowCompat": "androidx/widget/PopupWindowCompat",
+      "android/support/design/widget/FloatingActionButton$Behavior": "androidx/design/widget/FloatingActionButton$Behavior",
+      "android/support/v7/preference/PreferenceFragmentCompat$DividerDecoration": "androidx/preference/PreferenceFragmentCompat$DividerDecoration",
+      "android/support/transition/Styleable$PatternPathMotion": "androidx/transition/Styleable$PatternPathMotion",
+      "android/support/v4/media/session/MediaSessionCompat$Callback$CallbackHandler": "androidx/media/session/MediaSessionCompat$Callback$CallbackHandler",
+      "android/support/v4/app/INotificationSideChannel": "androidx/app/INotificationSideChannel",
+      "android/support/media/tv/TvContractCompat$Channels$VideoFormat": "androidx/media/tv/TvContractCompat$Channels$VideoFormat",
+      "android/support/v17/preference/LeanbackSettingsFragment$RootViewOnKeyListener": "androidx/leanback/preference/LeanbackSettingsFragment$RootViewOnKeyListener",
+      "android/support/v7/widget/ActionMenuView$MenuBuilderCallback": "androidx/widget/ActionMenuView$MenuBuilderCallback",
+      "android/support/design/widget/TabLayout$Mode": "androidx/design/widget/TabLayout$Mode",
+      "android/support/transition/ChangeTransform$Transforms": "androidx/transition/ChangeTransform$Transforms",
+      "android/support/v4/media/MediaBrowserServiceCompatApi21$ResultWrapper": "androidx/media/MediaBrowserServiceCompatApi21$ResultWrapper",
+      "android/support/v17/leanback/transition/TranslationAnimationCreator$TransitionPositionListener": "androidx/leanback/transition/TranslationAnimationCreator$TransitionPositionListener",
+      "android/support/text/emoji/widget/EmojiEditText": "androidx/text/emoji/widget/EmojiEditText",
+      "android/support/wear/R$styleable": "androidx/wear/R$styleable",
+      "android/support/v17/leanback/app/BrowseSupportFragment$FragmentHost": "androidx/leanback/app/BrowseSupportFragment$FragmentHost",
+      "android/support/transition/Scene": "androidx/transition/Scene",
+      "android/support/text/emoji/widget/EmojiTransformationMethod": "androidx/text/emoji/widget/EmojiTransformationMethod",
+      "android/support/v4/view/ViewCompat$ResolvedLayoutDirectionMode": "androidx/view/ViewCompat$ResolvedLayoutDirectionMode",
+      "android/support/v7/appcompat/R": "androidx/appcompat/R",
+      "android/support/v4/media/session/MediaSessionCompatApi24$Callback": "androidx/media/session/MediaSessionCompatApi24$Callback",
+      "android/support/v7/widget/RecyclerView": "androidx/widget/RecyclerView",
+      "android/support/v4/view/accessibility/AccessibilityManagerCompat$AccessibilityStateChangeListenerCompat": "androidx/view/accessibility/AccessibilityManagerCompat$AccessibilityStateChangeListenerCompat",
+      "android/support/v17/leanback/widget/FragmentAnimationProvider": "androidx/leanback/widget/FragmentAnimationProvider",
+      "android/support/v7/widget/ActivityChooserModel": "androidx/widget/ActivityChooserModel",
+      "android/support/media/tv/TvContractCompat$PreviewProgramColumns$InteractionType": "androidx/media/tv/TvContractCompat$PreviewProgramColumns$InteractionType",
+      "android/support/transition/Transition$TransitionListener": "androidx/transition/Transition$TransitionListener",
+      "android/support/v17/leanback/widget/PlaybackControlsRowPresenter$ViewHolder": "androidx/leanback/widget/PlaybackControlsRowPresenter$ViewHolder",
+      "android/support/design/widget/CoordinatorLayout": "androidx/widget/CoordinatorLayout",
+      "android/support/content/Query": "androidx/content/Query",
+      "android/support/v17/leanback/app/BackgroundManager$EmptyDrawable": "androidx/leanback/app/BackgroundManager$EmptyDrawable",
+      "android/support/v17/leanback/app/PlaybackSupportFragment$OnFadeCompleteListener": "androidx/leanback/app/PlaybackSupportFragment$OnFadeCompleteListener",
+      "android/support/v17/leanback/app/BrowseSupportFragment$MainFragmentAdapter": "androidx/leanback/app/BrowseSupportFragment$MainFragmentAdapter",
+      "android/support/v4/media/MediaBrowserCompat$ItemReceiver": "androidx/media/MediaBrowserCompat$ItemReceiver",
+      "android/support/transition/Styleable$VisibilityTransition": "androidx/transition/Styleable$VisibilityTransition",
+      "android/support/transition/TransitionValues": "androidx/transition/TransitionValues",
+      "android/support/v4/content/res/FontResourcesParserCompat$FamilyResourceEntry": "androidx/content/res/FontResourcesParserCompat$FamilyResourceEntry",
+      "android/support/v17/leanback/app/RowsSupportFragment$MainFragmentAdapter": "androidx/leanback/app/RowsSupportFragment$MainFragmentAdapter",
+      "android/support/v17/leanback/widget/Visibility": "androidx/leanback/widget/Visibility",
+      "android/support/design/widget/AppBarLayout$LayoutParams": "androidx/design/widget/AppBarLayout$LayoutParams",
+      "android/support/v4/media/MediaBrowserCompat$SubscriptionCallback$StubApi26": "androidx/media/MediaBrowserCompat$SubscriptionCallback$StubApi26",
+      "android/support/v4/widget/AutoScrollHelper$ClampedScroller": "androidx/widget/AutoScrollHelper$ClampedScroller",
+      "android/support/v7/preference/PreferenceFragmentCompat$OnPreferenceStartScreenCallback": "androidx/preference/PreferenceFragmentCompat$OnPreferenceStartScreenCallback",
+      "android/support/v7/graphics/Palette$Builder": "androidx/graphics/Palette$Builder",
+      "android/support/v4/view/accessibility/AccessibilityNodeInfoCompat$CollectionItemInfoCompat": "androidx/view/accessibility/AccessibilityNodeInfoCompat$CollectionItemInfoCompat",
+      "android/support/design/widget/StateListAnimator$Tuple": "androidx/design/widget/StateListAnimator$Tuple",
+      "android/support/v4/view/accessibility/AccessibilityManagerCompat$TouchExplorationStateChangeListener": "androidx/view/accessibility/AccessibilityManagerCompat$TouchExplorationStateChangeListener",
+      "android/support/text/emoji/EmojiCompat$SpanFactory": "androidx/text/emoji/EmojiCompat$SpanFactory",
+      "android/support/media/tv/TvContractCompat$Channels$Type": "androidx/media/tv/TvContractCompat$Channels$Type",
+      "android/support/v7/widget/GridLayout$LayoutParams": "androidx/widget/GridLayout$LayoutParams",
+      "android/support/v4/media/MediaBrowserCompat$SubscriptionCallback$StubApi21": "androidx/media/MediaBrowserCompat$SubscriptionCallback$StubApi21",
+      "android/support/v17/leanback/widget/WindowAlignment$Axis": "androidx/leanback/widget/WindowAlignment$Axis",
+      "android/support/v17/leanback/widget/ControlBarPresenter": "androidx/leanback/widget/ControlBarPresenter",
+      "android/support/constraint/ConstraintSet": "androidx/constraint/ConstraintSet",
+      "android/support/v17/leanback/transition/TransitionHelperKitkat": "androidx/leanback/transition/TransitionHelperKitkat",
+      "android/support/wear/widget/ScrollManager": "androidx/wear/widget/ScrollManager",
+      "android/support/content/ContentPager$QueryRunner$Callback": "androidx/content/ContentPager$QueryRunner$Callback",
+      "android/support/v4/graphics/TypefaceCompat$TypefaceCompatImpl": "androidx/graphics/TypefaceCompat$TypefaceCompatImpl",
+      "android/support/v7/widget/ContentFrameLayout": "androidx/widget/ContentFrameLayout",
+      "android/support/v4/app/ActionBarDrawerToggle$SetIndicatorInfo": "androidx/app/ActionBarDrawerToggle$SetIndicatorInfo",
+      "android/support/v4/util/TimeUtils": "androidx/util/TimeUtils",
+      "android/support/v7/widget/ActionBarBackgroundDrawableV21": "androidx/widget/ActionBarBackgroundDrawableV21",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$SkipNextAction": "androidx/leanback/widget/PlaybackControlsRow$SkipNextAction",
+      "android/support/design/internal/ParcelableSparseArray": "androidx/design/internal/ParcelableSparseArray",
+      "android/support/media/tv/Channel$Builder": "androidx/media/tv/Channel$Builder",
+      "android/support/v7/widget/AppCompatCompoundButtonHelper": "androidx/widget/AppCompatCompoundButtonHelper",
+      "android/support/v4/media/MediaBrowserCompatApi23$ItemCallback": "androidx/media/MediaBrowserCompatApi23$ItemCallback",
+      "android/support/v4/app/ActionBarDrawerToggle$Delegate": "androidx/app/ActionBarDrawerToggle$Delegate",
+      "android/support/graphics/drawable/AnimationUtilsCompat": "androidx/graphics/drawable/AnimationUtilsCompat",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$ShuffleAction": "androidx/leanback/widget/PlaybackControlsRow$ShuffleAction",
+      "android/support/v4/app/JobIntentService$JobServiceEngineImpl$WrapperWorkItem": "androidx/app/JobIntentService$JobServiceEngineImpl$WrapperWorkItem",
+      "android/support/v7/media/SystemMediaRouteProvider$SyncCallback": "androidx/media/SystemMediaRouteProvider$SyncCallback",
+      "android/support/v7/util/AsyncListUtil$ViewCallback": "androidx/util/AsyncListUtil$ViewCallback",
+      "android/support/v4/view/ViewPager$OnAdapterChangeListener": "androidx/view/ViewPager$OnAdapterChangeListener",
+      "android/support/v7/media/RegisteredMediaRouteProviderWatcher": "androidx/media/RegisteredMediaRouteProviderWatcher",
+      "android/support/transition/Fade$FadeAnimatorListener": "androidx/transition/Fade$FadeAnimatorListener",
+      "android/support/v4/content/res/FontResourcesParserCompat$FetchStrategy": "androidx/content/res/FontResourcesParserCompat$FetchStrategy",
+      "android/support/v17/leanback/graphics/FitWidthBitmapDrawable": "androidx/leanback/graphics/FitWidthBitmapDrawable",
+      "android/support/v7/widget/CardViewDelegate": "androidx/widget/CardViewDelegate",
+      "android/support/v4/media/MediaBrowserCompat$ItemCallback": "androidx/media/MediaBrowserCompat$ItemCallback",
+      "android/support/design/widget/BottomSheetDialog": "androidx/design/widget/BottomSheetDialog",
+      "android/support/v17/leanback/system/Settings$Customizations": "androidx/leanback/system/Settings$Customizations",
+      "android/support/design/widget/FloatingActionButtonImpl$InternalVisibilityChangedListener": "androidx/design/widget/FloatingActionButtonImpl$InternalVisibilityChangedListener",
+      "android/support/v7/media/RemotePlaybackClient$SessionActionCallback": "androidx/media/RemotePlaybackClient$SessionActionCallback",
+      "android/support/wear/ambient/AmbientDelegate$AmbientCallback": "androidx/wear/ambient/AmbientDelegate$AmbientCallback",
+      "android/support/v4/widget/FocusStrategy$BoundsAdapter": "androidx/widget/FocusStrategy$BoundsAdapter",
+      "android/support/v17/leanback/widget/DividerPresenter": "androidx/leanback/widget/DividerPresenter",
+      "android/support/text/emoji/EmojiProcessor$GlyphChecker": "androidx/text/emoji/EmojiProcessor$GlyphChecker",
+      "android/support/v7/preference/PreferenceFragmentCompat": "androidx/preference/PreferenceFragmentCompat",
+      "android/support/v7/widget/TooltipPopup": "androidx/widget/TooltipPopup",
+      "android/support/v4/view/accessibility/AccessibilityNodeProviderCompat": "androidx/view/accessibility/AccessibilityNodeProviderCompat",
+      "android/support/v4/media/MediaBrowserCompat$SearchCallback": "androidx/media/MediaBrowserCompat$SearchCallback",
+      "android/support/v4/media/session/IMediaControllerCallback": "androidx/media/session/IMediaControllerCallback",
+      "android/support/compat/R$styleable": "androidx/compat/R$styleable",
+      "android/support/v7/view/menu/MenuBuilder$ItemInvoker": "androidx/view/menu/MenuBuilder$ItemInvoker",
+      "android/support/v17/leanback/widget/MultiActionsProvider$MultiAction": "androidx/leanback/widget/MultiActionsProvider$MultiAction",
+      "android/support/v7/gridlayout/R$dimen": "androidx/gridlayout/R$dimen",
+      "android/support/v4/app/FragmentManagerImpl$FragmentTag": "androidx/app/FragmentManagerImpl$FragmentTag",
+      "android/support/v4/media/MediaDescriptionCompat$Builder": "androidx/media/MediaDescriptionCompat$Builder",
+      "android/support/v17/leanback/widget/PlaybackControlsPresenter$BoundData": "androidx/leanback/widget/PlaybackControlsPresenter$BoundData",
+      "android/support/v7/app/MediaRouteChooserDialog$RouteComparator": "androidx/app/MediaRouteChooserDialog$RouteComparator",
+      "android/support/v7/app/ActionBar": "androidx/app/ActionBar",
+      "android/support/design/widget/HeaderBehavior$FlingRunnable": "androidx/design/widget/HeaderBehavior$FlingRunnable",
+      "android/support/v7/widget/GapWorker$Task": "androidx/widget/GapWorker$Task",
+      "android/support/v4/view/AsyncLayoutInflater$InflateThread": "androidx/view/AsyncLayoutInflater$InflateThread",
+      "android/support/v17/leanback/R$string": "androidx/leanback/R$string",
+      "android/support/v4/content/LocalBroadcastManager$BroadcastRecord": "androidx/content/LocalBroadcastManager$BroadcastRecord",
+      "android/support/wear/widget/drawer/AbsListViewFlingWatcher": "androidx/wear/widget/drawer/AbsListViewFlingWatcher",
+      "android/support/v17/leanback/widget/ActionPresenterSelector$ActionViewHolder": "androidx/leanback/widget/ActionPresenterSelector$ActionViewHolder",
+      "android/support/v17/leanback/widget/ImageCardView": "androidx/leanback/widget/ImageCardView",
+      "android/support/v4/app/AlarmManagerCompat": "androidx/app/AlarmManagerCompat",
+      "android/support/v7/app/MediaRouterThemeHelper$ControllerColorType": "androidx/app/MediaRouterThemeHelper$ControllerColorType",
+      "android/support/v4/widget/SlidingPaneLayout$SlidingPanelLayoutImplBase": "androidx/widget/SlidingPaneLayout$SlidingPanelLayoutImplBase",
+      "android/support/v4/view/WindowCompat": "androidx/view/WindowCompat",
+      "android/support/v7/widget/ThemedSpinnerAdapter$Helper": "androidx/widget/ThemedSpinnerAdapter$Helper",
+      "android/support/v4/media/session/MediaControllerCompat$Callback$StubCompat": "androidx/media/session/MediaControllerCompat$Callback$StubCompat",
+      "android/support/v4/widget/NestedScrollView$AccessibilityDelegate": "androidx/widget/NestedScrollView$AccessibilityDelegate",
+      "android/support/annotation/MainThread": "androidx/annotation/MainThread",
+      "android/support/v17/leanback/app/RowsFragment$RowViewHolderExtra": "androidx/leanback/app/RowsFragment$RowViewHolderExtra",
+      "android/support/v17/leanback/widget/MultiActionsProvider": "androidx/leanback/widget/MultiActionsProvider",
+      "android/support/v7/mediarouter/R$id": "androidx/mediarouter/R$id",
+      "android/support/v4/view/ViewCompat$NestedScrollType": "androidx/view/ViewCompat$NestedScrollType",
+      "android/support/v4/text/TextDirectionHeuristicsCompat$TextDirectionAlgorithm": "androidx/text/TextDirectionHeuristicsCompat$TextDirectionAlgorithm",
+      "android/support/v4/media/session/MediaControllerCompatApi21$CallbackProxy": "androidx/media/session/MediaControllerCompatApi21$CallbackProxy",
+      "android/support/customtabs/TrustedWebUtils": "androidx/browser/customtabs/TrustedWebUtils",
+      "android/support/v4/text/BidiFormatter$Builder": "androidx/text/BidiFormatter$Builder",
+      "android/support/design/widget/TabLayout$TabView": "androidx/design/widget/TabLayout$TabView",
+      "android/support/wear/internal/widget/drawer/SinglePageUi$OnSelectedClickHandler": "androidx/wear/internal/widget/drawer/SinglePageUi$OnSelectedClickHandler",
+      "android/support/v17/leanback/widget/BrowseFrameLayout": "androidx/leanback/widget/BrowseFrameLayout",
+      "android/support/v4/widget/ImageViewCompat$BaseViewCompatImpl": "androidx/widget/ImageViewCompat$BaseViewCompatImpl",
+      "android/support/customtabs/PostMessageService": "androidx/browser/customtabs/PostMessageService",
+      "android/support/annotation/FontRes": "androidx/annotation/FontRes",
+      "android/support/transition/ViewGroupUtilsApi14": "androidx/transition/ViewGroupUtilsApi14",
+      "android/support/v4/view/ViewParentCompat": "androidx/view/ViewParentCompat",
+      "android/support/v17/leanback/widget/SectionRow": "androidx/leanback/widget/SectionRow",
+      "android/support/v7/preference/DropDownPreference": "androidx/preference/DropDownPreference",
+      "android/support/v4/widget/DrawerLayout$SavedState": "androidx/widget/DrawerLayout$SavedState",
+      "android/support/transition/AnimatorUtilsApi14": "androidx/transition/AnimatorUtilsApi14",
+      "android/support/transition/AnimatorUtilsApi19": "androidx/transition/AnimatorUtilsApi19",
+      "android/support/constraint/solver/widgets/ConstraintAnchor$Strength": "androidx/constraint/solver/widgets/ConstraintAnchor$Strength",
+      "android/support/v7/widget/RecyclerView$SmoothScroller": "androidx/widget/RecyclerView$SmoothScroller",
+      "android/support/design/R$drawable": "androidx/design/R$drawable",
+      "android/support/v7/util/BatchingListUpdateCallback": "androidx/util/BatchingListUpdateCallback",
+      "android/support/v17/leanback/app/BrandedSupportFragment": "androidx/leanback/app/BrandedSupportFragment",
+      "android/support/transition/ViewGroupUtilsApi18": "androidx/transition/ViewGroupUtilsApi18",
+      "android/support/v17/leanback/app/BrowseFragment$FragmentHost": "androidx/leanback/app/BrowseFragment$FragmentHost",
+      "android/support/v17/leanback/widget/MediaNowPlayingView": "androidx/leanback/widget/MediaNowPlayingView",
+      "android/support/v4/app/ActivityCompat$PermissionCompatDelegate": "androidx/app/ActivityCompat$PermissionCompatDelegate",
+      "android/support/v7/app/ActionBar$TabListener": "androidx/app/ActionBar$TabListener",
+      "android/support/design/widget/CoordinatorLayout$HierarchyChangeListener": "androidx/design/widget/CoordinatorLayout$HierarchyChangeListener",
+      "android/support/v7/app/AppCompatDelegateImplV9": "androidx/app/AppCompatDelegateImplV9",
+      "android/support/v4/app/LoaderManager$LoaderCallbacks": "androidx/app/LoaderManager$LoaderCallbacks",
+      "android/support/v4/view/MenuItemCompat$MenuItemCompatBaseImpl": "androidx/view/MenuItemCompat$MenuItemCompatBaseImpl",
+      "android/support/design/widget/BaseTransientBottomBar$SnackbarBaseLayout": "androidx/design/widget/BaseTransientBottomBar$SnackbarBaseLayout",
+      "android/support/text/emoji/EmojiCompat$CompatInternal19": "androidx/text/emoji/EmojiCompat$CompatInternal19",
+      "android/support/wear/R$fraction": "androidx/wear/R$fraction",
+      "android/support/v7/widget/DividerItemDecoration": "androidx/widget/DividerItemDecoration",
+      "android/support/v4/view/MenuItemCompat$OnActionExpandListener": "androidx/view/MenuItemCompat$OnActionExpandListener",
+      "android/support/v4/widget/SlidingPaneLayout$SlidingPanelLayoutImpl": "androidx/widget/SlidingPaneLayout$SlidingPanelLayoutImpl",
+      "android/support/v4/graphics/PathParser$ExtractFloatResult": "androidx/graphics/PathParser$ExtractFloatResult",
+      "android/support/graphics/drawable/ArgbEvaluator": "androidx/graphics/drawable/ArgbEvaluator",
+      "android/support/v17/leanback/widget/ShadowHelper": "androidx/leanback/widget/ShadowHelper",
+      "android/support/design/widget/FloatingActionButtonImpl$ElevateToTranslationZAnimation": "androidx/design/widget/FloatingActionButtonImpl$ElevateToTranslationZAnimation",
+      "android/support/v4/app/NotificationManagerCompat$SideChannelManager": "androidx/app/NotificationManagerCompat$SideChannelManager",
+      "android/support/v17/leanback/widget/PlaybackRowPresenter$ViewHolder": "androidx/leanback/widget/PlaybackRowPresenter$ViewHolder",
+      "android/support/v17/leanback/media/PlaybackBaseControlGlue": "androidx/leanback/media/PlaybackBaseControlGlue",
+      "android/support/v7/app/MediaRouteButton": "androidx/app/MediaRouteButton",
+      "android/support/v4/view/PagerTabStrip": "androidx/widget/PagerTabStrip",
+      "android/support/v7/widget/ActivityChooserView$InnerLayout": "androidx/widget/ActivityChooserView$InnerLayout",
+      "android/support/v17/leanback/widget/TitleHelper": "androidx/leanback/widget/TitleHelper",
+      "android/support/v7/media/RegisteredMediaRouteProvider": "androidx/media/RegisteredMediaRouteProvider",
+      "android/support/v4/print/PrintHelper$PrintHelperStub": "androidx/print/PrintHelper$PrintHelperStub",
+      "android/support/v7/media/MediaRouter": "androidx/media/MediaRouter",
+      "android/support/v4/widget/ViewDragHelper": "androidx/widget/ViewDragHelper",
+      "android/support/v4/media/MediaBrowserCompat$MediaItem": "androidx/media/MediaBrowserCompat$MediaItem",
+      "android/support/app/recommendation/ContentRecommendation$ContentMaturity": "androidx/app/recommendation/ContentRecommendation$ContentMaturity",
+      "android/support/v7/widget/SwitchCompat": "androidx/widget/SwitchCompat",
+      "android/support/v7/media/MediaSessionStatus": "androidx/media/MediaSessionStatus",
+      "android/support/v17/leanback/widget/picker/Picker$PickerScrollArrayAdapter": "androidx/leanback/widget/picker/Picker$PickerScrollArrayAdapter",
+      "android/support/v4/util/Pools": "androidx/util/Pools",
+      "android/support/v4/widget/SlidingPaneLayout$SavedState": "androidx/widget/SlidingPaneLayout$SavedState",
+      "android/support/v7/widget/ViewStubCompat$OnInflateListener": "androidx/widget/ViewStubCompat$OnInflateListener",
+      "android/support/design/widget/ViewOffsetHelper": "androidx/design/widget/ViewOffsetHelper",
+      "android/support/design/widget/FloatingActionButton$OnVisibilityChangedListener": "androidx/design/widget/FloatingActionButton$OnVisibilityChangedListener",
+      "android/support/compat/BuildConfig": "androidx/compat/BuildConfig",
+      "android/support/v4/app/FragmentManagerImpl$PopBackStackState": "androidx/app/FragmentManagerImpl$PopBackStackState",
+      "android/support/v7/media/MediaRouterJellybeanMr1$ActiveScanWorkaround": "androidx/media/MediaRouterJellybeanMr1$ActiveScanWorkaround",
+      "android/support/v17/leanback/widget/TitleViewAdapter": "androidx/leanback/widget/TitleViewAdapter",
+      "android/support/design/widget/TabLayout": "androidx/design/widget/TabLayout",
+      "android/support/v4/view/MenuItemCompat$MenuVersionImpl": "androidx/view/MenuItemCompat$MenuVersionImpl",
+      "android/support/v7/app/MediaRouteButton$MediaRouterCallback": "androidx/app/MediaRouteButton$MediaRouterCallback",
+      "android/support/v4/media/MediaDescriptionCompatApi21$Builder": "androidx/media/MediaDescriptionCompatApi21$Builder",
+      "android/support/design/widget/TabLayout$TabGravity": "androidx/design/widget/TabLayout$TabGravity",
+      "android/support/v17/leanback/widget/AbstractDetailsDescriptionPresenter": "androidx/leanback/widget/AbstractDetailsDescriptionPresenter",
+      "android/support/v7/widget/RecyclerView$RecycledViewPool$ScrapData": "androidx/widget/RecyclerView$RecycledViewPool$ScrapData",
+      "android/support/v17/leanback/media/MediaControllerAdapter": "androidx/leanback/media/MediaControllerAdapter",
+      "android/support/wear/internal/widget/drawer/MultiPagePresenter$Ui": "androidx/wear/internal/widget/drawer/MultiPagePresenter$Ui",
+      "android/support/v7/app/ToolbarActionBar": "androidx/app/ToolbarActionBar",
+      "android/support/v7/widget/ViewBoundsCheck$Callback": "androidx/widget/ViewBoundsCheck$Callback",
+      "android/support/text/emoji/widget/EmojiExtractEditText": "androidx/text/emoji/widget/EmojiExtractEditText",
+      "android/support/v4/app/FrameMetricsAggregator": "androidx/app/FrameMetricsAggregator",
+      "android/support/constraint/R": "androidx/constraint/R",
+      "android/support/v7/mediarouter/R$string": "androidx/mediarouter/R$string",
+      "android/support/text/emoji/bundled/BundledEmojiCompatConfig$InitRunnable": "androidx/text/emoji/bundled/BundledEmojiCompatConfig$InitRunnable",
+      "android/support/v17/leanback/transition/TransitionHelper$TransitionHelperApi21Impl": "androidx/leanback/transition/TransitionHelper$TransitionHelperApi21Impl",
+      "android/support/v7/widget/LinearLayoutManager": "androidx/widget/LinearLayoutManager",
+      "android/support/graphics/drawable/VectorDrawableCompat$VGroup": "androidx/graphics/drawable/VectorDrawableCompat$VGroup",
+      "android/support/v17/leanback/app/BackgroundManager": "androidx/leanback/app/BackgroundManager",
+      "android/support/v17/leanback/app/VideoFragmentGlueHost": "androidx/leanback/app/VideoFragmentGlueHost",
+      "android/support/v4/net/ConnectivityManagerCompat": "androidx/net/ConnectivityManagerCompat",
+      "android/support/annotation/NonNull": "androidx/annotation/NonNull",
+      "android/support/transition/ImageViewUtilsApi21": "androidx/transition/ImageViewUtilsApi21",
+      "android/support/v7/widget/Toolbar$SavedState": "androidx/widget/Toolbar$SavedState",
+      "android/support/v7/util/ThreadUtil$BackgroundCallback": "androidx/util/ThreadUtil$BackgroundCallback",
+      "android/support/v17/leanback/app/BaseFragment": "androidx/leanback/app/BaseFragment",
+      "android/support/v4/view/AccessibilityDelegateCompat$AccessibilityDelegateApi16Impl": "androidx/view/AccessibilityDelegateCompat$AccessibilityDelegateApi16Impl",
+      "android/support/v7/media/MediaRouterJellybeanMr2$UserRouteInfo": "androidx/media/MediaRouterJellybeanMr2$UserRouteInfo",
+      "android/support/v7/widget/DefaultItemAnimator$ChangeInfo": "androidx/widget/DefaultItemAnimator$ChangeInfo",
+      "android/support/v4/hardware/display/DisplayManagerCompat$DisplayManagerCompatApi14Impl": "androidx/hardware/display/DisplayManagerCompat$DisplayManagerCompatApi14Impl",
+      "android/support/v7/cardview/R": "androidx/cardview/R",
+      "android/support/v4/app/NotificationCompat": "androidx/app/NotificationCompat",
+      "android/support/v17/leanback/transition/TransitionHelper$TransitionHelperKitkatImpl": "androidx/leanback/transition/TransitionHelper$TransitionHelperKitkatImpl",
+      "android/support/v4/widget/CircularProgressDrawable$Ring": "androidx/widget/CircularProgressDrawable$Ring",
+      "android/support/v17/leanback/app/BrowseSupportFragment$ListRowFragmentFactory": "androidx/leanback/app/BrowseSupportFragment$ListRowFragmentFactory",
+      "android/support/v7/widget/LinearLayoutManager$AnchorInfo": "androidx/widget/LinearLayoutManager$AnchorInfo",
+      "android/support/v4/media/MediaBrowserCompatApi26$SubscriptionCallbackProxy": "androidx/media/MediaBrowserCompatApi26$SubscriptionCallbackProxy",
+      "android/support/v4/view/ViewCompat$ViewCompatApi19Impl": "androidx/view/ViewCompat$ViewCompatApi19Impl",
+      "android/support/v4/view/accessibility/AccessibilityNodeInfoCompat": "androidx/view/accessibility/AccessibilityNodeInfoCompat",
+      "android/support/v4/os/IResultReceiver$Stub$Proxy": "androidx/os/IResultReceiver$Stub$Proxy",
+      "android/support/v17/leanback/widget/PlaybackTransportRowPresenter$BoundData": "androidx/leanback/widget/PlaybackTransportRowPresenter$BoundData",
+      "android/support/transition/TransitionSet": "androidx/transition/TransitionSet",
+      "android/support/v7/graphics/drawable/DrawableWrapper": "androidx/graphics/drawable/DrawableWrapper",
+      "android/support/v7/media/MediaRouterJellybean$UserRouteInfo": "androidx/media/MediaRouterJellybean$UserRouteInfo",
+      "android/support/v7/app/MediaRouteActionProvider": "androidx/app/MediaRouteActionProvider",
+      "android/support/compat/R$layout": "androidx/compat/R$layout",
+      "android/support/v17/leanback/widget/ViewHolderTask": "androidx/leanback/widget/ViewHolderTask",
+      "android/support/v7/graphics/ColorCutQuantizer$Vbox": "androidx/graphics/ColorCutQuantizer$Vbox",
+      "android/support/text/emoji/EmojiProcessor$CodepointIndexFinder": "androidx/text/emoji/EmojiProcessor$CodepointIndexFinder",
+      "android/support/v4/content/CursorLoader": "androidx/content/CursorLoader",
+      "android/support/text/emoji/widget/EditTextAttributeHelper": "androidx/text/emoji/widget/EditTextAttributeHelper",
+      "android/support/wear/internal/widget/ResourcesUtil": "androidx/wear/internal/widget/ResourcesUtil",
+      "android/support/wear/R$array": "androidx/wear/R$array",
+      "android/support/v7/widget/RecyclerView$RecycledViewPool": "androidx/widget/RecyclerView$RecycledViewPool",
+      "android/support/transition/ImageViewUtilsApi14": "androidx/transition/ImageViewUtilsApi14",
+      "android/support/v7/gridlayout/R": "androidx/gridlayout/R",
+      "android/support/text/emoji/FontRequestEmojiCompatConfig": "androidx/text/emoji/FontRequestEmojiCompatConfig",
+      "android/support/text/emoji/EmojiMetadata": "androidx/text/emoji/EmojiMetadata",
+      "android/support/v4/widget/SlidingPaneLayout$DisableLayerRunnable": "androidx/widget/SlidingPaneLayout$DisableLayerRunnable",
+      "android/support/v4/util/Pools$SynchronizedPool": "androidx/util/Pools$SynchronizedPool",
+      "android/support/v17/leanback/graphics/BoundsRule$ValueRule": "androidx/leanback/graphics/BoundsRule$ValueRule",
+      "android/support/v7/widget/ActivityChooserView$ActivityChooserViewAdapter": "androidx/widget/ActivityChooserView$ActivityChooserViewAdapter",
+      "android/support/v7/mediarouter/R": "androidx/mediarouter/R",
+      "android/support/text/emoji/FontRequestEmojiCompatConfig$ExponentialBackoffRetryPolicy": "androidx/text/emoji/FontRequestEmojiCompatConfig$ExponentialBackoffRetryPolicy",
+      "android/support/v7/widget/AppCompatImageView": "androidx/widget/AppCompatImageView",
+      "android/support/v17/preference/R$layout": "androidx/leanback/preference/R$layout",
+      "android/support/v4/provider/FontsContractCompat$FontFamilyResult$FontResultStatus": "androidx/provider/FontsContractCompat$FontFamilyResult$FontResultStatus",
+      "android/support/graphics/drawable/VectorDrawableCompat$VPathRenderer": "androidx/graphics/drawable/VectorDrawableCompat$VPathRenderer",
+      "android/support/v4/app/JobIntentService$CompatWorkEnqueuer": "androidx/app/JobIntentService$CompatWorkEnqueuer",
+      "android/support/v17/leanback/app/BrowseSupportFragment$SetSelectionRunnable": "androidx/leanback/app/BrowseSupportFragment$SetSelectionRunnable",
+      "android/support/v4/media/MediaDescriptionCompatApi23$Builder": "androidx/media/MediaDescriptionCompatApi23$Builder",
+      "android/support/v17/leanback/widget/DetailsOverviewRowPresenter": "androidx/leanback/widget/DetailsOverviewRowPresenter",
+      "android/support/text/emoji/FontRequestEmojiCompatConfig$RetryPolicy": "androidx/text/emoji/FontRequestEmojiCompatConfig$RetryPolicy",
+      "android/support/v7/widget/ScrollingTabContainerView$TabView": "androidx/widget/ScrollingTabContainerView$TabView",
+      "android/support/annotation/DrawableRes": "androidx/annotation/DrawableRes",
+      "android/support/v4/view/ViewPager$LayoutParams": "androidx/view/ViewPager$LayoutParams",
+      "android/support/v17/leanback/widget/MediaItemActionPresenter$ViewHolder": "androidx/leanback/widget/MediaItemActionPresenter$ViewHolder",
+      "android/support/v7/app/AlertDialog$Builder": "androidx/app/AlertDialog$Builder",
+      "android/support/v4/util/Preconditions": "androidx/util/Preconditions",
+      "android/support/v4/app/FragmentTabHost": "androidx/app/FragmentTabHost",
+      "android/support/v17/leanback/widget/BaseGridView$OnTouchInterceptListener": "androidx/leanback/widget/BaseGridView$OnTouchInterceptListener",
+      "android/support/text/emoji/EmojiCompat$ListenerDispatcher": "androidx/text/emoji/EmojiCompat$ListenerDispatcher",
+      "android/support/wear/widget/drawer/WearableActionDrawerMenu$WearableActionDrawerMenuListener": "androidx/wear/widget/drawer/WearableActionDrawerMenu$WearableActionDrawerMenuListener",
+      "android/support/v4/app/INotificationSideChannel$Stub$Proxy": "androidx/app/INotificationSideChannel$Stub$Proxy",
+      "android/support/media/tv/TvContractCompat$Programs$Genres$Genre": "androidx/media/tv/TvContractCompat$Programs$Genres$Genre",
+      "android/support/text/emoji/widget/EmojiTextWatcher$InitCallbackImpl": "androidx/text/emoji/widget/EmojiTextWatcher$InitCallbackImpl",
+      "android/support/v17/leanback/widget/ParallaxTarget$DirectPropertyTarget": "androidx/leanback/widget/ParallaxTarget$DirectPropertyTarget",
+      "android/support/v7/app/ToolbarActionBar$ToolbarCallbackWrapper": "androidx/app/ToolbarActionBar$ToolbarCallbackWrapper",
+      "android/support/v4/widget/CompoundButtonCompat": "androidx/widget/CompoundButtonCompat",
+      "android/support/v4/content/ContentResolverCompat": "androidx/content/ContentResolverCompat",
+      "android/support/v17/leanback/widget/NonOverlappingRelativeLayout": "androidx/leanback/widget/NonOverlappingRelativeLayout",
+      "android/support/text/emoji/EmojiCompat$MetadataRepoLoaderCallback": "androidx/text/emoji/EmojiCompat$MetadataRepoLoaderCallback",
+      "android/support/v4/app/FragmentStatePagerAdapter": "androidx/app/FragmentStatePagerAdapter",
+      "android/support/v17/leanback/app/PlaybackSupportFragment": "androidx/leanback/app/PlaybackSupportFragment",
+      "android/support/v7/app/OverlayListView": "androidx/app/OverlayListView",
+      "android/support/v7/mediarouter/R$styleable": "androidx/mediarouter/R$styleable",
+      "android/support/v7/widget/DrawableUtils": "androidx/widget/DrawableUtils",
+      "android/support/v4/content/ModernAsyncTask$AsyncTaskResult": "androidx/content/ModernAsyncTask$AsyncTaskResult",
+      "android/support/constraint/BuildConfig": "androidx/constraint/BuildConfig",
+      "android/support/v4/app/SharedElementCallback": "androidx/app/SharedElementCallback",
+      "android/support/v7/recyclerview/BuildConfig": "androidx/recyclerview/BuildConfig",
+      "android/support/text/emoji/widget/EmojiKeyListener": "androidx/text/emoji/widget/EmojiKeyListener",
+      "android/support/v17/leanback/transition/FadeAndShortSlide$CalculateSlide": "androidx/leanback/transition/FadeAndShortSlide$CalculateSlide",
+      "android/support/v7/widget/ActionMenuPresenter$ActionButtonSubmenu": "androidx/widget/ActionMenuPresenter$ActionButtonSubmenu",
+      "android/support/v4/media/MediaMetadataCompat$Builder": "androidx/media/MediaMetadataCompat$Builder",
+      "android/support/design/widget/BottomSheetBehavior$SavedState": "androidx/design/widget/BottomSheetBehavior$SavedState",
+      "android/support/v4/media/session/MediaControllerCompatApi21$PlaybackInfo": "androidx/media/session/MediaControllerCompatApi21$PlaybackInfo",
+      "android/support/v7/widget/ActionMenuPresenter$PopupPresenterCallback": "androidx/widget/ActionMenuPresenter$PopupPresenterCallback",
+      "android/support/media/ExifInterface$ByteOrderedDataOutputStream": "androidx/media/ExifInterface$ByteOrderedDataOutputStream",
+      "android/support/v17/leanback/widget/Grid$Location": "androidx/leanback/widget/Grid$Location",
+      "android/support/v7/media/MediaRouterJellybeanMr1$CallbackProxy": "androidx/media/MediaRouterJellybeanMr1$CallbackProxy",
+      "android/support/v17/leanback/R$raw": "androidx/leanback/R$raw",
+      "android/support/media/tv/TvContractCompat$PreviewProgramColumns": "androidx/media/tv/TvContractCompat$PreviewProgramColumns",
+      "android/support/v17/leanback/widget/SeekBar$AccessibilitySeekListener": "androidx/leanback/widget/SeekBar$AccessibilitySeekListener",
+      "android/support/v4/print/PrintHelper$PrintHelperVersionImpl": "androidx/print/PrintHelper$PrintHelperVersionImpl",
+      "android/support/v17/leanback/app/ProgressBarManager": "androidx/leanback/app/ProgressBarManager",
+      "android/support/v7/app/MediaRouteChooserDialogFragment": "androidx/app/MediaRouteChooserDialogFragment",
+      "android/support/v4/content/FileProvider$SimplePathStrategy": "androidx/content/FileProvider$SimplePathStrategy",
+      "android/support/v17/leanback/app/BackgroundManager$BackgroundContinuityService": "androidx/leanback/app/BackgroundManager$BackgroundContinuityService",
+      "android/support/v4/media/session/IMediaSession$Stub": "androidx/media/session/IMediaSession$Stub",
+      "android/support/v4/widget/TintableImageSourceView": "androidx/widget/TintableImageSourceView",
+      "android/support/transition/ViewOverlayApi14$OverlayViewGroup": "androidx/transition/ViewOverlayApi14$OverlayViewGroup",
+      "android/support/design/widget/FloatingActionButtonImpl": "androidx/design/widget/FloatingActionButtonImpl",
+      "android/support/text/emoji/widget/EmojiEditableFactory": "androidx/text/emoji/widget/EmojiEditableFactory",
+      "android/support/transition/Visibility$Mode": "androidx/transition/Visibility$Mode",
+      "android/support/v17/leanback/widget/PagingIndicator$Dot": "androidx/leanback/widget/PagingIndicator$Dot",
+      "android/support/design/internal/NavigationSubMenu": "androidx/design/internal/NavigationSubMenu",
+      "android/support/v17/leanback/widget/AbstractDetailsDescriptionPresenter$ViewHolder": "androidx/leanback/widget/AbstractDetailsDescriptionPresenter$ViewHolder",
+      "android/support/v4/media/AudioAttributesCompat$AudioManagerHidden": "androidx/media/AudioAttributesCompat$AudioManagerHidden",
+      "android/support/v7/preference/CheckBoxPreference": "androidx/preference/CheckBoxPreference",
+      "android/support/design/widget/FloatingActionButtonLollipop$AlwaysStatefulGradientDrawable": "androidx/design/widget/FloatingActionButtonLollipop$AlwaysStatefulGradientDrawable",
+      "android/support/v4/media/RatingCompat$StarStyle": "androidx/media/RatingCompat$StarStyle",
+      "android/support/v7/preference/PreferenceGroup$PreferencePositionCallback": "androidx/preference/PreferenceGroup$PreferencePositionCallback",
+      "android/support/design/widget/BottomNavigationView": "androidx/design/widget/BottomNavigationView",
+      "android/support/v17/leanback/media/MediaPlayerAdapter": "androidx/leanback/media/MediaPlayerAdapter",
+      "android/support/v7/widget/SuggestionsAdapter$ChildViewCache": "androidx/widget/SuggestionsAdapter$ChildViewCache",
+      "android/support/v4/media/session/MediaSessionCompat$Callback$StubApi21": "androidx/media/session/MediaSessionCompat$Callback$StubApi21",
+      "android/support/v7/widget/ListPopupWindow$PopupScrollListener": "androidx/widget/ListPopupWindow$PopupScrollListener",
+      "android/support/v4/app/NotificationCompat$MessagingStyle": "androidx/app/NotificationCompat$MessagingStyle",
+      "android/support/wear/widget/SwipeDismissLayout$OnSwipeProgressChangedListener": "androidx/wear/widget/SwipeDismissLayout$OnSwipeProgressChangedListener",
+      "android/support/v7/media/RemotePlaybackClient$OnMessageReceivedListener": "androidx/media/RemotePlaybackClient$OnMessageReceivedListener",
+      "android/support/v7/util/MessageThreadUtil$SyncQueueItem": "androidx/util/MessageThreadUtil$SyncQueueItem",
+      "android/support/v4/view/MarginLayoutParamsCompat": "androidx/view/MarginLayoutParamsCompat",
+      "android/support/v4/media/session/MediaSessionCompat$Callback$StubApi24": "androidx/media/session/MediaSessionCompat$Callback$StubApi24",
+      "android/support/v17/leanback/widget/CheckableImageView": "androidx/leanback/widget/CheckableImageView",
+      "android/support/v4/media/session/MediaSessionCompat$Callback$StubApi23": "androidx/media/session/MediaSessionCompat$Callback$StubApi23",
+      "android/support/v7/widget/ThemeUtils": "androidx/widget/ThemeUtils",
+      "android/support/v7/preference/Preference$BaseSavedState": "androidx/preference/Preference$BaseSavedState",
+      "android/support/v4/widget/DrawerLayout$AccessibilityDelegate": "androidx/widget/DrawerLayout$AccessibilityDelegate",
+      "android/support/v4/app/ActivityOptionsCompat": "androidx/app/ActivityOptionsCompat",
+      "android/support/v4/media/session/PlaybackStateCompat$State": "androidx/media/session/PlaybackStateCompat$State",
+      "android/support/v7/widget/RecyclerView$ItemAnimator$ItemHolderInfo": "androidx/widget/RecyclerView$ItemAnimator$ItemHolderInfo",
+      "android/support/constraint/solver/widgets/ConstraintAnchor$Type": "androidx/constraint/solver/widgets/ConstraintAnchor$Type",
+      "android/support/v4/widget/TextViewCompat$TextViewCompatApi17Impl": "androidx/widget/TextViewCompat$TextViewCompatApi17Impl",
+      "android/support/v17/leanback/widget/ImeKeyMonitor": "androidx/leanback/widget/ImeKeyMonitor",
+      "android/support/v17/leanback/app/BrowseSupportFragment$MainFragmentRowsAdapter": "androidx/leanback/app/BrowseSupportFragment$MainFragmentRowsAdapter",
+      "android/support/v4/app/ActivityCompat": "androidx/app/ActivityCompat",
+      "android/support/v4/util/ObjectsCompat": "androidx/util/ObjectsCompat",
+      "android/support/v4/app/SupportActivity$ExtraData": "androidx/app/SupportActivity$ExtraData",
+      "android/support/v4/media/MediaBrowserProtocol": "androidx/media/MediaBrowserProtocol",
+      "android/support/design/widget/CollapsingTextHelper": "androidx/design/widget/CollapsingTextHelper",
+      "android/support/v14/preference/SwitchPreference$Listener": "androidx/preference/SwitchPreference$Listener",
+      "android/support/v7/preference/SwitchPreferenceCompat$Listener": "androidx/preference/SwitchPreferenceCompat$Listener",
+      "android/support/wear/internal/widget/drawer/SinglePageUi": "androidx/wear/internal/widget/drawer/SinglePageUi",
+      "android/support/v4/view/NestedScrollingChild2": "androidx/view/NestedScrollingChild2",
+      "android/support/customtabs/ICustomTabsService": "androidx/browser/customtabs/ICustomTabsService",
+      "android/support/recommendation/BuildConfig": "androidx/recommendation/BuildConfig",
+      "android/support/text/emoji/widget/EmojiAppCompatTextView": "androidx/text/emoji/widget/EmojiAppCompatTextView",
+      "android/support/v7/media/MediaRouterJellybean$RouteGroup": "androidx/media/MediaRouterJellybean$RouteGroup",
+      "android/support/v4/widget/DrawerLayout": "androidx/widget/DrawerLayout",
+      "android/support/v4/os/CancellationSignal$OnCancelListener": "androidx/os/CancellationSignal$OnCancelListener",
+      "android/support/v4/view/ViewCompat$ViewCompatApi17Impl": "androidx/view/ViewCompat$ViewCompatApi17Impl",
+      "android/support/v4/app/JobIntentService$CompatJobEngine": "androidx/app/JobIntentService$CompatJobEngine",
+      "android/support/v4/media/MediaBrowserCompat$CustomActionCallback": "androidx/media/MediaBrowserCompat$CustomActionCallback",
+      "android/support/v4/media/app/NotificationCompat$DecoratedMediaCustomViewStyle": "androidx/media/app/NotificationCompat$DecoratedMediaCustomViewStyle",
+      "android/support/v7/app/ActionBarDrawerToggle$Delegate": "androidx/app/ActionBarDrawerToggle$Delegate",
+      "android/support/v17/leanback/R$anim": "androidx/leanback/R$anim",
+      "android/support/v13/app/FragmentCompat$FragmentCompatBaseImpl": "androidx/app/FragmentCompat$FragmentCompatBaseImpl",
+      "android/support/v7/widget/SearchView$OnCloseListener": "androidx/widget/SearchView$OnCloseListener",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$OnPlaybackProgressCallback": "androidx/leanback/widget/PlaybackControlsRow$OnPlaybackProgressCallback",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$MoreActions": "androidx/leanback/widget/PlaybackControlsRow$MoreActions",
+      "android/support/v7/widget/ActivityChooserModel$ActivityResolveInfo": "androidx/widget/ActivityChooserModel$ActivityResolveInfo",
+      "android/support/annotation/AnimRes": "androidx/annotation/AnimRes",
+      "android/support/animation/Force": "androidx/animation/Force",
+      "android/support/v17/leanback/util/StateMachine$Event": "androidx/leanback/util/StateMachine$Event",
+      "android/support/v17/leanback/app/BrowseFragment$MainFragmentRowsAdapter": "androidx/leanback/app/BrowseFragment$MainFragmentRowsAdapter",
+      "android/support/v4/graphics/BitmapCompat": "androidx/graphics/BitmapCompat",
+      "android/support/v4/app/NotificationCompat$NotificationVisibility": "androidx/app/NotificationCompat$NotificationVisibility",
+      "android/support/v17/leanback/app/PlaybackFragment$SetSelectionRunnable": "androidx/leanback/app/PlaybackFragment$SetSelectionRunnable",
+      "android/support/v7/media/RegisteredMediaRouteProviderWatcher$Callback": "androidx/media/RegisteredMediaRouteProviderWatcher$Callback",
+      "android/support/v4/view/ViewCompat$FocusDirection": "androidx/view/ViewCompat$FocusDirection",
+      "android/support/design/widget/BottomSheetBehavior$SettleRunnable": "androidx/design/widget/BottomSheetBehavior$SettleRunnable",
+      "android/support/v17/leanback/widget/RoundedRectHelperApi21$RoundedRectOutlineProvider": "androidx/leanback/widget/RoundedRectHelperApi21$RoundedRectOutlineProvider",
+      "android/support/wear/widget/drawer/FlingWatcherFactory": "androidx/wear/widget/drawer/FlingWatcherFactory",
+      "android/support/v4/app/NotificationManagerCompat$Task": "androidx/app/NotificationManagerCompat$Task",
+      "android/support/animation/FlingAnimation$DragForce": "androidx/animation/FlingAnimation$DragForce",
+      "android/support/v7/widget/GridLayout$MutableInt": "androidx/widget/GridLayout$MutableInt",
+      "android/support/v7/util/DiffUtil": "androidx/util/DiffUtil",
+      "android/support/v4/app/FragmentManagerImpl$OpGenerator": "androidx/app/FragmentManagerImpl$OpGenerator",
+      "android/support/v4/view/ViewPager": "androidx/widget/ViewPager",
+      "android/support/v7/widget/TintTypedArray": "androidx/widget/TintTypedArray",
+      "android/support/text/emoji/widget/EmojiAppCompatEditText": "androidx/text/emoji/widget/EmojiAppCompatEditText",
+      "android/support/v4/view/ViewGroupCompat$ViewGroupCompatApi21Impl": "androidx/view/ViewGroupCompat$ViewGroupCompatApi21Impl",
+      "android/support/v4/media/MediaBrowserServiceCompat$ConnectionRecord": "androidx/media/MediaBrowserServiceCompat$ConnectionRecord",
+      "android/support/v7/view/menu/ActionMenuItemView": "androidx/view/menu/ActionMenuItemView",
+      "android/support/v4/app/NotificationCompatExtras": "androidx/app/NotificationCompatExtras",
+      "android/support/v7/view/menu/ListMenuPresenter": "androidx/view/menu/ListMenuPresenter",
+      "android/support/v14/preference/R": "androidx/preference/R",
+      "android/support/annotation/RequiresPermission": "androidx/annotation/RequiresPermission",
+      "android/support/v4/app/JobIntentService$GenericWorkItem": "androidx/app/JobIntentService$GenericWorkItem",
+      "android/support/v7/widget/RecyclerView$SmoothScroller$Action": "androidx/widget/RecyclerView$SmoothScroller$Action",
+      "android/support/design/R$attr": "androidx/design/R$attr",
+      "android/support/v4/content/SharedPreferencesCompat$EditorCompat$Helper": "androidx/content/SharedPreferencesCompat$EditorCompat$Helper",
+      "android/support/constraint/solver/widgets/ConstraintWidget": "androidx/constraint/solver/widgets/ConstraintWidget",
+      "android/support/fragment/BuildConfig": "androidx/fragment/BuildConfig",
+      "android/support/design/widget/NavigationView": "androidx/design/widget/NavigationView",
+      "android/support/v4/media/session/PlaybackStateCompatApi22": "androidx/media/session/PlaybackStateCompatApi22",
+      "android/support/v4/media/session/PlaybackStateCompatApi21": "androidx/media/session/PlaybackStateCompatApi21",
+      "android/support/media/instantvideo/preload/InstantVideoPreloadManager$InternalVideoPreloaderFactory": "androidx/media/instantvideo/preload/InstantVideoPreloadManager$InternalVideoPreloaderFactory",
+      "android/support/design/widget/BaseTransientBottomBar": "androidx/design/widget/BaseTransientBottomBar",
+      "android/support/wear/internal/widget/drawer/WearableNavigationDrawerPresenter": "androidx/wear/internal/widget/drawer/WearableNavigationDrawerPresenter",
+      "android/support/v4/media/session/MediaControllerCompat$Callback$StubApi21": "androidx/media/session/MediaControllerCompat$Callback$StubApi21",
+      "android/support/wear/widget/drawer/ScrollViewFlingWatcher": "androidx/wear/widget/drawer/ScrollViewFlingWatcher",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$FastForwardAction": "androidx/leanback/widget/PlaybackControlsRow$FastForwardAction",
+      "android/support/v7/widget/ActionBarOverlayLayout": "androidx/widget/ActionBarOverlayLayout",
+      "android/support/v4/app/FragmentTabHost$TabInfo": "androidx/app/FragmentTabHost$TabInfo",
+      "android/support/v7/widget/GridLayout$Bounds": "androidx/widget/GridLayout$Bounds",
+      "android/support/percent/BuildConfig": "androidx/BuildConfig",
+      "android/support/v7/app/ActionBar$OnMenuVisibilityListener": "androidx/app/ActionBar$OnMenuVisibilityListener",
+      "android/support/customtabs/PostMessageServiceConnection": "androidx/browser/customtabs/PostMessageServiceConnection",
+      "android/support/design/widget/TextInputLayout$TextInputAccessibilityDelegate": "androidx/design/widget/TextInputLayout$TextInputAccessibilityDelegate",
+      "android/support/v7/preference/Preference$OnPreferenceClickListener": "androidx/preference/Preference$OnPreferenceClickListener",
+      "android/support/v7/media/MediaRouterJellybean$RouteCategory": "androidx/media/MediaRouterJellybean$RouteCategory",
+      "android/support/v4/text/TextDirectionHeuristicCompat": "androidx/text/TextDirectionHeuristicCompat",
+      "android/support/v4/view/PointerIconCompat": "androidx/view/PointerIconCompat",
+      "android/support/design/internal/NavigationMenuPresenter$NavigationMenuAdapter": "androidx/design/internal/NavigationMenuPresenter$NavigationMenuAdapter",
+      "android/support/v17/leanback/widget/BaseCardView$AnimationBase": "androidx/leanback/widget/BaseCardView$AnimationBase",
+      "android/support/v7/widget/ScrollingTabContainerView": "androidx/widget/ScrollingTabContainerView",
+      "android/support/v4/text/util/LinkifyCompat": "androidx/text/util/LinkifyCompat",
+      "android/support/annotation/RequiresPermission$Read": "androidx/annotation/RequiresPermission$Read",
+      "android/support/customtabs/CustomTabsService$Result": "androidx/browser/customtabs/CustomTabsService$Result",
+      "android/support/v7/app/MediaRouteControllerDialog": "androidx/app/MediaRouteControllerDialog",
+      "android/support/v17/leanback/app/BrowseFragment": "androidx/leanback/app/BrowseFragment",
+      "android/support/v17/leanback/widget/OnChildViewHolderSelectedListener": "androidx/leanback/widget/OnChildViewHolderSelectedListener",
+      "android/support/design/internal/NavigationMenuPresenter$SubheaderViewHolder": "androidx/design/internal/NavigationMenuPresenter$SubheaderViewHolder",
+      "android/support/v7/mediarouter/R$attr": "androidx/mediarouter/R$attr",
+      "android/support/v7/widget/ActivityChooserView$Callbacks": "androidx/widget/ActivityChooserView$Callbacks",
+      "android/support/v4/widget/TextViewCompat$TextViewCompatApi16Impl": "androidx/widget/TextViewCompat$TextViewCompatApi16Impl",
+      "android/support/v4/content/AsyncTaskLoader$LoadTask": "androidx/content/AsyncTaskLoader$LoadTask",
+      "android/support/v17/leanback/widget/GuidedActionAdapter$ActionOnFocusListener": "androidx/leanback/widget/GuidedActionAdapter$ActionOnFocusListener",
+      "android/support/v7/media/SystemMediaRouteProvider$LegacyImpl": "androidx/media/SystemMediaRouteProvider$LegacyImpl",
+      "android/support/transition/ViewUtils": "androidx/transition/ViewUtils",
+      "android/support/v17/leanback/app/RowsSupportFragment$RowViewHolderExtra": "androidx/leanback/app/RowsSupportFragment$RowViewHolderExtra",
+      "android/support/v17/leanback/widget/ActionPresenterSelector$TwoLineActionPresenter": "androidx/leanback/widget/ActionPresenterSelector$TwoLineActionPresenter",
+      "android/support/v7/recyclerview/R$dimen": "androidx/recyclerview/R$dimen",
+      "android/support/v7/app/TwilightCalculator": "androidx/app/TwilightCalculator",
+      "android/support/v17/leanback/widget/ResizingTextView": "androidx/leanback/widget/ResizingTextView",
+      "android/support/design/widget/ViewUtilsLollipop": "androidx/design/widget/ViewUtilsLollipop",
+      "android/support/media/tv/TvContractCompat$PreviewProgramColumns$Availability": "androidx/media/tv/TvContractCompat$PreviewProgramColumns$Availability",
+      "android/support/v7/media/RemotePlaybackClient$ActionCallback": "androidx/media/RemotePlaybackClient$ActionCallback",
+      "android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter$Listener": "androidx/leanback/widget/FullWidthDetailsOverviewRowPresenter$Listener",
+      "android/support/v4/app/FragmentManagerImpl$AnimatorOnHWLayerIfNeededListener": "androidx/app/FragmentManagerImpl$AnimatorOnHWLayerIfNeededListener",
+      "android/support/v17/leanback/transition/TransitionHelper": "androidx/leanback/transition/TransitionHelper",
+      "android/support/v7/view/SupportActionModeWrapper$CallbackWrapper": "androidx/view/SupportActionModeWrapper$CallbackWrapper",
+      "android/support/v13/app/FragmentStatePagerAdapter": "androidx/app/FragmentStatePagerAdapter",
+      "android/support/v7/graphics/Palette$PaletteAsyncListener": "androidx/graphics/Palette$PaletteAsyncListener",
+      "android/support/v4/media/MediaBrowserServiceCompat": "androidx/media/MediaBrowserServiceCompat",
+      "android/support/v4/widget/NestedScrollView": "androidx/widget/NestedScrollView",
+      "android/support/v4/media/MediaBrowserCompat$ItemCallback$StubApi23": "androidx/media/MediaBrowserCompat$ItemCallback$StubApi23",
+      "android/support/v4/text/BidiFormatter$DirectionalityEstimator": "androidx/text/BidiFormatter$DirectionalityEstimator",
+      "android/support/text/emoji/FontRequestEmojiCompatConfig$FontRequestMetadataLoader": "androidx/text/emoji/FontRequestEmojiCompatConfig$FontRequestMetadataLoader",
+      "android/support/transition/ChangeClipBounds": "androidx/transition/ChangeClipBounds",
+      "android/support/v7/widget/PositionMap": "androidx/widget/PositionMap",
+      "android/support/v17/leanback/widget/ItemBridgeAdapter$ViewHolder": "androidx/leanback/widget/ItemBridgeAdapter$ViewHolder",
+      "android/support/v7/widget/TintContextWrapper": "androidx/widget/TintContextWrapper",
+      "android/support/v7/widget/MenuItemHoverListener": "androidx/widget/MenuItemHoverListener",
+      "android/support/v4/app/RemoteInputCompatBase": "androidx/app/RemoteInputCompatBase",
+      "android/support/v17/leanback/media/SurfaceHolderGlueHost": "androidx/leanback/media/SurfaceHolderGlueHost",
+      "android/support/v7/widget/LinearLayoutManager$LayoutChunkResult": "androidx/widget/LinearLayoutManager$LayoutChunkResult",
+      "android/support/v7/view/menu/MenuPresenter": "androidx/view/menu/MenuPresenter",
+      "android/support/v7/media/MediaRouterJellybean": "androidx/media/MediaRouterJellybean",
+      "android/support/annotation/ArrayRes": "androidx/annotation/ArrayRes",
+      "android/support/v4/media/session/MediaSessionCompat$ResultReceiverWrapper": "androidx/media/session/MediaSessionCompat$ResultReceiverWrapper",
+      "android/support/v17/leanback/widget/FocusHighlightHelper": "androidx/leanback/widget/FocusHighlightHelper",
+      "android/support/v4/media/session/MediaControllerCompatApi21$TransportControls": "androidx/media/session/MediaControllerCompatApi21$TransportControls",
+      "android/support/v4/media/MediaBrowserCompatApi21$SubscriptionCallbackProxy": "androidx/media/MediaBrowserCompatApi21$SubscriptionCallbackProxy",
+      "android/support/v7/mediarouter/R$dimen": "androidx/mediarouter/R$dimen",
+      "android/support/v4/app/NotificationManagerCompat$CancelTask": "androidx/app/NotificationManagerCompat$CancelTask",
+      "android/support/design/widget/BottomSheetBehavior$BottomSheetCallback": "androidx/design/widget/BottomSheetBehavior$BottomSheetCallback",
+      "android/support/v4/os/LocaleListCompat": "androidx/os/LocaleListCompat",
+      "android/support/v4/media/MediaBrowserCompat$MediaBrowserImplBase$MediaServiceConnection": "androidx/media/MediaBrowserCompat$MediaBrowserImplBase$MediaServiceConnection",
+      "android/support/design/internal/BottomNavigationPresenter": "androidx/design/internal/BottomNavigationPresenter",
+      "android/support/v7/view/SupportMenuInflater": "androidx/view/SupportMenuInflater",
+      "android/support/v4/app/ActivityOptionsCompat$ActivityOptionsCompatApi16Impl": "androidx/app/ActivityOptionsCompat$ActivityOptionsCompatApi16Impl",
+      "android/support/transition/AutoTransition": "androidx/transition/AutoTransition",
+      "android/support/v7/widget/RoundRectDrawable": "androidx/widget/RoundRectDrawable",
+      "android/support/graphics/drawable/VectorDrawableCompat$VFullPath": "androidx/graphics/drawable/VectorDrawableCompat$VFullPath",
+      "android/support/v4/widget/ListViewAutoScrollHelper": "androidx/widget/ListViewAutoScrollHelper",
+      "android/support/v4/media/MediaBrowserCompatApi21$MediaItem": "androidx/media/MediaBrowserCompatApi21$MediaItem",
+      "android/support/transition/FloatArrayEvaluator": "androidx/transition/FloatArrayEvaluator",
+      "android/support/design/widget/CollapsingToolbarLayout$OffsetUpdateListener": "androidx/design/widget/CollapsingToolbarLayout$OffsetUpdateListener",
+      "android/support/v7/preference/PreferenceManager$OnPreferenceTreeClickListener": "androidx/preference/PreferenceManager$OnPreferenceTreeClickListener",
+      "android/support/v17/leanback/widget/Parallax": "androidx/leanback/widget/Parallax",
+      "android/support/v4/media/MediaBrowserCompat$ConnectionCallback$StubApi21": "androidx/media/MediaBrowserCompat$ConnectionCallback$StubApi21",
+      "android/support/v4/os/CancellationSignal": "androidx/os/CancellationSignal",
+      "android/support/v17/leanback/media/PlaybackGlue$PlayerCallback": "androidx/leanback/media/PlaybackGlue$PlayerCallback",
+      "android/support/v4/widget/CompoundButtonCompat$CompoundButtonCompatApi21Impl": "androidx/widget/CompoundButtonCompat$CompoundButtonCompatApi21Impl",
+      "android/support/design/internal/BottomNavigationItemView": "androidx/design/internal/BottomNavigationItemView",
+      "android/support/v4/view/ViewGroupCompat$ViewGroupCompatApi18Impl": "androidx/view/ViewGroupCompat$ViewGroupCompatApi18Impl",
+      "android/support/text/emoji/flatbuffer/Struct": "androidx/text/emoji/flatbuffer/Struct",
+      "android/support/v17/leanback/widget/VerticalGridPresenter$VerticalGridItemBridgeAdapter": "androidx/leanback/widget/VerticalGridPresenter$VerticalGridItemBridgeAdapter",
+      "android/support/v4/view/ViewCompat$ViewCompatApi21Impl": "androidx/view/ViewCompat$ViewCompatApi21Impl",
+      "android/support/v17/leanback/widget/SearchEditText$OnKeyboardDismissListener": "androidx/leanback/widget/SearchEditText$OnKeyboardDismissListener",
+      "android/support/annotation/AttrRes": "androidx/annotation/AttrRes",
+      "android/support/v17/leanback/app/BrowseFragment$FragmentHostImpl": "androidx/leanback/app/BrowseFragment$FragmentHostImpl",
+      "android/support/v4/graphics/PathParser": "androidx/graphics/PathParser",
+      "android/support/v17/leanback/app/BackgroundManager$BitmapDrawable": "androidx/leanback/app/BackgroundManager$BitmapDrawable",
+      "android/support/v4/util/MapCollections$ArrayIterator": "androidx/util/MapCollections$ArrayIterator",
+      "android/support/v4/view/AsyncLayoutInflater": "androidx/view/AsyncLayoutInflater",
+      "android/support/v4/media/MediaBrowserServiceCompat$Result": "androidx/media/MediaBrowserServiceCompat$Result",
+      "android/support/v4/media/MediaBrowserServiceCompat$MediaBrowserServiceImpl": "androidx/media/MediaBrowserServiceCompat$MediaBrowserServiceImpl",
+      "android/support/v17/leanback/app/RowsFragment$MainFragmentAdapter": "androidx/leanback/app/RowsFragment$MainFragmentAdapter",
+      "android/support/v17/internal/widget/OutlineOnlyWithChildrenFrameLayout": "androidx/internal/widget/OutlineOnlyWithChildrenFrameLayout",
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplApi21$ExtraSession": "androidx/media/session/MediaSessionCompat$MediaSessionImplApi21$ExtraSession",
+      "android/support/v17/leanback/util/MathUtil": "androidx/leanback/util/MathUtil",
+      "android/support/v4/app/RemoteInputCompatBase$RemoteInput$Factory": "androidx/app/RemoteInputCompatBase$RemoteInput$Factory",
+      "android/support/animation/DynamicAnimation": "androidx/animation/DynamicAnimation",
+      "android/support/transition/Visibility": "androidx/transition/Visibility",
+      "android/support/v4/widget/PopupWindowCompat$PopupWindowCompatApi21Impl": "androidx/widget/PopupWindowCompat$PopupWindowCompatApi21Impl",
+      "android/support/v7/app/AppCompatViewInflater": "androidx/app/AppCompatViewInflater",
+      "android/support/v7/widget/ListPopupWindow$PopupTouchInterceptor": "androidx/widget/ListPopupWindow$PopupTouchInterceptor",
+      "android/support/v4/app/ServiceCompat$StopForegroundFlags": "androidx/app/ServiceCompat$StopForegroundFlags",
+      "android/support/graphics/drawable/VectorDrawableCompat$VClipPath": "androidx/graphics/drawable/VectorDrawableCompat$VClipPath",
+      "android/support/v7/app/MediaRouteControllerDialog$VolumeGroupAdapter": "androidx/app/MediaRouteControllerDialog$VolumeGroupAdapter",
+      "android/support/design/R$style": "androidx/design/R$style",
+      "android/support/v4/media/MediaBrowserCompat$MediaBrowserImplApi26": "androidx/media/MediaBrowserCompat$MediaBrowserImplApi26",
+      "android/support/constraint/R$styleable": "androidx/constraint/R$styleable",
+      "android/support/v7/media/MediaRouterJellybeanMr1$RouteInfo": "androidx/media/MediaRouterJellybeanMr1$RouteInfo",
+      "android/support/v4/widget/CircleImageView$OvalShadow": "androidx/widget/CircleImageView$OvalShadow",
+      "android/support/v7/preference/ListPreferenceDialogFragmentCompat": "androidx/preference/ListPreferenceDialogFragmentCompat",
+      "android/support/v7/preference/PreferenceFragmentCompat$OnPreferenceStartFragmentCallback": "androidx/preference/PreferenceFragmentCompat$OnPreferenceStartFragmentCallback",
+      "android/support/v4/view/PagerTitleStrip$PageListener": "androidx/view/PagerTitleStrip$PageListener",
+      "android/support/v4/media/MediaBrowserCompat$MediaBrowserImplApi21": "androidx/media/MediaBrowserCompat$MediaBrowserImplApi21",
+      "android/support/v7/app/AppCompatDelegate$ApplyableNightMode": "androidx/app/AppCompatDelegate$ApplyableNightMode",
+      "android/support/customtabs/ICustomTabsCallback": "androidx/browser/customtabs/ICustomTabsCallback",
+      "android/support/v17/preference/LeanbackListPreferenceDialogFragment": "androidx/leanback/preference/LeanbackListPreferenceDialogFragment",
+      "android/support/v17/leanback/widget/PresenterSwitcher": "androidx/leanback/widget/PresenterSwitcher",
+      "android/support/v4/media/MediaBrowserCompat$MediaBrowserImplApi23": "androidx/media/MediaBrowserCompat$MediaBrowserImplApi23",
+      "android/support/v17/leanback/widget/ShadowOverlayHelper$Options": "androidx/leanback/widget/ShadowOverlayHelper$Options",
+      "android/support/v4/text/TextDirectionHeuristicsCompat$FirstStrong": "androidx/text/TextDirectionHeuristicsCompat$FirstStrong",
+      "android/support/v7/widget/AppCompatSeekBar": "androidx/widget/AppCompatSeekBar",
+      "android/support/v17/leanback/widget/Util": "androidx/leanback/widget/Util",
+      "android/support/v4/util/MapCollections": "androidx/util/MapCollections",
+      "android/support/v4/widget/NestedScrollView$SavedState": "androidx/widget/NestedScrollView$SavedState",
+      "android/support/v7/widget/SimpleItemAnimator": "androidx/widget/SimpleItemAnimator",
+      "android/support/v4/media/MediaMetadataCompatApi21$Builder": "androidx/media/MediaMetadataCompatApi21$Builder",
+      "android/support/design/widget/DrawableUtils": "androidx/design/widget/DrawableUtils",
+      "android/support/wear/internal/widget/drawer/SinglePagePresenter": "androidx/wear/internal/widget/drawer/SinglePagePresenter",
+      "android/support/v4/app/FragmentContainer": "androidx/app/FragmentContainer",
+      "android/support/v7/media/MediaRouteProviderDescriptor": "androidx/media/MediaRouteProviderDescriptor",
+      "android/support/v4/media/session/PlaybackStateCompat$Actions": "androidx/media/session/PlaybackStateCompat$Actions",
+      "android/support/v14/preference/ListPreferenceDialogFragment": "androidx/preference/ListPreferenceDialogFragment",
+      "android/support/v4/widget/SwipeRefreshLayout$OnChildScrollUpCallback": "androidx/widget/SwipeRefreshLayout$OnChildScrollUpCallback",
+      "android/support/v4/media/AudioAttributesCompatApi21": "androidx/media/AudioAttributesCompatApi21",
+      "android/support/v7/media/MediaRouter$Callback": "androidx/media/MediaRouter$Callback",
+      "android/support/v4/content/pm/ShortcutInfoCompat$Builder": "androidx/content/pm/ShortcutInfoCompat$Builder",
+      "android/support/v7/util/SortedList$BatchedCallback": "androidx/util/SortedList$BatchedCallback",
+      "android/support/v7/cardview/R$style": "androidx/cardview/R$style",
+      "android/support/v7/media/MediaRouter$GlobalMediaRouter$ProviderCallback": "androidx/media/MediaRouter$GlobalMediaRouter$ProviderCallback",
+      "android/support/v4/widget/SimpleCursorAdapter$ViewBinder": "androidx/widget/SimpleCursorAdapter$ViewBinder",
+      "android/support/v7/util/TileList$Tile": "androidx/util/TileList$Tile",
+      "android/support/v17/leanback/widget/ItemBridgeAdapter$AdapterListener": "androidx/leanback/widget/ItemBridgeAdapter$AdapterListener",
+      "android/support/v4/widget/SlidingPaneLayout$DragHelperCallback": "androidx/widget/SlidingPaneLayout$DragHelperCallback",
+      "android/support/v4/media/MediaBrowserCompat$SearchResultReceiver": "androidx/media/MediaBrowserCompat$SearchResultReceiver",
+      "android/support/v17/leanback/widget/PlaybackRowPresenter": "androidx/leanback/widget/PlaybackRowPresenter",
+      "android/support/v7/media/MediaRouteProvider$ProviderMetadata": "androidx/media/MediaRouteProvider$ProviderMetadata",
+      "android/support/text/emoji/flatbuffer/MetadataList": "androidx/text/emoji/flatbuffer/MetadataList",
+      "android/support/v4/provider/TreeDocumentFile": "androidx/provider/TreeDocumentFile",
+      "android/support/v7/media/MediaSessionStatus$Builder": "androidx/media/MediaSessionStatus$Builder",
+      "android/support/text/emoji/widget/EmojiTextWatcher": "androidx/text/emoji/widget/EmojiTextWatcher",
+      "android/support/v17/leanback/app/GuidedStepSupportFragment": "androidx/leanback/app/GuidedStepSupportFragment",
+      "android/support/v17/leanback/widget/BrowseFrameLayout$OnFocusSearchListener": "androidx/leanback/widget/BrowseFrameLayout$OnFocusSearchListener",
+      "android/support/animation/AnimationHandler": "androidx/animation/AnimationHandler",
+      "android/support/wear/widget/drawer/WearableActionDrawerView": "androidx/wear/widget/drawer/WearableActionDrawerView",
+      "android/support/v4/media/MediaBrowserCompat$CustomActionResultReceiver": "androidx/media/MediaBrowserCompat$CustomActionResultReceiver",
+      "android/support/v7/widget/AppCompatSeekBarHelper": "androidx/widget/AppCompatSeekBarHelper",
+      "android/support/v4/widget/SlidingPaneLayout$AccessibilityDelegate": "androidx/widget/SlidingPaneLayout$AccessibilityDelegate",
+      "android/support/v17/leanback/widget/TitleViewAdapter$Provider": "androidx/leanback/widget/TitleViewAdapter$Provider",
+      "android/support/v7/widget/GridLayoutManager$SpanSizeLookup": "androidx/widget/GridLayoutManager$SpanSizeLookup",
+      "android/support/v4/content/res/ResourcesCompat$FontCallback": "androidx/content/res/ResourcesCompat$FontCallback",
+      "android/support/v4/util/CircularArray": "androidx/util/CircularArray",
+      "android/support/v17/leanback/util/StateMachine$State": "androidx/leanback/util/StateMachine$State",
+      "android/support/text/emoji/widget/EmojiTextView": "androidx/text/emoji/widget/EmojiTextView",
+      "android/support/v4/widget/CursorAdapter$MyDataSetObserver": "androidx/widget/CursorAdapter$MyDataSetObserver",
+      "android/support/v4/os/LocaleListCompat$LocaleListCompatBaseImpl": "androidx/os/LocaleListCompat$LocaleListCompatBaseImpl",
+      "android/support/v4/app/TaskStackBuilder$SupportParentable": "androidx/app/TaskStackBuilder$SupportParentable",
+      "android/support/v17/leanback/media/PlaybackControlGlue": "androidx/leanback/media/PlaybackControlGlue",
+      "android/support/v17/leanback/widget/GuidedActionEditText": "androidx/leanback/widget/GuidedActionEditText",
+      "android/support/v4/util/Pools$SimplePool": "androidx/util/Pools$SimplePool",
+      "android/support/v17/leanback/widget/ControlButtonPresenterSelector$ControlButtonPresenter": "androidx/leanback/widget/ControlButtonPresenterSelector$ControlButtonPresenter",
+      "android/support/v17/leanback/widget/PlaybackControlsPresenter$ViewHolder": "androidx/leanback/widget/PlaybackControlsPresenter$ViewHolder",
+      "android/support/wear/widget/drawer/WearableDrawerLayout": "androidx/wear/widget/drawer/WearableDrawerLayout",
+      "android/support/v7/widget/ActionBarContainer": "androidx/widget/ActionBarContainer",
+      "android/support/v7/widget/ShareActionProvider$ShareActivityChooserModelPolicy": "androidx/widget/ShareActionProvider$ShareActivityChooserModelPolicy",
+      "android/support/transition/ObjectAnimatorUtilsApi21": "androidx/transition/ObjectAnimatorUtilsApi21",
+      "android/support/v17/leanback/widget/BaseOnItemViewSelectedListener": "androidx/leanback/widget/BaseOnItemViewSelectedListener",
+      "android/support/v7/widget/StaggeredGridLayoutManager$LayoutParams": "androidx/widget/StaggeredGridLayoutManager$LayoutParams",
+      "android/support/v7/mediarouter/R$interpolator": "androidx/mediarouter/R$interpolator",
+      "android/support/v4/media/VolumeProviderCompatApi21": "androidx/media/VolumeProviderCompatApi21",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$PictureInPictureAction": "androidx/leanback/widget/PlaybackControlsRow$PictureInPictureAction",
+      "android/support/v7/util/MessageThreadUtil": "androidx/util/MessageThreadUtil",
+      "android/support/v4/util/LogWriter": "androidx/util/LogWriter",
+      "android/support/v7/preference/PreferenceDialogFragmentCompat": "androidx/preference/PreferenceDialogFragmentCompat",
+      "android/support/transition/ViewOverlayApi14": "androidx/transition/ViewOverlayApi14",
+      "android/support/v4/graphics/TypefaceCompatUtil": "androidx/graphics/TypefaceCompatUtil",
+      "android/support/media/tv/BasePreviewProgram": "androidx/media/tv/BasePreviewProgram",
+      "android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter$ViewHolder$DetailsOverviewRowListener": "androidx/leanback/widget/FullWidthDetailsOverviewRowPresenter$ViewHolder$DetailsOverviewRowListener",
+      "android/support/v7/widget/AlertDialogLayout": "androidx/widget/AlertDialogLayout",
+      "android/support/v7/widget/ActionBarOverlayLayout$LayoutParams": "androidx/widget/ActionBarOverlayLayout$LayoutParams",
+      "android/support/v4/view/NestedScrollingParentHelper": "androidx/view/NestedScrollingParentHelper",
+      "android/support/transition/ObjectAnimatorUtilsApi14": "androidx/transition/ObjectAnimatorUtilsApi14",
+      "android/support/text/emoji/EmojiCompat": "androidx/text/emoji/EmojiCompat",
+      "android/support/v4/media/MediaBrowserServiceCompatApi23$ServiceCompatProxy": "androidx/media/MediaBrowserServiceCompatApi23$ServiceCompatProxy",
+      "android/support/v17/leanback/widget/FocusHighlightHelper$FocusAnimator": "androidx/leanback/widget/FocusHighlightHelper$FocusAnimator",
+      "android/support/v17/leanback/app/PlaybackSupportFragment$SetSelectionRunnable": "androidx/leanback/app/PlaybackSupportFragment$SetSelectionRunnable",
+      "android/support/v4/widget/PopupWindowCompat$PopupWindowCompatApi23Impl": "androidx/widget/PopupWindowCompat$PopupWindowCompatApi23Impl",
+      "android/support/v7/preference/SwitchPreferenceCompat": "androidx/preference/SwitchPreferenceCompat",
+      "android/support/wear/widget/drawer/FlingWatcherFactory$FlingListener": "androidx/wear/widget/drawer/FlingWatcherFactory$FlingListener",
+      "android/support/v7/widget/ShareActionProvider": "androidx/widget/ShareActionProvider",
+      "android/support/v7/content/res/AppCompatResources": "androidx/content/res/AppCompatResources",
+      "android/support/transition/ViewOverlayApi18": "androidx/transition/ViewOverlayApi18",
+      "android/support/v7/widget/ListPopupWindow$ResizePopupRunnable": "androidx/widget/ListPopupWindow$ResizePopupRunnable",
+      "android/support/compat/R$integer": "androidx/compat/R$integer",
+      "android/support/v4/app/ActionBarDrawerToggle$SlideDrawable": "androidx/app/ActionBarDrawerToggle$SlideDrawable",
+      "android/support/transition/ChangeTransform$PathAnimatorMatrix": "androidx/transition/ChangeTransform$PathAnimatorMatrix",
+      "android/support/v17/leanback/graphics/ColorFilterDimmer": "androidx/leanback/graphics/ColorFilterDimmer",
+      "android/support/v7/media/MediaRouteDescriptor": "androidx/media/MediaRouteDescriptor",
+      "android/support/v7/preference/R$id": "androidx/preference/R$id",
+      "android/support/v14/preference/PreferenceFragment$ScrollToPreferenceObserver": "androidx/preference/PreferenceFragment$ScrollToPreferenceObserver",
+      "android/support/v4/internal/package-info": "androidx/internal/package-info",
+      "android/support/v4/media/MediaBrowserCompatApi21$SubscriptionCallback": "androidx/media/MediaBrowserCompatApi21$SubscriptionCallback",
+      "android/support/v7/view/menu/MenuHelper": "androidx/view/menu/MenuHelper",
+      "android/support/v17/leanback/widget/SpeechOrbView": "androidx/leanback/widget/SpeechOrbView",
+      "android/support/v7/media/SystemMediaRouteProvider$JellybeanImpl$SystemRouteController": "androidx/media/SystemMediaRouteProvider$JellybeanImpl$SystemRouteController",
+      "android/support/v7/widget/FitWindowsFrameLayout": "androidx/widget/FitWindowsFrameLayout",
+      "android/support/v7/preference/TwoStatePreference$SavedState": "androidx/preference/TwoStatePreference$SavedState",
+      "android/support/v17/leanback/widget/ShadowOverlayHelper$Builder": "androidx/leanback/widget/ShadowOverlayHelper$Builder",
+      "android/support/v17/leanback/widget/InvisibleRowPresenter": "androidx/leanback/widget/InvisibleRowPresenter",
+      "android/support/design/internal/NavigationMenuPresenter$SeparatorViewHolder": "androidx/design/internal/NavigationMenuPresenter$SeparatorViewHolder",
+      "android/support/design/widget/BaseTransientBottomBar$Duration": "androidx/design/widget/BaseTransientBottomBar$Duration",
+      "android/support/v7/widget/helper/ItemTouchUIUtilImpl": "androidx/widget/helper/ItemTouchUIUtilImpl",
+      "android/support/v17/leanback/widget/GuidedActionsRelativeLayout$InterceptKeyEventListener": "androidx/leanback/widget/GuidedActionsRelativeLayout$InterceptKeyEventListener",
+      "android/support/v4/os/IResultReceiver": "androidx/os/IResultReceiver",
+      "android/support/v17/leanback/widget/ShadowHelperApi21": "androidx/leanback/widget/ShadowHelperApi21",
+      "android/support/v17/leanback/widget/RowPresenter": "androidx/leanback/widget/RowPresenter",
+      "android/support/v4/media/MediaBrowserCompat$MediaBrowserImplBase": "androidx/media/MediaBrowserCompat$MediaBrowserImplBase",
+      "android/support/v4/app/BackStackRecord": "androidx/app/BackStackRecord",
+      "android/support/v4/view/WindowInsetsCompat": "androidx/view/WindowInsetsCompat",
+      "android/support/graphics/drawable/AnimatedVectorDrawableCompat": "androidx/graphics/drawable/AnimatedVectorDrawableCompat",
+      "android/support/v17/leanback/widget/PlaybackControlsRowPresenter": "androidx/leanback/widget/PlaybackControlsRowPresenter",
+      "android/support/transition/VisibilityPropagation": "androidx/transition/VisibilityPropagation",
+      "android/support/v17/leanback/media/PlaybackTransportControlGlue": "androidx/leanback/media/PlaybackTransportControlGlue",
+      "android/support/wear/widget/BoxInsetLayout$LayoutParams$BoxedEdges": "androidx/wear/widget/BoxInsetLayout$LayoutParams$BoxedEdges",
+      "android/support/annotation/LayoutRes": "androidx/annotation/LayoutRes",
+      "android/support/v4/widget/CursorAdapter": "androidx/widget/CursorAdapter",
+      "android/support/wear/ambient/AmbientMode$AmbientCallback": "androidx/wear/ambient/AmbientMode$AmbientCallback",
+      "android/support/v4/media/MediaBrowserServiceCompatApi21$BrowserRoot": "androidx/media/MediaBrowserServiceCompatApi21$BrowserRoot",
+      "android/support/v7/view/menu/MenuItemWrapperJB": "androidx/view/menu/MenuItemWrapperJB",
+      "android/support/text/emoji/widget/EmojiAppCompatButton": "androidx/text/emoji/widget/EmojiAppCompatButton",
+      "android/support/v4/view/ActionProvider$SubUiVisibilityListener": "androidx/view/ActionProvider$SubUiVisibilityListener",
+      "android/support/wear/widget/drawer/WearableActionDrawerMenu$WearableActionDrawerMenuItem$MenuItemChangedListener": "androidx/wear/widget/drawer/WearableActionDrawerMenu$WearableActionDrawerMenuItem$MenuItemChangedListener",
+      "android/support/v4/media/MediaBrowserCompat$ServiceBinderWrapper": "androidx/media/MediaBrowserCompat$ServiceBinderWrapper",
+      "android/support/v13/app/ActivityCompat": "androidx/app/ActivityCompat",
+      "android/support/v4/widget/ImageViewCompat$LollipopViewCompatImpl": "androidx/widget/ImageViewCompat$LollipopViewCompatImpl",
+      "android/support/annotation/UiThread": "androidx/annotation/UiThread",
+      "android/support/v4/media/session/MediaControllerCompatApi24": "androidx/media/session/MediaControllerCompatApi24",
+      "android/support/v7/media/RemoteControlClientCompat$JellybeanImpl$VolumeCallbackWrapper": "androidx/media/RemoteControlClientCompat$JellybeanImpl$VolumeCallbackWrapper",
+      "android/support/v4/media/session/MediaControllerCompatApi23": "androidx/media/session/MediaControllerCompatApi23",
+      "android/support/v4/media/session/MediaControllerCompatApi21": "androidx/media/session/MediaControllerCompatApi21",
+      "android/support/v4/print/PrintHelper$ScaleMode": "androidx/print/PrintHelper$ScaleMode",
+      "android/support/v7/widget/SearchView$SavedState": "androidx/widget/SearchView$SavedState",
+      "android/support/v7/widget/AppCompatDrawableManager$AvdcInflateDelegate": "androidx/widget/AppCompatDrawableManager$AvdcInflateDelegate",
+      "android/support/v7/preference/TwoStatePreference": "androidx/preference/TwoStatePreference",
+      "android/support/text/emoji/EmojiCompat$LoadState": "androidx/text/emoji/EmojiCompat$LoadState",
+      "android/support/v17/leanback/widget/HorizontalGridView": "androidx/leanback/widget/HorizontalGridView",
+      "android/support/v7/view/menu/ListMenuItemView": "androidx/view/menu/ListMenuItemView",
+      "android/support/transition/Styleable$TransitionSet": "androidx/transition/Styleable$TransitionSet",
+      "android/support/v17/leanback/app/PlaybackFragment$OnFadeCompleteListener": "androidx/leanback/app/PlaybackFragment$OnFadeCompleteListener",
+      "android/support/v7/widget/ActivityChooserModel$PersistHistoryAsyncTask": "androidx/widget/ActivityChooserModel$PersistHistoryAsyncTask",
+      "android/support/v4/util/ArraySet": "androidx/util/ArraySet",
+      "android/support/v7/widget/FastScroller$AnimationState": "androidx/widget/FastScroller$AnimationState",
+      "android/support/v7/widget/RecyclerView$ChildDrawingOrderCallback": "androidx/widget/RecyclerView$ChildDrawingOrderCallback",
+      "android/support/text/emoji/flatbuffer/Constants": "androidx/text/emoji/flatbuffer/Constants",
+      "android/support/v4/widget/DrawerLayout$LayoutParams": "androidx/widget/DrawerLayout$LayoutParams",
+      "android/support/v4/app/TaskStackBuilder": "androidx/app/TaskStackBuilder",
+      "android/support/v7/widget/ListPopupWindow$PopupDataSetObserver": "androidx/widget/ListPopupWindow$PopupDataSetObserver",
+      "android/support/v4/media/session/MediaSessionCompatApi24$CallbackProxy": "androidx/media/session/MediaSessionCompatApi24$CallbackProxy",
+      "android/support/v17/leanback/app/RowsSupportFragment$MainFragmentRowsAdapter": "androidx/leanback/app/RowsSupportFragment$MainFragmentRowsAdapter",
+      "android/support/v17/leanback/widget/picker/DatePicker": "androidx/leanback/widget/picker/DatePicker",
+      "android/support/v17/leanback/widget/SearchBar$SearchBarPermissionListener": "androidx/leanback/widget/SearchBar$SearchBarPermissionListener",
+      "android/support/v7/media/MediaItemMetadata": "androidx/media/MediaItemMetadata",
+      "android/support/v17/leanback/widget/ListRowPresenter": "androidx/leanback/widget/ListRowPresenter",
+      "android/support/v17/leanback/media/PlaybackBannerControlGlue$ACTION_": "androidx/leanback/media/PlaybackBannerControlGlue$ACTION_",
+      "android/support/v4/app/RemoteInput": "androidx/app/RemoteInput",
+      "android/support/text/emoji/MetadataListReader$ByteBufferReader": "androidx/text/emoji/MetadataListReader$ByteBufferReader",
+      "android/support/v17/leanback/widget/SearchEditText": "androidx/leanback/widget/SearchEditText",
+      "android/support/v4/app/NotificationCompat$CarExtender$UnreadConversation$Builder": "androidx/app/NotificationCompat$CarExtender$UnreadConversation$Builder",
+      "android/support/v7/preference/SeekBarPreference": "androidx/preference/SeekBarPreference",
+      "android/support/v17/leanback/R$transition": "androidx/leanback/R$transition",
+      "android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory": "androidx/graphics/drawable/RoundedBitmapDrawableFactory",
+      "android/support/v7/widget/PositionMap$ContainerHelpers": "androidx/widget/PositionMap$ContainerHelpers",
+      "android/support/v4/view/accessibility/AccessibilityManagerCompat$AccessibilityStateChangeListenerWrapper": "androidx/view/accessibility/AccessibilityManagerCompat$AccessibilityStateChangeListenerWrapper",
+      "android/support/design/widget/ViewUtils": "androidx/design/widget/ViewUtils",
+      "android/support/v4/widget/CompoundButtonCompat$CompoundButtonCompatApi23Impl": "androidx/widget/CompoundButtonCompat$CompoundButtonCompatApi23Impl",
+      "android/support/v7/widget/StaggeredGridLayoutManager$SavedState": "androidx/widget/StaggeredGridLayoutManager$SavedState",
+      "android/support/transition/PathMotion": "androidx/transition/PathMotion",
+      "android/support/wear/widget/drawer/WearableDrawerView": "androidx/wear/widget/drawer/WearableDrawerView",
+      "android/support/v4/media/VolumeProviderCompat$ControlType": "androidx/media/VolumeProviderCompat$ControlType",
+      "android/support/v4/view/animation/PathInterpolatorApi14": "androidx/view/animation/PathInterpolatorApi14",
+      "android/support/animation/AnimationHandler$FrameCallbackProvider16": "androidx/animation/AnimationHandler$FrameCallbackProvider16",
+      "android/support/v4/view/animation/FastOutSlowInInterpolator": "androidx/view/animation/FastOutSlowInInterpolator",
+      "android/support/animation/AnimationHandler$FrameCallbackProvider14": "androidx/animation/AnimationHandler$FrameCallbackProvider14",
+      "android/support/customtabs/CustomTabsServiceConnection": "androidx/browser/customtabs/CustomTabsServiceConnection",
+      "android/support/v17/leanback/app/BackgroundFragment": "androidx/leanback/app/BackgroundFragment",
+      "android/support/v17/leanback/widget/FocusHighlightHelper$BrowseItemFocusHighlight": "androidx/leanback/widget/FocusHighlightHelper$BrowseItemFocusHighlight",
+      "android/support/v17/leanback/app/HeadersFragment$OnHeaderClickedListener": "androidx/leanback/app/HeadersFragment$OnHeaderClickedListener",
+      "android/support/v7/media/MediaRouter$RouteInfo": "androidx/media/MediaRouter$RouteInfo",
+      "android/support/v14/preference/PreferenceFragment": "androidx/preference/PreferenceFragment",
+      "android/support/v4/media/session/PlaybackStateCompat$MediaKeyAction": "androidx/media/session/PlaybackStateCompat$MediaKeyAction",
+      "android/support/v17/leanback/widget/TitleView": "androidx/leanback/widget/TitleView",
+      "android/support/graphics/drawable/VectorDrawableCompat$VPath": "androidx/graphics/drawable/VectorDrawableCompat$VPath",
+      "android/support/v17/leanback/widget/AbstractMediaItemPresenter$ViewHolder": "androidx/leanback/widget/AbstractMediaItemPresenter$ViewHolder",
+      "android/support/v17/leanback/widget/BrowseRowsFrameLayout": "androidx/leanback/widget/BrowseRowsFrameLayout",
+      "android/support/v7/content/res/AppCompatResources$ColorStateListCacheEntry": "androidx/content/res/AppCompatResources$ColorStateListCacheEntry",
+      "android/support/design/R$dimen": "androidx/design/R$dimen",
+      "android/support/v7/preference/PreferenceInflater": "androidx/preference/PreferenceInflater",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$PlayPauseAction": "androidx/leanback/widget/PlaybackControlsRow$PlayPauseAction",
+      "android/support/v17/leanback/widget/PlaybackTransportRowPresenter": "androidx/leanback/widget/PlaybackTransportRowPresenter",
+      "android/support/wear/BuildConfig": "androidx/wear/BuildConfig",
+      "android/support/wear/widget/CircledImageView": "androidx/wear/widget/CircledImageView",
+      "android/support/v7/media/MediaRouterJellybean$SelectRouteWorkaround": "androidx/media/MediaRouterJellybean$SelectRouteWorkaround",
+      "android/support/v17/leanback/widget/ListRowHoverCardView": "androidx/leanback/widget/ListRowHoverCardView",
+      "android/support/v7/media/MediaRouterJellybean$GetDefaultRouteWorkaround": "androidx/media/MediaRouterJellybean$GetDefaultRouteWorkaround",
+      "android/support/text/emoji/widget/SpannableBuilder$WatcherWrapper": "androidx/text/emoji/widget/SpannableBuilder$WatcherWrapper",
+      "android/support/v17/preference/LeanbackListPreferenceDialogFragment$AdapterSingle": "androidx/leanback/preference/LeanbackListPreferenceDialogFragment$AdapterSingle",
+      "android/support/v17/leanback/app/OnboardingFragment": "androidx/leanback/app/OnboardingFragment",
+      "android/support/v7/view/menu/MenuPresenter$Callback": "androidx/view/menu/MenuPresenter$Callback",
+      "android/support/v4/graphics/drawable/DrawableWrapperApi14$DrawableWrapperStateBase": "androidx/graphics/drawable/DrawableWrapperApi14$DrawableWrapperStateBase",
+      "android/support/v17/leanback/graphics/CompositeDrawable$ChildDrawable": "androidx/leanback/graphics/CompositeDrawable$ChildDrawable",
+      "android/support/v17/leanback/widget/AbstractMediaListHeaderPresenter$ViewHolder": "androidx/leanback/widget/AbstractMediaListHeaderPresenter$ViewHolder",
+      "android/support/v7/view/menu/MenuItemWrapperICS$OnMenuItemClickListenerWrapper": "androidx/view/menu/MenuItemWrapperICS$OnMenuItemClickListenerWrapper",
+      "android/support/v7/widget/ContentFrameLayout$OnAttachListener": "androidx/widget/ContentFrameLayout$OnAttachListener",
+      "android/support/v17/leanback/widget/StaticShadowHelper": "androidx/leanback/widget/StaticShadowHelper",
+      "android/support/v7/widget/RecyclerView$OnScrollListener": "androidx/widget/RecyclerView$OnScrollListener",
+      "android/support/v17/leanback/graphics/FitWidthBitmapDrawable$BitmapState": "androidx/leanback/graphics/FitWidthBitmapDrawable$BitmapState",
+      "android/support/v17/leanback/widget/SeekBar": "androidx/leanback/widget/SeekBar",
+      "android/support/v4/widget/SlidingPaneLayout$SimplePanelSlideListener": "androidx/widget/SlidingPaneLayout$SimplePanelSlideListener",
+      "android/support/v17/leanback/widget/RowContainerView": "androidx/leanback/widget/RowContainerView",
+      "android/support/v7/widget/ForwardingListener$DisallowIntercept": "androidx/widget/ForwardingListener$DisallowIntercept",
+      "android/support/v7/app/AppCompatDelegateImplBase": "androidx/app/AppCompatDelegateImplBase",
+      "android/support/v17/leanback/app/PlaybackSupportFragmentGlueHost": "androidx/leanback/app/PlaybackSupportFragmentGlueHost",
+      "android/support/transition/Styleable$Transition": "androidx/transition/Styleable$Transition",
+      "android/support/v7/widget/ActionMenuPresenter": "androidx/widget/ActionMenuPresenter",
+      "android/support/v7/app/ActionBar$DisplayOptions": "androidx/app/ActionBar$DisplayOptions",
+      "android/support/v4/app/ShareCompat$IntentBuilder": "androidx/app/ShareCompat$IntentBuilder",
+      "android/support/v4/media/MediaMetadataCompat$LongKey": "androidx/media/MediaMetadataCompat$LongKey",
+      "android/support/v4/media/AudioAttributesCompatApi21$Wrapper": "androidx/media/AudioAttributesCompatApi21$Wrapper",
+      "android/support/exifinterface/BuildConfig": "androidx/exifinterface/BuildConfig",
+      "android/support/v17/leanback/widget/DetailsOverviewRow": "androidx/leanback/widget/DetailsOverviewRow",
+      "android/support/annotation/IdRes": "androidx/annotation/IdRes",
+      "android/support/v7/widget/ActivityChooserModel$HistoricalRecord": "androidx/widget/ActivityChooserModel$HistoricalRecord",
+      "android/support/v17/leanback/widget/SearchOrbView$Colors": "androidx/leanback/widget/SearchOrbView$Colors",
+      "android/support/v7/content/res/GrowingArrayUtils": "androidx/content/res/GrowingArrayUtils",
+      "android/support/text/emoji/MetadataRepo$Node": "androidx/text/emoji/MetadataRepo$Node",
+      "android/support/v17/leanback/app/BrowseFragment$MainFragmentItemViewSelectedListener": "androidx/leanback/app/BrowseFragment$MainFragmentItemViewSelectedListener",
+      "android/support/v17/leanback/app/SearchSupportFragment$ExternalQuery": "androidx/leanback/app/SearchSupportFragment$ExternalQuery",
+      "android/support/v17/leanback/widget/ShadowHelperJbmr2$ShadowImpl": "androidx/leanback/widget/ShadowHelperJbmr2$ShadowImpl",
+      "android/support/wear/widget/drawer/PageIndicatorView": "androidx/wear/widget/drawer/PageIndicatorView",
+      "android/support/v17/leanback/app/VerticalGridSupportFragment": "androidx/leanback/app/VerticalGridSupportFragment",
+      "android/support/v7/preference/PreferenceGroupAdapter$PreferenceLayout": "androidx/preference/PreferenceGroupAdapter$PreferenceLayout",
+      "android/support/v7/preference/internal/AbstractMultiSelectListPreference": "androidx/preference/internal/AbstractMultiSelectListPreference",
+      "android/support/v7/media/MediaRouteProviderDescriptor$Builder": "androidx/media/MediaRouteProviderDescriptor$Builder",
+      "android/support/v4/app/NotificationCompatSideChannelService": "androidx/app/NotificationCompatSideChannelService",
+      "android/support/v7/widget/GridLayoutManager": "androidx/widget/GridLayoutManager",
+      "android/support/v4/media/AudioAttributesCompat$AttributeUsage": "androidx/media/AudioAttributesCompat$AttributeUsage",
+      "android/support/v4/util/Pools$Pool": "androidx/util/Pools$Pool",
+      "android/support/transition/SidePropagation": "androidx/transition/SidePropagation",
+      "android/support/v17/leanback/widget/PlaybackSeekUi$Client": "androidx/leanback/widget/PlaybackSeekUi$Client",
+      "android/support/media/tv/TvContractCompat$Channels": "androidx/media/tv/TvContractCompat$Channels",
+      "android/support/v7/appcompat/R$style": "androidx/appcompat/R$style",
+      "android/support/v4/app/INotificationSideChannel$Stub": "androidx/app/INotificationSideChannel$Stub",
+      "android/support/compat/R$string": "androidx/compat/R$string",
+      "android/support/v4/os/EnvironmentCompat": "androidx/os/EnvironmentCompat",
+      "android/support/wear/ambient/SharedLibraryVersion": "androidx/wear/ambient/SharedLibraryVersion",
+      "android/support/v7/view/menu/MenuBuilder$Callback": "androidx/view/menu/MenuBuilder$Callback",
+      "android/support/v17/leanback/app/BrowseSupportFragment$MainFragmentRowsAdapterProvider": "androidx/leanback/app/BrowseSupportFragment$MainFragmentRowsAdapterProvider",
+      "android/support/v17/leanback/R": "androidx/leanback/R",
+      "android/support/transition/Slide": "androidx/transition/Slide",
+      "android/support/v4/os/ParcelableCompat$ParcelableCompatCreatorHoneycombMR2": "androidx/os/ParcelableCompat$ParcelableCompatCreatorHoneycombMR2",
+      "android/support/v17/leanback/widget/PlaybackSeekUi": "androidx/leanback/widget/PlaybackSeekUi",
+      "android/support/v4/view/ViewPropertyAnimatorUpdateListener": "androidx/view/ViewPropertyAnimatorUpdateListener",
+      "android/support/v4/widget/EdgeEffectCompat$EdgeEffectBaseImpl": "androidx/widget/EdgeEffectCompat$EdgeEffectBaseImpl",
+      "android/support/v7/widget/ForwardingListener$TriggerLongPress": "androidx/widget/ForwardingListener$TriggerLongPress",
+      "android/support/text/emoji/bundled/BuildConfig": "androidx/text/emoji/bundled/BuildConfig",
+      "android/support/v4/app/ActivityCompat$SharedElementCallback23Impl": "androidx/app/ActivityCompat$SharedElementCallback23Impl",
+      "android/support/v4/media/MediaBrowserCompatApi21$ConnectionCallback": "androidx/media/MediaBrowserCompatApi21$ConnectionCallback",
+      "android/support/v4/content/Loader$ForceLoadContentObserver": "androidx/content/Loader$ForceLoadContentObserver",
+      "android/support/v7/widget/ScrollingTabContainerView$TabClickListener": "androidx/widget/ScrollingTabContainerView$TabClickListener",
+      "android/support/v4/widget/TextViewCompat$TextViewCompatApi27Impl": "androidx/widget/TextViewCompat$TextViewCompatApi27Impl",
+      "android/support/v17/leanback/widget/GridLayoutManager$OnLayoutCompleteListener": "androidx/leanback/widget/GridLayoutManager$OnLayoutCompleteListener",
+      "android/support/v4/provider/SelfDestructiveThread$ReplyCallback": "androidx/provider/SelfDestructiveThread$ReplyCallback",
+      "android/support/v4/media/VolumeProviderCompat$Callback": "androidx/media/VolumeProviderCompat$Callback",
+      "android/support/v4/app/NotificationCompat$CarExtender$UnreadConversation": "androidx/app/NotificationCompat$CarExtender$UnreadConversation",
+      "android/support/graphics/drawable/AnimatorInflaterCompat": "androidx/graphics/drawable/AnimatorInflaterCompat",
+      "android/support/compat/R$id": "androidx/compat/R$id",
+      "android/support/v17/leanback/app/DetailsFragment$WaitEnterTransitionTimeout": "androidx/leanback/app/DetailsFragment$WaitEnterTransitionTimeout",
+      "android/support/media/tv/TvContractCompat$Channels$ServiceType": "androidx/media/tv/TvContractCompat$Channels$ServiceType",
+      "android/support/v17/leanback/widget/Presenter$ViewHolder": "androidx/leanback/widget/Presenter$ViewHolder",
+      "android/support/text/emoji/EmojiCompat$Config": "androidx/text/emoji/EmojiCompat$Config",
+      "android/support/v17/leanback/app/BackgroundManager$ChangeBackgroundRunnable": "androidx/leanback/app/BackgroundManager$ChangeBackgroundRunnable",
+      "android/support/v17/leanback/util/StateMachine$Transition": "androidx/leanback/util/StateMachine$Transition",
+      "android/support/v17/leanback/widget/picker/TimePicker": "androidx/leanback/widget/picker/TimePicker",
+      "android/support/v7/media/RegisteredMediaRouteProvider$Controller": "androidx/media/RegisteredMediaRouteProvider$Controller",
+      "android/support/text/emoji/TypefaceEmojiSpan": "androidx/text/emoji/TypefaceEmojiSpan",
+      "android/support/wear/widget/SwipeDismissFrameLayout": "androidx/wear/widget/SwipeDismissFrameLayout",
+      "android/support/v4/media/MediaBrowserCompatUtils": "androidx/media/MediaBrowserCompatUtils",
+      "android/support/v17/leanback/app/HeadersSupportFragment": "androidx/leanback/app/HeadersSupportFragment",
+      "android/support/v7/widget/SearchView$OnQueryTextListener": "androidx/widget/SearchView$OnQueryTextListener",
+      "android/support/v17/leanback/widget/AbstractMediaListHeaderPresenter": "androidx/leanback/widget/AbstractMediaListHeaderPresenter",
+      "android/support/design/widget/BaseTransientBottomBar$OnLayoutChangeListener": "androidx/design/widget/BaseTransientBottomBar$OnLayoutChangeListener",
+      "android/support/v14/preference/R$styleable": "androidx/preference/R$styleable",
+      "android/support/v17/leanback/transition/SlideKitkat": "androidx/leanback/transition/SlideKitkat",
+      "android/support/animation/AnimationHandler$AnimationFrameCallbackProvider": "androidx/animation/AnimationHandler$AnimationFrameCallbackProvider",
+      "android/support/v7/view/menu/ActionMenuItem": "androidx/view/menu/ActionMenuItem",
+      "android/support/v4/view/animation/PathInterpolatorCompat": "androidx/view/animation/PathInterpolatorCompat",
+      "android/support/v7/util/AsyncListUtil$DataCallback": "androidx/util/AsyncListUtil$DataCallback",
+      "android/support/v17/leanback/widget/ListRowPresenter$ListRowPresenterItemBridgeAdapter": "androidx/leanback/widget/ListRowPresenter$ListRowPresenterItemBridgeAdapter",
+      "android/support/v7/mediarouter/R$style": "androidx/mediarouter/R$style",
+      "android/support/customtabs/IPostMessageService$Stub": "androidx/browser/customtabs/IPostMessageService$Stub",
+      "android/support/v17/preference/BuildConfig": "androidx/leanback/preference/BuildConfig",
+      "android/support/wear/widget/CircularProgressLayout$OnTimerFinishedListener": "androidx/wear/widget/CircularProgressLayout$OnTimerFinishedListener",
+      "android/support/v7/widget/ActivityChooserModel$OnChooseActivityListener": "androidx/widget/ActivityChooserModel$OnChooseActivityListener",
+      "android/support/v4/graphics/drawable/DrawableWrapperApi21": "androidx/graphics/drawable/DrawableWrapperApi21",
+      "android/support/design/widget/FloatingActionButton$Size": "androidx/design/widget/FloatingActionButton$Size",
+      "android/support/v4/provider/DocumentFile": "androidx/provider/DocumentFile",
+      "android/support/v7/app/AppCompatDelegateImplBase$AppCompatWindowCallbackBase": "androidx/app/AppCompatDelegateImplBase$AppCompatWindowCallbackBase",
+      "android/support/annotation/AnyThread": "androidx/annotation/AnyThread",
+      "android/support/v13/app/FragmentCompat$FragmentCompatApi24Impl": "androidx/app/FragmentCompat$FragmentCompatApi24Impl",
+      "android/support/wear/ambient/SharedLibraryVersion$VersionHolder": "androidx/wear/ambient/SharedLibraryVersion$VersionHolder",
+      "android/support/v7/app/WindowDecorActionBar$ActionModeImpl": "androidx/app/WindowDecorActionBar$ActionModeImpl",
+      "android/support/constraint/solver/widgets/Guideline": "androidx/constraint/solver/widgets/Guideline",
+      "android/support/v17/leanback/widget/NonOverlappingView": "androidx/leanback/widget/NonOverlappingView",
+      "android/support/v7/preference/ListPreference": "androidx/preference/ListPreference",
+      "android/support/v17/leanback/widget/ShadowOverlayContainer": "androidx/leanback/widget/ShadowOverlayContainer",
+      "android/support/design/internal/NavigationMenuItemView": "androidx/design/internal/NavigationMenuItemView",
+      "android/support/v17/leanback/widget/ArrayObjectAdapter": "androidx/leanback/widget/ArrayObjectAdapter",
+      "android/support/v17/leanback/widget/CursorObjectAdapter": "androidx/leanback/widget/CursorObjectAdapter",
+      "android/support/v17/leanback/R$style": "androidx/leanback/R$style",
+      "android/support/v4/media/MediaBrowserCompatApi21": "androidx/media/MediaBrowserCompatApi21",
+      "android/support/v4/media/MediaBrowserCompatApi23": "androidx/media/MediaBrowserCompatApi23",
+      "android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper": "androidx/leanback/widget/FullWidthDetailsOverviewSharedElementHelper",
+      "android/support/v7/widget/ShareActionProvider$ShareMenuItemOnMenuItemClickListener": "androidx/widget/ShareActionProvider$ShareMenuItemOnMenuItemClickListener",
+      "android/support/v4/media/MediaBrowserCompatApi26": "androidx/media/MediaBrowserCompatApi26",
+      "android/support/v4/print/PrintHelper$Orientation": "androidx/print/PrintHelper$Orientation",
+      "android/support/v4/view/ViewPager$PageTransformer": "androidx/view/ViewPager$PageTransformer",
+      "android/support/transition/ViewGroupOverlayImpl": "androidx/transition/ViewGroupOverlayImpl",
+      "android/support/v4/app/ActivityOptionsCompat$ActivityOptionsCompatApi23Impl": "androidx/app/ActivityOptionsCompat$ActivityOptionsCompatApi23Impl",
+      "android/support/v4/view/ViewPropertyAnimatorListener": "androidx/view/ViewPropertyAnimatorListener",
+      "android/support/transition/Styleable$ChangeBounds": "androidx/transition/Styleable$ChangeBounds",
+      "android/support/annotation/Keep": "androidx/annotation/Keep",
+      "android/support/v4/app/NotificationCompat$DecoratedCustomViewStyle": "androidx/app/NotificationCompat$DecoratedCustomViewStyle",
+      "android/support/v4/app/ShareCompat$IntentReader": "androidx/app/ShareCompat$IntentReader",
+      "android/support/v17/leanback/widget/ActionPresenterSelector$ActionPresenter": "androidx/leanback/widget/ActionPresenterSelector$ActionPresenter",
+      "android/support/v7/util/MessageThreadUtil$MessageQueue": "androidx/util/MessageThreadUtil$MessageQueue",
+      "android/support/annotation/Px": "androidx/annotation/Px",
+      "android/support/v17/leanback/app/SearchFragment$SearchResultProvider": "androidx/leanback/app/SearchFragment$SearchResultProvider",
+      "android/support/v7/app/AppCompatDelegateImplV9$ListMenuDecorView": "androidx/app/AppCompatDelegateImplV9$ListMenuDecorView",
+      "android/support/v17/leanback/transition/TransitionHelper$TransitionHelperStubImpl$TransitionStub": "androidx/leanback/transition/TransitionHelper$TransitionHelperStubImpl$TransitionStub",
+      "android/support/v7/app/AppCompatDelegate": "androidx/app/AppCompatDelegate",
+      "android/support/v17/leanback/app/BrowseFragment$MainFragmentAdapter": "androidx/leanback/app/BrowseFragment$MainFragmentAdapter",
+      "android/support/v17/leanback/widget/ParallaxEffect$IntEffect": "androidx/leanback/widget/ParallaxEffect$IntEffect",
+      "android/support/v7/widget/GridLayout$Alignment": "androidx/widget/GridLayout$Alignment",
+      "android/support/v7/widget/helper/ItemTouchHelper$RecoverAnimation": "androidx/widget/helper/ItemTouchHelper$RecoverAnimation",
+      "android/support/v17/leanback/widget/picker/Picker": "androidx/leanback/widget/picker/Picker",
+      "android/support/v7/gridlayout/R$styleable": "androidx/gridlayout/R$styleable",
+      "android/support/v4/app/FragmentPagerAdapter": "androidx/app/FragmentPagerAdapter",
+      "android/support/v4/graphics/TypefaceCompatBaseImpl$StyleExtractor": "androidx/graphics/TypefaceCompatBaseImpl$StyleExtractor",
+      "android/support/v17/leanback/widget/SearchBar": "androidx/leanback/widget/SearchBar",
+      "android/support/wear/widget/drawer/WearableDrawerController": "androidx/wear/widget/drawer/WearableDrawerController",
+      "android/support/design/widget/FloatingActionButtonImpl$DisabledElevationAnimation": "androidx/design/widget/FloatingActionButtonImpl$DisabledElevationAnimation",
+      "android/support/annotation/FloatRange": "androidx/annotation/FloatRange",
+      "android/support/media/ExifInterface$ByteOrderedDataInputStream": "androidx/media/ExifInterface$ByteOrderedDataInputStream",
+      "android/support/v7/widget/TooltipCompat$Api26ViewCompatImpl": "androidx/widget/TooltipCompat$Api26ViewCompatImpl",
+      "android/support/v7/widget/RecyclerViewAccessibilityDelegate": "androidx/widget/RecyclerViewAccessibilityDelegate",
+      "android/support/v7/widget/AppCompatTextView": "androidx/widget/AppCompatTextView",
+      "android/support/transition/ChangeImageTransform": "androidx/transition/ChangeImageTransform",
+      "android/support/v4/app/SuperNotCalledException": "androidx/app/SuperNotCalledException",
+      "android/support/text/emoji/widget/EmojiTextViewHelper$HelperInternal19": "androidx/text/emoji/widget/EmojiTextViewHelper$HelperInternal19",
+      "android/support/v7/widget/GapWorker$LayoutPrefetchRegistryImpl": "androidx/widget/GapWorker$LayoutPrefetchRegistryImpl",
+      "android/support/v7/app/AppCompatDelegateImplV14$AppCompatWindowCallbackV14": "androidx/app/AppCompatDelegateImplV14$AppCompatWindowCallbackV14",
+      "android/support/v4/widget/TextViewCompat$TextViewCompatApi23Impl": "androidx/widget/TextViewCompat$TextViewCompatApi23Impl",
+      "android/support/v17/leanback/widget/ParallaxEffect$FloatEffect": "androidx/leanback/widget/ParallaxEffect$FloatEffect",
+      "android/support/v4/media/session/MediaSessionCompat": "androidx/media/session/MediaSessionCompat",
+      "android/support/v17/leanback/app/BrowseSupportFragment$FragmentHostImpl": "androidx/leanback/app/BrowseSupportFragment$FragmentHostImpl",
+      "android/support/design/widget/ShadowDrawableWrapper": "androidx/design/widget/ShadowDrawableWrapper",
+      "android/support/design/internal/NavigationMenuPresenter$HeaderViewHolder": "androidx/design/internal/NavigationMenuPresenter$HeaderViewHolder",
+      "android/support/v7/widget/PopupMenu": "androidx/widget/PopupMenu",
+      "android/support/v17/preference/LeanbackListPreferenceDialogFragment$ViewHolder": "androidx/leanback/preference/LeanbackListPreferenceDialogFragment$ViewHolder",
+      "android/support/annotation/BoolRes": "androidx/annotation/BoolRes",
+      "android/support/v7/media/RemotePlaybackClient": "androidx/media/RemotePlaybackClient",
+      "android/support/v4/view/LayoutInflaterCompat$LayoutInflaterCompatApi21Impl": "androidx/view/LayoutInflaterCompat$LayoutInflaterCompatApi21Impl",
+      "android/support/v7/preference/AndroidResources": "androidx/preference/AndroidResources",
+      "android/support/v7/app/AlertController$AlertParams$OnPrepareListViewListener": "androidx/app/AlertController$AlertParams$OnPrepareListViewListener",
+      "android/support/wear/widget/drawer/WearableNavigationDrawerView": "androidx/wear/widget/drawer/WearableNavigationDrawerView",
+      "android/support/v4/media/session/PlaybackStateCompat$ErrorCode": "androidx/media/session/PlaybackStateCompat$ErrorCode",
+      "android/support/v7/widget/ActionMenuView$ActionMenuPresenterCallback": "androidx/widget/ActionMenuView$ActionMenuPresenterCallback",
+      "android/support/v7/app/AlertController": "androidx/app/AlertController",
+      "android/support/v7/widget/FitWindowsViewGroup$OnFitSystemWindowsListener": "androidx/widget/FitWindowsViewGroup$OnFitSystemWindowsListener",
+      "android/support/v4/app/NotificationBuilderWithBuilderAccessor": "androidx/app/NotificationBuilderWithBuilderAccessor",
+      "android/support/v4/view/AbsSavedState": "androidx/view/AbsSavedState",
+      "android/support/v7/media/MediaRouteProvider$ProviderHandler": "androidx/media/MediaRouteProvider$ProviderHandler",
+      "android/support/v7/widget/AbsActionBarView$VisibilityAnimListener": "androidx/widget/AbsActionBarView$VisibilityAnimListener",
+      "android/support/design/internal/TextScale": "androidx/design/internal/TextScale",
+      "android/support/v7/widget/RecyclerViewAccessibilityDelegate$ItemDelegate": "androidx/widget/RecyclerViewAccessibilityDelegate$ItemDelegate",
+      "android/support/v4/widget/SlidingPaneLayout": "androidx/widget/SlidingPaneLayout",
+      "android/support/v17/leanback/widget/ScaleFrameLayout": "androidx/leanback/widget/ScaleFrameLayout",
+      "android/support/v4/app/FragmentTransaction": "androidx/app/FragmentTransaction",
+      "android/support/graphics/drawable/AnimatorInflaterCompat$PathDataEvaluator": "androidx/graphics/drawable/AnimatorInflaterCompat$PathDataEvaluator",
+      "android/support/wear/widget/drawer/WearableActionDrawerView$ActionItemViewHolder": "androidx/wear/widget/drawer/WearableActionDrawerView$ActionItemViewHolder",
+      "android/support/wear/ambient/AmbientDelegate": "androidx/wear/ambient/AmbientDelegate",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$ThumbsUpAction": "androidx/leanback/widget/PlaybackControlsRow$ThumbsUpAction",
+      "android/support/v7/widget/AppCompatSpinner": "androidx/widget/AppCompatSpinner",
+      "android/support/design/widget/NavigationView$SavedState": "androidx/design/widget/NavigationView$SavedState",
+      "android/support/v17/leanback/animation/LogDecelerateInterpolator": "androidx/leanback/animation/LogDecelerateInterpolator",
+      "android/support/v4/media/session/MediaControllerCompatApi21$Callback": "androidx/media/session/MediaControllerCompatApi21$Callback",
+      "android/support/v7/widget/helper/ItemTouchHelper": "androidx/widget/helper/ItemTouchHelper",
+      "android/support/graphics/drawable/AnimatedVectorDrawableCompat$AnimatedVectorDrawableCompatState": "androidx/graphics/drawable/AnimatedVectorDrawableCompat$AnimatedVectorDrawableCompatState",
+      "android/support/v4/graphics/drawable/DrawableWrapperApi14$DrawableWrapperState": "androidx/graphics/drawable/DrawableWrapperApi14$DrawableWrapperState",
+      "android/support/v4/util/DebugUtils": "androidx/util/DebugUtils",
+      "android/support/customtabs/CustomTabsCallback": "androidx/browser/customtabs/CustomTabsCallback",
+      "android/support/v13/app/FragmentCompat": "androidx/app/FragmentCompat",
+      "android/support/v7/widget/RecyclerView$ViewFlinger": "androidx/widget/RecyclerView$ViewFlinger",
+      "android/support/v17/leanback/app/BrowseFragment$SetSelectionRunnable": "androidx/leanback/app/BrowseFragment$SetSelectionRunnable",
+      "android/support/mediacompat/BuildConfig": "androidx/mediacompat/BuildConfig",
+      "android/support/customtabs/CustomTabsIntent$Builder": "androidx/browser/customtabs/CustomTabsIntent$Builder",
+      "android/support/v4/util/MapCollections$ValuesCollection": "androidx/util/MapCollections$ValuesCollection",
+      "android/support/v17/leanback/widget/StaggeredGrid": "androidx/leanback/widget/StaggeredGrid",
+      "android/support/v13/app/FragmentTabHost$SavedState": "androidx/app/FragmentTabHost$SavedState",
+      "android/support/v4/media/MediaBrowserServiceCompatApi23": "androidx/media/MediaBrowserServiceCompatApi23",
+      "android/support/v4/media/session/MediaButtonReceiver": "androidx/media/session/MediaButtonReceiver",
+      "android/support/v17/leanback/graphics/CompositeDrawable$CompositeState": "androidx/leanback/graphics/CompositeDrawable$CompositeState",
+      "android/support/transition/WindowIdApi14": "androidx/transition/WindowIdApi14",
+      "android/support/v4/media/MediaBrowserServiceCompatApi26": "androidx/media/MediaBrowserServiceCompatApi26",
+      "android/support/v4/media/MediaBrowserServiceCompatApi21": "androidx/media/MediaBrowserServiceCompatApi21",
+      "android/support/transition/WindowIdApi18": "androidx/transition/WindowIdApi18",
+      "android/support/v7/graphics/ColorCutQuantizer": "androidx/graphics/palette/ColorCutQuantizer",
+      "android/support/v4/media/session/MediaSessionCompatApi23$Callback": "androidx/media/session/MediaSessionCompatApi23$Callback",
+      "android/support/v17/leanback/widget/DetailsOverviewRowPresenter$ActionsItemBridgeAdapter": "androidx/leanback/widget/DetailsOverviewRowPresenter$ActionsItemBridgeAdapter",
+      "android/support/v7/app/MediaRouteButton$RemoteIndicatorLoader": "androidx/app/MediaRouteButton$RemoteIndicatorLoader",
+      "android/support/v7/preference/ListPreference$SavedState": "androidx/preference/ListPreference$SavedState",
+      "android/support/v7/media/RegisteredMediaRouteProvider$ReceiveHandler": "androidx/media/RegisteredMediaRouteProvider$ReceiveHandler",
+      "android/support/v17/leanback/widget/MediaRowFocusView": "androidx/leanback/widget/MediaRowFocusView",
+      "android/support/v14/preference/PreferenceFragment$OnPreferenceDisplayDialogCallback": "androidx/preference/PreferenceFragment$OnPreferenceDisplayDialogCallback",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$HighQualityAction": "androidx/leanback/widget/PlaybackControlsRow$HighQualityAction",
+      "android/support/v17/leanback/app/BaseRowSupportFragment": "androidx/leanback/app/BaseRowSupportFragment",
+      "android/support/v17/leanback/app/BrowseSupportFragment$MainFragmentItemViewSelectedListener": "androidx/leanback/app/BrowseSupportFragment$MainFragmentItemViewSelectedListener",
+      "android/support/v17/leanback/widget/StreamingTextView": "androidx/leanback/widget/StreamingTextView",
+      "android/support/transition/GhostViewImpl$Creator": "androidx/transition/GhostViewImpl$Creator",
+      "android/support/wear/widget/drawer/WearableActionDrawerMenu$WearableActionDrawerMenuItem": "androidx/wear/widget/drawer/WearableActionDrawerMenu$WearableActionDrawerMenuItem",
+      "android/support/v4/media/MediaBrowserCompat$Subscription": "androidx/media/MediaBrowserCompat$Subscription",
+      "android/support/v4/view/PagerTitleStrip$SingleLineAllCapsTransform": "androidx/view/PagerTitleStrip$SingleLineAllCapsTransform",
+      "android/support/v4/media/session/MediaControllerCompatApi24$TransportControls": "androidx/media/session/MediaControllerCompatApi24$TransportControls",
+      "android/support/v7/app/ActionBarDrawerToggleHoneycomb": "androidx/app/ActionBarDrawerToggleHoneycomb",
+      "android/support/v4/graphics/TypefaceCompatBaseImpl": "androidx/graphics/TypefaceCompatBaseImpl",
+      "android/support/transition/TranslationAnimationCreator": "androidx/transition/TranslationAnimationCreator",
+      "android/support/v7/app/MediaRouteChooserDialog": "androidx/app/MediaRouteChooserDialog",
+      "android/support/v17/leanback/widget/Parallax$FloatPropertyMarkerValue": "androidx/leanback/widget/Parallax$FloatPropertyMarkerValue",
+      "android/support/v4/widget/FocusStrategy$SequentialComparator": "androidx/widget/FocusStrategy$SequentialComparator",
+      "android/support/v4/media/MediaMetadataCompat$TextKey": "androidx/media/MediaMetadataCompat$TextKey",
+      "android/support/v17/leanback/app/BrowseSupportFragment": "androidx/leanback/app/BrowseSupportFragment",
+      "android/support/v7/widget/ListViewCompat$GateKeeperDrawable": "androidx/widget/ListViewCompat$GateKeeperDrawable",
+      "android/support/v4/media/session/MediaControllerCompatApi23$TransportControls": "androidx/media/session/MediaControllerCompatApi23$TransportControls",
+      "android/support/v13/view/inputmethod/InputConnectionCompat$InputContentInfoCompatApi25Impl": "androidx/view/inputmethod/InputConnectionCompat$InputContentInfoCompatApi25Impl",
+      "android/support/v7/preference/PreferenceManager$OnDisplayPreferenceDialogListener": "androidx/preference/PreferenceManager$OnDisplayPreferenceDialogListener",
+      "android/support/v7/media/MediaRouterJellybeanMr1$IsConnectingWorkaround": "androidx/media/MediaRouterJellybeanMr1$IsConnectingWorkaround",
+      "android/support/v4/view/accessibility/AccessibilityManagerCompat$TouchExplorationStateChangeListenerWrapper": "androidx/view/accessibility/AccessibilityManagerCompat$TouchExplorationStateChangeListenerWrapper",
+      "android/support/v7/widget/RecyclerView$ItemDecoration": "androidx/widget/RecyclerView$ItemDecoration",
+      "android/support/v4/widget/Space": "androidx/widget/Space",
+      "android/support/v17/leanback/app/BrowseSupportFragment$ExpandPreLayout": "androidx/leanback/app/BrowseSupportFragment$ExpandPreLayout",
+      "android/support/media/tv/TvContractCompat$ProgramColumns": "androidx/media/tv/TvContractCompat$ProgramColumns",
+      "android/support/v7/widget/DecorToolbar": "androidx/widget/DecorToolbar",
+      "android/support/design/widget/CheckableImageButton": "androidx/design/widget/CheckableImageButton",
+      "android/support/v4/widget/ImageViewCompat": "androidx/widget/ImageViewCompat",
+      "android/support/v7/preference/UnPressableLinearLayout": "androidx/preference/UnPressableLinearLayout",
+      "android/support/wear/widget/SwipeDismissFrameLayout$MyOnPreSwipeListener": "androidx/wear/widget/SwipeDismissFrameLayout$MyOnPreSwipeListener",
+      "android/support/v4/widget/CircularProgressDrawable": "androidx/widget/CircularProgressDrawable",
+      "android/support/design/R$string": "androidx/design/R$string",
+      "android/support/design/R$color": "androidx/design/R$color",
+      "android/support/v7/widget/TintInfo": "androidx/widget/TintInfo",
+      "android/support/v17/leanback/widget/HeaderItem": "androidx/leanback/widget/HeaderItem",
+      "android/support/v7/media/MediaRouter$RouteInfo$ConnectionState": "androidx/media/MediaRouter$RouteInfo$ConnectionState",
+      "android/support/v7/widget/DialogTitle": "androidx/widget/DialogTitle",
+      "android/support/v17/leanback/media/PlaybackTransportControlGlue$UpdatePlaybackStateHandler": "androidx/leanback/media/PlaybackTransportControlGlue$UpdatePlaybackStateHandler",
+      "android/support/v7/widget/RecyclerView$LayoutParams": "androidx/widget/RecyclerView$LayoutParams",
+      "android/support/v4/media/session/PlaybackStateCompatApi21$CustomAction": "androidx/media/session/PlaybackStateCompatApi21$CustomAction",
+      "android/support/customtabs/CustomTabsService": "androidx/browser/customtabs/CustomTabsService",
+      "android/support/v17/leanback/widget/GuidanceStylist$Guidance": "androidx/leanback/widget/GuidanceStylist$Guidance",
+      "android/support/v4/view/ViewCompat$ViewCompatApi23Impl": "androidx/view/ViewCompat$ViewCompatApi23Impl",
+      "android/support/wear/widget/WearableLinearLayoutManager": "androidx/wear/widget/WearableLinearLayoutManager",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$MultiAction": "androidx/leanback/widget/PlaybackControlsRow$MultiAction",
+      "android/support/v17/leanback/R$integer": "androidx/leanback/R$integer",
+      "android/support/v4/content/ModernAsyncTask$WorkerRunnable": "androidx/content/ModernAsyncTask$WorkerRunnable",
+      "android/support/v4/app/FragmentTabHost$DummyTabFactory": "androidx/app/FragmentTabHost$DummyTabFactory",
+      "android/support/v7/widget/AppCompatSpinner$DropDownAdapter": "androidx/widget/AppCompatSpinner$DropDownAdapter",
+      "android/support/v7/app/ToolbarActionBar$MenuBuilderCallback": "androidx/app/ToolbarActionBar$MenuBuilderCallback",
+      "android/support/v4/content/Loader": "androidx/content/Loader",
+      "android/support/v7/widget/MenuPopupWindow": "androidx/widget/MenuPopupWindow",
+      "android/support/v4/graphics/BitmapCompat$BitmapCompatApi19Impl": "androidx/graphics/BitmapCompat$BitmapCompatApi19Impl",
+      "android/support/v4/app/FrameMetricsAggregator$MetricType": "androidx/app/FrameMetricsAggregator$MetricType",
+      "android/support/v17/leanback/widget/picker/PickerUtility$TimeConstant": "androidx/leanback/widget/picker/PickerUtility$TimeConstant",
+      "android/support/v4/view/NestedScrollingParent2": "androidx/view/NestedScrollingParent2",
+      "android/support/design/widget/Snackbar$SnackbarLayout": "androidx/design/widget/Snackbar$SnackbarLayout",
+      "android/support/v4/app/LoaderManager": "androidx/app/LoaderManager",
+      "android/support/v17/leanback/app/BaseSupportFragment": "androidx/leanback/app/BaseSupportFragment",
+      "android/support/design/internal/NavigationMenuPresenter$NavigationMenuItem": "androidx/design/internal/NavigationMenuPresenter$NavigationMenuItem",
+      "android/support/v4/view/accessibility/AccessibilityNodeInfoCompat$RangeInfoCompat": "androidx/view/accessibility/AccessibilityNodeInfoCompat$RangeInfoCompat",
+      "android/support/text/emoji/MetadataRepo": "androidx/text/emoji/MetadataRepo",
+      "android/support/v17/leanback/widget/ItemAlignment": "androidx/leanback/widget/ItemAlignment",
+      "android/support/design/widget/TextInputEditText": "androidx/design/widget/TextInputEditText",
+      "android/support/v4/app/FragmentTransitionImpl": "androidx/app/FragmentTransitionImpl",
+      "android/support/animation/SpringAnimation": "androidx/animation/SpringAnimation",
+      "android/support/annotation/CheckResult": "androidx/annotation/CheckResult",
+      "android/support/v7/widget/AppCompatSpinner$DropdownPopup": "androidx/widget/AppCompatSpinner$DropdownPopup",
+      "android/support/v7/widget/ActivityChooserModel$ActivitySorter": "androidx/widget/ActivityChooserModel$ActivitySorter",
+      "android/support/wear/widget/drawer/WearableDrawerLayout$ClosePeekRunnable": "androidx/wear/widget/drawer/WearableDrawerLayout$ClosePeekRunnable",
+      "android/support/design/widget/TextInputLayout$SavedState": "androidx/design/widget/TextInputLayout$SavedState",
+      "android/support/v17/leanback/widget/picker/PickerUtility$DateConstant": "androidx/leanback/widget/picker/PickerUtility$DateConstant",
+      "android/support/v13/app/FragmentTabHost": "androidx/app/FragmentTabHost",
+      "android/support/v7/widget/ScrollingTabContainerView$TabAdapter": "androidx/widget/ScrollingTabContainerView$TabAdapter",
+      "android/support/v7/widget/ActionBarContextView": "androidx/widget/ActionBarContextView",
+      "android/support/design/internal/NavigationMenuPresenter$NavigationMenuHeaderItem": "androidx/design/internal/NavigationMenuPresenter$NavigationMenuHeaderItem",
+      "android/support/v17/leanback/graphics/CompositeDrawable": "androidx/leanback/graphics/CompositeDrawable",
+      "android/support/v7/preference/Preference$OnPreferenceChangeListener": "androidx/preference/Preference$OnPreferenceChangeListener",
+      "android/support/v4/media/MediaBrowserServiceCompat$BrowserRoot": "androidx/media/MediaBrowserServiceCompat$BrowserRoot",
+      "android/support/text/emoji/MetadataListReader$OpenTypeReader": "androidx/text/emoji/MetadataListReader$OpenTypeReader",
+      "android/support/v7/media/MediaRouterJellybean$VolumeCallbackProxy": "androidx/media/MediaRouterJellybean$VolumeCallbackProxy",
+      "android/support/v4/app/OneShotPreDrawListener": "androidx/app/OneShotPreDrawListener",
+      "android/support/design/widget/BottomNavigationView$OnNavigationItemSelectedListener": "androidx/design/widget/BottomNavigationView$OnNavigationItemSelectedListener",
+      "android/support/v7/widget/ActionMenuView": "androidx/widget/ActionMenuView",
+      "android/support/v4/view/NestedScrollingChildHelper": "androidx/view/NestedScrollingChildHelper",
+      "android/support/percent/PercentFrameLayout": "androidx/PercentFrameLayout",
+      "android/support/annotation/AnyRes": "androidx/annotation/AnyRes",
+      "android/support/wear/widget/CircledImageView$OvalShadowPainter": "androidx/wear/widget/CircledImageView$OvalShadowPainter",
+      "android/support/media/tv/TvContractCompat$Channels$Logo": "androidx/media/tv/TvContractCompat$Channels$Logo",
+      "android/support/v4/view/animation/LookupTableInterpolator": "androidx/view/animation/LookupTableInterpolator",
+      "android/support/v7/app/MediaRouteControllerDialog$MediaControllerCallback": "androidx/app/MediaRouteControllerDialog$MediaControllerCallback",
+      "android/support/v7/widget/FitWindowsViewGroup": "androidx/widget/FitWindowsViewGroup",
+      "android/support/v7/widget/ActionBarOverlayLayout$ActionBarVisibilityCallback": "androidx/widget/ActionBarOverlayLayout$ActionBarVisibilityCallback",
+      "android/support/wear/ambient/AmbientMode": "androidx/wear/ambient/AmbientMode",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$SkipPreviousAction": "androidx/leanback/widget/PlaybackControlsRow$SkipPreviousAction",
+      "android/support/v4/app/NotificationCompat$Builder": "androidx/app/NotificationCompat$Builder",
+      "android/support/design/R$layout": "androidx/design/R$layout",
+      "android/support/transition/FragmentTransitionSupport": "androidx/transition/FragmentTransitionSupport",
+      "android/support/v4/app/Fragment$AnimationInfo": "androidx/app/Fragment$AnimationInfo",
+      "android/support/transition/ChangeTransform": "androidx/transition/ChangeTransform",
+      "android/support/v7/gridlayout/BuildConfig": "androidx/gridlayout/BuildConfig",
+      "android/support/v4/view/ViewCompat$FocusRelativeDirection": "androidx/view/ViewCompat$FocusRelativeDirection",
+      "android/support/customtabs/CustomTabsSessionToken$MockCallback": "androidx/browser/customtabs/CustomTabsSessionToken$MockCallback",
+      "android/support/v4/app/TaskStackBuilder$TaskStackBuilderBaseImpl": "androidx/app/TaskStackBuilder$TaskStackBuilderBaseImpl",
+      "android/support/v4/media/AudioAttributesCompat$Builder": "androidx/media/AudioAttributesCompat$Builder",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$ThumbsAction": "androidx/leanback/widget/PlaybackControlsRow$ThumbsAction",
+      "android/support/v7/media/MediaItemStatus$Builder": "androidx/media/MediaItemStatus$Builder",
+      "android/support/v17/leanback/app/OnboardingSupportFragment": "androidx/leanback/app/OnboardingSupportFragment",
+      "android/support/v7/widget/LinearLayoutCompat$OrientationMode": "androidx/widget/LinearLayoutCompat$OrientationMode",
+      "android/support/v7/widget/AppCompatImageButton": "androidx/widget/AppCompatImageButton",
+      "android/support/v7/app/AppCompatViewInflater$DeclaredOnClickListener": "androidx/app/AppCompatViewInflater$DeclaredOnClickListener",
+      "android/support/v7/view/SupportMenuInflater$InflatedOnMenuItemClickListener": "androidx/view/SupportMenuInflater$InflatedOnMenuItemClickListener",
+      "android/support/v4/widget/ContentLoadingProgressBar": "androidx/widget/ContentLoadingProgressBar",
+      "android/support/v4/hardware/display/DisplayManagerCompat$DisplayManagerCompatApi17Impl": "androidx/hardware/display/DisplayManagerCompat$DisplayManagerCompatApi17Impl",
+      "android/support/v17/leanback/app/BrowseFragment$ListRowFragmentFactory": "androidx/leanback/app/BrowseFragment$ListRowFragmentFactory",
+      "android/support/v7/app/MediaRouteChooserDialog$RouteAdapter": "androidx/app/MediaRouteChooserDialog$RouteAdapter",
+      "android/support/v7/view/ContextThemeWrapper": "androidx/view/ContextThemeWrapper",
+      "android/support/design/widget/CoordinatorLayout$OnPreDrawListener": "androidx/design/widget/CoordinatorLayout$OnPreDrawListener",
+      "android/support/v4/util/ContainerHelpers": "androidx/util/ContainerHelpers",
+      "android/support/design/widget/SnackbarManager$Callback": "androidx/design/widget/SnackbarManager$Callback",
+      "android/support/design/internal/ForegroundLinearLayout": "androidx/design/internal/ForegroundLinearLayout",
+      "android/support/v4/app/NotificationCompatJellybean": "androidx/app/NotificationCompatJellybean",
+      "android/support/design/widget/CoordinatorLayout$Behavior": "androidx/design/widget/CoordinatorLayout$Behavior",
+      "android/support/v4/BuildConfig": "androidx/BuildConfig",
+      "android/support/compat/R$dimen": "androidx/compat/R$dimen",
+      "android/support/v17/leanback/app/BrowseSupportFragment$MainFragmentAdapterProvider": "androidx/leanback/app/BrowseSupportFragment$MainFragmentAdapterProvider",
+      "android/support/wear/widget/SwipeDismissLayout$OnDismissedListener": "androidx/wear/widget/SwipeDismissLayout$OnDismissedListener",
+      "android/support/v7/recyclerview/R": "androidx/recyclerview/R",
+      "android/support/v4/widget/SlidingPaneLayout$LayoutParams": "androidx/widget/SlidingPaneLayout$LayoutParams",
+      "android/support/v7/app/ToolbarActionBar$ActionMenuPresenterCallback": "androidx/app/ToolbarActionBar$ActionMenuPresenterCallback",
+      "android/support/v4/widget/DrawerLayout$DrawerListener": "androidx/widget/DrawerLayout$DrawerListener",
+      "android/support/v4/net/ConnectivityManagerCompat$RestrictBackgroundStatus": "androidx/net/ConnectivityManagerCompat$RestrictBackgroundStatus",
+      "android/support/v4/media/MediaMetadataCompat$RatingKey": "androidx/media/MediaMetadataCompat$RatingKey",
+      "android/support/v4/view/ActionProvider": "androidx/view/ActionProvider",
+      "android/support/v7/app/MediaRouteControllerDialogFragment": "androidx/app/MediaRouteControllerDialogFragment",
+      "android/support/v7/widget/TooltipCompatHandler": "androidx/widget/TooltipCompatHandler",
+      "android/support/design/widget/TabLayout$TabLayoutOnPageChangeListener": "androidx/design/widget/TabLayout$TabLayoutOnPageChangeListener",
+      "android/support/v7/widget/RecyclerView$ItemAnimatorRestoreListener": "androidx/widget/RecyclerView$ItemAnimatorRestoreListener",
+      "android/support/app/recommendation/ContentRecommendation$ContentType": "androidx/app/recommendation/ContentRecommendation$ContentType",
+      "android/support/v7/app/AlertController$AlertParams": "androidx/app/AlertController$AlertParams",
+      "android/support/v4/widget/DrawerLayout$SimpleDrawerListener": "androidx/widget/DrawerLayout$SimpleDrawerListener",
+      "android/support/v17/leanback/widget/FocusHighlightHelper$HeaderItemFocusHighlight": "androidx/leanback/widget/FocusHighlightHelper$HeaderItemFocusHighlight",
+      "android/support/v7/app/MediaRouteChooserDialog$MediaRouterCallback": "androidx/app/MediaRouteChooserDialog$MediaRouterCallback",
+      "android/support/v4/view/ViewCompat$ImportantForAccessibility": "androidx/view/ViewCompat$ImportantForAccessibility",
+      "android/support/v7/media/MediaRouterJellybean$RouteInfo": "androidx/media/MediaRouterJellybean$RouteInfo",
+      "android/support/v17/leanback/widget/SpeechRecognitionCallback": "androidx/leanback/widget/SpeechRecognitionCallback",
+      "android/support/v4/media/MediaBrowserCompatApi26$SubscriptionCallback": "androidx/media/MediaBrowserCompatApi26$SubscriptionCallback",
+      "android/support/media/tv/Program": "androidx/media/tv/Program",
+      "android/support/v4/view/accessibility/AccessibilityNodeInfoCompat$AccessibilityActionCompat": "androidx/view/accessibility/AccessibilityNodeInfoCompat$AccessibilityActionCompat",
+      "android/support/v4/app/FragmentTransitionCompat21": "androidx/app/FragmentTransitionCompat21",
+      "android/support/v7/media/MediaRouteSelector$Builder": "androidx/media/MediaRouteSelector$Builder",
+      "android/support/v4/hardware/fingerprint/FingerprintManagerCompat": "androidx/hardware/fingerprint/FingerprintManagerCompat",
+      "android/support/v17/leanback/app/HeadersFragment": "androidx/leanback/app/HeadersFragment",
+      "android/support/v17/leanback/R$dimen": "androidx/leanback/R$dimen",
+      "android/support/v4/content/res/ResourcesCompat": "androidx/content/res/ResourcesCompat",
+      "android/support/v4/view/ViewPager$SavedState": "androidx/view/ViewPager$SavedState",
+      "android/support/v17/leanback/widget/StaticShadowHelper$ShadowHelperJbmr2Impl": "androidx/leanback/widget/StaticShadowHelper$ShadowHelperJbmr2Impl",
+      "android/support/v4/widget/SwipeRefreshLayout": "androidx/widget/SwipeRefreshLayout",
+      "android/support/v17/leanback/widget/StaticShadowHelper$ShadowHelperVersionImpl": "androidx/leanback/widget/StaticShadowHelper$ShadowHelperVersionImpl",
+      "android/support/v4/os/ResultReceiver": "androidx/os/ResultReceiver",
+      "android/support/v17/leanback/widget/BaseCardView$InfoOffsetAnimation": "androidx/leanback/widget/BaseCardView$InfoOffsetAnimation",
+      "android/support/design/widget/SwipeDismissBehavior$SettleRunnable": "androidx/design/widget/SwipeDismissBehavior$SettleRunnable",
+      "android/support/v13/view/inputmethod/InputConnectionCompat$InputContentInfoCompatBaseImpl": "androidx/view/inputmethod/InputConnectionCompat$InputContentInfoCompatBaseImpl",
+      "android/support/v17/leanback/widget/FacetProvider": "androidx/leanback/widget/FacetProvider",
+      "android/support/v7/widget/FitWindowsLinearLayout": "androidx/widget/FitWindowsLinearLayout",
+      "android/support/v4/widget/SwipeProgressBar": "androidx/widget/SwipeProgressBar",
+      "android/support/v7/widget/ActionMenuPresenter$OverflowPopup": "androidx/widget/ActionMenuPresenter$OverflowPopup",
+      "android/support/v7/widget/AppCompatImageHelper": "androidx/widget/AppCompatImageHelper",
+      "android/support/v4/text/TextDirectionHeuristicsCompat": "androidx/text/TextDirectionHeuristicsCompat",
+      "android/support/compat/R$color": "androidx/compat/R$color",
+      "android/support/transition/Transition$EpicenterCallback": "androidx/transition/Transition$EpicenterCallback",
+      "android/support/transition/PropertyValuesHolderUtilsApi14": "androidx/transition/PropertyValuesHolderUtilsApi14",
+      "android/support/v17/leanback/widget/ObjectAdapter$DataObservable": "androidx/leanback/widget/ObjectAdapter$DataObservable",
+      "android/support/multidex/ZipUtil": "androidx/multidex/ZipUtil",
+      "android/support/v7/view/menu/MenuDialogHelper": "androidx/view/menu/MenuDialogHelper",
+      "android/support/v17/preference/R$id": "androidx/leanback/preference/R$id",
+      "android/support/v4/app/BundleCompat": "androidx/app/BundleCompat",
+      "android/support/v4/media/session/IMediaSession$Stub$Proxy": "androidx/media/session/IMediaSession$Stub$Proxy",
+      "android/support/v7/widget/AppCompatTextHelper": "androidx/widget/AppCompatTextHelper",
+      "android/support/v7/view/ActionMode$Callback": "androidx/view/ActionMode$Callback",
+      "android/support/v17/leanback/app/RowsSupportFragment": "androidx/leanback/app/RowsSupportFragment",
+      "android/support/v17/leanback/app/GuidedStepFragment$DummyFragment": "androidx/leanback/app/GuidedStepFragment$DummyFragment",
+      "android/support/v7/widget/util/SortedListAdapterCallback": "androidx/widget/util/SortedListAdapterCallback",
+      "android/support/design/internal/BottomNavigationPresenter$SavedState": "androidx/design/internal/BottomNavigationPresenter$SavedState",
+      "android/support/v7/widget/LinearSmoothScroller": "androidx/widget/LinearSmoothScroller",
+      "android/support/v17/leanback/media/MediaPlayerGlue$VideoPlayerSurfaceHolderCallback": "androidx/leanback/media/MediaPlayerGlue$VideoPlayerSurfaceHolderCallback",
+      "android/support/v7/preference/Preference": "androidx/preference/Preference",
+      "android/support/v4/os/UserManagerCompat": "androidx/os/UserManagerCompat",
+      "android/support/v7/widget/GridLayoutManager$DefaultSpanSizeLookup": "androidx/widget/GridLayoutManager$DefaultSpanSizeLookup",
+      "android/support/v17/leanback/app/PlaybackFragment": "androidx/leanback/app/PlaybackFragment",
+      "android/support/transition/ViewOverlayImpl": "androidx/transition/ViewOverlayImpl",
+      "android/support/transition/ViewOverlayApi14$OverlayViewGroup$TouchInterceptor": "androidx/transition/ViewOverlayApi14$OverlayViewGroup$TouchInterceptor",
+      "android/support/v7/view/menu/MenuAdapter": "androidx/view/menu/MenuAdapter",
+      "android/support/v4/app/NotificationCompat$MessagingStyle$Message": "androidx/app/NotificationCompat$MessagingStyle$Message",
+      "android/support/v4/graphics/drawable/DrawableWrapperApi21$DrawableWrapperStateLollipop": "androidx/graphics/drawable/DrawableWrapperApi21$DrawableWrapperStateLollipop",
+      "android/support/coreutils/BuildConfig": "androidx/coreutils/BuildConfig",
+      "android/support/v17/leanback/widget/ItemAlignmentFacet$ItemAlignmentDef": "androidx/leanback/widget/ItemAlignmentFacet$ItemAlignmentDef",
+      "android/support/v4/content/SharedPreferencesCompat": "androidx/content/SharedPreferencesCompat",
+      "android/support/v4/app/FragmentManager$BackStackEntry": "androidx/app/FragmentManager$BackStackEntry",
+      "android/support/transition/PropertyValuesHolderUtilsApi21": "androidx/transition/PropertyValuesHolderUtilsApi21",
+      "android/support/v17/leanback/R$color": "androidx/leanback/R$color",
+      "android/support/v7/view/menu/MenuView": "androidx/view/menu/MenuView",
+      "android/support/transition/Transition": "androidx/transition/Transition",
+      "android/support/v17/leanback/app/PlaybackFragmentGlueHost": "androidx/leanback/app/PlaybackFragmentGlueHost",
+      "android/support/v7/graphics/Target": "androidx/graphics/palette/Target",
+      "android/support/v7/view/StandaloneActionMode": "androidx/view/StandaloneActionMode",
+      "android/support/v13/view/DragAndDropPermissionsCompat$Api24DragAndDropPermissionsCompatImpl": "androidx/view/DragAndDropPermissionsCompat$Api24DragAndDropPermissionsCompatImpl",
+      "android/support/v7/widget/ViewInfoStore$ProcessCallback": "androidx/widget/ViewInfoStore$ProcessCallback",
+      "android/support/v4/media/session/MediaSessionCompatApi24": "androidx/media/session/MediaSessionCompatApi24",
+      "android/support/v4/widget/CursorFilter": "androidx/widget/CursorFilter",
+      "android/support/v4/media/session/MediaSessionCompatApi23": "androidx/media/session/MediaSessionCompatApi23",
+      "android/support/v4/media/session/MediaSessionCompatApi22": "androidx/media/session/MediaSessionCompatApi22",
+      "android/support/v7/app/ActionBarDrawerToggle$DelegateProvider": "androidx/app/ActionBarDrawerToggle$DelegateProvider",
+      "android/support/v4/media/session/MediaSessionCompatApi21": "androidx/media/session/MediaSessionCompatApi21",
+      "android/support/v7/widget/RecyclerView$OnItemTouchListener": "androidx/widget/RecyclerView$OnItemTouchListener",
+      "android/support/v4/media/MediaBrowserServiceCompat$ServiceHandler": "androidx/media/MediaBrowserServiceCompat$ServiceHandler",
+      "android/support/v4/view/PagerTitleStrip": "androidx/widget/PagerTitleStrip",
+      "android/support/v17/leanback/media/MediaPlayerAdapter$VideoPlayerSurfaceHolderCallback": "androidx/leanback/media/MediaPlayerAdapter$VideoPlayerSurfaceHolderCallback",
+      "android/support/v7/widget/ButtonBarLayout": "androidx/widget/ButtonBarLayout",
+      "android/support/annotation/PluralsRes": "androidx/annotation/PluralsRes",
+      "android/support/v7/appcompat/R$styleable": "androidx/appcompat/R$styleable",
+      "android/support/v7/widget/Toolbar": "androidx/widget/Toolbar",
+      "android/support/v17/leanback/app/DetailsFragmentBackgroundController": "androidx/leanback/app/DetailsFragmentBackgroundController",
+      "android/support/v7/view/menu/CascadingMenuPopup$CascadingMenuInfo": "androidx/view/menu/CascadingMenuPopup$CascadingMenuInfo",
+      "android/support/wear/widget/RoundedDrawable": "androidx/wear/widget/RoundedDrawable",
+      "android/support/v4/math/MathUtils": "androidx/math/MathUtils",
+      "android/support/design/widget/FloatingActionButton": "androidx/design/widget/FloatingActionButton",
+      "android/support/v7/mediarouter/R$drawable": "androidx/mediarouter/R$drawable",
+      "android/support/v4/view/MenuCompat": "androidx/view/MenuCompat",
+      "android/support/v17/leanback/widget/ListRowPresenter$SelectItemViewHolderTask": "androidx/leanback/widget/ListRowPresenter$SelectItemViewHolderTask",
+      "android/support/v7/appcompat/R$color": "androidx/appcompat/R$color",
+      "android/support/media/tv/BaseProgram$Builder": "androidx/media/tv/BaseProgram$Builder",
+      "android/support/v17/leanback/widget/ControlButtonPresenterSelector": "androidx/leanback/widget/ControlButtonPresenterSelector",
+      "android/support/v4/util/MapCollections$KeySet": "androidx/util/MapCollections$KeySet",
+      "android/support/annotation/XmlRes": "androidx/annotation/XmlRes",
+      "android/support/v7/widget/RecyclerView$LayoutManager$Properties": "androidx/widget/RecyclerView$LayoutManager$Properties",
+      "android/support/v4/media/MediaBrowserCompat$ConnectionCallback$ConnectionCallbackInternal": "androidx/media/MediaBrowserCompat$ConnectionCallback$ConnectionCallbackInternal",
+      "android/support/v4/app/RemoteInput$Builder": "androidx/app/RemoteInput$Builder",
+      "android/support/wear/widget/WearableRecyclerView": "androidx/wear/widget/WearableRecyclerView",
+      "android/support/v7/app/AppCompatDialog": "androidx/app/AppCompatDialog",
+      "android/support/v4/app/NotificationManagerCompat$SideChannelManager$ListenerRecord": "androidx/app/NotificationManagerCompat$SideChannelManager$ListenerRecord",
+      "android/support/v4/print/PrintHelper$OnPrintFinishCallback": "androidx/print/PrintHelper$OnPrintFinishCallback",
+      "android/support/v17/leanback/app/FragmentUtil": "androidx/leanback/app/FragmentUtil",
+      "android/support/v17/leanback/widget/RowPresenter$ContainerViewHolder": "androidx/leanback/widget/RowPresenter$ContainerViewHolder",
+      "android/support/v4/media/session/MediaControllerCompat$TransportControlsApi24": "androidx/media/session/MediaControllerCompat$TransportControlsApi24",
+      "android/support/v13/view/inputmethod/InputContentInfoCompat$InputContentInfoCompatImpl": "androidx/view/inputmethod/InputContentInfoCompat$InputContentInfoCompatImpl",
+      "android/support/v17/preference/LeanbackListPreferenceDialogFragment$ViewHolder$OnItemClickListener": "androidx/leanback/preference/LeanbackListPreferenceDialogFragment$ViewHolder$OnItemClickListener",
+      "android/support/v17/leanback/app/BackgroundManager$TranslucentLayerDrawable": "androidx/leanback/app/BackgroundManager$TranslucentLayerDrawable",
+      "android/support/v4/app/FragmentManagerState": "androidx/app/FragmentManagerState",
+      "android/support/v4/media/session/MediaControllerCompat$TransportControlsApi23": "androidx/media/session/MediaControllerCompat$TransportControlsApi23",
+      "android/support/v4/view/AsyncLayoutInflater$BasicInflater": "androidx/view/AsyncLayoutInflater$BasicInflater",
+      "android/support/v7/appcompat/R$dimen": "androidx/appcompat/R$dimen",
+      "android/support/v4/media/session/MediaControllerCompat$TransportControlsApi21": "androidx/media/session/MediaControllerCompat$TransportControlsApi21",
+      "android/support/wear/widget/CircularProgressLayout": "androidx/wear/widget/CircularProgressLayout",
+      "android/support/v7/media/SystemMediaRouteProvider$JellybeanMr1Impl": "androidx/media/SystemMediaRouteProvider$JellybeanMr1Impl",
+      "android/support/customtabs/ICustomTabsCallback$Stub": "androidx/browser/customtabs/ICustomTabsCallback$Stub",
+      "android/support/v17/leanback/widget/RowPresenter$ViewHolder": "androidx/leanback/widget/RowPresenter$ViewHolder",
+      "android/support/v7/widget/RecyclerView$LayoutManager$LayoutPrefetchRegistry": "androidx/widget/RecyclerView$LayoutManager$LayoutPrefetchRegistry",
+      "android/support/v4/media/MediaBrowserServiceCompatApi23$MediaBrowserServiceAdaptor": "androidx/media/MediaBrowserServiceCompatApi23$MediaBrowserServiceAdaptor",
+      "android/support/v17/leanback/app/ListRowDataAdapter": "androidx/leanback/app/ListRowDataAdapter",
+      "android/support/v4/graphics/drawable/DrawableWrapper": "androidx/graphics/drawable/DrawableWrapper",
+      "android/support/media/tv/BuildConfig": "androidx/media/tv/BuildConfig",
+      "android/support/v7/widget/SuggestionsAdapter": "androidx/widget/SuggestionsAdapter",
+      "android/support/v4/widget/TextViewCompat": "androidx/widget/TextViewCompat",
+      "android/support/animation/FlingAnimation": "androidx/animation/FlingAnimation",
+      "android/support/media/tv/PreviewProgram$Builder": "androidx/media/tv/PreviewProgram$Builder",
+      "android/support/v7/widget/RecyclerView$AdapterDataObservable": "androidx/widget/RecyclerView$AdapterDataObservable",
+      "android/support/v17/leanback/app/BaseRowSupportFragment$LateSelectionObserver": "androidx/leanback/app/BaseRowSupportFragment$LateSelectionObserver",
+      "android/support/design/internal/SnackbarContentLayout": "androidx/design/internal/SnackbarContentLayout",
+      "android/support/v17/leanback/widget/BaseGridView$OnMotionInterceptListener": "androidx/leanback/widget/BaseGridView$OnMotionInterceptListener",
+      "android/support/v17/leanback/widget/PlaybackTransportRowPresenter$ViewHolder": "androidx/leanback/widget/PlaybackTransportRowPresenter$ViewHolder",
+      "android/support/v7/widget/CardViewBaseImpl": "androidx/widget/CardViewBaseImpl",
+      "android/support/v4/provider/FontsContractCompat$FontFamilyResult": "androidx/provider/FontsContractCompat$FontFamilyResult",
+      "android/support/v4/os/ResultReceiver$MyRunnable": "androidx/os/ResultReceiver$MyRunnable",
+      "android/support/v7/media/MediaRouteProvider$RouteController": "androidx/media/MediaRouteProvider$RouteController",
+      "android/support/v14/preference/PreferenceFragment$DividerDecoration": "androidx/preference/PreferenceFragment$DividerDecoration",
+      "android/support/text/emoji/flatbuffer/MetadataItem": "androidx/text/emoji/flatbuffer/MetadataItem",
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplApi18": "androidx/media/session/MediaSessionCompat$MediaSessionImplApi18",
+      "android/support/v7/widget/ToolbarWidgetWrapper": "androidx/widget/ToolbarWidgetWrapper",
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplApi19": "androidx/media/session/MediaSessionCompat$MediaSessionImplApi19",
+      "android/support/v7/widget/helper/ItemTouchHelper$ItemTouchHelperGestureListener": "androidx/widget/helper/ItemTouchHelper$ItemTouchHelperGestureListener",
+      "android/support/v7/appcompat/R$layout": "androidx/appcompat/R$layout",
+      "android/support/text/emoji/widget/EmojiEditTextHelper$HelperInternal19": "androidx/text/emoji/widget/EmojiEditTextHelper$HelperInternal19",
+      "android/support/v17/leanback/app/BackgroundManager$BitmapDrawable$ConstantState": "androidx/leanback/app/BackgroundManager$BitmapDrawable$ConstantState",
+      "android/support/design/widget/FloatingActionButtonImpl$ShadowAnimatorImpl": "androidx/design/widget/FloatingActionButtonImpl$ShadowAnimatorImpl",
+      "android/support/v7/widget/FastScroller$AnimatorListener": "androidx/widget/FastScroller$AnimatorListener",
+      "android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter": "androidx/leanback/widget/FullWidthDetailsOverviewRowPresenter",
+      "android/support/v4/app/NotificationCompat$WearableExtender": "androidx/app/NotificationCompat$WearableExtender",
+      "android/support/v17/leanback/widget/FocusHighlightHandler": "androidx/leanback/widget/FocusHighlightHandler",
+      "android/support/transition/Slide$GravityFlag": "androidx/transition/Slide$GravityFlag",
+      "android/support/v4/app/FragmentManagerImpl$AnimateOnHWLayerIfNeededListener": "androidx/app/FragmentManagerImpl$AnimateOnHWLayerIfNeededListener",
+      "android/support/v4/widget/ListViewCompat": "androidx/widget/ListViewCompat",
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplApi21": "androidx/media/session/MediaSessionCompat$MediaSessionImplApi21",
+      "android/support/graphics/drawable/Animatable2Compat$AnimationCallback": "androidx/graphics/drawable/Animatable2Compat$AnimationCallback",
+      "android/support/v17/leanback/widget/ControlButtonPresenterSelector$ActionViewHolder": "androidx/leanback/widget/ControlButtonPresenterSelector$ActionViewHolder",
+      "android/support/transition/GhostViewApi14$Creator": "androidx/transition/GhostViewApi14$Creator",
+      "android/support/v4/widget/PopupWindowCompat$PopupWindowCompatApi19Impl": "androidx/widget/PopupWindowCompat$PopupWindowCompatApi19Impl",
+      "android/support/v17/leanback/widget/GuidedActionsStylist": "androidx/leanback/widget/GuidedActionsStylist",
+      "android/support/v4/app/ActivityCompat$SharedElementCallback21Impl": "androidx/app/ActivityCompat$SharedElementCallback21Impl",
+      "android/support/v17/leanback/app/BrowseFragment$FragmentFactory": "androidx/leanback/app/BrowseFragment$FragmentFactory",
+      "android/support/v7/widget/DefaultItemAnimator$MoveInfo": "androidx/widget/DefaultItemAnimator$MoveInfo",
+      "android/support/media/instantvideo/preload/InstantVideoPreloadManager$VideoPreloader": "androidx/media/instantvideo/preload/InstantVideoPreloadManager$VideoPreloader",
+      "android/support/v4/media/MediaBrowserCompat": "androidx/media/MediaBrowserCompat",
+      "android/support/v7/media/MediaRouter$RouteGroup": "androidx/media/MediaRouter$RouteGroup",
+      "android/support/v4/view/ViewCompat$OverScroll": "androidx/view/ViewCompat$OverScroll",
+      "android/support/v7/media/SystemMediaRouteProvider$LegacyImpl$VolumeChangeReceiver": "androidx/media/SystemMediaRouteProvider$LegacyImpl$VolumeChangeReceiver",
+      "android/support/v17/preference/LeanbackPreferenceFragmentTransitionHelperApi21": "androidx/leanback/preference/LeanbackPreferenceFragmentTransitionHelperApi21",
+      "android/support/v17/leanback/widget/BaseGridView$OnUnhandledKeyListener": "androidx/leanback/widget/BaseGridView$OnUnhandledKeyListener",
+      "android/support/v7/view/menu/ActionMenuItemView$ActionMenuItemForwardingListener": "androidx/view/menu/ActionMenuItemView$ActionMenuItemForwardingListener",
+      "android/support/v17/leanback/transition/FadeAndShortSlide": "androidx/leanback/transition/FadeAndShortSlide",
+      "android/support/v7/app/NavItemSelectedListener": "androidx/app/NavItemSelectedListener",
+      "android/support/v4/content/pm/ShortcutManagerCompat": "androidx/content/pm/ShortcutManagerCompat",
+      "android/support/v4/app/FragmentActivity$HostCallbacks": "androidx/app/FragmentActivity$HostCallbacks",
+      "android/support/design/widget/CoordinatorLayout$LayoutParams": "androidx/design/widget/CoordinatorLayout$LayoutParams",
+      "android/support/v4/view/MenuItemCompat$MenuItemCompatApi26Impl": "androidx/view/MenuItemCompat$MenuItemCompatApi26Impl",
+      "android/support/transition/ViewGroupOverlayApi18": "androidx/transition/ViewGroupOverlayApi18",
+      "android/support/v17/preference/LeanbackSettingsFragment": "androidx/leanback/preference/LeanbackSettingsFragment",
+      "android/support/v17/leanback/widget/RowHeaderPresenter$ViewHolder": "androidx/leanback/widget/RowHeaderPresenter$ViewHolder",
+      "android/support/wear/ambient/AmbientMode$AmbientController": "androidx/wear/ambient/AmbientMode$AmbientController",
+      "android/support/v7/cardview/R$color": "androidx/cardview/R$color",
+      "android/support/annotation/MenuRes": "androidx/annotation/MenuRes",
+      "android/support/v7/media/MediaRouterJellybeanMr2": "androidx/media/MediaRouterJellybeanMr2",
+      "android/support/v7/widget/GridLayout$PackedMap": "androidx/widget/GridLayout$PackedMap",
+      "android/support/v7/media/MediaRouterJellybeanMr1": "androidx/media/MediaRouterJellybeanMr1",
+      "android/support/transition/ViewGroupOverlayApi14": "androidx/transition/ViewGroupOverlayApi14",
+      "android/support/v7/app/ActionBarDrawerToggleHoneycomb$SetIndicatorInfo": "androidx/app/ActionBarDrawerToggleHoneycomb$SetIndicatorInfo",
+      "android/support/wear/widget/drawer/FlingWatcherFactory$FlingWatcher": "androidx/wear/widget/drawer/FlingWatcherFactory$FlingWatcher",
+      "android/support/v17/leanback/widget/SparseArrayObjectAdapter": "androidx/leanback/widget/SparseArrayObjectAdapter",
+      "android/support/v4/media/session/MediaSessionCompatApi21$CallbackProxy": "androidx/media/session/MediaSessionCompatApi21$CallbackProxy",
+      "android/support/v4/app/NotificationCompat$CarExtender": "androidx/app/NotificationCompat$CarExtender",
+      "android/support/v17/leanback/widget/PlaybackControlsRowView$OnUnhandledKeyListener": "androidx/leanback/widget/PlaybackControlsRowView$OnUnhandledKeyListener",
+      "android/support/v7/view/menu/MenuPopupHelper": "androidx/view/menu/MenuPopupHelper",
+      "android/support/v17/leanback/app/VideoSupportFragment": "androidx/leanback/app/VideoSupportFragment",
+      "android/support/media/tv/Channel": "androidx/media/tv/Channel",
+      "android/support/v4/media/AudioAttributesCompat$AttributeContentType": "androidx/media/AudioAttributesCompat$AttributeContentType",
+      "android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper$TransitionTimeOutRunnable": "androidx/leanback/widget/DetailsOverviewSharedElementHelper$TransitionTimeOutRunnable",
+      "android/support/v17/leanback/app/BrowseSupportFragment$BrowseTransitionListener": "androidx/leanback/app/BrowseSupportFragment$BrowseTransitionListener",
+      "android/support/v4/view/ViewPager$ViewPositionComparator": "androidx/view/ViewPager$ViewPositionComparator",
+      "android/support/v4/app/NotificationCompat$Action": "androidx/app/NotificationCompat$Action",
+      "android/support/v7/preference/PreferenceManager$SimplePreferenceComparisonCallback": "androidx/preference/PreferenceManager$SimplePreferenceComparisonCallback",
+      "android/support/media/tv/TvContractCompat$BaseTvColumns": "androidx/media/tv/TvContractCompat$BaseTvColumns",
+      "android/support/v4/media/session/PlaybackStateCompat$ShuffleMode": "androidx/media/session/PlaybackStateCompat$ShuffleMode",
+      "android/support/v7/app/WindowDecorActionBar$TabImpl": "androidx/app/WindowDecorActionBar$TabImpl",
+      "android/support/graphics/drawable/VectorDrawableCompat$VectorDrawableDelegateState": "androidx/graphics/drawable/VectorDrawableCompat$VectorDrawableDelegateState",
+      "android/support/v7/media/SystemMediaRouteProvider$JellybeanImpl": "androidx/media/SystemMediaRouteProvider$JellybeanImpl",
+      "android/support/v7/widget/VectorEnabledTintResources": "androidx/widget/VectorEnabledTintResources",
+      "android/support/v7/preference/EditTextPreferenceDialogFragmentCompat": "androidx/preference/EditTextPreferenceDialogFragmentCompat",
+      "android/support/v4/graphics/drawable/DrawableWrapperApi19$DrawableWrapperStateKitKat": "androidx/graphics/drawable/DrawableWrapperApi19$DrawableWrapperStateKitKat",
+      "android/support/v17/leanback/transition/TransitionHelperKitkat$CustomChangeBounds": "androidx/leanback/transition/TransitionHelperKitkat$CustomChangeBounds",
+      "android/support/v4/app/FragmentManagerImpl$StartEnterTransitionListener": "androidx/app/FragmentManagerImpl$StartEnterTransitionListener",
+      "android/support/v4/view/LayoutInflaterCompat$LayoutInflaterCompatBaseImpl": "androidx/view/LayoutInflaterCompat$LayoutInflaterCompatBaseImpl",
+      "android/support/v7/view/SupportMenuInflater$MenuState": "androidx/view/SupportMenuInflater$MenuState",
+      "android/support/v17/leanback/app/GuidedStepFragment": "androidx/leanback/app/GuidedStepFragment",
+      "android/support/v17/leanback/widget/PagingIndicator": "androidx/leanback/widget/PagingIndicator",
+      "android/support/v7/app/MediaRouteControllerDialog$MediaRouterCallback": "androidx/app/MediaRouteControllerDialog$MediaRouterCallback",
+      "android/support/design/widget/CoordinatorLayout$DefaultBehavior": "androidx/design/widget/CoordinatorLayout$DefaultBehavior",
+      "android/support/v4/os/LocaleListInterface": "androidx/os/LocaleListInterface",
+      "android/support/v4/hardware/fingerprint/FingerprintManagerCompat$AuthenticationCallback": "androidx/hardware/fingerprint/FingerprintManagerCompat$AuthenticationCallback",
+      "android/support/v17/leanback/widget/Parallax$FloatProperty": "androidx/leanback/widget/Parallax$FloatProperty",
+      "android/support/v4/app/NotificationCompat$Style": "androidx/app/NotificationCompat$Style",
+      "android/support/v4/app/FrameMetricsAggregator$FrameMetricsApi24Impl": "androidx/app/FrameMetricsAggregator$FrameMetricsApi24Impl",
+      "android/support/v17/leanback/app/HeadersSupportFragment$OnHeaderClickedListener": "androidx/leanback/app/HeadersSupportFragment$OnHeaderClickedListener",
+      "android/support/v7/preference/PreferenceManager$OnNavigateToScreenListener": "androidx/preference/PreferenceManager$OnNavigateToScreenListener",
+      "android/support/v7/widget/AdapterHelper": "androidx/widget/AdapterHelper",
+      "android/support/v17/leanback/transition/SlideKitkat$CalculateSlideHorizontal": "androidx/leanback/transition/SlideKitkat$CalculateSlideHorizontal",
+      "android/support/v4/graphics/ColorUtils": "androidx/graphics/ColorUtils",
+      "android/support/v7/widget/ActionMenuPresenter$OverflowMenuButton": "androidx/widget/ActionMenuPresenter$OverflowMenuButton",
+      "android/support/v7/widget/ListPopupWindow": "androidx/widget/ListPopupWindow",
+      "android/support/v4/media/MediaBrowserServiceCompatApi21$MediaBrowserServiceAdaptor": "androidx/media/MediaBrowserServiceCompatApi21$MediaBrowserServiceAdaptor",
+      "android/support/v17/leanback/widget/Row": "androidx/leanback/widget/Row",
+      "android/support/v17/leanback/widget/ShadowOverlayHelper": "androidx/leanback/widget/ShadowOverlayHelper",
+      "android/support/wear/internal/widget/drawer/MultiPagePresenter": "androidx/wear/internal/widget/drawer/MultiPagePresenter",
+      "android/support/animation/SpringForce": "androidx/animation/SpringForce",
+      "android/support/customtabs/ICustomTabsService$Stub$Proxy": "androidx/browser/customtabs/ICustomTabsService$Stub$Proxy",
+      "android/support/annotation/StringDef": "androidx/annotation/StringDef",
+      "android/support/v4/media/session/MediaControllerCompat$MediaControllerImpl": "androidx/media/session/MediaControllerCompat$MediaControllerImpl",
+      "android/support/design/widget/CircularBorderDrawableLollipop": "androidx/design/widget/CircularBorderDrawableLollipop",
+      "android/support/v17/leanback/widget/ControlBarPresenter$BoundData": "androidx/leanback/widget/ControlBarPresenter$BoundData",
+      "android/support/v7/widget/RecyclerView$Orientation": "androidx/widget/RecyclerView$Orientation",
+      "android/support/v7/media/MediaRouteProviderService$ReceiveHandler": "androidx/media/MediaRouteProviderService$ReceiveHandler",
+      "android/support/v4/view/ViewPropertyAnimatorListenerAdapter": "androidx/view/ViewPropertyAnimatorListenerAdapter",
+      "android/support/v7/graphics/Palette$Swatch": "androidx/graphics/Palette$Swatch",
+      "android/support/v17/leanback/widget/GridLayoutManager": "androidx/leanback/widget/GridLayoutManager",
+      "android/support/v17/leanback/media/PlaybackGlue": "androidx/leanback/media/PlaybackGlue",
+      "android/support/v17/leanback/widget/ShadowHelper$ShadowHelperApi21Impl": "androidx/leanback/widget/ShadowHelper$ShadowHelperApi21Impl",
+      "android/support/v4/view/ViewCompat": "androidx/view/ViewCompat",
+      "android/support/v17/leanback/widget/BackgroundHelper": "androidx/leanback/widget/BackgroundHelper",
+      "android/support/design/widget/AppBarLayout$OnOffsetChangedListener": "androidx/design/widget/AppBarLayout$OnOffsetChangedListener",
+      "android/support/v4/view/GestureDetectorCompat$GestureDetectorCompatImplJellybeanMr2": "androidx/view/GestureDetectorCompat$GestureDetectorCompatImplJellybeanMr2",
+      "android/support/v7/appcompat/R$attr": "androidx/appcompat/R$attr",
+      "android/support/transition/TransitionValuesMaps": "androidx/transition/TransitionValuesMaps",
+      "android/support/v4/view/ViewConfigurationCompat": "androidx/view/ViewConfigurationCompat",
+      "android/support/v4/media/MediaBrowserServiceCompat$ServiceCallbacks": "androidx/media/MediaBrowserServiceCompat$ServiceCallbacks",
+      "android/support/v4/widget/AutoSizeableTextView": "androidx/widget/AutoSizeableTextView",
+      "android/support/v4/view/ViewCompat$LayerType": "androidx/view/ViewCompat$LayerType",
+      "android/support/v17/leanback/widget/DividerRow": "androidx/leanback/widget/DividerRow",
+      "android/support/v7/widget/ActionMenuPresenter$SavedState": "androidx/widget/ActionMenuPresenter$SavedState",
+      "android/support/design/internal/NavigationMenu": "androidx/design/internal/NavigationMenu",
+      "android/support/v7/preference/Preference$OnPreferenceChangeInternalListener": "androidx/preference/Preference$OnPreferenceChangeInternalListener",
+      "android/support/v4/app/JobIntentService": "androidx/app/JobIntentService",
+      "android/support/v4/app/Fragment": "androidx/app/Fragment",
+      "android/support/v17/leanback/app/BrowseSupportFragment$BackStackListener": "androidx/leanback/app/BrowseSupportFragment$BackStackListener",
+      "android/support/v7/widget/RecyclerView$OnChildAttachStateChangeListener": "androidx/widget/RecyclerView$OnChildAttachStateChangeListener",
+      "android/support/v17/leanback/widget/PlaybackSeekDataProvider": "androidx/leanback/widget/PlaybackSeekDataProvider",
+      "android/support/content/ContentPager": "androidx/content/ContentPager",
+      "android/support/v4/util/MapCollections$MapIterator": "androidx/util/MapCollections$MapIterator",
+      "android/support/app/recommendation/ContentRecommendation": "androidx/app/recommendation/ContentRecommendation",
+      "android/support/v7/app/ActionBar$OnNavigationListener": "androidx/app/ActionBar$OnNavigationListener",
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplBase": "androidx/media/session/MediaSessionCompat$MediaSessionImplBase",
+      "android/support/transition/Styleable$ChangeTransform": "androidx/transition/Styleable$ChangeTransform",
+      "android/support/v7/media/SystemMediaRouteProvider$LegacyImpl$DefaultRouteController": "androidx/media/SystemMediaRouteProvider$LegacyImpl$DefaultRouteController",
+      "android/support/v4/net/DatagramSocketWrapper$DatagramSocketImplWrapper": "androidx/net/DatagramSocketWrapper$DatagramSocketImplWrapper",
+      "android/support/v17/leanback/R$layout": "androidx/leanback/R$layout",
+      "android/support/v4/app/FragmentHostCallback": "androidx/app/FragmentHostCallback",
+      "android/support/v7/widget/StaggeredGridLayoutManager$AnchorInfo": "androidx/widget/StaggeredGridLayoutManager$AnchorInfo",
+      "android/support/v7/widget/RecyclerView$State": "androidx/widget/RecyclerView$State",
+      "android/support/v7/media/MediaRouterJellybean$Callback": "androidx/media/MediaRouterJellybean$Callback",
+      "android/support/v14/preference/MultiSelectListPreferenceDialogFragment": "androidx/preference/MultiSelectListPreferenceDialogFragment",
+      "android/support/v4/media/MediaBrowserServiceCompatApi21$ServiceCompatProxy": "androidx/media/MediaBrowserServiceCompatApi21$ServiceCompatProxy",
+      "android/support/v4/text/util/LinkifyCompat$LinkSpec": "androidx/text/util/LinkifyCompat$LinkSpec",
+      "android/support/v4/app/NotificationManagerCompat$ServiceConnectedEvent": "androidx/app/NotificationManagerCompat$ServiceConnectedEvent",
+      "android/support/v4/graphics/drawable/IconCompat": "androidx/graphics/drawable/IconCompat",
+      "android/support/v17/leanback/graphics/ColorOverlayDimmer": "androidx/leanback/graphics/ColorOverlayDimmer",
+      "android/support/v17/leanback/R$styleable": "androidx/leanback/R$styleable",
+      "android/support/v4/view/AccessibilityDelegateCompat": "androidx/view/AccessibilityDelegateCompat",
+      "android/support/v7/cardview/R$dimen": "androidx/cardview/R$dimen",
+      "android/support/wear/widget/SwipeDismissFrameLayout$Callback": "androidx/wear/widget/SwipeDismissFrameLayout$Callback",
+      "android/support/transition/ArcMotion": "androidx/transition/ArcMotion",
+      "android/support/mediacompat/R$layout": "androidx/mediacompat/R$layout",
+      "android/support/v4/view/ViewPager$ItemInfo": "androidx/view/ViewPager$ItemInfo",
+      "android/support/v4/app/FragmentActivity": "androidx/app/FragmentActivity",
+      "android/support/animation/FloatPropertyCompat": "androidx/animation/FloatPropertyCompat",
+      "android/support/v17/leanback/widget/ObjectAdapter$DataObserver": "androidx/leanback/widget/ObjectAdapter$DataObserver",
+      "android/support/design/widget/AppBarLayout$LayoutParams$ScrollFlags": "androidx/design/widget/AppBarLayout$LayoutParams$ScrollFlags",
+      "android/support/v7/widget/AbsActionBarView": "androidx/widget/AbsActionBarView",
+      "android/support/v4/media/app/NotificationCompat": "androidx/media/app/NotificationCompat",
+      "android/support/v17/leanback/media/PlayerAdapter": "androidx/leanback/media/PlayerAdapter",
+      "android/support/v17/leanback/widget/GridLayoutManager$SavedState": "androidx/leanback/widget/GridLayoutManager$SavedState",
+      "android/support/transition/Fade": "androidx/transition/Fade",
+      "android/support/v17/leanback/R$animator": "androidx/leanback/R$animator",
+      "android/support/v4/view/ViewCompat$ScrollAxis": "androidx/view/ViewCompat$ScrollAxis",
+      "android/support/v17/leanback/widget/GuidedActionEditText$NoPaddingDrawable": "androidx/leanback/widget/GuidedActionEditText$NoPaddingDrawable",
+      "android/support/v7/widget/GridLayout$Axis": "androidx/widget/GridLayout$Axis",
+      "android/support/v4/app/FragmentManagerImpl$AnimationListenerWrapper": "androidx/app/FragmentManagerImpl$AnimationListenerWrapper",
+      "android/support/v4/view/ViewParentCompat$ViewParentCompatBaseImpl": "androidx/view/ViewParentCompat$ViewParentCompatBaseImpl",
+      "android/support/v7/util/DiffUtil$Snake": "androidx/util/DiffUtil$Snake",
+      "android/support/v7/app/AppCompatDelegateImplV9$PanelFeatureState$SavedState": "androidx/app/AppCompatDelegateImplV9$PanelFeatureState$SavedState",
+      "android/support/v17/leanback/widget/DetailsOverviewRowPresenter$ViewHolder": "androidx/leanback/widget/DetailsOverviewRowPresenter$ViewHolder",
+      "android/support/v4/media/RatingCompat$Style": "androidx/media/RatingCompat$Style",
+      "android/support/v7/widget/GridLayout$Spec": "androidx/widget/GridLayout$Spec",
+      "android/support/constraint/solver/widgets/ConstraintAnchor": "androidx/constraint/solver/widgets/ConstraintAnchor",
+      "android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper$TransitionTimeOutRunnable": "androidx/leanback/widget/FullWidthDetailsOverviewSharedElementHelper$TransitionTimeOutRunnable",
+      "android/support/graphics/drawable/animated/BuildConfig": "androidx/graphics/drawable/animated/BuildConfig",
+      "android/support/v4/view/LayoutInflaterFactory": "androidx/view/LayoutInflaterFactory",
+      "android/support/v7/preference/internal/package-info": "androidx/preference/internal/package-info",
+      "android/support/v17/leanback/app/BrowseFragment$MainFragmentAdapterProvider": "androidx/leanback/app/BrowseFragment$MainFragmentAdapterProvider",
+      "android/support/v7/app/OverlayListView$OverlayObject$OnAnimationEndListener": "androidx/app/OverlayListView$OverlayObject$OnAnimationEndListener",
+      "android/support/v7/app/AlertController$RecycleListView": "androidx/app/AlertController$RecycleListView",
+      "android/support/v4/view/ViewCompat$ViewCompatApi18Impl": "androidx/view/ViewCompat$ViewCompatApi18Impl",
+      "android/support/v4/text/TextUtilsCompat": "androidx/text/TextUtilsCompat",
+      "android/support/v17/leanback/widget/Action": "androidx/leanback/widget/Action",
+      "android/support/v7/widget/RecyclerView$ItemAnimator$AdapterChanges": "androidx/widget/RecyclerView$ItemAnimator$AdapterChanges",
+      "android/support/v4/media/session/MediaControllerCompat$MediaControllerExtraData": "androidx/media/session/MediaControllerCompat$MediaControllerExtraData",
+      "android/support/v4/media/session/MediaControllerCompat$TransportControlsBase": "androidx/media/session/MediaControllerCompat$TransportControlsBase",
+      "android/support/v13/view/inputmethod/InputConnectionCompat$InputConnectionCompatImpl": "androidx/view/inputmethod/InputConnectionCompat$InputConnectionCompatImpl",
+      "android/support/v4/media/ParceledListSliceAdapterApi21": "androidx/media/ParceledListSliceAdapterApi21",
+      "android/support/v17/leanback/widget/ItemBridgeAdapter": "androidx/leanback/widget/ItemBridgeAdapter",
+      "android/support/v7/appcompat/BuildConfig": "androidx/appcompat/BuildConfig",
+      "android/support/v13/view/inputmethod/InputConnectionCompat": "androidx/view/inputmethod/InputConnectionCompat",
+      "android/support/v4/widget/ResourceCursorAdapter": "androidx/widget/ResourceCursorAdapter",
+      "android/support/v7/view/WindowCallbackWrapper": "androidx/view/WindowCallbackWrapper",
+      "android/support/v7/widget/AdapterHelper$UpdateOp": "androidx/widget/AdapterHelper$UpdateOp",
+      "android/support/v4/content/res/FontResourcesParserCompat$FontFileResourceEntry": "androidx/content/res/FontResourcesParserCompat$FontFileResourceEntry",
+      "android/support/v4/app/NavUtils": "androidx/app/NavUtils",
+      "android/support/v4/internal/view/SupportMenuItem": "androidx/internal/view/SupportMenuItem",
+      "android/support/v7/widget/FastScroller$DragState": "androidx/widget/FastScroller$DragState",
+      "android/support/annotation/Size": "androidx/annotation/Size",
+      "android/support/wear/widget/drawer/WearableNavigationDrawerView$OnItemSelectedListener": "androidx/wear/widget/drawer/WearableNavigationDrawerView$OnItemSelectedListener",
+      "android/support/transition/WindowIdImpl": "androidx/transition/WindowIdImpl",
+      "android/support/v7/media/RemoteControlClientCompat$LegacyImpl": "androidx/media/RemoteControlClientCompat$LegacyImpl",
+      "android/support/transition/Slide$CalculateSlideVertical": "androidx/transition/Slide$CalculateSlideVertical",
+      "android/support/v17/leanback/app/VideoFragment": "androidx/leanback/app/VideoFragment",
+      "android/support/v4/widget/NestedScrollView$OnScrollChangeListener": "androidx/widget/NestedScrollView$OnScrollChangeListener",
+      "android/support/v7/media/MediaRouter$CallbackFlags": "androidx/media/MediaRouter$CallbackFlags",
+      "android/support/customtabs/IPostMessageService": "androidx/browser/customtabs/IPostMessageService",
+      "android/support/v4/util/AtomicFile": "androidx/util/AtomicFile",
+      "android/support/v4/provider/DocumentsContractApi19": "androidx/provider/DocumentsContractApi19",
+      "android/support/v17/leanback/widget/picker/Picker$ViewHolder": "androidx/leanback/widget/picker/Picker$ViewHolder",
+      "android/support/v4/widget/AutoScrollHelper": "androidx/widget/AutoScrollHelper",
+      "android/support/v4/widget/DrawerLayout$LockMode": "androidx/widget/DrawerLayout$LockMode",
+      "android/support/v17/leanback/transition/SlideKitkat$CalculateSlideVertical": "androidx/leanback/transition/SlideKitkat$CalculateSlideVertical",
+      "android/support/v4/os/BuildCompat": "androidx/os/BuildCompat",
+      "android/support/wear/ambient/SharedLibraryVersion$PresenceHolder": "androidx/wear/ambient/SharedLibraryVersion$PresenceHolder",
+      "android/support/transition/ObjectAnimatorUtilsImpl": "androidx/transition/ObjectAnimatorUtilsImpl",
+      "android/support/v17/leanback/BuildConfig": "androidx/leanback/BuildConfig",
+      "android/support/v7/widget/SearchView$OnSuggestionListener": "androidx/widget/SearchView$OnSuggestionListener",
+      "android/support/design/internal/NavigationMenuPresenter": "androidx/design/internal/NavigationMenuPresenter",
+      "android/support/v17/leanback/widget/ShadowHelper$ShadowHelperVersionImpl": "androidx/leanback/widget/ShadowHelper$ShadowHelperVersionImpl",
+      "android/support/v7/media/RemotePlaybackClient$ItemActionCallback": "androidx/media/RemotePlaybackClient$ItemActionCallback",
+      "android/support/graphics/drawable/BuildConfig": "androidx/graphics/drawable/BuildConfig",
+      "android/support/annotation/Dimension": "androidx/annotation/Dimension",
+      "android/support/v13/view/DragStartHelper$OnDragStartListener": "androidx/view/DragStartHelper$OnDragStartListener",
+      "android/support/text/emoji/R$id": "androidx/text/emoji/R$id",
+      "android/support/wear/widget/CurvingLayoutCallback": "androidx/wear/widget/CurvingLayoutCallback",
+      "android/support/v17/leanback/app/RowsFragment": "androidx/leanback/app/RowsFragment",
+      "android/support/v7/widget/TooltipCompat": "androidx/widget/TooltipCompat",
+      "android/support/v7/widget/SnapHelper": "androidx/widget/SnapHelper",
+      "android/support/v7/mediarouter/R$layout": "androidx/mediarouter/R$layout",
+      "android/support/transition/R$id": "androidx/transition/R$id",
+      "android/support/v4/graphics/BitmapCompat$BitmapCompatBaseImpl": "androidx/graphics/BitmapCompat$BitmapCompatBaseImpl",
+      "android/support/v4/media/VolumeProviderCompatApi21$Delegate": "androidx/media/VolumeProviderCompatApi21$Delegate",
+      "android/support/v17/leanback/widget/SearchBar$SearchBarListener": "androidx/leanback/widget/SearchBar$SearchBarListener",
+      "android/support/v17/leanback/app/SearchFragment": "androidx/leanback/app/SearchFragment",
+      "android/support/v4/view/LayoutInflaterCompat": "androidx/view/LayoutInflaterCompat",
+      "android/support/v7/widget/CardViewApi21Impl": "androidx/widget/CardViewApi21Impl",
+      "android/support/v17/leanback/widget/VideoSurfaceView": "androidx/leanback/widget/VideoSurfaceView",
+      "android/support/transition/GhostViewImpl": "androidx/transition/GhostViewImpl",
+      "android/support/transition/ChangeBounds": "androidx/transition/ChangeBounds",
+      "android/support/v17/leanback/app/HeadersFragment$OnHeaderViewSelectedListener": "androidx/leanback/app/HeadersFragment$OnHeaderViewSelectedListener",
+      "android/support/media/tv/PreviewProgram": "androidx/media/tv/PreviewProgram",
+      "android/support/annotation/RequiresApi": "androidx/annotation/RequiresApi",
+      "android/support/app/recommendation/RecommendationExtender": "androidx/app/recommendation/RecommendationExtender",
+      "android/support/v17/leanback/app/ErrorSupportFragment": "androidx/leanback/app/ErrorSupportFragment",
+      "android/support/v17/leanback/media/MediaPlayerGlue": "androidx/leanback/media/MediaPlayerGlue",
+      "android/support/v4/media/session/MediaSessionCompatApi21$QueueItem": "androidx/media/session/MediaSessionCompatApi21$QueueItem",
+      "android/support/v17/leanback/widget/AbstractMediaItemPresenter": "androidx/leanback/widget/AbstractMediaItemPresenter",
+      "android/support/annotation/StyleableRes": "androidx/annotation/StyleableRes",
+      "android/support/v4/media/session/PlaybackStateCompat$CustomAction": "androidx/media/session/PlaybackStateCompat$CustomAction",
+      "android/support/wear/widget/drawer/WearableDrawerLayout$TopDrawerDraggerCallback": "androidx/wear/widget/drawer/WearableDrawerLayout$TopDrawerDraggerCallback",
+      "android/support/v17/leanback/app/PermissionHelper": "androidx/leanback/app/PermissionHelper",
+      "android/support/transition/R": "androidx/transition/R",
+      "android/support/v17/leanback/transition/SlideKitkat$SlideAnimatorListener": "androidx/leanback/transition/SlideKitkat$SlideAnimatorListener",
+      "android/support/v7/graphics/drawable/DrawerArrowDrawable": "androidx/graphics/drawable/DrawerArrowDrawable",
+      "android/support/v17/leanback/widget/ClassPresenterSelector": "androidx/leanback/widget/ClassPresenterSelector",
+      "android/support/v17/leanback/widget/ControlBarPresenter$OnControlSelectedListener": "androidx/leanback/widget/ControlBarPresenter$OnControlSelectedListener",
+      "android/support/v4/app/NotificationCompat$GroupAlertBehavior": "androidx/app/NotificationCompat$GroupAlertBehavior",
+      "android/support/text/emoji/widget/EmojiInputFilter$InitCallbackImpl": "androidx/text/emoji/widget/EmojiInputFilter$InitCallbackImpl",
+      "android/support/v7/appcompat/R$bool": "androidx/appcompat/R$bool",
+      "android/support/v4/widget/TextViewCompat$AutoSizeTextType": "androidx/widget/TextViewCompat$AutoSizeTextType",
+      "android/support/v4/app/NotificationCompat$BadgeIconType": "androidx/app/NotificationCompat$BadgeIconType",
+      "android/support/v4/app/NotificationCompat$BigTextStyle": "androidx/app/NotificationCompat$BigTextStyle",
+      "android/support/annotation/ColorInt": "androidx/annotation/ColorInt",
+      "android/support/text/emoji/EmojiSpan": "androidx/text/emoji/EmojiSpan",
+      "android/support/wear/widget/SwipeDismissFrameLayout$MyOnDismissedListener": "androidx/wear/widget/SwipeDismissFrameLayout$MyOnDismissedListener",
+      "android/support/percent/PercentRelativeLayout": "androidx/PercentRelativeLayout",
+      "android/support/text/emoji/widget/EmojiInputFilter": "androidx/text/emoji/widget/EmojiInputFilter",
+      "android/support/media/tv/TvContractCompat$PreviewPrograms": "androidx/media/tv/TvContractCompat$PreviewPrograms",
+      "android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter$ViewHolder": "androidx/leanback/widget/FullWidthDetailsOverviewRowPresenter$ViewHolder",
+      "android/support/v17/leanback/app/BrowseFragment$BackStackListener": "androidx/leanback/app/BrowseFragment$BackStackListener",
+      "android/support/text/emoji/EmojiProcessor$ProcessorSm": "androidx/text/emoji/EmojiProcessor$ProcessorSm",
+      "android/support/v4/view/ViewCompat$ViewCompatBaseImpl": "androidx/view/ViewCompat$ViewCompatBaseImpl",
+      "android/support/design/internal/BottomNavigationMenu": "androidx/design/internal/BottomNavigationMenu",
+      "android/support/v7/view/menu/BaseMenuWrapper": "androidx/view/menu/BaseMenuWrapper",
+      "android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory$DefaultRoundedBitmapDrawable": "androidx/graphics/drawable/RoundedBitmapDrawableFactory$DefaultRoundedBitmapDrawable",
+      "android/support/v17/leanback/widget/OnItemViewClickedListener": "androidx/leanback/widget/OnItemViewClickedListener",
+      "android/support/v4/app/ShareCompat": "androidx/app/ShareCompat",
+      "android/support/v4/app/DialogFragment": "androidx/app/DialogFragment",
+      "android/support/v4/os/ConfigurationCompat": "androidx/os/ConfigurationCompat",
+      "android/support/v4/graphics/drawable/DrawableCompat": "androidx/graphics/drawable/DrawableCompat",
+      "android/support/v17/leanback/widget/PlaybackTransportRowView": "androidx/leanback/widget/PlaybackTransportRowView",
+      "android/support/annotation/ColorRes": "androidx/annotation/ColorRes",
+      "android/support/v4/database/DatabaseUtilsCompat": "androidx/database/DatabaseUtilsCompat",
+      "android/support/v7/app/AppCompatDelegateImplBase$ActionBarDrawableToggleImpl": "androidx/app/AppCompatDelegateImplBase$ActionBarDrawableToggleImpl",
+      "android/support/v7/widget/ForwardingListener": "androidx/widget/ForwardingListener",
+      "android/support/annotation/NavigationRes": "androidx/annotation/NavigationRes",
+      "android/support/v4/widget/TextViewCompat$TextViewCompatApi18Impl": "androidx/widget/TextViewCompat$TextViewCompatApi18Impl",
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplBase$Command": "androidx/media/session/MediaSessionCompat$MediaSessionImplBase$Command",
+      "android/support/transition/Styleable$ArcMotion": "androidx/transition/Styleable$ArcMotion",
+      "android/support/v17/leanback/transition/TransitionHelper$TransitionHelperStubImpl": "androidx/leanback/transition/TransitionHelper$TransitionHelperStubImpl",
+      "android/support/text/emoji/widget/EmojiEditTextHelper$HelperInternal": "androidx/text/emoji/widget/EmojiEditTextHelper$HelperInternal",
+      "android/support/wear/widget/BezierSCurveInterpolator": "androidx/wear/widget/BezierSCurveInterpolator",
+      "android/support/v4/view/NestedScrollingParent": "androidx/view/NestedScrollingParent",
+      "android/support/v7/widget/ListPopupWindow$ListSelectorHider": "androidx/widget/ListPopupWindow$ListSelectorHider",
+      "android/support/transition/PathProperty": "androidx/transition/PathProperty",
+      "android/support/v4/provider/FontsContractCompat$FontInfo": "androidx/provider/FontsContractCompat$FontInfo",
+      "android/support/v17/leanback/widget/PlaybackControlsRow": "androidx/leanback/widget/PlaybackControlsRow",
+      "android/support/v17/leanback/widget/Presenter": "androidx/leanback/widget/Presenter",
+      "android/support/v17/leanback/app/VerticalGridFragment": "androidx/leanback/app/VerticalGridFragment",
+      "android/support/v4/app/LoaderManagerImpl$LoaderInfo": "androidx/app/LoaderManagerImpl$LoaderInfo",
+      "android/support/v7/widget/RoundRectDrawableWithShadow": "androidx/widget/RoundRectDrawableWithShadow",
+      "android/support/v7/app/AppCompatDelegateImplV9$PanelFeatureState": "androidx/app/AppCompatDelegateImplV9$PanelFeatureState",
+      "android/support/v7/media/SystemMediaRouteProvider$JellybeanImpl$UserRouteRecord": "androidx/media/SystemMediaRouteProvider$JellybeanImpl$UserRouteRecord",
+      "android/support/v4/view/accessibility/AccessibilityManagerCompat": "androidx/view/accessibility/AccessibilityManagerCompat",
+      "android/support/v4/view/ScrollingView": "androidx/view/ScrollingView",
+      "android/support/customtabs/CustomTabsIntent": "androidx/browser/customtabs/CustomTabsIntent",
+      "android/support/v17/leanback/transition/TransitionListener": "androidx/leanback/transition/TransitionListener",
+      "android/support/annotation/DimenRes": "androidx/annotation/DimenRes",
+      "android/support/v17/leanback/widget/Parallax$IntProperty": "androidx/leanback/widget/Parallax$IntProperty",
+      "android/support/v4/app/FragmentManagerImpl$AnimationOrAnimator": "androidx/app/FragmentManagerImpl$AnimationOrAnimator",
+      "android/support/v4/widget/TextViewCompat$TextViewCompatBaseImpl": "androidx/widget/TextViewCompat$TextViewCompatBaseImpl",
+      "android/support/v17/leanback/app/BrowseFragment$ExpandPreLayout": "androidx/leanback/app/BrowseFragment$ExpandPreLayout",
+      "android/support/v13/view/DragAndDropPermissionsCompat$BaseDragAndDropPermissionsCompatImpl": "androidx/view/DragAndDropPermissionsCompat$BaseDragAndDropPermissionsCompatImpl",
+      "android/support/multidex/MultiDexExtractor": "androidx/multidex/MultiDexExtractor",
+      "android/support/v17/leanback/widget/GuidedDatePickerAction$Builder": "androidx/leanback/widget/GuidedDatePickerAction$Builder",
+      "android/support/v7/widget/AppCompatRatingBar": "androidx/widget/AppCompatRatingBar",
+      "android/support/wear/R$string": "androidx/wear/R$string",
+      "android/support/v7/app/AppCompatDelegateImplN": "androidx/app/AppCompatDelegateImplN",
+      "android/support/v17/leanback/widget/GridLayoutManager$PendingMoveSmoothScroller": "androidx/leanback/widget/GridLayoutManager$PendingMoveSmoothScroller",
+      "android/support/v17/leanback/widget/GuidedActionItemContainer": "androidx/leanback/widget/GuidedActionItemContainer",
+      "android/support/transition/ObjectAnimatorUtils": "androidx/transition/ObjectAnimatorUtils",
+      "android/support/v4/view/accessibility/AccessibilityNodeInfoCompat$CollectionInfoCompat": "androidx/view/accessibility/AccessibilityNodeInfoCompat$CollectionInfoCompat",
+      "android/support/design/widget/CoordinatorLayout$DispatchChangeEvent": "androidx/design/widget/CoordinatorLayout$DispatchChangeEvent",
+      "android/support/annotation/HalfFloat": "androidx/annotation/HalfFloat",
+      "android/support/v4/view/ViewCompat$ViewCompatApi16Impl": "androidx/view/ViewCompat$ViewCompatApi16Impl",
+      "android/support/v7/text/AllCapsTransformationMethod": "androidx/text/AllCapsTransformationMethod",
+      "android/support/v4/app/FragmentController": "androidx/app/FragmentController",
+      "android/support/v17/leanback/app/SearchSupportFragment$SearchResultProvider": "androidx/leanback/app/SearchSupportFragment$SearchResultProvider",
+      "android/support/v17/leanback/widget/RoundedRectHelper$StubImpl": "androidx/leanback/widget/RoundedRectHelper$StubImpl",
+      "android/support/v4/graphics/drawable/RoundedBitmapDrawable": "androidx/graphics/drawable/RoundedBitmapDrawable",
+      "android/support/v4/widget/ScrollerCompat": "androidx/widget/ScrollerCompat",
+      "android/support/v17/leanback/widget/RoundedRectHelper$Api21Impl": "androidx/leanback/widget/RoundedRectHelper$Api21Impl",
+      "android/support/wear/internal/widget/drawer/SinglePagePresenter$Ui": "androidx/wear/internal/widget/drawer/SinglePagePresenter$Ui",
+      "android/support/v7/app/AppCompatDelegateImplV14$AutoNightModeManager": "androidx/app/AppCompatDelegateImplV14$AutoNightModeManager",
+      "android/support/v17/leanback/widget/ImeKeyMonitor$ImeKeyListener": "androidx/leanback/widget/ImeKeyMonitor$ImeKeyListener",
+      "android/support/v4/view/InputDeviceCompat": "androidx/view/InputDeviceCompat",
+      "android/support/wear/widget/CircularProgressLayoutController": "androidx/wear/widget/CircularProgressLayoutController",
+      "android/support/v17/leanback/widget/PlaybackTransportRowView$OnUnhandledKeyListener": "androidx/leanback/widget/PlaybackTransportRowView$OnUnhandledKeyListener",
+      "android/support/v4/view/ViewCompat$AccessibilityLiveRegion": "androidx/view/ViewCompat$AccessibilityLiveRegion",
+      "android/support/v13/app/FragmentCompat$FragmentCompatImpl": "androidx/app/FragmentCompat$FragmentCompatImpl",
+      "android/support/design/widget/Snackbar": "androidx/design/widget/Snackbar",
+      "android/support/v7/preference/PreferenceGroupAdapter": "androidx/preference/PreferenceGroupAdapter",
+      "android/support/v4/view/MenuItemCompat": "androidx/view/MenuItemCompat",
+      "android/support/v7/widget/ChildHelper$Bucket": "androidx/widget/ChildHelper$Bucket",
+      "android/support/v7/util/DiffUtil$DiffResult": "androidx/util/DiffUtil$DiffResult",
+      "android/support/v13/app/FragmentCompat$PermissionCompatDelegate": "androidx/app/FragmentCompat$PermissionCompatDelegate",
+      "android/support/v4/view/MotionEventCompat": "androidx/view/MotionEventCompat",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$ClosedCaptioningAction": "androidx/leanback/widget/PlaybackControlsRow$ClosedCaptioningAction",
+      "android/support/v4/app/FragmentState": "androidx/app/FragmentState",
+      "android/support/v7/widget/CardView": "androidx/widget/CardView",
+      "android/support/v13/view/inputmethod/InputContentInfoCompat$InputContentInfoCompatApi25Impl": "androidx/view/inputmethod/InputContentInfoCompat$InputContentInfoCompatApi25Impl",
+      "android/support/v4/widget/PopupWindowCompat$PopupWindowCompatBaseImpl": "androidx/widget/PopupWindowCompat$PopupWindowCompatBaseImpl",
+      "android/support/media/tv/TvContractCompat$PreviewProgramColumns$Type": "androidx/media/tv/TvContractCompat$PreviewProgramColumns$Type",
+      "android/support/v4/media/session/MediaSessionCompat$OnActiveChangeListener": "androidx/media/session/MediaSessionCompat$OnActiveChangeListener",
+      "android/support/design/widget/BottomSheetBehavior": "androidx/design/widget/BottomSheetBehavior",
+      "android/support/customtabs/CustomTabsSession": "androidx/browser/customtabs/CustomTabsSession",
+      "android/support/v7/media/RemotePlaybackClient$StatusCallback": "androidx/media/RemotePlaybackClient$StatusCallback",
+      "android/support/v17/leanback/app/HeadersSupportFragment$OnHeaderViewSelectedListener": "androidx/leanback/app/HeadersSupportFragment$OnHeaderViewSelectedListener",
+      "android/support/v4/view/ViewPager$OnPageChangeListener": "androidx/view/ViewPager$OnPageChangeListener",
+      "android/support/v4/app/BackStackRecord$Op": "androidx/app/BackStackRecord$Op",
+      "android/support/media/ExifInterface$ExifAttribute": "androidx/media/ExifInterface$ExifAttribute",
+      "android/support/transition/ChangeBounds$ViewBounds": "androidx/transition/ChangeBounds$ViewBounds",
+      "android/support/v17/leanback/widget/NonOverlappingLinearLayoutWithForeground": "androidx/leanback/widget/NonOverlappingLinearLayoutWithForeground",
+      "android/support/v4/app/NotificationCompat$BigPictureStyle": "androidx/app/NotificationCompat$BigPictureStyle",
+      "android/support/design/widget/FloatingActionButton$ShadowDelegateImpl": "androidx/design/widget/FloatingActionButton$ShadowDelegateImpl",
+      "android/support/media/instantvideo/preload/InstantVideoPreloadManager$VideoPreloaderFactory": "androidx/media/instantvideo/preload/InstantVideoPreloadManager$VideoPreloaderFactory",
+      "android/support/v7/app/MediaRouteDialogHelper": "androidx/app/MediaRouteDialogHelper",
+      "android/support/media/ExifInterface$ExifTag": "androidx/media/ExifInterface$ExifTag",
+      "android/support/v17/leanback/widget/BaseCardView$InfoHeightAnimation": "androidx/leanback/widget/BaseCardView$InfoHeightAnimation",
+      "android/support/v13/view/inputmethod/EditorInfoCompat$EditorInfoCompatApi25Impl": "androidx/view/inputmethod/EditorInfoCompat$EditorInfoCompatApi25Impl",
+      "android/support/transition/TransitionSet$TransitionSetListener": "androidx/transition/TransitionSet$TransitionSetListener",
+      "android/support/v17/leanback/transition/SlideKitkat$CalculateSlide": "androidx/leanback/transition/SlideKitkat$CalculateSlide",
+      "android/support/v4/app/ActivityCompat$OnRequestPermissionsResultCallback": "androidx/app/ActivityCompat$OnRequestPermissionsResultCallback",
+      "android/support/v7/widget/AppCompatRadioButton": "androidx/widget/AppCompatRadioButton",
+      "android/support/v4/app/TaskStackBuilder$TaskStackBuilderApi16Impl": "androidx/app/TaskStackBuilder$TaskStackBuilderApi16Impl",
+      "android/support/v7/media/MediaRouter$RouteInfo$PlaybackVolume": "androidx/media/MediaRouter$RouteInfo$PlaybackVolume",
+      "android/support/v17/preference/LeanbackListPreferenceDialogFragment$AdapterMulti": "androidx/leanback/preference/LeanbackListPreferenceDialogFragment$AdapterMulti",
+      "android/support/v4/print/PrintHelper$PrintHelperApi19": "androidx/print/PrintHelper$PrintHelperApi19",
+      "android/support/v7/media/MediaRouter$RouteInfo$DeviceType": "androidx/media/MediaRouter$RouteInfo$DeviceType",
+      "android/support/v4/media/MediaBrowserCompat$SubscriptionCallback": "androidx/media/MediaBrowserCompat$SubscriptionCallback",
+      "android/support/v4/media/MediaBrowserCompat$MediaItem$Flags": "androidx/media/MediaBrowserCompat$MediaItem$Flags",
+      "android/support/v17/leanback/R$attr": "androidx/leanback/R$attr",
+      "android/support/v7/media/MediaRouteDescriptor$Builder": "androidx/media/MediaRouteDescriptor$Builder",
+      "android/support/v7/media/MediaRouteProviderService": "androidx/media/MediaRouteProviderService",
+      "android/support/v4/app/ActivityCompat$RequestPermissionsRequestCodeValidator": "androidx/app/ActivityCompat$RequestPermissionsRequestCodeValidator",
+      "android/support/v17/leanback/widget/ControlBar$OnChildFocusedListener": "androidx/leanback/widget/ControlBar$OnChildFocusedListener",
+      "android/support/v7/media/MediaRouterApi24$RouteInfo": "androidx/media/MediaRouterApi24$RouteInfo",
+      "android/support/v4/app/JobIntentService$WorkEnqueuer": "androidx/app/JobIntentService$WorkEnqueuer",
+      "android/support/v7/preference/DialogPreference$TargetFragment": "androidx/preference/DialogPreference$TargetFragment",
+      "android/support/wear/widget/BoxInsetLayout$LayoutParams": "androidx/wear/widget/BoxInsetLayout$LayoutParams",
+      "android/support/v4/util/SimpleArrayMap": "androidx/util/SimpleArrayMap",
+      "android/support/v4/widget/EdgeEffectCompat": "androidx/widget/EdgeEffectCompat",
+      "android/support/v13/app/FragmentCompat$FragmentCompatApi15Impl": "androidx/app/FragmentCompat$FragmentCompatApi15Impl",
+      "android/support/v4/print/PrintHelper$PrintHelperApi23": "androidx/print/PrintHelper$PrintHelperApi23",
+      "android/support/percent/R$styleable": "androidx/R$styleable",
+      "android/support/v4/print/PrintHelper$PrintHelperApi24": "androidx/print/PrintHelper$PrintHelperApi24",
+      "android/support/v4/content/res/FontResourcesParserCompat": "androidx/content/res/FontResourcesParserCompat",
+      "android/support/design/widget/SnackbarManager$SnackbarRecord": "androidx/design/widget/SnackbarManager$SnackbarRecord",
+      "android/support/v7/util/DiffUtil$Range": "androidx/util/DiffUtil$Range",
+      "android/support/v4/media/MediaBrowserCompat$MediaBrowserImpl": "androidx/media/MediaBrowserCompat$MediaBrowserImpl",
+      "android/support/v4/print/PrintHelper$PrintHelperApi20": "androidx/print/PrintHelper$PrintHelperApi20",
+      "android/support/v4/media/session/PlaybackStateCompat$RepeatMode": "androidx/media/session/PlaybackStateCompat$RepeatMode",
+      "android/support/v7/media/MediaRouteProviderProtocol": "androidx/media/MediaRouteProviderProtocol",
+      "android/support/transition/Transition$ArrayListManager": "androidx/transition/Transition$ArrayListManager",
+      "android/support/text/emoji/widget/EmojiButton": "androidx/text/emoji/widget/EmojiButton",
+      "android/support/v4/view/ActionProvider$VisibilityListener": "androidx/view/ActionProvider$VisibilityListener",
+      "android/support/v7/widget/AppCompatProgressBarHelper": "androidx/widget/AppCompatProgressBarHelper",
+      "android/support/v7/widget/LinearLayoutCompat": "androidx/widget/LinearLayoutCompat",
+      "android/support/v4/app/Fragment$OnStartEnterTransitionListener": "androidx/app/Fragment$OnStartEnterTransitionListener",
+      "android/support/v7/app/AppCompatDialogFragment": "androidx/app/AppCompatDialogFragment",
+      "android/support/graphics/drawable/Animatable2Compat": "androidx/graphics/drawable/Animatable2Compat",
+      "android/support/design/widget/TabLayout$PagerAdapterObserver": "androidx/design/widget/TabLayout$PagerAdapterObserver",
+      "android/support/v7/widget/StaggeredGridLayoutManager$LazySpanLookup$FullSpanItem": "androidx/widget/StaggeredGridLayoutManager$LazySpanLookup$FullSpanItem",
+      "android/support/v4/content/pm/ShortcutInfoCompat": "androidx/content/pm/ShortcutInfoCompat",
+      "android/support/v4/view/ScaleGestureDetectorCompat": "androidx/view/ScaleGestureDetectorCompat",
+      "android/support/v17/leanback/widget/ShadowHelperApi21$ShadowImpl": "androidx/leanback/widget/ShadowHelperApi21$ShadowImpl",
+      "android/support/v7/appcompat/R$id": "androidx/appcompat/R$id",
+      "android/support/v17/leanback/transition/Scale": "androidx/leanback/transition/Scale",
+      "android/support/v7/widget/ViewBoundsCheck": "androidx/widget/ViewBoundsCheck",
+      "android/support/design/widget/BottomSheetBehavior$State": "androidx/design/widget/BottomSheetBehavior$State",
+      "android/support/v7/app/ActionBarDrawerToggle$JellybeanMr2Delegate": "androidx/app/ActionBarDrawerToggle$JellybeanMr2Delegate",
+      "android/support/v7/internal/widget/PreferenceImageView": "androidx/internal/widget/PreferenceImageView",
+      "android/support/content/ContentPager$CursorCache": "androidx/content/ContentPager$CursorCache",
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplBase$MessageHandler": "androidx/media/session/MediaSessionCompat$MediaSessionImplBase$MessageHandler",
+      "android/support/v4/app/NotificationCompat$Action$Extender": "androidx/app/NotificationCompat$Action$Extender",
+      "android/support/v7/widget/Toolbar$OnMenuItemClickListener": "androidx/widget/Toolbar$OnMenuItemClickListener",
+      "android/support/multidex/MultiDex$V4": "androidx/multidex/MultiDex$V4",
+      "android/support/v4/app/ActionBarDrawerToggle": "androidx/app/ActionBarDrawerToggle",
+      "android/support/v7/media/RemoteControlClientCompat": "androidx/media/RemoteControlClientCompat",
+      "android/support/v4/media/app/NotificationCompat$MediaStyle": "androidx/media/app/NotificationCompat$MediaStyle",
+      "android/support/v17/leanback/transition/TransitionEpicenterCallback": "androidx/leanback/transition/TransitionEpicenterCallback",
+      "android/support/v4/content/LocalBroadcastManager$ReceiverRecord": "androidx/content/LocalBroadcastManager$ReceiverRecord",
+      "android/support/v7/view/menu/BaseMenuPresenter": "androidx/view/menu/BaseMenuPresenter",
+      "android/support/v4/view/accessibility/AccessibilityManagerCompat$AccessibilityStateChangeListener": "androidx/view/accessibility/AccessibilityManagerCompat$AccessibilityStateChangeListener",
+      "android/support/design/widget/TabLayout$AdapterChangeListener": "androidx/design/widget/TabLayout$AdapterChangeListener",
+      "android/support/v7/widget/RecyclerView$RecyclerListener": "androidx/widget/RecyclerView$RecyclerListener",
+      "android/support/media/tv/ChannelLogoUtils": "androidx/media/tv/ChannelLogoUtils",
+      "android/support/v4/media/session/PlaybackStateCompat$CustomAction$Builder": "androidx/media/session/PlaybackStateCompat$CustomAction$Builder",
+      "android/support/v17/leanback/widget/GuidedActionAdapter": "androidx/leanback/widget/GuidedActionAdapter",
+      "android/support/v17/leanback/widget/ItemBridgeAdapter$Wrapper": "androidx/leanback/widget/ItemBridgeAdapter$Wrapper",
+      "android/support/v17/leanback/widget/DetailsOverviewRow$Listener": "androidx/leanback/widget/DetailsOverviewRow$Listener",
+      "android/support/annotation/InterpolatorRes": "androidx/annotation/InterpolatorRes",
+      "android/support/v4/widget/CursorAdapter$ChangeObserver": "androidx/widget/CursorAdapter$ChangeObserver",
+      "android/support/v4/widget/SimpleCursorAdapter$CursorToStringConverter": "androidx/widget/SimpleCursorAdapter$CursorToStringConverter",
+      "android/support/v7/widget/helper/ItemTouchUIUtilImpl$BaseImpl": "androidx/widget/helper/ItemTouchUIUtilImpl$BaseImpl",
+      "android/support/v4/provider/RawDocumentFile": "androidx/provider/RawDocumentFile",
+      "android/support/text/emoji/widget/EmojiExtractTextLayout$ButtonOnclickListener": "androidx/text/emoji/widget/EmojiExtractTextLayout$ButtonOnclickListener",
+      "android/support/v7/view/menu/MenuItemWrapperJB$ActionProviderWrapperJB": "androidx/view/menu/MenuItemWrapperJB$ActionProviderWrapperJB",
+      "android/support/media/tv/TvContractCompat$RecordedPrograms": "androidx/media/tv/TvContractCompat$RecordedPrograms",
+      "android/support/v17/leanback/widget/picker/Picker$PickerValueListener": "androidx/leanback/widget/picker/Picker$PickerValueListener",
+      "android/support/v4/media/session/IMediaControllerCallback$Stub": "androidx/media/session/IMediaControllerCallback$Stub",
+      "android/support/v7/preference/PreferenceManager": "androidx/preference/PreferenceManager",
+      "android/support/transition/GhostViewApi21$Creator": "androidx/transition/GhostViewApi21$Creator",
+      "android/support/v7/widget/ActionMenuView$ActionMenuChildView": "androidx/widget/ActionMenuView$ActionMenuChildView",
+      "android/support/v17/leanback/app/GuidedStepSupportFragment$DummyFragment": "androidx/leanback/app/GuidedStepSupportFragment$DummyFragment",
+      "android/support/v4/app/BaseFragmentActivityApi14": "androidx/app/BaseFragmentActivityApi14",
+      "android/support/v14/preference/SwitchPreference": "androidx/preference/SwitchPreference",
+      "android/support/v4/app/BaseFragmentActivityApi16": "androidx/app/BaseFragmentActivityApi16",
+      "android/support/v7/preference/PreferenceFragmentCompat$ScrollToPreferenceObserver": "androidx/preference/PreferenceFragmentCompat$ScrollToPreferenceObserver",
+      "android/support/v4/graphics/PaintCompat": "androidx/graphics/PaintCompat",
+      "android/support/v4/media/AudioAttributesCompat": "androidx/media/AudioAttributesCompat",
+      "android/support/v4/media/session/MediaSessionCompat$QueueItem": "androidx/media/session/MediaSessionCompat$QueueItem",
+      "android/support/transition/Transition$AnimationInfo": "androidx/transition/Transition$AnimationInfo",
+      "android/support/v7/app/MediaRouteControllerDialog$VolumeChangeListener": "androidx/app/MediaRouteControllerDialog$VolumeChangeListener",
+      "android/support/v4/widget/DrawerLayout$ViewDragCallback": "androidx/widget/DrawerLayout$ViewDragCallback",
+      "android/support/design/widget/FloatingActionButtonImpl$ResetElevationAnimation": "androidx/design/widget/FloatingActionButtonImpl$ResetElevationAnimation",
+      "android/support/design/widget/TabLayout$OnTabSelectedListener": "androidx/design/widget/TabLayout$OnTabSelectedListener",
+      "android/support/annotation/VisibleForTesting": "androidx/annotation/VisibleForTesting",
+      "android/support/v4/app/NotificationCompatSideChannelService$NotificationSideChannelStub": "androidx/app/NotificationCompatSideChannelService$NotificationSideChannelStub",
+      "android/support/annotation/RawRes": "androidx/annotation/RawRes",
+      "android/support/design/R$anim": "androidx/design/R$anim",
+      "android/support/transition/Transition$MatchOrder": "androidx/transition/Transition$MatchOrder",
+      "android/support/v7/widget/RecyclerView$SimpleOnItemTouchListener": "androidx/widget/RecyclerView$SimpleOnItemTouchListener",
+      "android/support/transition/AnimatorUtilsImpl": "androidx/transition/AnimatorUtilsImpl",
+      "android/support/v4/view/OnApplyWindowInsetsListener": "androidx/view/OnApplyWindowInsetsListener",
+      "android/support/wear/widget/SwipeDismissLayout": "androidx/wear/widget/SwipeDismissLayout",
+      "android/support/mediacompat/R$color": "androidx/mediacompat/R$color",
+      "android/support/v7/preference/PreferenceManager$PreferenceComparisonCallback": "androidx/preference/PreferenceManager$PreferenceComparisonCallback",
+      "android/support/v7/widget/ActionMenuView$OnMenuItemClickListener": "androidx/widget/ActionMenuView$OnMenuItemClickListener",
+      "android/support/v7/widget/TooltipCompat$BaseViewCompatImpl": "androidx/widget/TooltipCompat$BaseViewCompatImpl",
+      "android/support/wear/widget/drawer/WearableNavigationDrawerView$NavigationStyle": "androidx/wear/widget/drawer/WearableNavigationDrawerView$NavigationStyle",
+      "android/support/transition/PatternPathMotion": "androidx/transition/PatternPathMotion",
+      "android/support/v7/palette/BuildConfig": "androidx/palette/BuildConfig",
+      "android/support/transition/Styleable$TransitionTarget": "androidx/transition/Styleable$TransitionTarget",
+      "android/support/mediacompat/R": "androidx/mediacompat/R",
+      "android/support/v7/media/MediaRouterJellybeanMr1$Callback": "androidx/media/MediaRouterJellybeanMr1$Callback",
+      "android/support/v17/leanback/widget/ControlBarPresenter$OnControlClickedListener": "androidx/leanback/widget/ControlBarPresenter$OnControlClickedListener",
+      "android/support/v4/view/LayoutInflaterCompat$Factory2Wrapper": "androidx/view/LayoutInflaterCompat$Factory2Wrapper",
+      "android/support/v7/widget/GridLayoutManager$LayoutParams": "androidx/widget/GridLayoutManager$LayoutParams",
+      "android/support/v7/widget/GridLayout": "androidx/widget/GridLayout",
+      "android/support/v4/media/MediaBrowserServiceCompat$ServiceBinderImpl": "androidx/media/MediaBrowserServiceCompat$ServiceBinderImpl",
+      "android/support/v7/widget/AppCompatCheckBox": "androidx/widget/AppCompatCheckBox",
+      "android/support/v4/view/GestureDetectorCompat$GestureDetectorCompatImpl": "androidx/view/GestureDetectorCompat$GestureDetectorCompatImpl",
+      "android/support/v17/preference/BaseLeanbackPreferenceFragment": "androidx/leanback/preference/BaseLeanbackPreferenceFragment",
+      "android/support/v17/leanback/app/GuidedStepRootLayout": "androidx/leanback/app/GuidedStepRootLayout",
+      "android/support/v4/app/FragmentManager$FragmentLifecycleCallbacks": "androidx/app/FragmentManager$FragmentLifecycleCallbacks",
+      "android/support/v4/media/MediaMetadataCompatApi21": "androidx/media/MediaMetadataCompatApi21",
+      "android/support/v7/app/MediaRouterThemeHelper": "androidx/app/MediaRouterThemeHelper",
+      "android/support/v4/util/MapCollections$EntrySet": "androidx/util/MapCollections$EntrySet",
+      "android/support/v7/widget/ViewBoundsCheck$ViewBounds": "androidx/widget/ViewBoundsCheck$ViewBounds",
+      "android/support/design/widget/HeaderScrollingViewBehavior": "androidx/design/widget/HeaderScrollingViewBehavior",
+      "android/support/v7/app/ActionBarDrawerToggle$IcsDelegate": "androidx/app/ActionBarDrawerToggle$IcsDelegate",
+      "android/support/v4/media/session/ParcelableVolumeInfo": "androidx/media/session/ParcelableVolumeInfo",
+      "android/support/v17/leanback/widget/GuidedAction$Builder": "androidx/leanback/widget/GuidedAction$Builder",
+      "android/support/v7/view/menu/CascadingMenuPopup": "androidx/view/menu/CascadingMenuPopup",
+      "android/support/v7/view/menu/MenuPopup": "androidx/view/menu/MenuPopup",
+      "android/support/v7/app/AlertDialog": "androidx/app/AlertDialog",
+      "android/support/v7/widget/RecyclerView$SavedState": "androidx/widget/RecyclerView$SavedState",
+      "android/support/wear/widget/drawer/WearableActionDrawerView$TitleViewHolder": "androidx/wear/widget/drawer/WearableActionDrawerView$TitleViewHolder",
+      "android/support/v13/view/inputmethod/InputContentInfoCompat$InputContentInfoCompatBaseImpl": "androidx/view/inputmethod/InputContentInfoCompat$InputContentInfoCompatBaseImpl",
+      "android/support/v17/leanback/app/VideoSupportFragmentGlueHost": "androidx/leanback/app/VideoSupportFragmentGlueHost",
+      "android/support/text/emoji/EmojiProcessor": "androidx/text/emoji/EmojiProcessor",
+      "android/support/v17/leanback/widget/ActionPresenterSelector": "androidx/leanback/widget/ActionPresenterSelector",
+      "android/support/v13/view/inputmethod/EditorInfoCompat$EditorInfoCompatImpl": "androidx/view/inputmethod/EditorInfoCompat$EditorInfoCompatImpl",
+      "android/support/text/emoji/widget/EmojiExtractTextLayout": "androidx/text/emoji/widget/EmojiExtractTextLayout",
+      "android/support/v17/leanback/widget/GuidedAction": "androidx/leanback/widget/GuidedAction",
+      "android/support/v17/leanback/util/StateMachine$Condition": "androidx/leanback/util/StateMachine$Condition",
+      "android/support/text/emoji/flatbuffer/Table": "androidx/text/emoji/flatbuffer/Table",
+      "android/support/v4/os/OperationCanceledException": "androidx/os/OperationCanceledException",
+      "android/support/v7/media/RegisteredMediaRouteProvider$PrivateHandler": "androidx/media/RegisteredMediaRouteProvider$PrivateHandler",
+      "android/support/v7/widget/RecyclerView$Adapter": "androidx/widget/RecyclerView$Adapter",
+      "android/support/v13/BuildConfig": "androidx/BuildConfig",
+      "android/support/v7/util/ListUpdateCallback": "androidx/util/ListUpdateCallback",
+      "android/support/v4/media/MediaDescriptionCompatApi21": "androidx/media/MediaDescriptionCompatApi21",
+      "android/support/v4/view/ViewCompat$FocusRealDirection": "androidx/view/ViewCompat$FocusRealDirection",
+      "android/support/v4/media/session/MediaControllerCompat$Callback": "androidx/media/session/MediaControllerCompat$Callback",
+      "android/support/v4/media/MediaDescriptionCompatApi23": "androidx/media/MediaDescriptionCompatApi23",
+      "android/support/v4/view/accessibility/AccessibilityEventCompat": "androidx/view/accessibility/AccessibilityEventCompat",
+      "android/support/text/emoji/FontRequestEmojiCompatConfig$FontProviderHelper": "androidx/text/emoji/FontRequestEmojiCompatConfig$FontProviderHelper",
+      "android/support/v4/app/NotificationCompat$Action$Builder": "androidx/app/NotificationCompat$Action$Builder",
+      "android/support/v4/view/accessibility/AccessibilityNodeProviderCompat$AccessibilityNodeProviderApi16": "androidx/view/accessibility/AccessibilityNodeProviderCompat$AccessibilityNodeProviderApi16",
+      "android/support/annotation/AnimatorRes": "androidx/annotation/AnimatorRes",
+      "android/support/v17/leanback/widget/GuidanceStylist": "androidx/leanback/widget/GuidanceStylist",
+      "android/support/v17/leanback/widget/StaticShadowHelper$ShadowHelperStubImpl": "androidx/leanback/widget/StaticShadowHelper$ShadowHelperStubImpl",
+      "android/support/v4/view/accessibility/AccessibilityNodeProviderCompat$AccessibilityNodeProviderApi19": "androidx/view/accessibility/AccessibilityNodeProviderCompat$AccessibilityNodeProviderApi19",
+      "android/support/v7/util/ThreadUtil": "androidx/util/ThreadUtil",
+      "android/support/content/InMemoryCursor$ObserverRelay": "androidx/content/InMemoryCursor$ObserverRelay",
+      "android/support/wear/R$drawable": "androidx/wear/R$drawable",
+      "android/support/constraint/ConstraintLayout$LayoutParams": "androidx/constraint/ConstraintLayout$LayoutParams",
+      "android/support/v7/widget/StaggeredGridLayoutManager$LazySpanLookup": "androidx/widget/StaggeredGridLayoutManager$LazySpanLookup",
+      "android/support/transition/BuildConfig": "androidx/transition/BuildConfig",
+      "android/support/v17/leanback/app/SearchFragment$ExternalQuery": "androidx/leanback/app/SearchFragment$ExternalQuery",
+      "android/support/media/tv/TvContractCompat$Programs$Genres": "androidx/media/tv/TvContractCompat$Programs$Genres",
+      "android/support/v13/view/inputmethod/InputConnectionCompat$OnCommitContentListener": "androidx/view/inputmethod/InputConnectionCompat$OnCommitContentListener",
+      "android/support/content/ContentPager$CursorDisposition": "androidx/content/ContentPager$CursorDisposition",
+      "android/support/v4/view/AsyncLayoutInflater$OnInflateFinishedListener": "androidx/view/AsyncLayoutInflater$OnInflateFinishedListener",
+      "android/support/v4/media/session/MediaControllerCompat$MediaControllerImplBase": "androidx/media/session/MediaControllerCompat$MediaControllerImplBase",
+      "android/support/v4/util/PatternsCompat": "androidx/util/PatternsCompat",
+      "android/support/v4/media/MediaBrowserServiceCompat$ServiceCallbacksCompat": "androidx/media/MediaBrowserServiceCompat$ServiceCallbacksCompat",
+      "android/support/v7/widget/AppCompatCompoundButtonHelper$DirectSetButtonDrawableInterface": "androidx/widget/AppCompatCompoundButtonHelper$DirectSetButtonDrawableInterface",
+      "android/support/v17/leanback/media/PlaybackGlueHost": "androidx/leanback/media/PlaybackGlueHost",
+      "android/support/v4/content/ModernAsyncTask": "androidx/content/ModernAsyncTask",
+      "android/support/v4/view/ViewCompat$ViewCompatApi15Impl": "androidx/view/ViewCompat$ViewCompatApi15Impl",
+      "android/support/v4/os/ResultReceiver$MyResultReceiver": "androidx/os/ResultReceiver$MyResultReceiver",
+      "android/support/v7/widget/helper/ItemTouchHelper$Callback": "androidx/widget/helper/ItemTouchHelper$Callback",
+      "android/support/v17/leanback/app/BrowseFragment$MainFragmentRowsAdapterProvider": "androidx/leanback/app/BrowseFragment$MainFragmentRowsAdapterProvider",
+      "android/support/annotation/Nullable": "androidx/annotation/Nullable",
+      "android/support/v4/os/IResultReceiver$Stub": "androidx/os/IResultReceiver$Stub",
+      "android/support/v7/widget/Toolbar$ExpandedActionViewMenuPresenter": "androidx/widget/Toolbar$ExpandedActionViewMenuPresenter",
+      "android/support/v17/leanback/widget/picker/PickerUtility": "androidx/leanback/widget/picker/PickerUtility",
+      "android/support/v4/view/ViewPager$MyAccessibilityDelegate": "androidx/view/ViewPager$MyAccessibilityDelegate",
+      "android/support/v4/app/FragmentTransaction$Transit": "androidx/app/FragmentTransaction$Transit",
+      "android/support/v7/widget/DefaultItemAnimator": "androidx/widget/DefaultItemAnimator",
+      "android/support/v4/view/PagerAdapter": "androidx/widget/PagerAdapter",
+      "android/support/v7/media/MediaRouteProviderService$PrivateHandler": "androidx/media/MediaRouteProviderService$PrivateHandler",
+      "android/support/v4/media/session/IMediaControllerCallback$Stub$Proxy": "androidx/media/session/IMediaControllerCallback$Stub$Proxy",
+      "android/support/v4/media/RatingCompat": "androidx/media/RatingCompat",
+      "android/support/v7/widget/GridLayout$Assoc": "androidx/widget/GridLayout$Assoc",
+      "android/support/v17/leanback/app/DetailsSupportFragment$SetSelectionRunnable": "androidx/leanback/app/DetailsSupportFragment$SetSelectionRunnable",
+      "android/support/v7/util/DiffUtil$Callback": "androidx/util/DiffUtil$Callback",
+      "android/support/v7/widget/ActivityChooserModel$ActivityChooserModelClient": "androidx/widget/ActivityChooserModel$ActivityChooserModelClient",
+      "android/support/v7/widget/PagerSnapHelper": "androidx/widget/PagerSnapHelper",
+      "android/support/v17/leanback/widget/GridLayoutManager$LayoutParams": "androidx/leanback/widget/GridLayoutManager$LayoutParams",
+      "android/support/percent/R": "androidx/R",
+      "android/support/transition/Styleable$Fade": "androidx/transition/Styleable$Fade",
+      "android/support/design/widget/FloatingActionButtonLollipop": "androidx/design/widget/FloatingActionButtonLollipop",
+      "android/support/v17/leanback/widget/ActionPresenterSelector$OneLineActionPresenter": "androidx/leanback/widget/ActionPresenterSelector$OneLineActionPresenter",
+      "android/support/transition/ViewUtilsApi22": "androidx/transition/ViewUtilsApi22",
+      "android/support/v7/widget/LinearLayoutCompat$LayoutParams": "androidx/widget/LinearLayoutCompat$LayoutParams",
+      "android/support/transition/ViewUtilsApi21": "androidx/transition/ViewUtilsApi21",
+      "android/support/v17/leanback/app/BrandedFragment": "androidx/leanback/app/BrandedFragment",
+      "android/support/text/emoji/bundled/BundledEmojiCompatConfig$BundledMetadataLoader": "androidx/text/emoji/bundled/BundledEmojiCompatConfig$BundledMetadataLoader",
+      "android/support/v17/preference/R": "androidx/leanback/preference/R",
+      "android/support/v4/content/res/TypedArrayUtils": "androidx/content/res/TypedArrayUtils",
+      "android/support/v7/app/ActionBar$LayoutParams": "androidx/app/ActionBar$LayoutParams",
+      "android/support/transition/Visibility$DisappearListener": "androidx/transition/Visibility$DisappearListener",
+      "android/support/v7/view/menu/MenuView$ItemView": "androidx/view/menu/MenuView$ItemView",
+      "android/support/text/emoji/flatbuffer/FlatBufferBuilder": "androidx/text/emoji/flatbuffer/FlatBufferBuilder",
+      "android/support/v17/leanback/app/BaseRowFragment$LateSelectionObserver": "androidx/leanback/app/BaseRowFragment$LateSelectionObserver",
+      "android/support/wear/widget/SwipeDismissFrameLayout$MyOnSwipeProgressChangedListener": "androidx/wear/widget/SwipeDismissFrameLayout$MyOnSwipeProgressChangedListener",
+      "android/support/v4/content/PermissionChecker$PermissionResult": "androidx/content/PermissionChecker$PermissionResult",
+      "android/support/v7/media/MediaRouter$ControlRequestCallback": "androidx/media/MediaRouter$ControlRequestCallback",
+      "android/support/wear/widget/drawer/WearableNavigationDrawerView$WearableNavigationDrawerAdapter": "androidx/wear/widget/drawer/WearableNavigationDrawerView$WearableNavigationDrawerAdapter",
+      "android/support/v13/view/inputmethod/InputContentInfoCompat": "androidx/view/inputmethod/InputContentInfoCompat",
+      "android/support/transition/ViewUtilsApi19": "androidx/transition/ViewUtilsApi19",
+      "android/support/transition/ViewUtilsApi18": "androidx/transition/ViewUtilsApi18",
+      "android/support/v7/widget/AppCompatDrawableManager$InflateDelegate": "androidx/widget/AppCompatDrawableManager$InflateDelegate",
+      "android/support/v7/preference/R$styleable": "androidx/preference/R$styleable",
+      "android/support/v13/view/DragAndDropPermissionsCompat": "androidx/view/DragAndDropPermissionsCompat",
+      "android/support/v4/content/res/FontResourcesParserCompat$FontFamilyFilesResourceEntry": "androidx/content/res/FontResourcesParserCompat$FontFamilyFilesResourceEntry",
+      "android/support/transition/ViewUtilsApi14": "androidx/transition/ViewUtilsApi14",
+      "android/support/v7/view/menu/MenuItemWrapperICS": "androidx/view/menu/MenuItemWrapperICS",
+      "android/support/design/widget/CollapsingToolbarLayout": "androidx/design/widget/CollapsingToolbarLayout",
+      "android/support/dynamicanimation/BuildConfig": "androidx/dynamicanimation/BuildConfig",
+      "android/support/v4/util/ArrayMap": "androidx/util/ArrayMap",
+      "android/support/v17/leanback/widget/ParallaxTarget$PropertyValuesHolderTarget": "androidx/leanback/widget/ParallaxTarget$PropertyValuesHolderTarget",
+      "android/support/wear/widget/drawer/WearableActionDrawerView$ActionListAdapter": "androidx/wear/widget/drawer/WearableActionDrawerView$ActionListAdapter",
+      "android/support/v4/media/MediaBrowserCompat$MediaBrowserServiceCallbackImpl": "androidx/media/MediaBrowserCompat$MediaBrowserServiceCallbackImpl",
+      "android/support/wear/widget/SimpleAnimatorListener": "androidx/wear/widget/SimpleAnimatorListener",
+      "android/support/v17/leanback/widget/FacetProviderAdapter": "androidx/leanback/widget/FacetProviderAdapter",
+      "android/support/v4/widget/SlidingPaneLayout$SlidingPanelLayoutImplJBMR1": "androidx/widget/SlidingPaneLayout$SlidingPanelLayoutImplJBMR1",
+      "android/support/v7/widget/SearchView": "androidx/widget/SearchView",
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplBase$MediaSessionStub": "androidx/media/session/MediaSessionCompat$MediaSessionImplBase$MediaSessionStub",
+      "android/support/v7/widget/TooltipCompat$ViewCompatImpl": "androidx/widget/TooltipCompat$ViewCompatImpl",
+      "android/support/v13/view/DragAndDropPermissionsCompat$DragAndDropPermissionsCompatImpl": "androidx/view/DragAndDropPermissionsCompat$DragAndDropPermissionsCompatImpl",
+      "android/support/customtabs/IPostMessageService$Stub$Proxy": "androidx/browser/customtabs/IPostMessageService$Stub$Proxy",
+      "android/support/v17/leanback/widget/ItemAlignment$Axis": "androidx/leanback/widget/ItemAlignment$Axis",
+      "android/support/v7/widget/RecyclerView$ViewHolder": "androidx/widget/RecyclerView$ViewHolder",
+      "android/support/v7/widget/GapWorker": "androidx/widget/GapWorker",
+      "android/support/v7/media/MediaItemStatus": "androidx/media/MediaItemStatus",
+      "android/support/transition/Explode": "androidx/transition/Explode",
+      "android/support/v17/leanback/widget/GuidedActionAdapter$ActionEditListener": "androidx/leanback/widget/GuidedActionAdapter$ActionEditListener",
+      "android/support/v4/text/BidiFormatter": "androidx/text/BidiFormatter",
+      "android/support/v7/widget/CardViewApi17Impl": "androidx/widget/CardViewApi17Impl",
+      "android/support/v7/media/MediaRouter$RouteInfo$PlaybackType": "androidx/media/MediaRouter$RouteInfo$PlaybackType",
+      "android/support/v4/view/ViewGroupCompat$ViewGroupCompatBaseImpl": "androidx/view/ViewGroupCompat$ViewGroupCompatBaseImpl",
+      "android/support/v4/view/ViewParentCompat$ViewParentCompatApi21Impl": "androidx/view/ViewParentCompat$ViewParentCompatApi21Impl",
+      "android/support/v7/widget/StaggeredGridLayoutManager": "androidx/widget/StaggeredGridLayoutManager",
+      "android/support/v4/widget/FocusStrategy": "androidx/widget/FocusStrategy",
+      "android/support/customtabs/ICustomTabsCallback$Stub$Proxy": "androidx/browser/customtabs/ICustomTabsCallback$Stub$Proxy",
+      "android/support/v7/media/MediaRouteProvider": "androidx/media/MediaRouteProvider",
+      "android/support/v4/net/DatagramSocketWrapper": "androidx/net/DatagramSocketWrapper",
+      "android/support/design/widget/SnackbarManager": "androidx/design/widget/SnackbarManager",
+      "android/support/v17/leanback/media/MediaControllerGlue": "androidx/leanback/media/MediaControllerGlue",
+      "android/support/v7/widget/PopupMenu$OnMenuItemClickListener": "androidx/widget/PopupMenu$OnMenuItemClickListener",
+      "android/support/v7/widget/helper/ItemTouchUIUtilImpl$Api21Impl": "androidx/widget/helper/ItemTouchUIUtilImpl$Api21Impl",
+      "android/support/text/emoji/widget/EmojiTextViewHelper": "androidx/text/emoji/widget/EmojiTextViewHelper",
+      "android/support/v4/media/session/MediaSessionCompat$Callback": "androidx/media/session/MediaSessionCompat$Callback",
+      "android/support/design/internal/NavigationMenuPresenter$NavigationMenuTextItem": "androidx/design/internal/NavigationMenuPresenter$NavigationMenuTextItem",
+      "android/support/v13/app/FragmentCompat$OnRequestPermissionsResultCallback": "androidx/app/FragmentCompat$OnRequestPermissionsResultCallback",
+      "android/support/design/widget/AppBarLayout$Behavior$DragCallback": "androidx/design/widget/AppBarLayout$Behavior$DragCallback",
+      "android/support/text/emoji/widget/EmojiEditTextHelper": "androidx/text/emoji/widget/EmojiEditTextHelper",
+      "android/support/v7/widget/AppCompatTextHelperV17": "androidx/widget/AppCompatTextHelperV17",
+      "android/support/v4/widget/SimpleCursorAdapter": "androidx/widget/SimpleCursorAdapter",
+      "android/support/mediacompat/R$integer": "androidx/mediacompat/R$integer",
+      "android/support/v17/leanback/widget/Grid$Provider": "androidx/leanback/widget/Grid$Provider",
+      "android/support/v13/view/ViewCompat": "androidx/view/ViewCompat",
+      "android/support/v14/preference/MultiSelectListPreference$SavedState": "androidx/preference/MultiSelectListPreference$SavedState",
+      "android/support/v4/view/NestedScrollingChild": "androidx/view/NestedScrollingChild",
+      "android/support/v7/preference/R$layout": "androidx/preference/R$layout",
+      "android/support/v4/app/FragmentTransition": "androidx/app/FragmentTransition",
+      "android/support/v4/app/NotificationCompat$Action$WearableExtender": "androidx/app/NotificationCompat$Action$WearableExtender",
+      "android/support/v17/preference/LeanbackPreferenceDialogFragment": "androidx/leanback/preference/LeanbackPreferenceDialogFragment",
+      "android/support/annotation/WorkerThread": "androidx/annotation/WorkerThread",
+      "android/support/v7/app/MediaRouteDialogFactory": "androidx/app/MediaRouteDialogFactory",
+      "android/support/v7/view/ActionMode": "androidx/view/ActionMode",
+      "android/support/v4/provider/FontsContractCompat$FontRequestCallback$FontRequestFailReason": "androidx/provider/FontsContractCompat$FontRequestCallback$FontRequestFailReason",
+      "android/support/v17/leanback/R$drawable": "androidx/leanback/R$drawable",
+      "android/support/annotation/StringRes": "androidx/annotation/StringRes",
+      "android/support/v4/app/RemoteInputCompatBase$RemoteInput": "androidx/app/RemoteInputCompatBase$RemoteInput",
+      "android/support/v13/app/FragmentTabHost$TabInfo": "androidx/app/FragmentTabHost$TabInfo",
+      "android/support/v7/app/ActionBarDrawerToggle$ToolbarCompatDelegate": "androidx/app/ActionBarDrawerToggle$ToolbarCompatDelegate",
+      "android/support/v7/widget/PopupMenu$OnDismissListener": "androidx/widget/PopupMenu$OnDismissListener",
+      "android/support/transition/AnimatorUtilsApi14$AnimatorPauseListenerCompat": "androidx/transition/AnimatorUtilsApi14$AnimatorPauseListenerCompat",
+      "android/support/v4/app/JobIntentService$CommandProcessor": "androidx/app/JobIntentService$CommandProcessor",
+      "android/support/v17/leanback/widget/VerticalGridView": "androidx/leanback/widget/VerticalGridView",
+      "android/support/v4/app/FragmentManager": "androidx/app/FragmentManager",
+      "android/support/v4/app/BackStackState": "androidx/app/BackStackState",
+      "android/support/text/emoji/R": "androidx/text/emoji/R",
+      "android/support/v4/media/session/MediaSessionCompatApi21$Callback": "androidx/media/session/MediaSessionCompatApi21$Callback",
+      "android/support/transition/ChangeScroll": "androidx/transition/ChangeScroll",
+      "android/support/v4/view/ViewCompat$LayoutDirectionMode": "androidx/view/ViewCompat$LayoutDirectionMode",
+      "android/support/v7/widget/AdapterHelper$Callback": "androidx/widget/AdapterHelper$Callback",
+      "android/support/wear/R$layout": "androidx/wear/R$layout",
+      "android/support/v17/leanback/widget/GuidedActionAdapter$ClickListener": "androidx/leanback/widget/GuidedActionAdapter$ClickListener",
+      "android/support/v4/media/session/MediaControllerCompat$MediaControllerImplApi21$ExtraCallback": "androidx/media/session/MediaControllerCompat$MediaControllerImplApi21$ExtraCallback",
+      "android/support/customtabs/ICustomTabsService$Stub": "androidx/browser/customtabs/ICustomTabsService$Stub",
+      "android/support/v17/leanback/widget/ListRowView": "androidx/leanback/widget/ListRowView",
+      "android/support/v7/widget/ActivityChooserView": "androidx/widget/ActivityChooserView",
+      "android/support/v4/os/TraceCompat": "androidx/os/TraceCompat",
+      "android/support/transition/ImageViewUtils": "androidx/transition/ImageViewUtils",
+      "android/support/v4/app/FragmentManager$OnBackStackChangedListener": "androidx/app/FragmentManager$OnBackStackChangedListener",
+      "android/support/v7/app/AppCompatDelegateImplV23$AppCompatWindowCallbackV23": "androidx/app/AppCompatDelegateImplV23$AppCompatWindowCallbackV23",
+      "android/support/transition/GhostViewApi14": "androidx/transition/GhostViewApi14",
+      "android/support/design/widget/SwipeDismissBehavior$SwipeDirection": "androidx/design/widget/SwipeDismissBehavior$SwipeDirection",
+      "android/support/v17/leanback/widget/SearchOrbView": "androidx/leanback/widget/SearchOrbView",
+      "android/support/v4/app/NotificationManagerCompat$NotifyTask": "androidx/app/NotificationManagerCompat$NotifyTask",
+      "android/support/v4/util/LruCache": "androidx/util/LruCache",
+      "android/support/v7/widget/ActionMenuView$LayoutParams": "androidx/widget/ActionMenuView$LayoutParams",
+      "android/support/v7/widget/helper/ItemTouchHelper$ViewDropHandler": "androidx/widget/helper/ItemTouchHelper$ViewDropHandler",
+      "android/support/v7/content/res/AppCompatColorStateListInflater": "androidx/content/res/AppCompatColorStateListInflater",
+      "android/support/v7/widget/ActionMenuPresenter$OpenOverflowRunnable": "androidx/widget/ActionMenuPresenter$OpenOverflowRunnable",
+      "android/support/v7/media/MediaRouter$GlobalMediaRouter$CallbackHandler": "androidx/media/MediaRouter$GlobalMediaRouter$CallbackHandler",
+      "android/support/design/widget/AppBarLayout$Behavior": "androidx/design/widget/AppBarLayout$Behavior",
+      "android/support/v4/widget/ExploreByTouchHelper": "androidx/widget/ExploreByTouchHelper",
+      "android/support/transition/PropertyValuesHolderUtilsImpl": "androidx/transition/PropertyValuesHolderUtilsImpl",
+      "android/support/v14/preference/PreferenceDialogFragment": "androidx/preference/PreferenceDialogFragment",
+      "android/support/transition/GhostViewApi21": "androidx/transition/GhostViewApi21",
+      "android/support/text/emoji/MetadataListReader$InputStreamOpenTypeReader": "androidx/text/emoji/MetadataListReader$InputStreamOpenTypeReader",
+      "android/support/transition/RectEvaluator": "androidx/transition/RectEvaluator",
+      "android/support/v7/preference/BuildConfig": "androidx/preference/BuildConfig",
+      "android/support/v4/view/VelocityTrackerCompat": "androidx/view/VelocityTrackerCompat",
+      "android/support/v7/widget/AppCompatAutoCompleteTextView": "androidx/widget/AppCompatAutoCompleteTextView",
+      "android/support/v7/media/MediaRouterJellybean$VolumeCallback": "androidx/media/MediaRouterJellybean$VolumeCallback",
+      "android/support/media/tv/WatchNextProgram": "androidx/media/tv/WatchNextProgram",
+      "android/support/wear/internal/widget/drawer/MultiPageUi$NavigationPagerAdapter": "androidx/wear/internal/widget/drawer/MultiPageUi$NavigationPagerAdapter",
+      "android/support/v4/widget/ExploreByTouchHelper$MyNodeProvider": "androidx/widget/ExploreByTouchHelper$MyNodeProvider",
+      "android/support/v7/widget/RecyclerView$AdapterDataObserver": "androidx/widget/RecyclerView$AdapterDataObserver",
+      "android/support/v4/media/session/IMediaSession": "androidx/media/session/IMediaSession",
+      "android/support/v17/preference/LeanbackSettingsRootView": "androidx/leanback/preference/LeanbackSettingsRootView",
+      "android/support/v7/widget/AppCompatButton": "androidx/widget/AppCompatButton",
+      "android/support/constraint/solver/widgets/ConstraintWidget$DimensionBehaviour": "androidx/constraint/solver/widgets/ConstraintWidget$DimensionBehaviour",
+      "android/support/graphics/drawable/AnimatedVectorDrawableCompat$AnimatedVectorDrawableDelegateState": "androidx/graphics/drawable/AnimatedVectorDrawableCompat$AnimatedVectorDrawableDelegateState",
+      "android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController": "androidx/leanback/app/DetailsSupportFragmentBackgroundController",
+      "android/support/v17/leanback/widget/ThumbsBar": "androidx/leanback/widget/ThumbsBar",
+      "android/support/v4/media/session/MediaSessionCompat$Token": "androidx/media/session/MediaSessionCompat$Token",
+      "android/support/v7/mediarouter/R$integer": "androidx/mediarouter/R$integer",
+      "android/support/v7/app/WindowDecorActionBar": "androidx/app/WindowDecorActionBar",
+      "android/support/v4/app/Fragment$SavedState": "androidx/app/Fragment$SavedState",
+      "android/support/v17/leanback/widget/StaggeredGrid$Location": "androidx/leanback/widget/StaggeredGrid$Location",
+      "android/support/v17/leanback/widget/DiffCallback": "androidx/leanback/widget/DiffCallback",
+      "android/support/v4/os/ParcelableCompat": "androidx/os/ParcelableCompat",
+      "android/support/transition/ViewGroupUtils": "androidx/transition/ViewGroupUtils",
+      "android/support/v7/media/MediaRouter$GlobalMediaRouter$MediaSessionRecord": "androidx/media/MediaRouter$GlobalMediaRouter$MediaSessionRecord",
+      "android/support/v7/widget/ViewBoundsCheck$BoundFlags": "androidx/widget/ViewBoundsCheck$BoundFlags",
+      "android/support/wear/R": "androidx/wear/R",
+      "android/support/v17/leanback/app/DetailsSupportFragment$WaitEnterTransitionTimeout": "androidx/leanback/app/DetailsSupportFragment$WaitEnterTransitionTimeout",
+      "android/support/v4/widget/ViewDragHelper$Callback": "androidx/widget/ViewDragHelper$Callback",
+      "android/support/v7/widget/DropDownListView": "androidx/widget/DropDownListView",
+      "android/support/v17/leanback/transition/TransitionHelper$TransitionHelperVersionImpl": "androidx/leanback/transition/TransitionHelper$TransitionHelperVersionImpl",
+      "android/support/transition/TransitionUtils$MatrixEvaluator": "androidx/transition/TransitionUtils$MatrixEvaluator",
+      "android/support/v4/hardware/display/DisplayManagerCompat": "androidx/hardware/display/DisplayManagerCompat",
+      "android/support/media/tv/TvContractCompat$Channels$VideoResolution": "androidx/media/tv/TvContractCompat$Channels$VideoResolution",
+      "android/support/v4/app/NotificationCompatBuilder": "androidx/app/NotificationCompatBuilder",
+      "android/support/v4/media/session/MediaControllerCompat$TransportControls": "androidx/media/session/MediaControllerCompat$TransportControls",
+      "android/support/v7/view/menu/SubMenuBuilder": "androidx/view/menu/SubMenuBuilder",
+      "android/support/v4/media/session/MediaSessionCompatApi23$CallbackProxy": "androidx/media/session/MediaSessionCompatApi23$CallbackProxy",
+      "android/support/v7/recyclerview/R$id": "androidx/recyclerview/R$id",
+      "android/support/wear/widget/WearableLinearLayoutManager$LayoutCallback": "androidx/wear/widget/WearableLinearLayoutManager$LayoutCallback",
+      "android/support/v17/leanback/widget/PresenterSelector": "androidx/leanback/widget/PresenterSelector",
+      "android/support/v4/app/JobIntentService$JobServiceEngineImpl": "androidx/app/JobIntentService$JobServiceEngineImpl",
+      "android/support/v4/app/ActionBarDrawerToggle$DelegateProvider": "androidx/app/ActionBarDrawerToggle$DelegateProvider",
+      "android/support/v17/leanback/widget/GuidedActionsRelativeLayout": "androidx/leanback/widget/GuidedActionsRelativeLayout",
+      "android/support/v7/widget/RecyclerView$LayoutManager": "androidx/widget/RecyclerView$LayoutManager",
+      "android/support/v4/print/PrintHelper": "androidx/print/PrintHelper",
+      "android/support/v7/util/AsyncListUtil": "androidx/util/AsyncListUtil",
+      "android/support/transition/TransitionListenerAdapter": "androidx/transition/TransitionListenerAdapter",
+      "android/support/v7/view/menu/MenuItemWrapperICS$ActionProviderWrapper": "androidx/view/menu/MenuItemWrapperICS$ActionProviderWrapper",
+      "android/support/v7/app/TwilightManager": "androidx/app/TwilightManager",
+      "android/support/v17/leanback/transition/LeanbackTransitionHelper$LeanbackTransitionHelperDefault": "androidx/leanback/transition/LeanbackTransitionHelper$LeanbackTransitionHelperDefault",
+      "android/support/v4/app/NotificationCompat$InboxStyle": "androidx/app/NotificationCompat$InboxStyle",
+      "android/support/v14/preference/MultiSelectListPreference": "androidx/preference/MultiSelectListPreference",
+      "android/support/v13/view/inputmethod/EditorInfoCompat$EditorInfoCompatBaseImpl": "androidx/view/inputmethod/EditorInfoCompat$EditorInfoCompatBaseImpl",
+      "android/support/v7/preference/SeekBarPreference$SavedState": "androidx/preference/SeekBarPreference$SavedState",
+      "android/support/v17/leanback/widget/PlaybackControlsRowPresenter$BoundData": "androidx/leanback/widget/PlaybackControlsRowPresenter$BoundData",
+      "android/support/customtabs/CustomTabsSessionToken": "androidx/browser/customtabs/CustomTabsSessionToken",
+      "android/support/v4/media/session/MediaControllerCompat$PlaybackInfo": "androidx/media/session/MediaControllerCompat$PlaybackInfo",
+      "android/support/v17/leanback/app/DetailsBackgroundVideoHelper": "androidx/leanback/app/DetailsBackgroundVideoHelper",
+      "android/support/v17/leanback/app/RowsFragment$MainFragmentRowsAdapter": "androidx/leanback/app/RowsFragment$MainFragmentRowsAdapter",
+      "android/support/v7/app/OverlayListView$OverlayObject": "androidx/app/OverlayListView$OverlayObject",
+      "android/support/v4/provider/SingleDocumentFile": "androidx/provider/SingleDocumentFile",
+      "android/support/v7/app/AppCompatDelegateImplV9$ActionModeCallbackWrapperV9": "androidx/app/AppCompatDelegateImplV9$ActionModeCallbackWrapperV9",
+      "android/support/v4/widget/TintableCompoundButton": "androidx/widget/TintableCompoundButton",
+      "android/support/v7/graphics/Target$Builder": "androidx/graphics/Target$Builder",
+      "android/support/v17/leanback/widget/NonOverlappingFrameLayout": "androidx/leanback/widget/NonOverlappingFrameLayout",
+      "android/support/annotation/IntegerRes": "androidx/annotation/IntegerRes",
+      "android/support/media/tv/CollectionUtils": "androidx/media/tv/CollectionUtils",
+      "android/support/v4/provider/FontsContractCompat$FontRequestCallback": "androidx/provider/FontsContractCompat$FontRequestCallback",
+      "android/support/design/internal/BottomNavigationMenuView": "androidx/design/internal/BottomNavigationMenuView",
+      "android/support/v4/graphics/drawable/RoundedBitmapDrawable21": "androidx/graphics/drawable/RoundedBitmapDrawable21",
+      "android/support/design/widget/CoordinatorLayout$SavedState": "androidx/design/widget/CoordinatorLayout$SavedState",
+      "android/support/text/emoji/BuildConfig": "androidx/text/emoji/BuildConfig",
+      "android/support/media/tv/TvContractCompat": "androidx/media/tv/TvContractCompat",
+      "android/support/v7/media/RemoteControlClientCompat$PlaybackInfo": "androidx/media/RemoteControlClientCompat$PlaybackInfo",
+      "android/support/v7/app/AppCompatDelegateImplV9$ActionMenuPresenterCallback": "androidx/app/AppCompatDelegateImplV9$ActionMenuPresenterCallback",
+      "android/support/v17/leanback/widget/StreamingTextView$DottySpan": "androidx/leanback/widget/StreamingTextView$DottySpan",
+      "android/support/v7/view/menu/ActionMenuItemView$PopupCallback": "androidx/view/menu/ActionMenuItemView$PopupCallback",
+      "android/support/percent/PercentLayoutHelper": "androidx/PercentLayoutHelper",
+      "android/support/v17/leanback/transition/LeanbackTransitionHelper$LeanbackTransitionHelperVersion": "androidx/leanback/transition/LeanbackTransitionHelper$LeanbackTransitionHelperVersion",
+      "android/support/v17/leanback/widget/VerticalGridPresenter$ViewHolder": "androidx/leanback/widget/VerticalGridPresenter$ViewHolder",
+      "android/support/media/tv/BaseProgram": "androidx/media/tv/BaseProgram",
+      "android/support/v4/view/ViewGroupCompat": "androidx/view/ViewGroupCompat",
+      "android/support/media/instantvideo/preload/InstantVideoPreloadManager$AsyncTaskVideoPreloader": "androidx/media/instantvideo/preload/InstantVideoPreloadManager$AsyncTaskVideoPreloader",
+      "android/support/v4/widget/FocusStrategy$CollectionAdapter": "androidx/widget/FocusStrategy$CollectionAdapter",
+      "android/support/v7/util/SortedList$Callback": "androidx/util/SortedList$Callback",
+      "android/support/v17/leanback/widget/Parallax$PropertyMarkerValue": "androidx/leanback/widget/Parallax$PropertyMarkerValue",
+      "android/support/v4/text/TextDirectionHeuristicsCompat$AnyStrong": "androidx/text/TextDirectionHeuristicsCompat$AnyStrong",
+      "android/support/v14/preference/PreferenceFragment$OnPreferenceStartScreenCallback": "androidx/preference/PreferenceFragment$OnPreferenceStartScreenCallback",
+      "android/support/v17/leanback/widget/picker/PickerColumn": "androidx/leanback/widget/picker/PickerColumn",
+      "android/support/transition/TransitionPropagation": "androidx/transition/TransitionPropagation",
+      "android/support/v17/leanback/widget/WindowAlignment": "androidx/leanback/widget/WindowAlignment",
+      "android/support/v17/leanback/transition/TranslationAnimationCreator": "androidx/leanback/transition/TranslationAnimationCreator",
+      "android/support/v7/media/MediaRouterApi24": "androidx/media/MediaRouterApi24",
+      "android/support/transition/Styleable$Slide": "androidx/transition/Styleable$Slide",
+      "android/support/v7/view/menu/StandardMenuPopup": "androidx/view/menu/StandardMenuPopup",
+      "android/support/v4/widget/PopupMenuCompat": "androidx/widget/PopupMenuCompat",
+      "android/support/design/widget/CollapsingToolbarLayout$LayoutParams$CollapseMode": "androidx/design/widget/CollapsingToolbarLayout$LayoutParams$CollapseMode",
+      "android/support/v17/leanback/widget/ObjectAdapter": "androidx/leanback/widget/ObjectAdapter",
+      "android/support/v4/view/GestureDetectorCompat": "androidx/view/GestureDetectorCompat",
+      "android/support/v17/leanback/widget/Parallax$IntPropertyMarkerValue": "androidx/leanback/widget/Parallax$IntPropertyMarkerValue",
+      "android/support/v4/view/ViewCompat$ViewCompatApi26Impl": "androidx/view/ViewCompat$ViewCompatApi26Impl",
+      "android/support/v7/media/RemoteControlClientCompat$VolumeCallback": "androidx/media/RemoteControlClientCompat$VolumeCallback",
+      "android/support/design/widget/AnimationUtils": "androidx/design/widget/AnimationUtils",
+      "android/support/v4/view/ViewCompat$ScrollIndicators": "androidx/view/ViewCompat$ScrollIndicators",
+      "android/support/media/tv/WatchNextProgram$Builder": "androidx/media/tv/WatchNextProgram$Builder",
+      "android/support/v7/graphics/Palette$Filter": "androidx/graphics/Palette$Filter",
+      "android/support/annotation/BinderThread": "androidx/annotation/BinderThread",
+      "android/support/v17/leanback/widget/FocusHighlightHelper$HeaderItemFocusHighlight$HeaderFocusAnimator": "androidx/leanback/widget/FocusHighlightHelper$HeaderItemFocusHighlight$HeaderFocusAnimator",
+      "android/support/media/tv/Program$Builder": "androidx/media/tv/Program$Builder",
+      "android/support/v4/hardware/fingerprint/FingerprintManagerCompat$AuthenticationResult": "androidx/hardware/fingerprint/FingerprintManagerCompat$AuthenticationResult",
+      "android/support/v4/os/LocaleListCompat$LocaleListCompatApi24Impl": "androidx/os/LocaleListCompat$LocaleListCompatApi24Impl",
+      "android/support/v17/leanback/widget/GuidedActionAdapter$FocusListener": "androidx/leanback/widget/GuidedActionAdapter$FocusListener",
+      "android/support/v17/leanback/widget/ControlBarPresenter$ViewHolder": "androidx/leanback/widget/ControlBarPresenter$ViewHolder",
+      "android/support/v7/graphics/drawable/DrawerArrowDrawable$ArrowDirection": "androidx/graphics/drawable/DrawerArrowDrawable$ArrowDirection",
+      "android/support/v4/view/ViewPager$DecorView": "androidx/view/ViewPager$DecorView",
+      "android/support/v4/view/ViewParentCompat$ViewParentCompatApi19Impl": "androidx/view/ViewParentCompat$ViewParentCompatApi19Impl",
+      "android/support/v7/widget/StaggeredGridLayoutManager$Span": "androidx/widget/StaggeredGridLayoutManager$Span",
+      "android/support/wear/widget/ProgressDrawable": "androidx/wear/widget/ProgressDrawable",
+      "android/support/v7/media/MediaRouterJellybeanMr2$RouteInfo": "androidx/media/MediaRouterJellybeanMr2$RouteInfo",
+      "android/support/v4/graphics/PathParser$PathDataNode": "androidx/graphics/PathParser$PathDataNode",
+      "android/support/v17/leanback/graphics/ColorFilterCache": "androidx/leanback/graphics/ColorFilterCache",
+      "android/support/text/emoji/EmojiCompat$InitCallback": "androidx/text/emoji/EmojiCompat$InitCallback",
+      "android/support/v17/leanback/app/BrowseFragment$MainFragmentAdapterRegistry": "androidx/leanback/app/BrowseFragment$MainFragmentAdapterRegistry",
+      "android/support/transition/PropertyValuesHolderUtils": "androidx/transition/PropertyValuesHolderUtils",
+      "android/support/v7/widget/ActivityChooserModel$DefaultSorter": "androidx/widget/ActivityChooserModel$DefaultSorter",
+      "android/support/v7/app/AlertController$CheckedItemAdapter": "androidx/app/AlertController$CheckedItemAdapter",
+      "android/support/design/widget/TabItem": "androidx/design/widget/TabItem",
+      "android/support/v4/media/MediaBrowserCompatApi21$ConnectionCallbackProxy": "androidx/media/MediaBrowserCompatApi21$ConnectionCallbackProxy",
+      "android/support/content/LoaderQueryRunner": "androidx/content/LoaderQueryRunner",
+      "android/support/v17/leanback/app/BrowseSupportFragment$FragmentFactory": "androidx/leanback/app/BrowseSupportFragment$FragmentFactory",
+      "android/support/v7/app/AppCompatDelegateImplN$AppCompatWindowCallbackN": "androidx/app/AppCompatDelegateImplN$AppCompatWindowCallbackN",
+      "android/support/wear/widget/drawer/WearableDrawerLayout$DrawerDraggerCallback": "androidx/wear/widget/drawer/WearableDrawerLayout$DrawerDraggerCallback",
+      "android/support/content/BuildConfig": "androidx/content/BuildConfig",
+      "android/support/v7/widget/OpReorderer": "androidx/widget/OpReorderer",
+      "android/support/media/instantvideo/preload/InstantVideoPreloadManager": "androidx/media/instantvideo/preload/InstantVideoPreloadManager",
+      "android/support/v4/view/ViewPropertyAnimatorCompat": "androidx/view/ViewPropertyAnimatorCompat",
+      "android/support/v13/app/FragmentCompat$FragmentCompatApi23Impl": "androidx/app/FragmentCompat$FragmentCompatApi23Impl",
+      "android/support/v4/media/MediaBrowserServiceCompat$MediaBrowserServiceImplApi23": "androidx/media/MediaBrowserServiceCompat$MediaBrowserServiceImplApi23",
+      "android/support/v4/internal/view/SupportSubMenu": "androidx/internal/view/SupportSubMenu",
+      "android/support/text/emoji/EmojiProcessor$Action": "androidx/text/emoji/EmojiProcessor$Action",
+      "android/support/v4/media/MediaBrowserServiceCompat$MediaBrowserServiceImplApi21": "androidx/media/MediaBrowserServiceCompat$MediaBrowserServiceImplApi21",
+      "android/support/v17/leanback/widget/DetailsOverviewLogoPresenter$ViewHolder": "androidx/leanback/widget/DetailsOverviewLogoPresenter$ViewHolder",
+      "android/support/v7/widget/OrientationHelper": "androidx/widget/OrientationHelper",
+      "android/support/v4/app/FragmentTransition$FragmentContainerTransition": "androidx/app/FragmentTransition$FragmentContainerTransition",
+      "android/support/multidex/BuildConfig": "androidx/multidex/BuildConfig",
+      "android/support/v4/media/MediaBrowserServiceCompat$MediaBrowserServiceImplApi26": "androidx/media/MediaBrowserServiceCompat$MediaBrowserServiceImplApi26",
+      "android/support/v7/preference/PreferenceViewHolder": "androidx/preference/PreferenceViewHolder",
+      "android/support/graphics/drawable/VectorDrawableCommon": "androidx/graphics/drawable/VectorDrawableCommon",
+      "android/support/v4/view/animation/FastOutLinearInInterpolator": "androidx/view/animation/FastOutLinearInInterpolator",
+      "android/support/v4/media/MediaBrowserServiceCompatApi26$MediaBrowserServiceAdaptor": "androidx/media/MediaBrowserServiceCompatApi26$MediaBrowserServiceAdaptor",
+      "android/support/v7/view/SupportActionModeWrapper": "androidx/view/SupportActionModeWrapper",
+      "android/support/v7/app/AppCompatDelegateImplV11": "androidx/app/AppCompatDelegateImplV11",
+      "android/support/v7/app/AppCompatDelegateImplV14": "androidx/app/AppCompatDelegateImplV14",
+      "android/support/v4/graphics/TypefaceCompatApi26Impl": "androidx/graphics/TypefaceCompatApi26Impl",
+      "android/support/v17/leanback/media/PlaybackGlueHost$PlayerCallback": "androidx/leanback/media/PlaybackGlueHost$PlayerCallback",
+      "android/support/design/widget/BottomNavigationView$SavedState": "androidx/design/widget/BottomNavigationView$SavedState",
+      "android/support/v7/preference/R$attr": "androidx/preference/R$attr",
+      "android/support/text/emoji/R$styleable": "androidx/text/emoji/R$styleable",
+      "android/support/v4/view/animation/LinearOutSlowInInterpolator": "androidx/view/animation/LinearOutSlowInInterpolator",
+      "android/support/customtabs/BuildConfig": "androidx/browser/customtabs/BuildConfig",
+      "android/support/v7/widget/LinearLayoutManager$LayoutState": "androidx/widget/LinearLayoutManager$LayoutState",
+      "android/support/wear/widget/BoxInsetLayout": "androidx/wear/widget/BoxInsetLayout",
+      "android/support/media/instantvideo/BuildConfig": "androidx/media/instantvideo/BuildConfig",
+      "android/support/design/widget/HeaderBehavior": "androidx/design/widget/HeaderBehavior",
+      "android/support/v17/leanback/widget/PageRow": "androidx/leanback/widget/PageRow",
+      "android/support/v7/widget/ViewStubCompat": "androidx/widget/ViewStubCompat",
+      "android/support/v7/widget/SearchView$AutoCompleteTextViewReflector": "androidx/widget/SearchView$AutoCompleteTextViewReflector",
+      "android/support/v17/leanback/widget/OnChildLaidOutListener": "androidx/leanback/widget/OnChildLaidOutListener",
+      "android/support/v7/app/TwilightManager$TwilightState": "androidx/app/TwilightManager$TwilightState",
+      "android/support/v7/widget/FastScroller": "androidx/widget/FastScroller",
+      "android/support/design/widget/CoordinatorLayout$ViewElevationComparator": "androidx/design/widget/CoordinatorLayout$ViewElevationComparator",
+      "android/support/transition/TransitionManager": "androidx/transition/TransitionManager",
+      "android/support/v7/widget/AppCompatDrawableManager": "androidx/widget/AppCompatDrawableManager",
+      "android/support/animation/DynamicAnimation$OnAnimationUpdateListener": "androidx/animation/DynamicAnimation$OnAnimationUpdateListener",
+      "android/support/v4/graphics/TypefaceCompat": "androidx/graphics/TypefaceCompat",
+      "android/support/v17/preference/LeanbackPreferenceFragment": "androidx/leanback/preference/LeanbackPreferenceFragment",
+      "android/support/v17/leanback/widget/ParallaxTarget": "androidx/leanback/widget/ParallaxTarget",
+      "android/support/annotation/StyleRes": "androidx/annotation/StyleRes",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$ThumbsDownAction": "androidx/leanback/widget/PlaybackControlsRow$ThumbsDownAction",
+      "android/support/v17/leanback/media/PlaybackTransportControlGlue$SeekUiClient": "androidx/leanback/media/PlaybackTransportControlGlue$SeekUiClient",
+      "android/support/v7/media/SystemMediaRouteProvider$JellybeanImpl$SystemRouteRecord": "androidx/media/SystemMediaRouteProvider$JellybeanImpl$SystemRouteRecord",
+      "android/support/v17/leanback/widget/ShadowHelper$ShadowHelperStubImpl": "androidx/leanback/widget/ShadowHelper$ShadowHelperStubImpl",
+      "android/support/animation/DynamicAnimation$ViewProperty": "androidx/animation/DynamicAnimation$ViewProperty",
+      "android/support/v7/app/AppCompatDelegateImplV23": "androidx/app/AppCompatDelegateImplV23",
+      "android/support/v4/app/NotificationManagerCompat": "androidx/app/NotificationManagerCompat",
+      "android/support/v4/media/session/MediaControllerCompat": "androidx/media/session/MediaControllerCompat",
+      "android/support/v17/leanback/widget/GuidedDatePickerAction": "androidx/leanback/widget/GuidedDatePickerAction",
+      "android/support/v4/widget/CircularProgressDrawable$ProgressDrawableSize": "androidx/widget/CircularProgressDrawable$ProgressDrawableSize",
+      "android/support/v17/leanback/widget/Presenter$ViewHolderTask": "androidx/leanback/widget/Presenter$ViewHolderTask",
+      "android/support/text/emoji/bundled/BundledEmojiCompatConfig": "androidx/text/emoji/bundled/BundledEmojiCompatConfig",
+      "android/support/content/ContentPager$CursorView": "androidx/content/ContentPager$CursorView",
+      "android/support/transition/TranslationAnimationCreator$TransitionPositionListener": "androidx/transition/TranslationAnimationCreator$TransitionPositionListener",
+      "android/support/v7/recyclerview/R$styleable": "androidx/recyclerview/R$styleable",
+      "android/support/v17/leanback/widget/PersistentFocusWrapper": "androidx/leanback/widget/PersistentFocusWrapper",
+      "android/support/v4/view/accessibility/AccessibilityWindowInfoCompat": "androidx/view/accessibility/AccessibilityWindowInfoCompat",
+      "android/support/v17/leanback/widget/PlaybackControlsRow$RewindAction": "androidx/leanback/widget/PlaybackControlsRow$RewindAction",
+      "android/support/v7/widget/AppCompatPopupWindow": "androidx/widget/AppCompatPopupWindow",
+      "android/support/coreui/BuildConfig": "androidx/coreui/BuildConfig",
+      "android/support/mediacompat/R$id": "androidx/mediacompat/R$id",
+      "android/support/v17/leanback/widget/ItemAlignmentFacet": "androidx/leanback/widget/ItemAlignmentFacet",
+      "android/support/v4/view/GestureDetectorCompat$GestureDetectorCompatImplBase$GestureHandler": "androidx/view/GestureDetectorCompat$GestureDetectorCompatImplBase$GestureHandler",
+      "android/support/v17/leanback/widget/GuidedAction$BuilderBase": "androidx/leanback/widget/GuidedAction$BuilderBase",
+      "android/support/v17/leanback/widget/RoundedRectHelper$Impl": "androidx/leanback/widget/RoundedRectHelper$Impl",
+      "android/support/v7/media/MediaRouterJellybean$CallbackProxy": "androidx/media/MediaRouterJellybean$CallbackProxy",
+      "android/support/design/widget/CollapsingToolbarLayout$LayoutParams": "androidx/design/widget/CollapsingToolbarLayout$LayoutParams",
+      "android/support/v7/preference/DialogPreference": "androidx/preference/DialogPreference",
+      "android/support/v7/preference/EditTextPreference": "androidx/preference/EditTextPreference",
+      "android/support/v4/media/MediaBrowserCompatApi23$ItemCallbackProxy": "androidx/media/MediaBrowserCompatApi23$ItemCallbackProxy",
+      "android/support/v4/text/util/LinkifyCompat$LinkifyMask": "androidx/text/util/LinkifyCompat$LinkifyMask",
+      "android/support/v7/widget/helper/ItemTouchHelper$SimpleCallback": "androidx/widget/helper/ItemTouchHelper$SimpleCallback",
+      "android/support/wear/ambient/AmbientMode$AmbientCallbackProvider": "androidx/wear/ambient/AmbientMode$AmbientCallbackProvider",
+      "android/support/v7/widget/CardViewImpl": "androidx/widget/CardViewImpl",
+      "android/support/animation/FloatValueHolder": "androidx/animation/FloatValueHolder",
+      "android/support/transition/MatrixUtils": "androidx/transition/MatrixUtils",
+      "android/support/v14/preference/PreferenceFragment$OnPreferenceStartFragmentCallback": "androidx/preference/PreferenceFragment$OnPreferenceStartFragmentCallback",
+      "android/support/v4/widget/SlidingPaneLayout$PanelSlideListener": "androidx/widget/SlidingPaneLayout$PanelSlideListener",
+      "android/support/v7/util/SortedList": "androidx/util/SortedList",
+      "android/support/v4/view/AccessibilityDelegateCompat$AccessibilityDelegateBaseImpl": "androidx/view/AccessibilityDelegateCompat$AccessibilityDelegateBaseImpl",
+      "android/support/v7/app/MediaRouteControllerDialog$FetchArtTask": "androidx/app/MediaRouteControllerDialog$FetchArtTask",
+      "android/support/compat/R$drawable": "androidx/compat/R$drawable",
+      "android/support/transition/Visibility$VisibilityInfo": "androidx/transition/Visibility$VisibilityInfo",
+      "android/support/v7/widget/ThemedSpinnerAdapter": "androidx/widget/ThemedSpinnerAdapter",
+      "android/support/v17/leanback/widget/GuidanceStylingRelativeLayout": "androidx/leanback/widget/GuidanceStylingRelativeLayout",
+      "android/support/v7/media/MediaRouter$ProviderInfo": "androidx/media/MediaRouter$ProviderInfo",
+      "android/support/v7/media/MediaControlIntent": "androidx/media/MediaControlIntent",
+      "android/support/v17/leanback/widget/ListRow": "androidx/leanback/widget/ListRow",
+      "android/support/v7/view/menu/ListMenuPresenter$MenuAdapter": "androidx/view/menu/ListMenuPresenter$MenuAdapter",
+      "android/support/v4/app/FrameMetricsAggregator$FrameMetricsBaseImpl": "androidx/app/FrameMetricsAggregator$FrameMetricsBaseImpl",
+      "android/support/design/widget/TabLayout$SlidingTabStrip": "androidx/design/widget/TabLayout$SlidingTabStrip",
+      "android/support/content/ContentPager$ContentCallback": "androidx/content/ContentPager$ContentCallback",
+      "android/support/v4/media/MediaBrowserServiceCompat$MediaBrowserServiceImplBase": "androidx/media/MediaBrowserServiceCompat$MediaBrowserServiceImplBase",
+      "android/support/v7/util/TileList": "androidx/util/TileList",
+      "android/support/v7/widget/ActionBarBackgroundDrawable": "androidx/widget/ActionBarBackgroundDrawable",
+      "android/support/v4/widget/CursorFilter$CursorFilterClient": "androidx/widget/CursorFilter$CursorFilterClient",
+      "android/support/v17/leanback/database/CursorMapper": "androidx/leanback/database/CursorMapper",
+      "android/support/v17/leanback/transition/LeanbackTransitionHelper$LeanbackTransitionHelperKitKatImpl": "androidx/leanback/transition/LeanbackTransitionHelper$LeanbackTransitionHelperKitKatImpl",
+      "android/support/v7/cardview/R$styleable": "androidx/cardview/R$styleable",
+      "android/support/v17/leanback/transition/TransitionHelperApi21": "androidx/leanback/transition/TransitionHelperApi21",
+      "android/support/v7/widget/ViewInfoStore": "androidx/widget/ViewInfoStore",
+      "android/support/design/widget/BaseTransientBottomBar$BaseCallback$DismissEvent": "androidx/design/widget/BaseTransientBottomBar$BaseCallback$DismissEvent",
+      "android/support/percent/PercentLayoutHelper$PercentLayoutInfo": "androidx/PercentLayoutHelper$PercentLayoutInfo",
+      "android/support/v7/app/AppCompatCallback": "androidx/app/AppCompatCallback",
+      "android/support/wear/R$style": "androidx/wear/R$style",
+      "android/support/v17/leanback/widget/ItemAlignmentFacetHelper": "androidx/leanback/widget/ItemAlignmentFacetHelper",
+      "android/support/v7/view/menu/MenuItemImpl": "androidx/view/menu/MenuItemImpl",
+      "android/support/v4/content/ContextCompat": "androidx/content/ContextCompat",
+      "android/support/percent/PercentLayoutHelper$PercentMarginLayoutParams": "androidx/PercentLayoutHelper$PercentMarginLayoutParams",
+      "android/support/v7/widget/LayoutState": "androidx/widget/LayoutState",
+      "android/support/animation/AnimationHandler$AnimationFrameCallback": "androidx/animation/AnimationHandler$AnimationFrameCallback",
+      "android/support/v17/leanback/widget/SingleRow": "androidx/leanback/widget/SingleRow",
+      "android/support/v4/content/ModernAsyncTask$InternalHandler": "androidx/content/ModernAsyncTask$InternalHandler",
+      "android/support/transition/ImageViewUtilsImpl": "androidx/transition/ImageViewUtilsImpl",
+      "android/support/v7/widget/RtlSpacingHelper": "androidx/widget/RtlSpacingHelper",
+      "android/support/v4/content/PermissionChecker": "androidx/content/PermissionChecker",
+      "android/support/v7/preference/PreferenceCategory": "androidx/preference/PreferenceCategory",
+      "android/support/annotation/IntDef": "androidx/annotation/IntDef",
+      "android/support/v4/app/BundleCompat$BundleCompatBaseImpl": "androidx/app/BundleCompat$BundleCompatBaseImpl",
+      "android/support/v7/app/MediaRouteExpandCollapseButton": "androidx/app/MediaRouteExpandCollapseButton",
+      "android/support/v17/leanback/animation/LogAccelerateInterpolator": "androidx/leanback/animation/LogAccelerateInterpolator",
+      "android/support/v13/app/FragmentPagerAdapter": "androidx/app/FragmentPagerAdapter",
+      "android/support/content/InMemoryCursor": "androidx/content/InMemoryCursor",
+      "android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter$ActionsItemBridgeAdapter": "androidx/leanback/widget/FullWidthDetailsOverviewRowPresenter$ActionsItemBridgeAdapter",
+      "android/support/v7/widget/AppCompatTextViewAutoSizeHelper": "androidx/widget/AppCompatTextViewAutoSizeHelper",
+      "android/support/multidex/instrumentation/BuildConfig": "androidx/multidex/instrumentation/BuildConfig",
+      "android/support/v7/preference/PreferenceGroup": "androidx/preference/PreferenceGroup",
+      "android/support/v7/media/RegisteredMediaRouteProvider$Connection": "androidx/media/RegisteredMediaRouteProvider$Connection",
+      "android/support/v4/os/ParcelableCompatCreatorCallbacks": "androidx/os/ParcelableCompatCreatorCallbacks",
+      "android/support/v4/media/MediaMetadataCompat$BitmapKey": "androidx/media/MediaMetadataCompat$BitmapKey",
+      "android/support/v7/app/MediaRouteActionProvider$MediaRouterCallback": "androidx/app/MediaRouteActionProvider$MediaRouterCallback",
+      "android/support/v7/view/ViewPropertyAnimatorCompatSet": "androidx/view/ViewPropertyAnimatorCompatSet",
+      "android/support/v7/widget/AppCompatMultiAutoCompleteTextView": "androidx/widget/AppCompatMultiAutoCompleteTextView",
+      "android/support/v17/leanback/widget/GridLayoutManager$GridLinearSmoothScroller": "androidx/leanback/widget/GridLayoutManager$GridLinearSmoothScroller",
+      "android/support/design/internal/NavigationMenuView": "androidx/design/internal/NavigationMenuView",
+      "android/support/v17/leanback/app/SearchSupportFragment": "androidx/leanback/app/SearchSupportFragment",
+      "android/support/v7/media/SystemMediaRouteProvider$Api24Impl": "androidx/media/SystemMediaRouteProvider$Api24Impl",
+      "android/support/v4/content/FileProvider$PathStrategy": "androidx/content/FileProvider$PathStrategy",
+      "android/support/v17/leanback/util/StateMachine": "androidx/leanback/util/StateMachine",
+      "android/support/v7/widget/AppCompatCheckedTextView": "androidx/widget/AppCompatCheckedTextView",
+      "android/support/v4/media/session/PlaybackStateCompat$Builder": "androidx/media/session/PlaybackStateCompat$Builder",
+      "android/support/v17/leanback/widget/DetailsParallaxDrawable": "androidx/leanback/widget/DetailsParallaxDrawable",
+      "android/support/v17/leanback/widget/GuidedDatePickerAction$BuilderBase": "androidx/leanback/widget/GuidedDatePickerAction$BuilderBase",
+      "android/support/v17/leanback/widget/OnItemViewSelectedListener": "androidx/leanback/widget/OnItemViewSelectedListener",
+      "android/support/v7/widget/ShareActionProvider$OnShareTargetSelectedListener": "androidx/widget/ShareActionProvider$OnShareTargetSelectedListener",
+      "android/support/v4/app/JobIntentService$CompatWorkItem": "androidx/app/JobIntentService$CompatWorkItem",
+      "android/support/v7/preference/MultiSelectListPreferenceDialogFragmentCompat": "androidx/preference/MultiSelectListPreferenceDialogFragmentCompat",
+      "android/support/v17/leanback/widget/OnActionClickedListener": "androidx/leanback/widget/OnActionClickedListener",
+      "android/support/design/widget/SwipeDismissBehavior$OnDismissListener": "androidx/design/widget/SwipeDismissBehavior$OnDismissListener",
+      "android/support/design/R$id": "androidx/design/R$id",
+      "android/support/content/ContentPager$Stats": "androidx/content/ContentPager$Stats",
+      "android/support/v17/leanback/widget/SinglePresenterSelector": "androidx/leanback/widget/SinglePresenterSelector",
+      "android/support/v7/widget/GridLayout$Arc": "androidx/widget/GridLayout$Arc",
+      "android/support/v17/leanback/widget/BaseGridView$OnKeyInterceptListener": "androidx/leanback/widget/BaseGridView$OnKeyInterceptListener",
+      "android/support/customtabs/CustomTabsService$Relation": "androidx/browser/customtabs/CustomTabsService$Relation",
+      "android/support/v4/content/WakefulBroadcastReceiver": "androidx/content/WakefulBroadcastReceiver",
+      "android/support/v4/os/LocaleHelper": "androidx/os/LocaleHelper",
+      "android/support/v7/app/ActionBar$NavigationMode": "androidx/app/ActionBar$NavigationMode",
+      "android/support/v7/media/RemotePlaybackClient$ActionReceiver": "androidx/media/RemotePlaybackClient$ActionReceiver",
+      "android/support/v7/view/menu/CascadingMenuPopup$HorizPosition": "androidx/view/menu/CascadingMenuPopup$HorizPosition",
+      "android/support/v13/view/inputmethod/EditorInfoCompat": "androidx/view/inputmethod/EditorInfoCompat",
+      "android/support/v17/leanback/widget/Grid": "androidx/leanback/widget/Grid",
+      "android/support/annotation/TransitionRes": "androidx/annotation/TransitionRes",
+      "android/support/v4/media/VolumeProviderCompat": "androidx/media/VolumeProviderCompat",
+      "android/support/multidex/MultiDexApplication": "androidx/multidex/MultiDexApplication",
+      "android/support/text/emoji/EmojiCompat$MetadataRepoLoader": "androidx/text/emoji/EmojiCompat$MetadataRepoLoader",
+      "android/support/design/widget/TextInputLayout": "androidx/design/widget/TextInputLayout",
+      "android/support/v4/view/ViewCompat$ViewCompatApi24Impl": "androidx/view/ViewCompat$ViewCompatApi24Impl",
+      "android/support/v4/provider/FontRequest": "androidx/provider/FontRequest",
+      "android/support/v4/media/session/MediaButtonReceiver$MediaButtonConnectionCallback": "androidx/media/session/MediaButtonReceiver$MediaButtonConnectionCallback",
+      "android/support/v7/widget/RecyclerView$SmoothScroller$ScrollVectorProvider": "androidx/widget/RecyclerView$SmoothScroller$ScrollVectorProvider",
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImpl": "androidx/media/session/MediaSessionCompat$MediaSessionImpl",
+      "android/support/v4/content/ModernAsyncTask$Status": "androidx/content/ModernAsyncTask$Status",
+      "android/support/v7/widget/AppCompatDrawableManager$ColorFilterLruCache": "androidx/widget/AppCompatDrawableManager$ColorFilterLruCache",
+      "android/support/multidex/MultiDex": "androidx/multidex/MultiDex",
+      "android/support/wear/ambient/WearableControllerProvider": "androidx/wear/ambient/WearableControllerProvider",
+      "android/support/v17/leanback/widget/ForegroundHelper": "androidx/leanback/widget/ForegroundHelper",
+      "android/support/v4/app/DialogFragment$DialogStyle": "androidx/app/DialogFragment$DialogStyle",
+      "android/support/v4/graphics/TypefaceCompatApi24Impl": "androidx/graphics/TypefaceCompatApi24Impl",
+      "android/support/v7/preference/R": "androidx/preference/R",
+      "android/support/v7/app/ActionBar$Tab": "androidx/app/ActionBar$Tab",
+      "android/support/transition/CircularPropagation": "androidx/transition/CircularPropagation",
+      "android/support/v7/app/ResourcesFlusher": "androidx/app/ResourcesFlusher",
+      "android/support/text/emoji/MetadataListReader$OffsetInfo": "androidx/text/emoji/MetadataListReader$OffsetInfo",
+      "android/support/v4/app/ActivityOptionsCompat$ActivityOptionsCompatApi24Impl": "androidx/app/ActivityOptionsCompat$ActivityOptionsCompatApi24Impl",
+      "android/support/v4/content/SharedPreferencesCompat$EditorCompat": "androidx/content/SharedPreferencesCompat$EditorCompat",
+      "android/support/v7/widget/RecyclerView$OnFlingListener": "androidx/widget/RecyclerView$OnFlingListener",
+      "android/support/animation/AnimationHandler$AnimationCallbackDispatcher": "androidx/animation/AnimationHandler$AnimationCallbackDispatcher",
+      "android/support/v7/widget/ResourcesWrapper": "androidx/widget/ResourcesWrapper",
+      "android/support/v17/leanback/widget/BrowseFrameLayout$OnChildFocusListener": "androidx/leanback/widget/BrowseFrameLayout$OnChildFocusListener",
+      "android/support/v7/widget/AppCompatEditText": "androidx/widget/AppCompatEditText",
+      "android/support/media/tv/TvContractCompat$WatchNextPrograms": "androidx/media/tv/TvContractCompat$WatchNextPrograms",
+      "android/support/v4/widget/ListPopupWindowCompat": "androidx/widget/ListPopupWindowCompat",
+      "android/support/v7/preference/PreferenceFragmentCompat$OnPreferenceDisplayDialogCallback": "androidx/preference/PreferenceFragmentCompat$OnPreferenceDisplayDialogCallback",
+      "android/support/v7/util/DiffUtil$PostponedUpdate": "androidx/util/DiffUtil$PostponedUpdate",
+      "android/support/transition/TransitionManager$MultiListener": "androidx/transition/TransitionManager$MultiListener",
+      "android/support/v4/view/ViewPropertyAnimatorCompat$ViewPropertyAnimatorListenerApi14": "androidx/view/ViewPropertyAnimatorCompat$ViewPropertyAnimatorListenerApi14",
+      "android/support/v17/leanback/widget/ViewsStateBundle": "androidx/leanback/widget/ViewsStateBundle",
+      "android/support/v4/provider/FontsContractCompat$TypefaceResult": "androidx/provider/FontsContractCompat$TypefaceResult",
+      "android/support/v4/widget/DrawerLayout$State": "androidx/widget/DrawerLayout$State",
+      "android/support/v4/widget/SwipeRefreshLayout$OnRefreshListener": "androidx/widget/SwipeRefreshLayout$OnRefreshListener",
+      "android/support/media/ExifInterface$Rational": "androidx/media/ExifInterface$Rational",
+      "android/support/v4/view/ViewPager$PagerObserver": "androidx/view/ViewPager$PagerObserver",
+      "android/support/design/widget/StateListAnimator": "androidx/design/widget/StateListAnimator",
+      "android/support/v4/media/MediaBrowserCompat$CallbackHandler": "androidx/media/MediaBrowserCompat$CallbackHandler",
+      "android/support/customtabs/CustomTabsClient": "androidx/browser/customtabs/CustomTabsClient",
+      "android/support/v4/media/MediaBrowserServiceCompatApi26$ServiceCompatProxy": "androidx/media/MediaBrowserServiceCompatApi26$ServiceCompatProxy",
+      "android/support/transition/Slide$CalculateSlideHorizontal": "androidx/transition/Slide$CalculateSlideHorizontal",
+      "android/support/v17/leanback/media/PlaybackBannerControlGlue$SPEED": "androidx/leanback/media/PlaybackBannerControlGlue$SPEED",
+      "android/support/annotation/CallSuper": "androidx/annotation/CallSuper",
+      "android/support/design/widget/Snackbar$Callback": "androidx/design/widget/Snackbar$Callback",
+      "android/support/v4/app/ActivityManagerCompat": "androidx/app/ActivityManagerCompat",
+      "android/support/v17/leanback/widget/RoundedRectHelperApi21": "androidx/leanback/widget/RoundedRectHelperApi21",
+      "android/support/v7/graphics/Palette": "androidx/graphics/palette/Palette",
+      "android/support/wear/R$color": "androidx/wear/R$color",
+      "android/support/v17/leanback/widget/ItemBridgeAdapter$OnFocusChangeListener": "androidx/leanback/widget/ItemBridgeAdapter$OnFocusChangeListener",
+      "android/support/v7/media/MediaRouteProviderService$ProviderCallback": "androidx/media/MediaRouteProviderService$ProviderCallback",
+      "android/support/media/ExifInterface": "androidx/media/ExifInterface",
+      "android/support/v4/app/FragmentManagerImpl": "androidx/app/FragmentManagerImpl",
+      "android/support/v13/app/FragmentTabHost$DummyTabFactory": "androidx/app/FragmentTabHost$DummyTabFactory",
+      "android/support/app/recommendation/ContentRecommendation$Builder": "androidx/app/recommendation/ContentRecommendation$Builder",
+      "android/support/v17/leanback/widget/RowHeaderView": "androidx/leanback/widget/RowHeaderView",
+      "android/support/v4/widget/DrawerLayout$EdgeGravity": "androidx/widget/DrawerLayout$EdgeGravity",
+      "android/support/v7/view/menu/MenuWrapperICS": "androidx/view/menu/MenuWrapperICS",
+      "android/support/v7/widget/RoundRectDrawableWithShadow$RoundRectHelper": "androidx/widget/RoundRectDrawableWithShadow$RoundRectHelper",
+      "android/support/v4/media/session/MediaControllerCompat$Callback$MessageHandler": "androidx/media/session/MediaControllerCompat$Callback$MessageHandler",
+      "android/support/v4/text/ICUCompat": "androidx/text/ICUCompat",
+      "android/support/v17/leanback/widget/PlaybackSeekDataProvider$ResultCallback": "androidx/leanback/widget/PlaybackSeekDataProvider$ResultCallback",
+      "android/support/v7/widget/ViewUtils": "androidx/widget/ViewUtils",
+      "android/support/v7/appcompat/R$string": "androidx/appcompat/R$string",
+      "android/support/constraint/ConstraintLayout": "androidx/constraint/ConstraintLayout",
+      "android/support/v4/view/ViewPager$SimpleOnPageChangeListener": "androidx/view/ViewPager$SimpleOnPageChangeListener",
+      "android/support/wear/internal/widget/drawer/MultiPageUi": "androidx/wear/internal/widget/drawer/MultiPageUi",
+      "android/support/v17/leanback/media/PlayerAdapter$Callback": "androidx/leanback/media/PlayerAdapter$Callback",
+      "android/support/design/widget/BaseTransientBottomBar$ContentViewCallback": "androidx/design/widget/BaseTransientBottomBar$ContentViewCallback",
+      "android/support/annotation/RestrictTo$Scope": "androidx/annotation/RestrictTo$Scope",
+      "android/support/v4/content/AsyncTaskLoader": "androidx/content/AsyncTaskLoader",
+      "android/support/v17/leanback/widget/ParallaxEffect": "androidx/leanback/widget/ParallaxEffect",
+      "android/support/v17/leanback/app/BackgroundManager$DrawableWrapper": "androidx/leanback/app/BackgroundManager$DrawableWrapper",
+      "android/support/v4/app/ListFragment": "androidx/app/ListFragment",
+      "android/support/design/widget/DirectedAcyclicGraph": "androidx/widget/DirectedAcyclicGraph",
+      "android/support/design/widget/AppBarLayout": "androidx/design/widget/AppBarLayout",
+      "android/support/v7/media/RemoteControlClientCompat$JellybeanImpl": "androidx/media/RemoteControlClientCompat$JellybeanImpl",
+      "android/support/design/widget/ViewGroupUtils": "androidx/widget/ViewGroupUtils",
+      "android/support/design/R$styleable": "androidx/design/R$styleable",
+      "android/support/animation/DynamicAnimation$OnAnimationEndListener": "androidx/animation/DynamicAnimation$OnAnimationEndListener",
+      "android/support/media/tv/TvContractUtils": "androidx/media/tv/TvContractUtils",
+      "android/support/v4/app/JobIntentService$JobWorkEnqueuer": "androidx/app/JobIntentService$JobWorkEnqueuer",
+      "android/support/percent/PercentLayoutHelper$PercentLayoutParams": "androidx/PercentLayoutHelper$PercentLayoutParams",
+      "android/support/v4/util/Pair": "androidx/util/Pair",
+      "android/support/text/emoji/appcompat/BuildConfig": "androidx/text/emoji/appcompat/BuildConfig",
+      "android/support/v17/leanback/transition/LeanbackTransitionHelperKitKat": "androidx/leanback/transition/LeanbackTransitionHelperKitKat",
+      "android/support/v13/view/DragStartHelper": "androidx/view/DragStartHelper",
+      "android/support/v7/widget/ListViewCompat": "androidx/widget/ListViewCompat",
+      "android/support/v7/preference/CheckBoxPreference$Listener": "androidx/preference/CheckBoxPreference$Listener",
+      "android/support/v7/app/AppCompatDelegate$NightMode": "androidx/app/AppCompatDelegate$NightMode",
+      "android/support/v17/leanback/transition/SlideNoPropagation": "androidx/leanback/transition/SlideNoPropagation",
+      "android/support/v7/media/MediaRouteProviderService$ClientRecord": "androidx/media/MediaRouteProviderService$ClientRecord",
+      "android/support/graphics/drawable/VectorDrawableCompat$VectorDrawableCompatState": "androidx/graphics/drawable/VectorDrawableCompat$VectorDrawableCompatState",
+      "android/support/text/emoji/R$layout": "androidx/text/emoji/R$layout",
+      "android/support/v4/media/session/MediaSessionCompat$SessionFlags": "androidx/media/session/MediaSessionCompat$SessionFlags",
+      "android/support/v7/preference/PreferenceRecyclerViewAccessibilityDelegate": "androidx/preference/PreferenceRecyclerViewAccessibilityDelegate",
+      "android/support/transition/AnimatorUtils": "androidx/transition/AnimatorUtils",
+      "android/support/v17/leanback/system/Settings": "androidx/leanback/system/Settings",
+      "android/support/v4/app/FragmentActivity$NonConfigurationInstances": "androidx/app/FragmentActivity$NonConfigurationInstances",
+      "android/support/v17/leanback/widget/GuidedActionAdapter$EditListener": "androidx/leanback/widget/GuidedActionAdapter$EditListener",
+      "android/support/v7/media/MediaRouteProvider$Callback": "androidx/media/MediaRouteProvider$Callback",
+      "android/support/v7/app/AppCompatDelegateImplV9$PanelMenuPresenterCallback": "androidx/app/AppCompatDelegateImplV9$PanelMenuPresenterCallback",
+      "android/support/constraint/ConstraintSet$Constraint": "androidx/constraint/ConstraintSet$Constraint",
+      "android/support/wear/R$dimen": "androidx/wear/R$dimen"
+    },
+    "fields": {
+      "android/support/v4/view/AbsSavedState": {
+        "androidx/view/AbsSavedState": [
+          "CREATOR",
+          "EMPTY_STATE"
+        ]
+      },
+      "android/support/v4/view/PagerTabStrip": {
+        "androidx/widget/PagerTabStrip": [
+          "TAG",
+          "TAB_PADDING",
+          "TAB_SPACING",
+          "FULL_UNDERLINE_HEIGHT",
+          "MIN_PADDING_BOTTOM",
+          "MIN_STRIP_HEIGHT",
+          "MIN_TEXT_SPACING",
+          "INDICATOR_HEIGHT"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat$Channels": {
+        "androidx/media/tv/TvContractCompat$Channels": [
+          "VIDEO_FORMAT_4320P",
+          "VIDEO_RESOLUTION_HD",
+          "VIDEO_RESOLUTION_ED",
+          "VIDEO_FORMAT_720P",
+          "COLUMN_TRANSIENT",
+          "VIDEO_FORMAT_TO_RESOLUTION_MAP",
+          "COLUMN_DISPLAY_NAME",
+          "VIDEO_FORMAT_240P",
+          "COLUMN_VIDEO_FORMAT",
+          "COLUMN_APP_LINK_TEXT",
+          "COLUMN_APP_LINK_POSTER_ART_URI",
+          "VIDEO_FORMAT_360P",
+          "TYPE_OTHER",
+          "COLUMN_NETWORK_AFFILIATION",
+          "TYPE_PAL",
+          "SERVICE_TYPE_OTHER",
+          "VIDEO_FORMAT_480P",
+          "VIDEO_FORMAT_480I",
+          "CONTENT_URI",
+          "TYPE_CMMB",
+          "TYPE_ATSC_C",
+          "TYPE_ATSC_T",
+          "VIDEO_RESOLUTION_FHD",
+          "COLUMN_APP_LINK_INTENT_URI",
+          "VIDEO_FORMAT_2160P",
+          "TYPE_SECAM",
+          "COLUMN_INTERNAL_PROVIDER_FLAG2",
+          "COLUMN_INTERNAL_PROVIDER_FLAG1",
+          "COLUMN_INTERNAL_PROVIDER_FLAG4",
+          "COLUMN_INTERNAL_PROVIDER_FLAG3",
+          "TYPE_T_DMB",
+          "CONTENT_TYPE",
+          "COLUMN_TRANSPORT_STREAM_ID",
+          "VIDEO_FORMAT_576P",
+          "VIDEO_FORMAT_576I",
+          "COLUMN_LOCKED",
+          "COLUMN_SERVICE_TYPE",
+          "TYPE_ISDB_S",
+          "TYPE_ISDB_T",
+          "TYPE_ISDB_C",
+          "COLUMN_DESCRIPTION",
+          "TYPE_DVB_S2",
+          "TYPE_DVB_T2",
+          "TYPE_DVB_SH",
+          "TYPE_DTMB",
+          "COLUMN_INPUT_ID",
+          "VIDEO_RESOLUTION_SD",
+          "COLUMN_VERSION_NUMBER",
+          "COLUMN_SEARCHABLE",
+          "COLUMN_SERVICE_ID",
+          "TYPE_1SEG",
+          "TYPE_DVB_C2",
+          "TYPE_DVB_C",
+          "TYPE_DVB_H",
+          "TYPE_DVB_S",
+          "TYPE_DVB_T",
+          "CONTENT_ITEM_TYPE",
+          "SERVICE_TYPE_AUDIO",
+          "TYPE_ATSC_M_H",
+          "TYPE_NTSC",
+          "COLUMN_BROWSABLE",
+          "TYPE_ISDB_TB",
+          "COLUMN_INTERNAL_PROVIDER_DATA",
+          "COLUMN_DISPLAY_NUMBER",
+          "COLUMN_SYSTEM_APPROVED",
+          "VIDEO_FORMAT_1080I",
+          "VIDEO_FORMAT_1080P",
+          "COLUMN_TYPE",
+          "VIDEO_RESOLUTION_UHD",
+          "COLUMN_APP_LINK_ICON_URI",
+          "TYPE_S_DMB",
+          "COLUMN_APP_LINK_COLOR",
+          "SERVICE_TYPE_AUDIO_VIDEO",
+          "TYPE_PREVIEW",
+          "COLUMN_ORIGINAL_NETWORK_ID",
+          "COLUMN_INTERNAL_PROVIDER_ID"
+        ]
+      },
+      "android/support/v7/widget/ViewBoundsCheck": {
+        "androidx/widget/ViewBoundsCheck": [
+          "FLAG_CVS_EQ_PVE",
+          "FLAG_CVS_EQ_PVS",
+          "GT",
+          "LT",
+          "EQ",
+          "FLAG_CVS_GT_PVS",
+          "FLAG_CVS_GT_PVE",
+          "FLAG_CVE_EQ_PVE",
+          "FLAG_CVE_EQ_PVS",
+          "MASK",
+          "CVS_PVE_POS",
+          "CVE_PVE_POS",
+          "FLAG_CVS_LT_PVE",
+          "FLAG_CVS_LT_PVS",
+          "CVS_PVS_POS",
+          "FLAG_CVE_LT_PVS",
+          "FLAG_CVE_LT_PVE",
+          "CVE_PVS_POS",
+          "FLAG_CVE_GT_PVS",
+          "FLAG_CVE_GT_PVE"
+        ]
+      },
+      "android/support/constraint/ConstraintLayout$LayoutParams": {
+        "androidx/constraint/ConstraintLayout$LayoutParams": [
+          "topToTop",
+          "goneTopMargin",
+          "verticalWeight",
+          "horizontalDimensionFixed",
+          "goneBottomMargin",
+          "matchConstraintMaxHeight",
+          "resolveGoneLeftMargin",
+          "leftMargin",
+          "MATCH_CONSTRAINT",
+          "resolvedRightToLeft",
+          "needsBaseline",
+          "startToEnd",
+          "TOP",
+          "horizontalChainStyle",
+          "guidePercent",
+          "CHAIN_SPREAD",
+          "topMargin",
+          "goneStartMargin",
+          "goneRightMargin",
+          "UNSET",
+          "HORIZONTAL",
+          "dimensionRatioValue",
+          "MATCH_CONSTRAINT_SPREAD",
+          "END",
+          "guideBegin",
+          "matchConstraintMaxWidth",
+          "verticalDimensionFixed",
+          "resolvedRightToRight",
+          "BASELINE",
+          "START",
+          "resolvedHorizontalBias",
+          "bottomToBottom",
+          "MATCH_CONSTRAINT_WRAP",
+          "startToStart",
+          "RIGHT",
+          "orientation",
+          "matchConstraintDefaultHeight",
+          "guideEnd",
+          "bottomToTop",
+          "CHAIN_PACKED",
+          "isGuideline",
+          "dimensionRatioSide",
+          "dimensionRatio",
+          "goneLeftMargin",
+          "matchConstraintMinWidth",
+          "PARENT_ID",
+          "endToStart",
+          "LEFT",
+          "horizontalBias",
+          "leftToLeft",
+          "BOTTOM",
+          "resolveGoneRightMargin",
+          "leftToRight",
+          "verticalBias",
+          "goneEndMargin",
+          "VERTICAL",
+          "rightMargin",
+          "rightToRight",
+          "resolvedLeftToLeft",
+          "topToBottom",
+          "endToEnd",
+          "matchConstraintDefaultWidth",
+          "matchConstraintMinHeight",
+          "height",
+          "CHAIN_SPREAD_INSIDE",
+          "widget",
+          "resolvedLeftToRight",
+          "baselineToBaseline",
+          "rightToLeft",
+          "verticalChainStyle",
+          "editorAbsoluteY",
+          "editorAbsoluteX",
+          "bottomMargin",
+          "width",
+          "horizontalWeight"
+        ]
+      },
+      "android/support/v4/media/session/PlaybackStateCompat": {
+        "androidx/media/session/PlaybackStateCompat": [
+          "STATE_NONE",
+          "ACTION_SET_SHUFFLE_MODE",
+          "ACTION_SKIP_TO_QUEUE_ITEM",
+          "ERROR_CODE_CONTENT_ALREADY_PLAYING",
+          "STATE_ERROR",
+          "SHUFFLE_MODE_NONE",
+          "CREATOR",
+          "STATE_SKIPPING_TO_PREVIOUS",
+          "PLAYBACK_POSITION_UNKNOWN",
+          "REPEAT_MODE_INVALID",
+          "REPEAT_MODE_GROUP",
+          "ACTION_SET_REPEAT_MODE",
+          "ACTION_SKIP_TO_PREVIOUS",
+          "ACTION_PREPARE",
+          "ERROR_CODE_SKIP_LIMIT_REACHED",
+          "REPEAT_MODE_NONE",
+          "ACTION_PREPARE_FROM_URI",
+          "STATE_PLAYING",
+          "STATE_SKIPPING_TO_NEXT",
+          "ACTION_FAST_FORWARD",
+          "ERROR_CODE_END_OF_QUEUE",
+          "ERROR_CODE_PARENTAL_CONTROL_RESTRICTED",
+          "STATE_BUFFERING",
+          "ACTION_REWIND",
+          "KEYCODE_MEDIA_PAUSE",
+          "ACTION_PLAY_FROM_MEDIA_ID",
+          "STATE_FAST_FORWARDING",
+          "ACTION_STOP",
+          "KEYCODE_MEDIA_PLAY",
+          "ACTION_PLAY",
+          "ACTION_SET_CAPTIONING_ENABLED",
+          "ERROR_CODE_NOT_SUPPORTED",
+          "STATE_STOPPED",
+          "ACTION_PLAY_PAUSE",
+          "SHUFFLE_MODE_ALL",
+          "ERROR_CODE_AUTHENTICATION_EXPIRED",
+          "ERROR_CODE_APP_ERROR",
+          "ACTION_SEEK_TO",
+          "ERROR_CODE_CONCURRENT_STREAM_LIMIT",
+          "REPEAT_MODE_ALL",
+          "ERROR_CODE_NOT_AVAILABLE_IN_REGION",
+          "ERROR_CODE_ACTION_ABORTED",
+          "STATE_CONNECTING",
+          "ACTION_SKIP_TO_NEXT",
+          "SHUFFLE_MODE_INVALID",
+          "ACTION_PLAY_FROM_SEARCH",
+          "ERROR_CODE_UNKNOWN_ERROR",
+          "ACTION_PAUSE",
+          "ACTION_PLAY_FROM_URI",
+          "REPEAT_MODE_ONE",
+          "ACTION_SET_RATING",
+          "ACTION_PREPARE_FROM_SEARCH",
+          "STATE_PAUSED",
+          "SHUFFLE_MODE_GROUP",
+          "STATE_REWINDING",
+          "ACTION_PREPARE_FROM_MEDIA_ID",
+          "ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED",
+          "STATE_SKIPPING_TO_QUEUE_ITEM",
+          "ACTION_SET_SHUFFLE_MODE_ENABLED"
+        ]
+      },
+      "android/support/v7/appcompat/R$styleable": {
+        "androidx/appcompat/R$styleable": [
+          "MenuItem_android_title",
+          "Toolbar_android_gravity",
+          "ActionMode_titleTextStyle",
+          "ActionBar_popupTheme",
+          "MenuView_android_itemTextAppearance",
+          "SearchView_goIcon",
+          "MenuItem_actionLayout",
+          "Toolbar_navigationIcon",
+          "ColorStateListItem_android_alpha",
+          "AppCompatTheme_android_windowAnimationStyle",
+          "LinearLayoutCompat_android_orientation",
+          "AppCompatTheme_windowActionBar",
+          "MenuItem_showAsAction",
+          "ColorStateListItem_android_color",
+          "ActivityChooserView_initialActivityCount",
+          "AppCompatSeekBar_tickMarkTint",
+          "CompoundButton_android_button",
+          "MenuGroup_android_orderInCategory",
+          "PopupWindow_overlapAnchor",
+          "ViewBackgroundHelper_backgroundTint",
+          "PopupWindow",
+          "Toolbar_contentInsetEndWithActions",
+          "MenuItem_android_titleCondensed",
+          "TextAppearance",
+          "MenuItem_android_id",
+          "LinearLayoutCompat_measureWithLargestChild",
+          "AppCompatTextView_autoSizeTextType",
+          "AppCompatTheme_windowMinWidthMajor",
+          "DrawerArrowToggle_color",
+          "AppCompatTheme",
+          "SwitchCompat_trackTintMode",
+          "AppCompatTheme_windowActionBarOverlay",
+          "DrawerArrowToggle_spinBars",
+          "LinearLayoutCompat",
+          "AppCompatTextHelper",
+          "ActionMode_subtitleTextStyle",
+          "Toolbar_titleTextAppearance",
+          "ActivityChooserView",
+          "LinearLayoutCompat_divider",
+          "MenuItem_android_alphabeticShortcut",
+          "Toolbar_subtitleTextColor",
+          "AppCompatImageView_tint",
+          "AppCompatTheme_windowFixedHeightMajor",
+          "LinearLayoutCompat_android_baselineAlignedChildIndex",
+          "AppCompatTheme_windowMinWidthMinor",
+          "SearchView_suggestionRowLayout",
+          "ListPopupWindow_android_dropDownHorizontalOffset",
+          "ActionBar_subtitleTextStyle",
+          "Toolbar_titleMarginEnd",
+          "Toolbar_titleMarginTop",
+          "LinearLayoutCompat_Layout",
+          "TextAppearance_android_textColor",
+          "Toolbar_subtitleTextAppearance",
+          "ActionBar_displayOptions",
+          "Toolbar_title",
+          "Spinner_android_entries",
+          "MenuItem_numericModifiers",
+          "RecycleListView",
+          "AppCompatTextHelper_android_drawableEnd",
+          "SearchView_searchHintIcon",
+          "Toolbar_collapseIcon",
+          "AppCompatImageView",
+          "MenuItem_android_icon",
+          "ActionBar_contentInsetStart",
+          "MenuItem_android_onClick",
+          "SearchView_searchIcon",
+          "MenuItem_actionViewClass",
+          "MenuGroup_android_enabled",
+          "Toolbar_subtitle",
+          "MenuGroup_android_id",
+          "TextAppearance_android_fontFamily",
+          "ViewBackgroundHelper_android_background",
+          "TextAppearance_android_textColorHint",
+          "LinearLayoutCompat_android_baselineAligned",
+          "MenuItem_contentDescription",
+          "SearchView_voiceIcon",
+          "ActionBar_background",
+          "ActionMenuItemView",
+          "SwitchCompat_switchMinWidth",
+          "AppCompatTheme_windowFixedWidthMajor",
+          "ActionMenuItemView_android_minWidth",
+          "AlertDialog_buttonPanelSideLayout",
+          "SearchView_defaultQueryHint",
+          "MenuItem_android_numericShortcut",
+          "ActionBar_homeAsUpIndicator",
+          "AppCompatTextHelper_android_drawableTop",
+          "DrawerArrowToggle_arrowHeadLength",
+          "TextAppearance_android_shadowRadius",
+          "Toolbar_titleMargins",
+          "SwitchCompat",
+          "ActionBar_height",
+          "LinearLayoutCompat_Layout_android_layout_gravity",
+          "AlertDialog_multiChoiceItemLayout",
+          "CompoundButton_buttonTint",
+          "SearchView_android_imeOptions",
+          "MenuGroup",
+          "ActionBar_customNavigationLayout",
+          "Toolbar_navigationContentDescription",
+          "Toolbar_popupTheme",
+          "View",
+          "ActionBar",
+          "SwitchCompat_android_textOff",
+          "MenuGroup_android_menuCategory",
+          "MenuItem_tooltipText",
+          "AppCompatTextView",
+          "Spinner",
+          "ViewStubCompat_android_inflatedId",
+          "Spinner_popupTheme",
+          "SearchView_closeIcon",
+          "TextAppearance_textAllCaps",
+          "SwitchCompat_trackTint",
+          "Toolbar_logoDescription",
+          "MenuView_android_itemBackground",
+          "TextAppearance_android_textSize",
+          "SearchView_queryBackground",
+          "MenuItem_android_checked",
+          "SearchView_commitIcon",
+          "LinearLayoutCompat_Layout_android_layout_weight",
+          "ViewStubCompat_android_id",
+          "AppCompatTextView_autoSizePresetSizes",
+          "ActionBar_hideOnContentScroll",
+          "Toolbar_contentInsetStartWithNavigation",
+          "AppCompatTextHelper_android_drawableBottom",
+          "PopupWindow_android_popupBackground",
+          "Toolbar_buttonGravity",
+          "AlertDialog",
+          "TextAppearance_android_textStyle",
+          "SwitchCompat_thumbTintMode",
+          "MenuItem_android_checkable",
+          "AppCompatTheme_windowFixedWidthMinor",
+          "TextAppearance_android_textColorLink",
+          "Toolbar_titleMarginStart",
+          "RecycleListView_paddingBottomNoButtons",
+          "ActionMode_closeItemLayout",
+          "Toolbar",
+          "Toolbar_collapseContentDescription",
+          "MenuItem_android_menuCategory",
+          "AppCompatTextHelper_android_textAppearance",
+          "View_theme",
+          "MenuItem_iconTintMode",
+          "Toolbar_contentInsetLeft",
+          "Toolbar_contentInsetStart",
+          "LinearLayoutCompat_android_weightSum",
+          "SwitchCompat_android_textOn",
+          "AppCompatSeekBar",
+          "MenuItem_actionProviderClass",
+          "Toolbar_titleMargin",
+          "AlertDialog_singleChoiceItemLayout",
+          "Toolbar_contentInsetRight",
+          "LinearLayoutCompat_showDividers",
+          "SwitchCompat_android_thumb",
+          "AlertDialog_showTitle",
+          "TextAppearance_android_shadowDy",
+          "TextAppearance_android_shadowDx",
+          "AppCompatTheme_windowActionModeOverlay",
+          "MenuItem_android_visible",
+          "MenuView",
+          "SearchView",
+          "MenuItem",
+          "SearchView_queryHint",
+          "SwitchCompat_thumbTint",
+          "SwitchCompat_thumbTextPadding",
+          "AlertDialog_listLayout",
+          "ActionBar_subtitle",
+          "AlertDialog_android_layout",
+          "ListPopupWindow_android_dropDownVerticalOffset",
+          "Toolbar_titleMarginBottom",
+          "AppCompatSeekBar_android_thumb",
+          "ListPopupWindow",
+          "ButtonBarLayout_allowStacking",
+          "MenuGroup_android_checkableBehavior",
+          "SwitchCompat_switchPadding",
+          "LinearLayoutCompat_android_gravity",
+          "AppCompatTheme_windowNoTitle",
+          "ActionBar_icon",
+          "AppCompatTextView_autoSizeMinTextSize",
+          "Toolbar_logo",
+          "ViewStubCompat_android_layout",
+          "MenuItem_android_enabled",
+          "MenuItem_iconTint",
+          "AppCompatTextHelper_android_drawableRight",
+          "AppCompatTheme_android_windowIsFloating",
+          "Spinner_android_popupBackground",
+          "TextAppearance_android_shadowColor",
+          "Toolbar_maxButtonHeight",
+          "TextAppearance_android_typeface",
+          "DrawerArrowToggle_drawableSize",
+          "DrawerArrowToggle_barLength",
+          "CompoundButton",
+          "ActionMode_height",
+          "DrawerArrowToggle_arrowShaftLength",
+          "DrawerArrowToggle_gapBetweenBars",
+          "SearchView_android_focusable",
+          "ActionMode",
+          "AppCompatTextHelper_android_drawableStart",
+          "SearchView_android_maxWidth",
+          "ActivityChooserView_expandActivityOverflowButtonDrawable",
+          "ActionMode_background",
+          "ActionBar_backgroundSplit",
+          "SwitchCompat_track",
+          "MenuItem_alphabeticModifiers",
+          "TextAppearance_fontFamily",
+          "DrawerArrowToggle_thickness",
+          "AppCompatTextHelper_android_drawableLeft",
+          "ActionBar_contentInsetEnd",
+          "Spinner_android_dropDownWidth",
+          "ColorStateListItem_alpha",
+          "LinearLayoutCompat_dividerPadding",
+          "ViewStubCompat",
+          "View_android_theme",
+          "ActionBar_backgroundStacked",
+          "SearchView_android_inputType",
+          "AlertDialog_listItemLayout",
+          "AppCompatTheme_panelBackground",
+          "AppCompatImageView_srcCompat",
+          "ColorStateListItem",
+          "AppCompatTheme_windowFixedHeightMinor",
+          "MenuView_preserveIconSpacing",
+          "ActionBar_logo",
+          "AppCompatSeekBar_tickMarkTintMode",
+          "SwitchCompat_showText",
+          "AppCompatTextView_autoSizeStepGranularity",
+          "Toolbar_contentInsetEnd",
+          "SearchView_submitBackground",
+          "MenuView_subMenuArrow",
+          "CompoundButton_buttonTintMode",
+          "MenuItem_android_orderInCategory",
+          "ViewBackgroundHelper_backgroundTintMode",
+          "SwitchCompat_switchTextAppearance",
+          "ActionBar_titleTextStyle",
+          "Toolbar_titleTextColor",
+          "MenuGroup_android_visible",
+          "SwitchCompat_splitTrack",
+          "ButtonBarLayout",
+          "AppCompatSeekBar_tickMark",
+          "Spinner_android_prompt",
+          "AppCompatTextView_autoSizeMaxTextSize",
+          "ActionBar_elevation",
+          "ActionBarLayout_android_layout_gravity",
+          "DrawerArrowToggle",
+          "ActionBar_title",
+          "AppCompatImageView_tintMode",
+          "SearchView_layout",
+          "ViewBackgroundHelper",
+          "RecycleListView_paddingTopNoTitle",
+          "ActionBarLayout",
+          "SearchView_iconifiedByDefault"
+        ]
+      },
+      "android/support/text/emoji/appcompat/BuildConfig": {
+        "androidx/text/emoji/appcompat/BuildConfig": [
+          "DEBUG",
+          "APPLICATION_ID",
+          "FLAVOR",
+          "VERSION_CODE",
+          "BUILD_TYPE",
+          "VERSION_NAME"
+        ]
+      },
+      "android/support/v17/leanback/widget/FocusHighlight": {
+        "androidx/leanback/widget/FocusHighlight": [
+          "ZOOM_FACTOR_SMALL",
+          "ZOOM_FACTOR_XSMALL",
+          "ZOOM_FACTOR_NONE",
+          "ZOOM_FACTOR_LARGE",
+          "ZOOM_FACTOR_MEDIUM"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplBase$Command": {
+        "androidx/media/session/MediaSessionCompat$MediaSessionImplBase$Command": [
+          "extras",
+          "command",
+          "stub"
+        ]
+      },
+      "android/support/v7/appcompat/R$attr": {
+        "androidx/appcompat/R$attr": [
+          "checkboxStyle",
+          "colorButtonNormal",
+          "editTextStyle",
+          "actionDropDownStyle",
+          "colorControlNormal",
+          "colorAccent",
+          "actionBarSize",
+          "listMenuViewStyle",
+          "buttonStyle",
+          "colorControlHighlight",
+          "panelMenuListTheme",
+          "seekBarStyle",
+          "actionModeStyle",
+          "alertDialogStyle",
+          "isLightTheme",
+          "ratingBarStyle",
+          "radioButtonStyle",
+          "actionBarTabTextStyle",
+          "alertDialogCenterButtons",
+          "actionBarStyle",
+          "listPopupWindowStyle",
+          "actionBarPopupTheme",
+          "actionOverflowButtonStyle",
+          "spinnerStyle",
+          "popupMenuStyle",
+          "colorPrimaryDark",
+          "drawerArrowStyle",
+          "actionBarWidgetTheme",
+          "alpha",
+          "actionBarTabStyle",
+          "imageButtonStyle",
+          "colorControlActivated",
+          "toolbarStyle",
+          "homeAsUpIndicator",
+          "toolbarNavigationButtonStyle",
+          "colorPrimary",
+          "actionBarTheme",
+          "actionOverflowMenuStyle",
+          "dropDownListViewStyle",
+          "actionModePopupWindowStyle",
+          "actionModeShareDrawable",
+          "dialogTheme",
+          "alertDialogTheme",
+          "searchViewStyle",
+          "colorSwitchThumbNormal",
+          "actionBarTabBarStyle",
+          "textColorSearchUrl",
+          "switchStyle",
+          "autoCompleteTextViewStyle"
+        ]
+      },
+      "android/support/v7/widget/StaggeredGridLayoutManager$Span": {
+        "androidx/widget/StaggeredGridLayoutManager$Span": [
+          "INVALID_LINE"
+        ]
+      },
+      "android/support/v4/app/NotificationManagerCompat": {
+        "androidx/app/NotificationManagerCompat": [
+          "OP_POST_NOTIFICATION",
+          "sEnabledNotificationListeners",
+          "IMPORTANCE_HIGH",
+          "SIDE_CHANNEL_RETRY_MAX_COUNT",
+          "TAG",
+          "SETTING_ENABLED_NOTIFICATION_LISTENERS",
+          "sSideChannelManager",
+          "sLock",
+          "IMPORTANCE_DEFAULT",
+          "SIDE_CHANNEL_RETRY_BASE_INTERVAL_MS",
+          "EXTRA_USE_SIDE_CHANNEL",
+          "IMPORTANCE_NONE",
+          "sEnabledNotificationListenersLock",
+          "ACTION_BIND_SIDE_CHANNEL",
+          "CHECK_OP_NO_THROW",
+          "sEnabledNotificationListenerPackages",
+          "IMPORTANCE_LOW",
+          "IMPORTANCE_MAX",
+          "MAX_SIDE_CHANNEL_SDK_VERSION",
+          "IMPORTANCE_MIN",
+          "IMPORTANCE_UNSPECIFIED"
+        ]
+      },
+      "android/support/v4/util/LruCache": {
+        "androidx/util/LruCache": [
+          "map",
+          "hitCount",
+          "missCount",
+          "maxSize",
+          "putCount",
+          "createCount",
+          "evictionCount",
+          "size"
+        ]
+      },
+      "android/support/v4/content/FileProvider": {
+        "androidx/content/FileProvider": [
+          "META_DATA_FILE_PROVIDER_PATHS",
+          "TAG_EXTERNAL_CACHE",
+          "TAG_FILES_PATH",
+          "TAG_EXTERNAL_FILES",
+          "ATTR_PATH",
+          "ATTR_NAME",
+          "DEVICE_ROOT",
+          "sCache",
+          "COLUMNS",
+          "TAG_EXTERNAL",
+          "TAG_ROOT_PATH",
+          "TAG_CACHE_PATH"
+        ]
+      },
+      "android/support/v4/media/AudioAttributesCompat": {
+        "androidx/media/AudioAttributesCompat": [
+          "FLAG_LOW_LATENCY",
+          "FLAG_DEEP_BUFFER",
+          "USAGE_NOTIFICATION",
+          "SUPPRESSIBLE_USAGES",
+          "SUPPRESSIBLE_CALL",
+          "USAGE_NOTIFICATION_COMMUNICATION_INSTANT",
+          "USAGE_NOTIFICATION_RINGTONE",
+          "USAGE_NOTIFICATION_EVENT",
+          "USAGE_VIRTUAL_SOURCE",
+          "FLAG_BYPASS_MUTE",
+          "USAGE_ASSISTANCE_SONIFICATION",
+          "CONTENT_TYPE_SPEECH",
+          "FLAG_BYPASS_INTERRUPTION_POLICY",
+          "SDK_USAGES",
+          "USAGE_GAME",
+          "USAGE_UNKNOWN",
+          "USAGE_NOTIFICATION_COMMUNICATION_DELAYED",
+          "FLAG_ALL_PUBLIC",
+          "FLAG_SCO",
+          "FLAG_SECURE",
+          "FLAG_ALL",
+          "USAGE_VOICE_COMMUNICATION",
+          "USAGE_VOICE_COMMUNICATION_SIGNALLING",
+          "USAGE_MEDIA",
+          "USAGE_ALARM",
+          "CONTENT_TYPE_MOVIE",
+          "TAG",
+          "FLAG_HW_AV_SYNC",
+          "sForceLegacyBehavior",
+          "USAGE_ASSISTANCE_NAVIGATION_GUIDANCE",
+          "FLAG_BEACON",
+          "CONTENT_TYPE_UNKNOWN",
+          "USAGE_ASSISTANT",
+          "FLAG_AUDIBILITY_ENFORCED",
+          "FLAG_HW_HOTWORD",
+          "USAGE_NOTIFICATION_COMMUNICATION_REQUEST",
+          "USAGE_ASSISTANCE_ACCESSIBILITY",
+          "CONTENT_TYPE_MUSIC",
+          "SUPPRESSIBLE_NOTIFICATION",
+          "CONTENT_TYPE_SONIFICATION"
+        ]
+      },
+      "android/support/v7/mediarouter/R$id": {
+        "androidx/mediarouter/R$id": [
+          "mr_custom_control",
+          "mr_art",
+          "mr_name",
+          "mr_control_subtitle",
+          "mr_control_title",
+          "mr_control_playback_ctrl",
+          "mr_chooser_title",
+          "mr_group_expand_collapse",
+          "mr_close",
+          "mr_chooser_list",
+          "mr_volume_group_list",
+          "mr_expandable_area",
+          "mr_chooser_route_desc",
+          "mr_chooser_route_icon",
+          "mr_control_divider",
+          "volume_item_container",
+          "mr_chooser_route_name",
+          "mr_volume_control",
+          "mr_dialog_area",
+          "mr_default_control",
+          "mr_volume_slider",
+          "mr_volume_item_icon",
+          "mr_media_main_control",
+          "mr_playback_control",
+          "mr_control_title_container"
+        ]
+      },
+      "android/support/text/emoji/flatbuffer/Table": {
+        "androidx/text/emoji/flatbuffer/Table": [
+          "UTF8_CHARSET",
+          "bb",
+          "bb_pos",
+          "UTF8_DECODER",
+          "CHAR_BUFFER"
+        ]
+      },
+      "android/support/v17/leanback/R$id": {
+        "androidx/leanback/R$id": [
+          "paused",
+          "content_container",
+          "guidedactions_item_title",
+          "container_list",
+          "lb_parallax_source",
+          "description_dock",
+          "guidedactions_list",
+          "browse_grid_dock",
+          "details_overview_image",
+          "scale_frame",
+          "details_overview_right_panel",
+          "playback_progress",
+          "guidedactions_sub_list_background",
+          "guidedactions_root2",
+          "mediaItemDetails",
+          "button_start",
+          "title_badge",
+          "lb_search_text_editor",
+          "bottom_spacer",
+          "lb_slide_transition_value",
+          "info_field",
+          "mediaItemActionsContainer",
+          "thumbs_row",
+          "controls_container",
+          "guidedactions_list_background2",
+          "guidedactions_item_content",
+          "lb_action_button",
+          "guidedactions_item_icon",
+          "guidedactions_item_checkmark",
+          "lb_control_closed_captioning",
+          "browse_grid",
+          "title_orb",
+          "details_root",
+          "guidedactions_list_background",
+          "total_time",
+          "controls_card",
+          "lb_control_more_actions",
+          "lb_control_shuffle",
+          "mediaRowSeparator",
+          "image",
+          "lb_control_fast_rewind",
+          "row_header",
+          "controls_card_right_panel",
+          "description",
+          "background_imagein",
+          "title_text",
+          "details_fragment_root",
+          "playback_fragment_background",
+          "browse_frame",
+          "title",
+          "current_time",
+          "browse_headers_dock",
+          "guidedactions_sub_list",
+          "details_overview_actions_background",
+          "background_imageout",
+          "guidedactions_item_chevron",
+          "mediaItemDuration",
+          "lb_control_skip_previous",
+          "browse_container_dock",
+          "lb_control_skip_next",
+          "mediaListHeader",
+          "main_image",
+          "lb_control_thumbs_down",
+          "mediaItemNumberViewFlipper",
+          "details_overview",
+          "actionIcon",
+          "guidedactions_item_description",
+          "guidance_container",
+          "guidedstep_background",
+          "guidedactions_activator_item",
+          "transport_row",
+          "playback_controls_dock",
+          "page_container",
+          "lb_shadow_focused",
+          "icon",
+          "guidedactions_content",
+          "playing",
+          "lb_control_high_quality",
+          "guidance_description",
+          "details_frame",
+          "guidance_icon",
+          "control_bar",
+          "page_indicator",
+          "lb_search_bar_speech_orb",
+          "details_rows_dock",
+          "row_header_description",
+          "lb_control_thumbs_up",
+          "secondary_controls_dock",
+          "button",
+          "lb_shadow_impl",
+          "lb_focus_animator",
+          "spacer",
+          "lb_search_bar_badge",
+          "initial",
+          "lb_control_repeat",
+          "guidedactions_content2",
+          "guidance_title",
+          "message",
+          "action_fragment_root",
+          "lb_shadow_normal",
+          "guidedactions_root",
+          "lb_details_description_title",
+          "guidance_breadcrumb",
+          "action_fragment",
+          "background_container",
+          "lb_row_container_header_dock",
+          "details_background_view",
+          "browse_title_group",
+          "main_icon",
+          "video_surface_container",
+          "lb_search_frame",
+          "picker",
+          "lb_control_play_pause",
+          "lb_details_description_body",
+          "controls_dock",
+          "lb_control_picture_in_picture",
+          "lb_results_frame",
+          "grid_frame",
+          "lb_control_fast_forward",
+          "details_overview_description",
+          "mediaItemRow",
+          "mediaItemName",
+          "content_fragment",
+          "details_overview_actions",
+          "more_actions_dock",
+          "fade_out_edge",
+          "label",
+          "action_fragment_background",
+          "browse_headers",
+          "foreground_container",
+          "transitionPosition",
+          "lb_search_bar",
+          "error_frame",
+          "guidedactions_list2",
+          "lb_details_description_subtitle",
+          "lb_search_bar_items",
+          "mediaRowSelector",
+          "bar3",
+          "bar2",
+          "bar1",
+          "logo",
+          "search_orb",
+          "row_content",
+          "guidedstep_background_view_root"
+        ]
+      },
+      "android/support/v17/leanback/widget/picker/Picker$ViewHolder": {
+        "androidx/leanback/widget/picker/Picker$ViewHolder": [
+          "textView",
+          "itemView"
+        ]
+      },
+      "android/support/v4/media/MediaMetadataCompat": {
+        "androidx/media/MediaMetadataCompat": [
+          "METADATA_KEY_COMPILATION",
+          "METADATA_KEY_ART",
+          "METADATA_KEY_NUM_TRACKS",
+          "METADATA_KEY_ALBUM",
+          "METADATA_TYPE_TEXT",
+          "METADATA_TYPE_LONG",
+          "METADATA_KEY_TRACK_NUMBER",
+          "METADATA_KEY_ARTIST",
+          "METADATA_KEY_DOWNLOAD_STATUS",
+          "METADATA_KEY_AUTHOR",
+          "METADATA_KEY_DATE",
+          "METADATA_KEY_DISPLAY_TITLE",
+          "METADATA_KEY_DISPLAY_DESCRIPTION",
+          "METADATA_KEY_DURATION",
+          "METADATA_KEY_YEAR",
+          "METADATA_TYPE_BITMAP",
+          "METADATA_KEY_USER_RATING",
+          "METADATA_KEY_ALBUM_ART_URI",
+          "METADATA_KEY_MEDIA_URI",
+          "METADATA_KEY_MEDIA_ID",
+          "PREFERRED_BITMAP_ORDER",
+          "CREATOR",
+          "METADATA_KEY_BT_FOLDER_TYPE",
+          "METADATA_KEY_TITLE",
+          "METADATA_KEY_DISPLAY_ICON_URI",
+          "PREFERRED_URI_ORDER",
+          "METADATA_TYPE_RATING",
+          "METADATA_KEY_WRITER",
+          "PREFERRED_DESCRIPTION_ORDER",
+          "TAG",
+          "METADATA_KEY_COMPOSER",
+          "METADATA_KEY_ALBUM_ART",
+          "METADATA_KEY_GENRE",
+          "METADATA_KEY_ART_URI",
+          "METADATA_KEY_DISPLAY_ICON",
+          "METADATA_KEY_ALBUM_ARTIST",
+          "METADATA_KEY_ADVERTISEMENT",
+          "METADATA_KEYS_TYPE",
+          "METADATA_KEY_RATING",
+          "METADATA_KEY_DISPLAY_SUBTITLE",
+          "METADATA_KEY_DISC_NUMBER"
+        ]
+      },
+      "android/support/transition/Fade": {
+        "androidx/transition/Fade": [
+          "PROPNAME_TRANSITION_ALPHA",
+          "IN",
+          "LOG_TAG",
+          "OUT"
+        ]
+      },
+      "android/support/v17/leanback/R$layout": {
+        "androidx/leanback/R$layout": [
+          "lb_rows_fragment",
+          "lb_video_surface",
+          "lb_headers_fragment",
+          "lb_image_card_view_themed_badge_left",
+          "lb_search_orb",
+          "lb_details_fragment",
+          "lb_guidedstep_fragment",
+          "lb_image_card_view",
+          "lb_details_overview",
+          "lb_playback_controls",
+          "lb_guidedactions_datepicker_item",
+          "lb_image_card_view_themed_title",
+          "lb_picker_column",
+          "lb_playback_transport_controls_row",
+          "lb_image_card_view_themed_badge_right",
+          "lb_row_media_item",
+          "lb_row_container",
+          "lb_search_bar",
+          "lb_shadow",
+          "lb_error_fragment",
+          "lb_guidedbuttonactions",
+          "lb_browse_fragment",
+          "lb_guidedactions_item",
+          "lb_browse_title",
+          "lb_list_row",
+          "lb_section_header",
+          "lb_image_card_view_themed_content",
+          "lb_action_1_line",
+          "lb_media_list_header",
+          "lb_media_item_number_view_flipper",
+          "lb_vertical_grid_fragment",
+          "lb_divider",
+          "lb_details_description",
+          "lb_playback_now_playing_bars",
+          "lb_row_media_item_action",
+          "lb_fullwidth_details_overview",
+          "lb_picker",
+          "lb_guidedstep_background",
+          "lb_guidance",
+          "lb_picker_item",
+          "lb_speech_orb",
+          "lb_vertical_grid",
+          "lb_control_button_primary",
+          "lb_search_fragment",
+          "lb_playback_fragment",
+          "lb_picker_separator",
+          "lb_onboarding_fragment",
+          "lb_playback_controls_row",
+          "lb_row_header",
+          "lb_list_row_hovercard",
+          "lb_control_bar",
+          "lb_header",
+          "lb_guidedactions",
+          "lb_action_2_lines",
+          "lb_control_button_secondary",
+          "lb_title_view",
+          "lb_fullwidth_details_overview_logo"
+        ]
+      },
+      "android/support/coreui/BuildConfig": {
+        "androidx/coreui/BuildConfig": [
+          "APPLICATION_ID",
+          "DEBUG",
+          "FLAVOR",
+          "VERSION_CODE",
+          "VERSION_NAME",
+          "BUILD_TYPE"
+        ]
+      },
+      "android/support/v4/app/NotificationCompat": {
+        "androidx/app/NotificationCompat": [
+          "EXTRA_BACKGROUND_IMAGE_URI",
+          "FLAG_FOREGROUND_SERVICE",
+          "CATEGORY_SYSTEM",
+          "EXTRA_REMOTE_INPUT_HISTORY",
+          "EXTRA_LARGE_ICON",
+          "EXTRA_SHOW_WHEN",
+          "EXTRA_COMPACT_ACTIONS",
+          "CATEGORY_ERROR",
+          "GROUP_ALERT_CHILDREN",
+          "BADGE_ICON_LARGE",
+          "PRIORITY_DEFAULT",
+          "EXTRA_PEOPLE",
+          "STREAM_DEFAULT",
+          "VISIBILITY_PRIVATE",
+          "FLAG_ONLY_ALERT_ONCE",
+          "CATEGORY_EMAIL",
+          "DEFAULT_VIBRATE",
+          "CATEGORY_PROGRESS",
+          "FLAG_ONGOING_EVENT",
+          "EXTRA_PROGRESS_MAX",
+          "EXTRA_TITLE",
+          "CATEGORY_PROMO",
+          "EXTRA_SELF_DISPLAY_NAME",
+          "VISIBILITY_SECRET",
+          "PRIORITY_LOW",
+          "EXTRA_LARGE_ICON_BIG",
+          "CATEGORY_TRANSPORT",
+          "DEFAULT_SOUND",
+          "CATEGORY_CALL",
+          "EXTRA_SMALL_ICON",
+          "CATEGORY_RECOMMENDATION",
+          "EXTRA_PROGRESS",
+          "PRIORITY_HIGH",
+          "EXTRA_CONVERSATION_TITLE",
+          "GROUP_ALERT_SUMMARY",
+          "EXTRA_INFO_TEXT",
+          "BADGE_ICON_NONE",
+          "EXTRA_BIG_TEXT",
+          "EXTRA_TEXT_LINES",
+          "EXTRA_PICTURE",
+          "PRIORITY_MIN",
+          "FLAG_HIGH_PRIORITY",
+          "COLOR_DEFAULT",
+          "PRIORITY_MAX",
+          "EXTRA_TEMPLATE",
+          "FLAG_LOCAL_ONLY",
+          "CATEGORY_ALARM",
+          "EXTRA_SUMMARY_TEXT",
+          "BADGE_ICON_SMALL",
+          "DEFAULT_ALL",
+          "CATEGORY_STATUS",
+          "CATEGORY_EVENT",
+          "GROUP_ALERT_ALL",
+          "EXTRA_SHOW_CHRONOMETER",
+          "DEFAULT_LIGHTS",
+          "VISIBILITY_PUBLIC",
+          "CATEGORY_SOCIAL",
+          "CATEGORY_MESSAGE",
+          "FLAG_INSISTENT",
+          "CATEGORY_REMINDER",
+          "EXTRA_AUDIO_CONTENTS_URI",
+          "CATEGORY_SERVICE",
+          "EXTRA_TITLE_BIG",
+          "FLAG_AUTO_CANCEL",
+          "EXTRA_MEDIA_SESSION",
+          "EXTRA_MESSAGES",
+          "EXTRA_TEXT",
+          "FLAG_SHOW_LIGHTS",
+          "FLAG_GROUP_SUMMARY",
+          "FLAG_NO_CLEAR",
+          "EXTRA_SUB_TEXT",
+          "EXTRA_PROGRESS_INDETERMINATE"
+        ]
+      },
+      "android/support/content/BuildConfig": {
+        "androidx/content/BuildConfig": [
+          "FLAVOR",
+          "APPLICATION_ID",
+          "DEBUG",
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "VERSION_CODE"
+        ]
+      },
+      "android/support/animation/AnimationHandler": {
+        "androidx/animation/AnimationHandler": [
+          "sAnimatorHandler",
+          "FRAME_DELAY_MS"
+        ]
+      },
+      "android/support/media/ExifInterface": {
+        "androidx/media/ExifInterface": [
+          "FLAG_FLASH_RED_EYE_SUPPORTED",
+          "sTagSetForCompatibility",
+          "TAG_CUSTOM_RENDERED",
+          "TAG_SENSITIVITY_TYPE",
+          "GAIN_CONTROL_HIGH_GAIN_UP",
+          "TAG_FOCAL_PLANE_Y_RESOLUTION",
+          "LIGHT_SOURCE_OTHER",
+          "TAG_GPS_TIMESTAMP",
+          "TAG_COMPRESSION",
+          "IFD_INTEROPERABILITY_TAGS",
+          "IFD_FORMAT_DOUBLE",
+          "TAG_PIXEL_Y_DIMENSION",
+          "TAG_GPS_IMG_DIRECTION_REF",
+          "JPEG_INTERCHANGE_FORMAT_LENGTH_TAG",
+          "FLIPPED_ROTATION_ORDER",
+          "LIGHT_SOURCE_WARM_WHITE_FLUORESCENT",
+          "LIGHT_SOURCE_UNKNOWN",
+          "WHITE_BALANCE_MANUAL",
+          "TAG_SUBSEC_TIME",
+          "FILE_SOURCE_DSC",
+          "IFD_FORMAT_SSHORT",
+          "MARKER",
+          "LONGITUDE_WEST",
+          "IMAGE_TYPE_UNKNOWN",
+          "METERING_MODE_SPOT",
+          "IMAGE_TYPE_CR2",
+          "TAG_GPS_DOP",
+          "MAX_THUMBNAIL_SIZE",
+          "SENSOR_TYPE_TWO_CHIP",
+          "TAG_GPS_TRACK",
+          "SENSITIVITY_TYPE_REI_AND_ISO",
+          "SENSOR_TYPE_ONE_CHIP",
+          "GPS_MEASUREMENT_NO_DIFFERENTIAL",
+          "ORIENTATION_ROTATE_90",
+          "TAG_WHITE_POINT",
+          "PEF_SIGNATURE",
+          "TAG_GPS_IMG_DIRECTION",
+          "ORIGINAL_RESOLUTION_IMAGE",
+          "METERING_MODE_CENTER_WEIGHT_AVERAGE",
+          "TAG_ORF_CAMERA_SETTINGS_IFD_POINTER",
+          "TAG_ISO_SPEED",
+          "IMAGE_TYPE_DNG",
+          "GAIN_CONTROL_NONE",
+          "LONGITUDE_EAST",
+          "IFD_TYPE_ORF_MAKER_NOTE",
+          "TAG_DEVICE_SETTING_DESCRIPTION",
+          "TAG_BRIGHTNESS_VALUE",
+          "TAG_GPS_MAP_DATUM",
+          "METERING_MODE_MULTI_SPOT",
+          "TAG_RW2_ISO",
+          "TAG_ORF_PREVIEW_IMAGE_START",
+          "LIGHT_SOURCE_FLUORESCENT",
+          "COLOR_SPACE_S_RGB",
+          "IMAGE_TYPE_SRW",
+          "FLAG_FLASH_RETURN_LIGHT_DETECTED",
+          "SUBJECT_DISTANCE_RANGE_DISTANT_VIEW",
+          "TAG_ISO_SPEED_LATITUDE_YYY",
+          "RAF_INFO_SIZE",
+          "TAG",
+          "ORIENTATION_NORMAL",
+          "TAG_SUB_IFD_POINTER",
+          "LIGHT_SOURCE_TUNGSTEN",
+          "RESOLUTION_UNIT_CENTIMETERS",
+          "ALTITUDE_ABOVE_SEA_LEVEL",
+          "BYTE_ALIGN_MM",
+          "METERING_MODE_OTHER",
+          "TAG_EXIF_IFD_POINTER",
+          "BYTE_ALIGN_II",
+          "TAG_GPS_TRACK_REF",
+          "SHARPNESS_NORMAL",
+          "FILE_SOURCE_OTHER",
+          "TAG_OECF",
+          "SENSOR_TYPE_COLOR_SEQUENTIAL",
+          "sFormatter",
+          "FLAG_FLASH_MODE_COMPULSORY_FIRING",
+          "GPS_SPEED_KNOTS",
+          "DATA_DEFLATE_ZIP",
+          "TAG_DNG_VERSION",
+          "IMAGE_TYPE_ARW",
+          "TAG_RELATED_SOUND_FILE",
+          "TAG_BODY_SERIAL_NUMBER",
+          "EXPOSURE_PROGRAM_NOT_DEFINED",
+          "SIGNATURE_CHECK_SIZE",
+          "JPEG_INTERCHANGE_FORMAT_TAG",
+          "TAG_RW2_SENSOR_RIGHT_BORDER",
+          "TAG_CAMARA_OWNER_NAME",
+          "TAG_SPATIAL_FREQUENCY_RESPONSE",
+          "COLOR_SPACE_UNCALIBRATED",
+          "EXPOSURE_PROGRAM_NORMAL",
+          "EXPOSURE_PROGRAM_SHUTTER_PRIORITY",
+          "TAG_THUMBNAIL_LENGTH",
+          "TAG_TRANSFER_FUNCTION",
+          "IMAGE_TYPE_RW2",
+          "TAG_RW2_SENSOR_LEFT_BORDER",
+          "TAG_CFA_PATTERN",
+          "TAG_THUMBNAIL_IMAGE_LENGTH",
+          "TAG_GPS_H_POSITIONING_ERROR",
+          "sGpsTimestampPattern",
+          "PEF_MAKER_NOTE_SKIP_SIZE",
+          "IFD_FORMAT_STRING",
+          "TAG_SUBJECT_DISTANCE",
+          "TAG_GPS_SPEED_REF",
+          "SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO",
+          "TAG_ORIENTATION",
+          "TAG_PHOTOMETRIC_INTERPRETATION",
+          "LIGHT_SOURCE_DAYLIGHT",
+          "TAG_MODEL",
+          "IFD_TYPE_GPS",
+          "LIGHT_SOURCE_SHADE",
+          "Y_CB_CR_POSITIONING_CO_SITED",
+          "TAG_RAF_IMAGE_SIZE",
+          "IFD_FORMAT_BYTES_PER_FORMAT",
+          "SENSITIVITY_TYPE_SOS_AND_REI",
+          "TAG_Y_RESOLUTION",
+          "TAG_GPS_DIFFERENTIAL",
+          "EXPOSURE_MODE_AUTO",
+          "MARKER_SOS",
+          "MARKER_SOI",
+          "IFD_TYPE_PREVIEW",
+          "IMAGE_TYPE_RAF",
+          "IFD_FORMAT_SBYTE",
+          "ORIENTATION_FLIP_VERTICAL",
+          "TAG_LENS_SERIAL_NUMBER",
+          "TAG_FLASHPIX_VERSION",
+          "EXIF_ASCII_PREFIX",
+          "IFD_TYPE_ORF_IMAGE_PROCESSING",
+          "TAG_ORF_IMAGE_PROCESSING_IFD_POINTER",
+          "DATA_LOSSY_JPEG",
+          "TAG_GPS_SPEED",
+          "TAG_USER_COMMENT",
+          "TAG_SUBSEC_TIME_ORIGINAL",
+          "TAG_THUMBNAIL_IMAGE_WIDTH",
+          "IFD_FORMAT_UNDEFINED",
+          "RW2_SIGNATURE",
+          "ORF_MAKER_NOTE_HEADER_2",
+          "ORF_MAKER_NOTE_HEADER_1",
+          "TAG_WHITE_BALANCE",
+          "TAG_ISO_SPEED_LATITUDE_ZZZ",
+          "TAG_PHOTOGRAPHIC_SENSITIVITY",
+          "SCENE_CAPTURE_TYPE_LANDSCAPE",
+          "MARKER_COM",
+          "TAG_HAS_THUMBNAIL",
+          "TAG_EXPOSURE_TIME",
+          "TAG_GPS_SATELLITES",
+          "TAG_COLOR_SPACE",
+          "TAG_GPS_LATITUDE_REF",
+          "IMAGE_TYPE_JPEG",
+          "START_CODE",
+          "TAG_APERTURE_VALUE",
+          "TAG_BITS_PER_SAMPLE",
+          "TAG_DIGITAL_ZOOM_RATIO",
+          "METERING_MODE_PATTERN",
+          "TAG_SHUTTER_SPEED_VALUE",
+          "DATA_PACK_BITS_COMPRESSED",
+          "sExifPointerTagMap",
+          "EXPOSURE_PROGRAM_APERTURE_PRIORITY",
+          "TAG_SAMPLES_PER_PIXEL",
+          "TAG_FILE_SOURCE",
+          "LIGHT_SOURCE_DAY_WHITE_FLUORESCENT",
+          "IFD_EXIF_TAGS",
+          "TAG_GPS_INFO_IFD_POINTER",
+          "TAG_GAMMA",
+          "IMAGE_TYPE_ORF",
+          "TAG_GAIN_CONTROL",
+          "IFD_TYPE_EXIF",
+          "TAG_SUBJECT_AREA",
+          "FORMAT_CHUNKY",
+          "ASCII",
+          "ORF_IMAGE_PROCESSING_TAGS",
+          "TAG_ORF_THUMBNAIL_IMAGE",
+          "IMAGE_TYPE_PEF",
+          "IFD_TYPE_ORF_CAMERA_SETTINGS",
+          "EXPOSURE_MODE_MANUAL",
+          "TAG_GPS_DATESTAMP",
+          "IFD_FORMAT_SRATIONAL",
+          "TAG_SUBJECT_LOCATION",
+          "FILE_SOURCE_REFLEX_SCANNER",
+          "TAG_LENS_SPECIFICATION",
+          "LIGHT_SOURCE_DAYLIGHT_FLUORESCENT",
+          "TAG_COMPONENTS_CONFIGURATION",
+          "TAG_REFERENCE_BLACK_WHITE",
+          "IMAGE_TYPE_NEF",
+          "GAIN_CONTROL_HIGH_GAIN_DOWN",
+          "LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN",
+          "ORIENTATION_TRANSVERSE",
+          "IFD_FORMAT_URATIONAL",
+          "EXPOSURE_PROGRAM_LANDSCAPE_MODE",
+          "IMAGE_TYPE_NRW",
+          "TAG_FLASH",
+          "RAF_SIGNATURE",
+          "EXPOSURE_PROGRAM_ACTION",
+          "TAG_PLANAR_CONFIGURATION",
+          "LIGHT_SOURCE_CLOUDY_WEATHER",
+          "FLAG_FLASH_FIRED",
+          "EXPOSURE_MODE_AUTO_BRACKET",
+          "ORIENTATION_TRANSPOSE",
+          "REDUCED_RESOLUTION_IMAGE",
+          "WHITE_BALANCE_AUTO",
+          "TAG_FOCAL_PLANE_RESOLUTION_UNIT",
+          "PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO",
+          "DATA_UNCOMPRESSED",
+          "MARKER_EOI",
+          "TAG_SUBSEC_TIME_DIGITIZED",
+          "TAG_THUMBNAIL_DATA",
+          "TAG_GPS_DEST_BEARING_REF",
+          "EXPOSURE_PROGRAM_PORTRAIT_MODE",
+          "TAG_GPS_ALTITUDE",
+          "DATA_JPEG",
+          "TAG_GPS_DEST_LATITUDE_REF",
+          "ALTITUDE_BELOW_SEA_LEVEL",
+          "TAG_F_NUMBER",
+          "SUBJECT_DISTANCE_RANGE_UNKNOWN",
+          "TAG_SPECTRAL_SENSITIVITY",
+          "SCENE_CAPTURE_TYPE_NIGHT",
+          "TAG_PIXEL_X_DIMENSION",
+          "TAG_DEFAULT_CROP_SIZE",
+          "LIGHT_SOURCE_D75",
+          "LIGHT_SOURCE_D65",
+          "GPS_MEASUREMENT_INTERRUPTED",
+          "TAG_GPS_DEST_DISTANCE",
+          "LIGHT_SOURCE_D50",
+          "LIGHT_SOURCE_D55",
+          "ORIENTATION_ROTATE_180",
+          "SATURATION_NORMAL",
+          "TAG_THUMBNAIL_OFFSET",
+          "RESOLUTION_UNIT_INCHES",
+          "ORF_CAMERA_SETTINGS_TAGS",
+          "IFD_FORMAT_BYTE",
+          "TAG_LENS_MAKE",
+          "JPEG_SIGNATURE",
+          "EXPOSURE_PROGRAM_MANUAL",
+          "EXPOSURE_PROGRAM_CREATIVE",
+          "SUBJECT_DISTANCE_RANGE_CLOSE_VIEW",
+          "TAG_MAX_APERTURE_VALUE",
+          "DEBUG",
+          "METERING_MODE_AVERAGE",
+          "RENDERED_PROCESS_NORMAL",
+          "LIGHT_SOURCE_STANDARD_LIGHT_B",
+          "LIGHT_SOURCE_STANDARD_LIGHT_C",
+          "LIGHT_SOURCE_STANDARD_LIGHT_A",
+          "TAG_ISO_SPEED_RATINGS",
+          "TAG_STANDARD_OUTPUT_SENSITIVITY",
+          "PHOTOMETRIC_INTERPRETATION_YCBCR",
+          "TAG_ARTIST",
+          "IFD_TYPE_THUMBNAIL",
+          "PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO",
+          "FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED",
+          "TAG_FOCAL_PLANE_X_RESOLUTION",
+          "TAG_LIGHT_SOURCE",
+          "MARKER_SOF1",
+          "MARKER_SOF2",
+          "MARKER_SOF0",
+          "MARKER_SOF9",
+          "MARKER_SOF7",
+          "MARKER_SOF5",
+          "MARKER_SOF6",
+          "MARKER_SOF3",
+          "sExifTagMapsForWriting",
+          "SHARPNESS_SOFT",
+          "TAG_SCENE_TYPE",
+          "TAG_GPS_DEST_LONGITUDE",
+          "sNonZeroTimePattern",
+          "GPS_DIRECTION_MAGNETIC",
+          "EXIF_TAGS",
+          "TAG_GPS_AREA_INFORMATION",
+          "FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION",
+          "IFD_THUMBNAIL_TAGS",
+          "IFD_FORMAT_ULONG",
+          "TAG_INTEROPERABILITY_IFD_POINTER",
+          "TAG_SUBFILE_TYPE",
+          "TAG_RW2_SENSOR_TOP_BORDER",
+          "TAG_INTEROPERABILITY_INDEX",
+          "GPS_MEASUREMENT_3D",
+          "GPS_DIRECTION_TRUE",
+          "GPS_MEASUREMENT_2D",
+          "sExifTagMapsForReading",
+          "TAG_JPEG_INTERCHANGE_FORMAT",
+          "LATITUDE_SOUTH",
+          "PHOTOMETRIC_INTERPRETATION_RGB",
+          "BITS_PER_SAMPLE_RGB",
+          "CONTRAST_HARD",
+          "SHARPNESS_HARD",
+          "LATITUDE_NORTH",
+          "TAG_CONTRAST",
+          "ORIENTATION_FLIP_HORIZONTAL",
+          "TAG_GPS_LONGITUDE",
+          "TAG_COMPRESSED_BITS_PER_PIXEL",
+          "TAG_METERING_MODE",
+          "BITS_PER_SAMPLE_GREYSCALE_1",
+          "BITS_PER_SAMPLE_GREYSCALE_2",
+          "TAG_ROWS_PER_STRIP",
+          "GPS_DISTANCE_MILES",
+          "TAG_MAKER_NOTE",
+          "SUBJECT_DISTANCE_RANGE_MACRO",
+          "GAIN_CONTROL_LOW_GAIN_DOWN",
+          "SATURATION_HIGH",
+          "SCENE_TYPE_DIRECTLY_PHOTOGRAPHED",
+          "LIGHT_SOURCE_WHITE_FLUORESCENT",
+          "TAG_SHARPNESS",
+          "GPS_DISTANCE_KILOMETERS",
+          "TAG_GPS_LATITUDE",
+          "TAG_RW2_SENSOR_BOTTOM_BORDER",
+          "WHITEBALANCE_AUTO",
+          "TAG_SCENE_CAPTURE_TYPE",
+          "TAG_STRIP_BYTE_COUNTS",
+          "TAG_GPS_LONGITUDE_REF",
+          "GPS_MEASUREMENT_IN_PROGRESS",
+          "ORIENTATION_UNDEFINED",
+          "RAF_OFFSET_TO_JPEG_IMAGE_OFFSET",
+          "TAG_SUBJECT_DISTANCE_RANGE",
+          "ROTATION_ORDER",
+          "TAG_GPS_STATUS",
+          "ORF_MAKER_NOTE_HEADER_1_SIZE",
+          "TAG_GPS_DEST_BEARING",
+          "TAG_Y_CB_CR_COEFFICIENTS",
+          "TAG_MAKE",
+          "IFD_TYPE_PEF",
+          "TAG_RESOLUTION_UNIT",
+          "TAG_IMAGE_DESCRIPTION",
+          "SENSOR_TYPE_NOT_DEFINED",
+          "ORF_MAKER_NOTE_HEADER_2_SIZE",
+          "IFD_FORMAT_IFD",
+          "TAG_SATURATION",
+          "TAG_FOCAL_LENGTH_IN_35MM_FILM",
+          "TAG_FOCAL_LENGTH",
+          "SENSITIVITY_TYPE_SOS_AND_ISO",
+          "TAG_EXIF_VERSION",
+          "TAG_ORF_PREVIEW_IMAGE_LENGTH",
+          "GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED",
+          "IFD_FORMAT_SINGLE",
+          "CONTRAST_NORMAL",
+          "TAG_PRIMARY_CHROMATICITIES",
+          "TAG_LENS_MODEL",
+          "TAG_IMAGE_LENGTH",
+          "TAG_RW2_JPG_FROM_RAW",
+          "SATURATION_LOW",
+          "TAG_SOFTWARE",
+          "IFD_TIFF_TAGS",
+          "SENSITIVITY_TYPE_ISO_SPEED",
+          "TAG_GPS_PROCESSING_METHOD",
+          "TAG_X_RESOLUTION",
+          "LIGHT_SOURCE_COOL_WHITE_FLUORESCENT",
+          "DATA_HUFFMAN_COMPRESSED",
+          "SENSOR_TYPE_THREE_CHIP",
+          "TAG_IMAGE_WIDTH",
+          "METERING_MODE_PARTIAL",
+          "SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR",
+          "LIGHT_SOURCE_FINE_WEATHER",
+          "TAG_EXPOSURE_INDEX",
+          "TAG_STRIP_OFFSETS",
+          "TAG_EXPOSURE_PROGRAM",
+          "TAG_IMAGE_UNIQUE_ID",
+          "IFD_FORMAT_USHORT",
+          "TAG_GPS_VERSION_ID",
+          "CONTRAST_SOFT",
+          "TAG_DATETIME_DIGITIZED",
+          "EXIF_POINTER_TAGS",
+          "FLAG_FLASH_NO_FLASH_FUNCTION",
+          "IFD_FORMAT_NAMES",
+          "ORF_MAKER_NOTE_TAGS",
+          "TAG_EXPOSURE_BIAS_VALUE",
+          "TAG_GPS_DEST_LONGITUDE_REF",
+          "IFD_OFFSET",
+          "ORF_SIGNATURE_1",
+          "ORF_SIGNATURE_2",
+          "METERING_MODE_UNKNOWN",
+          "GPS_SPEED_KILOMETERS_PER_HOUR",
+          "FORMAT_PLANAR",
+          "MARKER_SOF10",
+          "MARKER_SOF11",
+          "MARKER_SOF13",
+          "MARKER_SOF14",
+          "MARKER_SOF15",
+          "IFD_FORMAT_SLONG",
+          "TAG_COPYRIGHT",
+          "TAG_GPS_DEST_DISTANCE_REF",
+          "TAG_GPS_MEASURE_MODE",
+          "Y_CB_CR_POSITIONING_CENTERED",
+          "TAG_Y_CB_CR_POSITIONING",
+          "GPS_DISTANCE_NAUTICAL_MILES",
+          "WHITEBALANCE_MANUAL",
+          "GAIN_CONTROL_LOW_GAIN_UP",
+          "IDENTIFIER_EXIF_APP1",
+          "DATA_JPEG_COMPRESSED",
+          "SCENE_CAPTURE_TYPE_PORTRAIT",
+          "GPS_SPEED_MILES_PER_HOUR",
+          "IFD_TYPE_PRIMARY",
+          "TAG_Y_CB_CR_SUB_SAMPLING",
+          "TAG_GPS_ALTITUDE_REF",
+          "SENSITIVITY_TYPE_SOS",
+          "TAG_SENSING_METHOD",
+          "TAG_ORF_ASPECT_FRAME",
+          "TAG_NEW_SUBFILE_TYPE",
+          "TAG_EXPOSURE_MODE",
+          "ORIENTATION_ROTATE_270",
+          "IFD_GPS_TAGS",
+          "RAF_JPEG_LENGTH_VALUE_SIZE",
+          "TAG_FLASH_ENERGY",
+          "TAG_RECOMMENDED_EXPOSURE_INDEX",
+          "SENSOR_TYPE_TRILINEAR",
+          "SCENE_CAPTURE_TYPE_STANDARD",
+          "PEF_TAGS",
+          "SENSITIVITY_TYPE_UNKNOWN",
+          "TAG_DATETIME",
+          "TAG_JPEG_INTERCHANGE_FORMAT_LENGTH",
+          "LIGHT_SOURCE_FLASH",
+          "FLAG_FLASH_MODE_AUTO",
+          "MARKER_APP1",
+          "SENSITIVITY_TYPE_REI",
+          "TAG_DATETIME_ORIGINAL",
+          "TAG_GPS_DEST_LATITUDE",
+          "FILE_SOURCE_TRANSPARENT_SCANNER",
+          "RENDERED_PROCESS_CUSTOM",
+          "IFD_TYPE_INTEROPERABILITY"
+        ]
+      },
+      "android/support/v4/widget/ViewDragHelper": {
+        "androidx/widget/ViewDragHelper": [
+          "DIRECTION_HORIZONTAL",
+          "TAG",
+          "INVALID_POINTER",
+          "EDGE_SIZE",
+          "EDGE_LEFT",
+          "STATE_IDLE",
+          "STATE_DRAGGING",
+          "EDGE_ALL",
+          "DIRECTION_ALL",
+          "EDGE_RIGHT",
+          "sInterpolator",
+          "EDGE_TOP",
+          "STATE_SETTLING",
+          "BASE_SETTLE_DURATION",
+          "EDGE_BOTTOM",
+          "MAX_SETTLE_DURATION",
+          "DIRECTION_VERTICAL"
+        ]
+      },
+      "android/support/design/widget/NavigationView": {
+        "androidx/design/widget/NavigationView": [
+          "EMPTY_STATE_SET",
+          "CHECKED_STATE_SET",
+          "PRESENTER_NAVIGATION_VIEW_ID",
+          "DISABLED_STATE_SET"
+        ]
+      },
+      "android/support/customtabs/ICustomTabsCallback$Stub": {
+        "androidx/browser/customtabs/ICustomTabsCallback$Stub": [
+          "TRANSACTION_onMessageChannelReady",
+          "TRANSACTION_onPostMessage",
+          "TRANSACTION_onNavigationEvent",
+          "TRANSACTION_onRelationshipValidationResult",
+          "TRANSACTION_extraCallback",
+          "DESCRIPTOR"
+        ]
+      },
+      "android/support/v7/media/MediaRouterJellybeanMr1$ActiveScanWorkaround": {
+        "androidx/media/MediaRouterJellybeanMr1$ActiveScanWorkaround": [
+          "WIFI_DISPLAY_SCAN_INTERVAL"
+        ]
+      },
+      "android/support/v17/leanback/widget/GridLayoutManager$LayoutParams": {
+        "androidx/leanback/widget/GridLayoutManager$LayoutParams": [
+          "bottomMargin",
+          "leftMargin",
+          "topMargin",
+          "width",
+          "height",
+          "rightMargin"
+        ]
+      },
+      "android/support/v7/cardview/R$styleable": {
+        "androidx/cardview/R$styleable": [
+          "CardView_contentPaddingRight",
+          "CardView",
+          "CardView_android_minWidth",
+          "CardView_cardCornerRadius",
+          "CardView_contentPaddingLeft",
+          "CardView_cardBackgroundColor",
+          "CardView_contentPadding",
+          "CardView_contentPaddingBottom",
+          "CardView_cardElevation",
+          "CardView_cardUseCompatPadding",
+          "CardView_contentPaddingTop",
+          "CardView_android_minHeight",
+          "CardView_cardPreventCornerOverlap",
+          "CardView_cardMaxElevation"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsRow$ThumbsAction": {
+        "androidx/leanback/widget/PlaybackControlsRow$ThumbsAction": [
+          "INDEX_OUTLINE",
+          "OUTLINE",
+          "SOLID",
+          "INDEX_SOLID"
+        ]
+      },
+      "android/support/v4/media/session/IMediaSession$Stub": {
+        "androidx/media/session/IMediaSession$Stub": [
+          "TRANSACTION_playFromUri",
+          "TRANSACTION_playFromSearch",
+          "TRANSACTION_getRepeatMode",
+          "TRANSACTION_previous",
+          "TRANSACTION_getPlaybackState",
+          "TRANSACTION_adjustVolume",
+          "TRANSACTION_setShuffleMode",
+          "TRANSACTION_setVolumeTo",
+          "TRANSACTION_prepareFromSearch",
+          "TRANSACTION_removeQueueItemAt",
+          "TRANSACTION_playFromMediaId",
+          "TRANSACTION_getPackageName",
+          "TRANSACTION_sendCommand",
+          "TRANSACTION_isTransportControlEnabled",
+          "TRANSACTION_pause",
+          "DESCRIPTOR",
+          "TRANSACTION_rewind",
+          "TRANSACTION_getRatingType",
+          "TRANSACTION_prepareFromUri",
+          "TRANSACTION_getMetadata",
+          "TRANSACTION_addQueueItemAt",
+          "TRANSACTION_getQueueTitle",
+          "TRANSACTION_getLaunchPendingIntent",
+          "TRANSACTION_getQueue",
+          "TRANSACTION_registerCallbackListener",
+          "TRANSACTION_getShuffleMode",
+          "TRANSACTION_seekTo",
+          "TRANSACTION_prepareFromMediaId",
+          "TRANSACTION_setShuffleModeEnabledRemoved",
+          "TRANSACTION_removeQueueItem",
+          "TRANSACTION_setRepeatMode",
+          "TRANSACTION_getFlags",
+          "TRANSACTION_prepare",
+          "TRANSACTION_isShuffleModeEnabledRemoved",
+          "TRANSACTION_addQueueItem",
+          "TRANSACTION_isCaptioningEnabled",
+          "TRANSACTION_setCaptioningEnabled",
+          "TRANSACTION_rateWithExtras",
+          "TRANSACTION_stop",
+          "TRANSACTION_getVolumeAttributes",
+          "TRANSACTION_next",
+          "TRANSACTION_skipToQueueItem",
+          "TRANSACTION_rate",
+          "TRANSACTION_unregisterCallbackListener",
+          "TRANSACTION_play",
+          "TRANSACTION_getTag",
+          "TRANSACTION_sendMediaButton",
+          "TRANSACTION_sendCustomAction",
+          "TRANSACTION_fastForward",
+          "TRANSACTION_getExtras"
+        ]
+      },
+      "android/support/v4/provider/FontsContractCompat$Columns": {
+        "androidx/provider/FontsContractCompat$Columns": [
+          "TTC_INDEX",
+          "FILE_ID",
+          "RESULT_CODE",
+          "WEIGHT",
+          "ITALIC",
+          "VARIATION_SETTINGS",
+          "RESULT_CODE_OK",
+          "RESULT_CODE_MALFORMED_QUERY",
+          "RESULT_CODE_FONT_UNAVAILABLE",
+          "RESULT_CODE_FONT_NOT_FOUND"
+        ]
+      },
+      "android/support/v4/media/MediaBrowserProtocol": {
+        "androidx/media/MediaBrowserProtocol": [
+          "DATA_CALLING_UID",
+          "EXTRA_MESSENGER_BINDER",
+          "DATA_ROOT_HINTS",
+          "CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER",
+          "EXTRA_SERVICE_VERSION",
+          "SERVICE_VERSION_1",
+          "DATA_OPTIONS",
+          "CLIENT_MSG_DISCONNECT",
+          "EXTRA_SESSION_BINDER",
+          "SERVICE_VERSION_CURRENT",
+          "CLIENT_VERSION_CURRENT",
+          "EXTRA_CLIENT_VERSION",
+          "CLIENT_VERSION_1",
+          "CLIENT_MSG_GET_MEDIA_ITEM",
+          "DATA_MEDIA_ITEM_LIST",
+          "DATA_MEDIA_SESSION_TOKEN",
+          "SERVICE_MSG_ON_CONNECT",
+          "DATA_RESULT_RECEIVER",
+          "CLIENT_MSG_SEND_CUSTOM_ACTION",
+          "CLIENT_MSG_CONNECT",
+          "SERVICE_MSG_ON_CONNECT_FAILED",
+          "SERVICE_MSG_ON_LOAD_CHILDREN",
+          "DATA_MEDIA_ITEM_ID",
+          "DATA_CALLBACK_TOKEN",
+          "DATA_SEARCH_QUERY",
+          "DATA_CUSTOM_ACTION_EXTRAS",
+          "CLIENT_MSG_SEARCH",
+          "DATA_SEARCH_EXTRAS",
+          "CLIENT_MSG_ADD_SUBSCRIPTION",
+          "DATA_CUSTOM_ACTION",
+          "CLIENT_MSG_REGISTER_CALLBACK_MESSENGER",
+          "DATA_PACKAGE_NAME",
+          "CLIENT_MSG_REMOVE_SUBSCRIPTION"
+        ]
+      },
+      "android/support/v17/leanback/R$color": {
+        "androidx/leanback/R$color": [
+          "lb_error_background_color_opaque",
+          "lb_playback_controls_background_dark",
+          "lb_default_brand_color_dark",
+          "lb_error_background_color_translucent",
+          "lb_background_protection",
+          "lb_speech_orb_recording",
+          "lb_default_brand_color",
+          "lb_page_indicator_dot",
+          "lb_search_bar_hint",
+          "lb_playback_progress_color_no_theme",
+          "lb_speech_orb_not_recording",
+          "lb_search_bar_text_speech_mode",
+          "lb_view_dim_mask_color",
+          "lb_playback_controls_background_light",
+          "lb_playback_media_row_highlight_color",
+          "lb_default_search_color",
+          "lb_playback_icon_highlight_no_theme",
+          "lb_search_bar_hint_speech_mode",
+          "lb_page_indicator_arrow_shadow",
+          "lb_speech_orb_not_recording_icon",
+          "lb_speech_orb_not_recording_pulsed",
+          "lb_search_bar_text",
+          "lb_page_indicator_arrow_background"
+        ]
+      },
+      "android/support/transition/ViewGroupUtilsApi18": {
+        "androidx/transition/ViewGroupUtilsApi18": [
+          "sSuppressLayoutMethod",
+          "TAG",
+          "sSuppressLayoutMethodFetched"
+        ]
+      },
+      "android/support/v4/text/TextDirectionHeuristicsCompat": {
+        "androidx/text/TextDirectionHeuristicsCompat": [
+          "STATE_UNKNOWN",
+          "RTL",
+          "LOCALE",
+          "ANYRTL_LTR",
+          "LTR",
+          "FIRSTSTRONG_RTL",
+          "FIRSTSTRONG_LTR",
+          "STATE_TRUE",
+          "STATE_FALSE"
+        ]
+      },
+      "android/support/v7/widget/ListViewCompat": {
+        "androidx/widget/ListViewCompat": [
+          "INVALID_POSITION",
+          "NO_POSITION",
+          "STATE_SET_NOTHING"
+        ]
+      },
+      "android/support/v17/leanback/app/GuidedStepSupportFragment": {
+        "androidx/leanback/app/GuidedStepSupportFragment": [
+          "SLIDE_FROM_BOTTOM",
+          "SLIDE_FROM_SIDE",
+          "EXTRA_BUTTON_ACTION_PREFIX",
+          "TAG_LEAN_BACK_ACTIONS_FRAGMENT",
+          "ENTRY_NAME_ENTRANCE",
+          "DEBUG",
+          "UI_STYLE_DEFAULT",
+          "UI_STYLE_REPLACE",
+          "IS_FRAMEWORK_FRAGMENT",
+          "UI_STYLE_ACTIVITY_ROOT",
+          "EXTRA_UI_STYLE",
+          "UI_STYLE_ENTRANCE",
+          "entranceTransitionType",
+          "TAG",
+          "ENTRY_NAME_REPLACE",
+          "EXTRA_ACTION_PREFIX"
+        ]
+      },
+      "android/support/v7/media/MediaRouter$GlobalMediaRouter$CallbackHandler": {
+        "androidx/media/MediaRouter$GlobalMediaRouter$CallbackHandler": [
+          "MSG_TYPE_MASK",
+          "MSG_PROVIDER_REMOVED",
+          "MSG_ROUTE_SELECTED",
+          "MSG_ROUTE_VOLUME_CHANGED",
+          "MSG_PROVIDER_ADDED",
+          "MSG_TYPE_ROUTE",
+          "MSG_ROUTE_REMOVED",
+          "MSG_ROUTE_UNSELECTED",
+          "MSG_TYPE_PROVIDER",
+          "MSG_PROVIDER_CHANGED",
+          "MSG_ROUTE_ADDED",
+          "MSG_ROUTE_PRESENTATION_DISPLAY_CHANGED",
+          "MSG_ROUTE_CHANGED"
+        ]
+      },
+      "android/support/v7/view/menu/ActionMenuItem": {
+        "androidx/view/menu/ActionMenuItem": [
+          "EXCLUSIVE",
+          "CHECKED",
+          "ENABLED",
+          "CHECKABLE",
+          "NO_ICON",
+          "HIDDEN"
+        ]
+      },
+      "android/support/v4/app/NotificationCompat$WearableExtender": {
+        "androidx/app/NotificationCompat$WearableExtender": [
+          "SCREEN_TIMEOUT_LONG",
+          "KEY_FLAGS",
+          "KEY_DISMISSAL_ID",
+          "SIZE_LARGE",
+          "KEY_GRAVITY",
+          "KEY_CONTENT_ICON",
+          "FLAG_START_SCROLL_BOTTOM",
+          "DEFAULT_FLAGS",
+          "DEFAULT_CONTENT_ICON_GRAVITY",
+          "FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE",
+          "UNSET_ACTION_INDEX",
+          "DEFAULT_GRAVITY",
+          "FLAG_HINT_SHOW_BACKGROUND_ONLY",
+          "SIZE_XSMALL",
+          "KEY_CUSTOM_CONTENT_HEIGHT",
+          "FLAG_HINT_AVOID_BACKGROUND_CLIPPING",
+          "SIZE_DEFAULT",
+          "KEY_BACKGROUND",
+          "FLAG_BIG_PICTURE_AMBIENT",
+          "SCREEN_TIMEOUT_SHORT",
+          "SIZE_FULL_SCREEN",
+          "KEY_ACTIONS",
+          "EXTRA_WEARABLE_EXTENSIONS",
+          "KEY_CONTENT_ACTION_INDEX",
+          "FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY",
+          "KEY_CONTENT_ICON_GRAVITY",
+          "KEY_DISPLAY_INTENT",
+          "SIZE_SMALL",
+          "KEY_CUSTOM_SIZE_PRESET",
+          "KEY_HINT_SCREEN_TIMEOUT",
+          "FLAG_HINT_HIDE_ICON",
+          "KEY_BRIDGE_TAG",
+          "SIZE_MEDIUM",
+          "KEY_PAGES"
+        ]
+      },
+      "android/support/design/R$styleable": {
+        "androidx/design/R$styleable": [
+          "TabLayout_tabSelectedTextColor",
+          "BottomSheetBehavior_Layout_behavior_peekHeight",
+          "TextInputLayout_counterOverflowTextAppearance",
+          "BottomNavigationView_itemTextColor",
+          "ScrimInsetsFrameLayout_insetForeground",
+          "TabItem_android_icon",
+          "CoordinatorLayout",
+          "TextInputLayout_counterTextAppearance",
+          "TabLayout_tabMode",
+          "TextInputLayout_hintAnimationEnabled",
+          "TextInputLayout_passwordToggleTint",
+          "NavigationView_android_fitsSystemWindows",
+          "AppBarLayout_android_background",
+          "BottomSheetBehavior_Layout",
+          "FloatingActionButton_fabSize",
+          "TextInputLayout_android_hint",
+          "FloatingActionButton_elevation",
+          "TabItem_android_text",
+          "CollapsingToolbarLayout_expandedTitleTextAppearance",
+          "TextInputLayout_hintTextAppearance",
+          "BottomNavigationView_elevation",
+          "BottomNavigationView_itemIconTint",
+          "CollapsingToolbarLayout_collapsedTitleTextAppearance",
+          "TabLayout_tabPaddingEnd",
+          "TextInputLayout",
+          "TextInputLayout_counterEnabled",
+          "TextInputLayout_passwordToggleContentDescription",
+          "NavigationView_itemBackground",
+          "CollapsingToolbarLayout_expandedTitleMarginBottom",
+          "AppBarLayout_android_keyboardNavigationCluster",
+          "FloatingActionButton_Behavior_Layout",
+          "NavigationView_itemTextAppearance",
+          "TabLayout_tabBackground",
+          "TabLayout_tabContentStart",
+          "ScrollingViewBehavior_Layout",
+          "TabItem_android_layout",
+          "TextInputLayout_hintEnabled",
+          "CollapsingToolbarLayout_scrimVisibleHeightTrigger",
+          "TabLayout_tabPaddingTop",
+          "CoordinatorLayout_Layout_layout_anchorGravity",
+          "CoordinatorLayout_statusBarBackground",
+          "NavigationView",
+          "CollapsingToolbarLayout_expandedTitleMarginEnd",
+          "CoordinatorLayout_Layout_layout_anchor",
+          "TabLayout_tabMinWidth",
+          "TabLayout_tabPaddingStart",
+          "TextInputLayout_errorEnabled",
+          "TabLayout_tabMaxWidth",
+          "TabLayout_tabTextColor",
+          "CollapsingToolbarLayout_collapsedTitleGravity",
+          "BottomNavigationView",
+          "TabLayout_tabTextAppearance",
+          "NavigationView_itemIconTint",
+          "TabLayout_tabIndicatorColor",
+          "TabLayout",
+          "TabLayout_tabIndicatorHeight",
+          "NavigationView_headerLayout",
+          "CoordinatorLayout_Layout",
+          "BottomNavigationView_menu",
+          "CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier",
+          "NavigationView_menu",
+          "TextInputLayout_passwordToggleDrawable",
+          "ScrimInsetsFrameLayout",
+          "CoordinatorLayout_Layout_layout_insetEdge",
+          "CollapsingToolbarLayout_titleEnabled",
+          "ForegroundLinearLayout",
+          "TabLayout_tabGravity",
+          "CollapsingToolbarLayout_contentScrim",
+          "ForegroundLinearLayout_android_foreground",
+          "CollapsingToolbarLayout_expandedTitleGravity",
+          "TextInputLayout_errorTextAppearance",
+          "TabLayout_tabPaddingBottom",
+          "CollapsingToolbarLayout",
+          "AppBarLayout",
+          "FloatingActionButton_pressedTranslationZ",
+          "FloatingActionButton_Behavior_Layout_behavior_autoHide",
+          "FloatingActionButton_useCompatPadding",
+          "NavigationView_android_maxWidth",
+          "CollapsingToolbarLayout_title",
+          "CollapsingToolbarLayout_Layout",
+          "SnackbarLayout_maxActionInlineWidth",
+          "ForegroundLinearLayout_android_foregroundGravity",
+          "AppBarLayout_android_touchscreenBlocksFocus",
+          "ScrollingViewBehavior_Layout_behavior_overlapTop",
+          "BottomSheetBehavior_Layout_behavior_skipCollapsed",
+          "CollapsingToolbarLayout_expandedTitleMarginTop",
+          "BottomNavigationView_itemBackground",
+          "FloatingActionButton_rippleColor",
+          "NavigationView_android_background",
+          "SnackbarLayout_elevation",
+          "TextInputLayout_android_textColorHint",
+          "NavigationView_itemTextColor",
+          "BottomSheetBehavior_Layout_behavior_hideable",
+          "AppBarLayout_Layout_layout_scrollInterpolator",
+          "FloatingActionButton_backgroundTint",
+          "AppBarLayout_Layout_layout_scrollFlags",
+          "CollapsingToolbarLayout_Layout_layout_collapseMode",
+          "TabLayout_tabPadding",
+          "FloatingActionButton_backgroundTintMode",
+          "CoordinatorLayout_Layout_layout_behavior",
+          "CoordinatorLayout_Layout_android_layout_gravity",
+          "AppBarLayout_elevation",
+          "ForegroundLinearLayout_foregroundInsidePadding",
+          "TabItem",
+          "AppBarLayout_expanded",
+          "FloatingActionButton",
+          "TextInputLayout_passwordToggleTintMode",
+          "SnackbarLayout_android_maxWidth",
+          "TextInputLayout_passwordToggleEnabled",
+          "CollapsingToolbarLayout_expandedTitleMargin",
+          "NavigationView_elevation",
+          "FloatingActionButton_borderWidth",
+          "CoordinatorLayout_Layout_layout_keyline",
+          "SnackbarLayout",
+          "CollapsingToolbarLayout_toolbarId",
+          "CoordinatorLayout_keylines",
+          "CollapsingToolbarLayout_scrimAnimationDuration",
+          "TextInputLayout_counterMaxLength",
+          "CoordinatorLayout_Layout_layout_dodgeInsetEdges",
+          "AppBarLayout_Layout",
+          "CollapsingToolbarLayout_statusBarScrim",
+          "CollapsingToolbarLayout_expandedTitleMarginStart"
+        ]
+      },
+      "android/support/text/emoji/MetadataListReader": {
+        "androidx/text/emoji/MetadataListReader": [
+          "META_TABLE_NAME",
+          "EMJI_TAG_DEPRECATED",
+          "EMJI_TAG"
+        ]
+      },
+      "android/support/v4/widget/DrawerLayout": {
+        "androidx/widget/DrawerLayout": [
+          "TAG",
+          "DRAWER_ELEVATION",
+          "SET_DRAWER_SHADOW_FROM_ELEVATION",
+          "STATE_DRAGGING",
+          "MIN_FLING_VELOCITY",
+          "TOUCH_SLOP_SENSITIVITY",
+          "LOCK_MODE_UNDEFINED",
+          "MIN_DRAWER_MARGIN",
+          "STATE_IDLE",
+          "THEME_ATTRS",
+          "LOCK_MODE_LOCKED_OPEN",
+          "ALLOW_EDGE_LOCK",
+          "CAN_HIDE_DESCENDANTS",
+          "CHILDREN_DISALLOW_INTERCEPT",
+          "PEEK_DELAY",
+          "LOCK_MODE_UNLOCKED",
+          "DEFAULT_SCRIM_COLOR",
+          "STATE_SETTLING",
+          "LOCK_MODE_LOCKED_CLOSED",
+          "LAYOUT_ATTRS"
+        ]
+      },
+      "android/support/v4/content/ModernAsyncTask": {
+        "androidx/content/ModernAsyncTask": [
+          "MESSAGE_POST_RESULT",
+          "MESSAGE_POST_PROGRESS",
+          "sDefaultExecutor",
+          "KEEP_ALIVE",
+          "sThreadFactory",
+          "sPoolWorkQueue",
+          "THREAD_POOL_EXECUTOR",
+          "CORE_POOL_SIZE",
+          "MAXIMUM_POOL_SIZE",
+          "sHandler",
+          "LOG_TAG"
+        ]
+      },
+      "android/support/v7/media/MediaControlIntent": {
+        "androidx/media/MediaControlIntent": [
+          "EXTRA_SESSION_STATUS_UPDATE_RECEIVER",
+          "CATEGORY_REMOTE_PLAYBACK",
+          "ACTION_START_SESSION",
+          "ACTION_PLAY",
+          "ACTION_SEEK",
+          "ERROR_UNSUPPORTED_OPERATION",
+          "ERROR_INVALID_ITEM_ID",
+          "ACTION_ENQUEUE",
+          "ACTION_SEND_MESSAGE",
+          "EXTRA_ITEM_CONTENT_POSITION",
+          "ERROR_UNKNOWN",
+          "ACTION_STOP",
+          "CATEGORY_LIVE_VIDEO",
+          "EXTRA_ITEM_STATUS_UPDATE_RECEIVER",
+          "EXTRA_ITEM_METADATA",
+          "EXTRA_SESSION_ID",
+          "EXTRA_MESSAGE",
+          "EXTRA_ITEM_HTTP_HEADERS",
+          "CATEGORY_LIVE_AUDIO",
+          "ACTION_END_SESSION",
+          "EXTRA_MESSAGE_RECEIVER",
+          "ACTION_GET_SESSION_STATUS",
+          "ACTION_REMOVE",
+          "EXTRA_ITEM_STATUS",
+          "EXTRA_ERROR_CODE",
+          "ACTION_GET_STATUS",
+          "ERROR_INVALID_SESSION_ID",
+          "EXTRA_SESSION_STATUS",
+          "EXTRA_ITEM_ID",
+          "ACTION_RESUME",
+          "ACTION_PAUSE"
+        ]
+      },
+      "android/support/design/widget/CoordinatorLayout$LayoutParams": {
+        "androidx/design/widget/CoordinatorLayout$LayoutParams": [
+          "keyline",
+          "topMargin",
+          "leftMargin",
+          "anchorGravity",
+          "bottomMargin",
+          "rightMargin",
+          "height",
+          "gravity",
+          "dodgeInsetEdges",
+          "insetEdge"
+        ]
+      },
+      "android/support/design/internal/NavigationMenuPresenter$NormalViewHolder": {
+        "androidx/design/internal/NavigationMenuPresenter$NormalViewHolder": [
+          "itemView"
+        ]
+      },
+      "android/support/v7/recyclerview/R$styleable": {
+        "androidx/recyclerview/R$styleable": [
+          "RecyclerView_fastScrollHorizontalThumbDrawable",
+          "RecyclerView_fastScrollVerticalTrackDrawable",
+          "RecyclerView_android_descendantFocusability",
+          "RecyclerView_spanCount",
+          "RecyclerView_stackFromEnd",
+          "RecyclerView_reverseLayout",
+          "RecyclerView_fastScrollVerticalThumbDrawable",
+          "RecyclerView_layoutManager",
+          "RecyclerView_android_orientation",
+          "RecyclerView",
+          "RecyclerView_fastScrollEnabled",
+          "RecyclerView_fastScrollHorizontalTrackDrawable"
+        ]
+      },
+      "android/support/v4/app/ActionBarDrawerToggle": {
+        "androidx/app/ActionBarDrawerToggle": [
+          "TAG",
+          "ID_HOME",
+          "THEME_ATTRS",
+          "TOGGLE_DRAWABLE_OFFSET"
+        ]
+      },
+      "android/support/v7/widget/GridLayout$Axis": {
+        "androidx/widget/GridLayout$Axis": [
+          "backwardLinks",
+          "orderPreserved",
+          "trailingMargins",
+          "leadingMargins",
+          "locationsValid",
+          "groupBounds",
+          "hasWeights",
+          "groupBoundsValid",
+          "PENDING",
+          "arcsValid",
+          "trailingMarginsValid",
+          "arcs",
+          "locations",
+          "backwardLinksValid",
+          "leadingMarginsValid",
+          "maxIndex",
+          "horizontal",
+          "forwardLinksValid",
+          "definedCount",
+          "NEW",
+          "deltas",
+          "parentMax",
+          "parentMin",
+          "COMPLETE",
+          "hasWeightsValid",
+          "forwardLinks"
+        ]
+      },
+      "android/support/v4/app/BundleCompat$BundleCompatBaseImpl": {
+        "androidx/app/BundleCompat$BundleCompatBaseImpl": [
+          "sGetIBinderMethod",
+          "sGetIBinderMethodFetched",
+          "sPutIBinderMethodFetched",
+          "TAG",
+          "sPutIBinderMethod"
+        ]
+      },
+      "android/support/v7/app/AppCompatViewInflater": {
+        "androidx/app/AppCompatViewInflater": [
+          "sOnClickAttrs",
+          "sConstructorMap",
+          "sClassPrefixList",
+          "sConstructorSignature",
+          "LOG_TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/SearchBar": {
+        "androidx/leanback/widget/SearchBar": [
+          "FULL_RIGHT_VOLUME",
+          "DEBUG",
+          "DEFAULT_RATE",
+          "FULL_LEFT_VOLUME",
+          "DO_NOT_LOOP",
+          "DEFAULT_PRIORITY",
+          "TAG"
+        ]
+      },
+      "android/support/v7/appcompat/R$drawable": {
+        "androidx/appcompat/R$drawable": [
+          "abc_ic_ab_back_material",
+          "abc_text_select_handle_middle_mtrl_dark",
+          "abc_text_select_handle_left_mtrl_light",
+          "abc_textfield_activated_mtrl_alpha",
+          "abc_text_select_handle_left_mtrl_dark",
+          "abc_text_cursor_material",
+          "abc_text_select_handle_right_mtrl_light",
+          "abc_ratingbar_material",
+          "abc_ic_menu_share_mtrl_alpha",
+          "abc_ratingbar_small_material",
+          "abc_ic_menu_paste_mtrl_am_alpha",
+          "abc_textfield_search_default_mtrl_alpha",
+          "abc_menu_hardkey_panel_mtrl_mult",
+          "abc_text_select_handle_right_mtrl_dark",
+          "abc_dialog_material_background",
+          "abc_ratingbar_indicator_material",
+          "abc_btn_colored_material",
+          "abc_edit_text_material",
+          "abc_btn_borderless_material",
+          "abc_btn_check_material",
+          "abc_ab_share_pack_mtrl_alpha",
+          "abc_tab_indicator_material",
+          "abc_spinner_textfield_background_material",
+          "abc_ic_commit_search_api_mtrl_alpha",
+          "abc_textfield_default_mtrl_alpha",
+          "abc_switch_track_mtrl_alpha",
+          "abc_seekbar_thumb_material",
+          "abc_list_divider_mtrl_alpha",
+          "abc_spinner_mtrl_am_alpha",
+          "abc_btn_radio_material",
+          "abc_cab_background_top_material",
+          "abc_cab_background_top_mtrl_alpha",
+          "abc_text_select_handle_middle_mtrl_light",
+          "abc_vector_test",
+          "abc_btn_default_mtrl_shape",
+          "abc_switch_thumb_material",
+          "abc_seekbar_track_material",
+          "abc_popup_background_mtrl_mult",
+          "abc_seekbar_tick_mark_material",
+          "abc_ic_menu_copy_mtrl_am_alpha",
+          "abc_ic_menu_selectall_mtrl_alpha",
+          "abc_textfield_search_activated_mtrl_alpha",
+          "abc_cab_background_internal_bg",
+          "abc_ic_menu_cut_mtrl_alpha",
+          "abc_textfield_search_material"
+        ]
+      },
+      "android/support/v17/leanback/widget/GuidedActionsStylist": {
+        "androidx/leanback/widget/GuidedActionsStylist": [
+          "sGuidedActionItemAlignFacet",
+          "TAG",
+          "VIEW_TYPE_DEFAULT",
+          "VIEW_TYPE_DATE_PICKER"
+        ]
+      },
+      "android/support/v17/leanback/R$dimen": {
+        "androidx/leanback/R$dimen": [
+          "lb_details_v2_align_pos_for_description",
+          "lb_details_overview_image_margin_vertical",
+          "lb_search_browse_rows_align_top",
+          "lb_material_shadow_normal_z",
+          "lb_details_v2_left",
+          "lb_details_v2_description_margin_top",
+          "lb_playback_controls_child_margin_bigger",
+          "lb_details_v2_actions_height",
+          "lb_playback_transport_thumbs_height",
+          "lb_details_rows_align_top",
+          "lb_control_icon_width",
+          "lb_page_indicator_dot_radius",
+          "lb_playback_controls_z",
+          "lb_error_under_image_baseline_margin",
+          "lb_browse_rows_margin_start",
+          "lb_playback_transport_thumbs_margin",
+          "lb_playback_transport_hero_thumbs_width",
+          "lb_details_description_under_subtitle_baseline_margin",
+          "lb_rounded_rect_corner_radius",
+          "lb_search_orb_unfocused_z",
+          "lb_playback_transport_progressbar_active_bar_height",
+          "picker_item_height",
+          "lb_page_indicator_arrow_shadow_offset",
+          "lb_page_indicator_arrow_gap",
+          "lb_details_description_title_baseline",
+          "lb_details_v2_blank_height",
+          "lb_search_bar_height",
+          "lb_playback_controls_child_margin_default",
+          "lb_details_v2_logo_margin_start",
+          "lb_browse_selected_row_top_padding",
+          "lb_details_cover_drawable_parallax_movement",
+          "lb_playback_transport_hero_thumbs_height",
+          "lb_details_overview_height_small",
+          "lb_material_shadow_focused_z",
+          "lb_playback_transport_thumbs_width",
+          "lb_browse_rows_margin_top",
+          "lb_action_padding_horizontal",
+          "lb_page_indicator_arrow_radius",
+          "lb_details_description_body_line_spacing",
+          "lb_browse_expanded_selected_row_top_padding",
+          "lb_browse_header_select_scale",
+          "lb_details_v2_align_pos_for_actions",
+          "lb_action_with_icon_padding_start",
+          "lb_page_indicator_arrow_shadow_radius",
+          "lb_playback_transport_progressbar_bar_height",
+          "lb_playback_controls_child_margin_biggest",
+          "lb_playback_controls_padding_bottom",
+          "lb_browse_expanded_row_no_hovercard_bottom_padding",
+          "lb_browse_header_select_duration",
+          "lb_playback_other_rows_center_to_bottom",
+          "lb_details_overview_image_margin_horizontal",
+          "lb_search_orb_focused_z",
+          "lb_error_under_message_baseline_margin",
+          "lb_playback_major_fade_translate_y",
+          "lb_page_indicator_dot_gap",
+          "lb_details_overview_height_large",
+          "lb_details_overview_actions_fade_size",
+          "lb_action_with_icon_padding_end",
+          "lb_details_description_title_line_spacing",
+          "lb_playback_minor_fade_translate_y",
+          "lb_playback_transport_progressbar_active_radius",
+          "lb_details_description_under_title_baseline_margin"
+        ]
+      },
+      "android/support/v7/appcompat/R$layout": {
+        "androidx/appcompat/R$layout": [
+          "abc_screen_toolbar",
+          "abc_screen_simple",
+          "abc_action_mode_close_item_material",
+          "abc_dialog_title_material",
+          "abc_list_menu_item_checkbox",
+          "abc_activity_chooser_view",
+          "abc_search_dropdown_item_icons_2line",
+          "support_simple_spinner_dropdown_item",
+          "abc_list_menu_item_radio",
+          "abc_popup_menu_header_item_layout",
+          "abc_list_menu_item_layout",
+          "tooltip",
+          "abc_action_menu_layout",
+          "abc_list_menu_item_icon",
+          "abc_action_menu_item_layout",
+          "abc_action_bar_title_item",
+          "abc_popup_menu_item_layout",
+          "abc_activity_chooser_view_list_item",
+          "abc_search_view",
+          "abc_expanded_menu_layout",
+          "abc_screen_simple_overlay_action_mode"
+        ]
+      },
+      "android/support/v7/appcompat/R$id": {
+        "androidx/appcompat/R$id": [
+          "submit_area",
+          "split_action_bar",
+          "scrollIndicatorUp",
+          "search_button",
+          "contentPanel",
+          "title",
+          "action_mode_close_button",
+          "custom",
+          "search_edit_frame",
+          "decor_content_parent",
+          "action_bar_title",
+          "submenuarrow",
+          "search_voice_btn",
+          "title_template",
+          "action_bar",
+          "action_bar_subtitle",
+          "alertTitle",
+          "default_activity_button",
+          "search_close_btn",
+          "textSpacerNoTitle",
+          "action_mode_bar_stub",
+          "titleDividerNoCustom",
+          "action_bar_container",
+          "parentPanel",
+          "shortcut",
+          "icon",
+          "search_src_text",
+          "activity_chooser_view_content",
+          "search_plate",
+          "customPanel",
+          "edit_query",
+          "action_menu_presenter",
+          "spacer",
+          "scrollIndicatorDown",
+          "scrollView",
+          "message",
+          "buttonPanel",
+          "topPanel",
+          "list_item",
+          "action_context_bar",
+          "search_go_btn",
+          "textSpacerNoButtons",
+          "search_mag_icon",
+          "action_bar_activity_content",
+          "expand_activities_button",
+          "image"
+        ]
+      },
+      "android/support/v7/widget/Toolbar$LayoutParams": {
+        "androidx/widget/Toolbar$LayoutParams": [
+          "gravity",
+          "EXPANDED",
+          "width",
+          "SYSTEM",
+          "leftMargin",
+          "CUSTOM",
+          "bottomMargin",
+          "rightMargin",
+          "topMargin",
+          "height"
+        ]
+      },
+      "android/support/v4/app/NotificationCompatJellybean": {
+        "androidx/app/NotificationCompatJellybean": [
+          "KEY_LABEL",
+          "sActionIntentField",
+          "KEY_ACTION_INTENT",
+          "sActionClass",
+          "sExtrasLock",
+          "KEY_REMOTE_INPUTS",
+          "KEY_ALLOWED_DATA_TYPES",
+          "sActionsLock",
+          "KEY_CHOICES",
+          "sExtrasField",
+          "EXTRA_DATA_ONLY_REMOTE_INPUTS",
+          "sActionTitleField",
+          "sActionIconField",
+          "KEY_EXTRAS",
+          "KEY_TITLE",
+          "sActionsAccessFailed",
+          "TAG",
+          "KEY_ICON",
+          "EXTRA_ALLOW_GENERATED_REPLIES",
+          "KEY_ALLOW_FREE_FORM_INPUT",
+          "KEY_DATA_ONLY_REMOTE_INPUTS",
+          "sExtrasFieldAccessFailed",
+          "KEY_RESULT_KEY",
+          "sActionsField"
+        ]
+      },
+      "android/support/v7/widget/GridLayout": {
+        "androidx/widget/GridLayout": [
+          "RIGHT",
+          "DEFAULT_COUNT",
+          "DEFAULT_ORIENTATION",
+          "ROW_ORDER_PRESERVED",
+          "TOP",
+          "LEADING",
+          "START",
+          "BASELINE",
+          "UNDEFINED",
+          "ALIGN_BOUNDS",
+          "CENTER",
+          "MAX_SIZE",
+          "ALIGNMENT_MODE",
+          "COLUMN_COUNT",
+          "ROW_COUNT",
+          "CAN_STRETCH",
+          "USE_DEFAULT_MARGINS",
+          "FILL",
+          "HORIZONTAL",
+          "DEFAULT_CONTAINER_MARGIN",
+          "LOG_PRINTER",
+          "ALIGN_MARGINS",
+          "VERTICAL",
+          "DEFAULT_ALIGNMENT_MODE",
+          "COLUMN_ORDER_PRESERVED",
+          "ORIENTATION",
+          "LEFT",
+          "TRAILING",
+          "DEFAULT_ORDER_PRESERVED",
+          "BOTTOM",
+          "END",
+          "DEFAULT_USE_DEFAULT_MARGINS",
+          "INFLEXIBLE",
+          "UNINITIALIZED_HASH",
+          "UNDEFINED_ALIGNMENT",
+          "NO_PRINTER"
+        ]
+      },
+      "android/support/wear/widget/BoxInsetLayout$LayoutParams": {
+        "androidx/wear/widget/BoxInsetLayout$LayoutParams": [
+          "BOX_ALL",
+          "BOX_LEFT",
+          "BOX_TOP",
+          "gravity",
+          "height",
+          "topMargin",
+          "rightMargin",
+          "bottomMargin",
+          "boxedEdges",
+          "BOX_RIGHT",
+          "width",
+          "leftMargin",
+          "BOX_NONE",
+          "BOX_BOTTOM"
+        ]
+      },
+      "android/support/design/widget/TabLayout": {
+        "androidx/design/widget/TabLayout": [
+          "GRAVITY_FILL",
+          "TAB_MIN_WIDTH_MARGIN",
+          "DEFAULT_HEIGHT_WITH_TEXT_ICON",
+          "ANIMATION_DURATION",
+          "INVALID_WIDTH",
+          "FIXED_WRAP_GUTTER_MIN",
+          "MOTION_NON_ADJACENT_OFFSET",
+          "DEFAULT_HEIGHT",
+          "MODE_FIXED",
+          "SELECTED_STATE_SET",
+          "MODE_SCROLLABLE",
+          "EMPTY_STATE_SET",
+          "sTabPool",
+          "GRAVITY_CENTER",
+          "DEFAULT_GAP_TEXT_ICON"
+        ]
+      },
+      "android/support/v4/view/MotionEventCompat": {
+        "androidx/view/MotionEventCompat": [
+          "ACTION_SCROLL",
+          "AXIS_RUDDER",
+          "AXIS_BRAKE",
+          "AXIS_TOOL_MINOR",
+          "AXIS_GENERIC_3",
+          "AXIS_GENERIC_4",
+          "AXIS_GENERIC_5",
+          "AXIS_GENERIC_6",
+          "AXIS_GENERIC_7",
+          "AXIS_GENERIC_8",
+          "AXIS_GENERIC_9",
+          "AXIS_GENERIC_1",
+          "AXIS_GENERIC_2",
+          "AXIS_DISTANCE",
+          "AXIS_ORIENTATION",
+          "AXIS_LTRIGGER",
+          "AXIS_HSCROLL",
+          "ACTION_POINTER_DOWN",
+          "AXIS_TILT",
+          "AXIS_WHEEL",
+          "AXIS_Y",
+          "AXIS_Z",
+          "AXIS_X",
+          "AXIS_SCROLL",
+          "AXIS_TOUCH_MAJOR",
+          "ACTION_HOVER_ENTER",
+          "AXIS_GAS",
+          "ACTION_HOVER_MOVE",
+          "ACTION_HOVER_EXIT",
+          "AXIS_THROTTLE",
+          "AXIS_HAT_X",
+          "AXIS_HAT_Y",
+          "AXIS_SIZE",
+          "ACTION_POINTER_INDEX_SHIFT",
+          "AXIS_RTRIGGER",
+          "AXIS_RELATIVE_X",
+          "AXIS_RELATIVE_Y",
+          "AXIS_RY",
+          "AXIS_RZ",
+          "AXIS_RX",
+          "AXIS_TOUCH_MINOR",
+          "ACTION_POINTER_INDEX_MASK",
+          "BUTTON_PRIMARY",
+          "AXIS_PRESSURE",
+          "AXIS_TOOL_MAJOR",
+          "AXIS_GENERIC_13",
+          "AXIS_GENERIC_12",
+          "AXIS_GENERIC_11",
+          "AXIS_GENERIC_10",
+          "AXIS_GENERIC_16",
+          "AXIS_GENERIC_15",
+          "AXIS_GENERIC_14",
+          "ACTION_POINTER_UP",
+          "ACTION_MASK",
+          "AXIS_VSCROLL"
+        ]
+      },
+      "android/support/v4/view/PagerTitleStrip": {
+        "androidx/widget/PagerTitleStrip": [
+          "ATTRS",
+          "SIDE_ALPHA",
+          "TEXT_ATTRS",
+          "TEXT_SPACING"
+        ]
+      },
+      "android/support/v7/preference/BuildConfig": {
+        "androidx/preference/BuildConfig": [
+          "APPLICATION_ID",
+          "FLAVOR",
+          "VERSION_CODE",
+          "DEBUG",
+          "VERSION_NAME",
+          "BUILD_TYPE"
+        ]
+      },
+      "android/support/v4/graphics/TypefaceCompatApi26Impl": {
+        "androidx/graphics/TypefaceCompatApi26Impl": [
+          "sAddFontFromAssetManager",
+          "sFreeze",
+          "TAG",
+          "RESOLVE_BY_FONT_TABLE",
+          "sFontFamily",
+          "ADD_FONT_FROM_ASSET_MANAGER_METHOD",
+          "sCreateFromFamiliesWithDefault",
+          "FONT_FAMILY_CLASS",
+          "ABORT_CREATION_METHOD",
+          "sFontFamilyCtor",
+          "CREATE_FROM_FAMILIES_WITH_DEFAULT_METHOD",
+          "sAbortCreation",
+          "ADD_FONT_FROM_BUFFER_METHOD",
+          "sAddFontFromBuffer",
+          "FREEZE_METHOD"
+        ]
+      },
+      "android/support/mediacompat/BuildConfig": {
+        "androidx/mediacompat/BuildConfig": [
+          "DEBUG",
+          "APPLICATION_ID",
+          "FLAVOR",
+          "VERSION_CODE",
+          "BUILD_TYPE",
+          "VERSION_NAME"
+        ]
+      },
+      "android/support/v7/app/AppCompatDelegate": {
+        "androidx/app/AppCompatDelegate": [
+          "sCompatVectorFromResourcesEnabled",
+          "MODE_NIGHT_FOLLOW_SYSTEM",
+          "MODE_NIGHT_YES",
+          "TAG",
+          "FEATURE_SUPPORT_ACTION_BAR_OVERLAY",
+          "sDefaultNightMode",
+          "MODE_NIGHT_NO",
+          "MODE_NIGHT_AUTO",
+          "FEATURE_ACTION_MODE_OVERLAY",
+          "FEATURE_SUPPORT_ACTION_BAR",
+          "MODE_NIGHT_UNSPECIFIED"
+        ]
+      },
+      "android/support/v7/cardview/BuildConfig": {
+        "androidx/cardview/BuildConfig": [
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "VERSION_CODE",
+          "DEBUG",
+          "APPLICATION_ID",
+          "FLAVOR"
+        ]
+      },
+      "android/support/v7/view/menu/ListMenuItemView": {
+        "androidx/view/menu/ListMenuItemView": [
+          "TAG"
+        ]
+      },
+      "android/support/media/instantvideo/preload/InstantVideoPreloadManager": {
+        "androidx/media/instantvideo/preload/InstantVideoPreloadManager": [
+          "DEBUG",
+          "sInstance",
+          "TAG",
+          "DEFAULT_MAX_VIDEO_COUNT"
+        ]
+      },
+      "android/support/graphics/drawable/AndroidResources": {
+        "androidx/graphics/drawable/AndroidResources": [
+          "STYLEABLE_ANIMATED_VECTOR_DRAWABLE_TARGET",
+          "STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH_NAME",
+          "STYLEABLE_VECTOR_DRAWABLE_GROUP_NAME",
+          "STYLEABLE_ANIMATED_VECTOR_DRAWABLE_DRAWABLE",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_END",
+          "STYLEABLE_PATH_INTERPOLATOR",
+          "STYLEABLE_PROPERTY_VALUES_HOLDER_PROPERTY_NAME",
+          "STYLEABLE_KEYFRAME_INTERPOLATOR",
+          "STYLEABLE_KEYFRAME_FRACTION",
+          "STYLEABLE_ANIMATOR_REPEAT_MODE",
+          "STYLEABLE_ANIMATED_VECTOR_DRAWABLE_TARGET_NAME",
+          "STYLEABLE_VECTOR_DRAWABLE_VIEWPORT_WIDTH",
+          "FAST_OUT_LINEAR_IN",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_LINE_JOIN",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_PATH_DATA",
+          "STYLEABLE_VECTOR_DRAWABLE_TINT_MODE",
+          "STYLEABLE_VECTOR_DRAWABLE_TINT",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_NAME",
+          "STYLEABLE_KEYFRAME_VALUE_TYPE",
+          "STYLEABLE_PATH_INTERPOLATOR_PATH_DATA",
+          "STYLEABLE_ANIMATOR_START_OFFSET",
+          "STYLEABLE_VECTOR_DRAWABLE_GROUP",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_COLOR",
+          "STYLEABLE_ANIMATED_VECTOR_DRAWABLE_TARGET_ANIMATION",
+          "STYLEABLE_VECTOR_DRAWABLE_GROUP_ROTATION",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_WIDTH",
+          "STYLEABLE_PROPERTY_ANIMATOR_PROPERTY_Y_NAME",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_ALPHA",
+          "STYLEABLE_ANIMATOR_INTERPOLATOR",
+          "STYLEABLE_VECTOR_DRAWABLE_WIDTH",
+          "STYLEABLE_ANIMATOR_SET_ORDERING",
+          "STYLEABLE_ANIMATED_VECTOR_DRAWABLE",
+          "STYLEABLE_ANIMATOR_DURATION",
+          "STYLEABLE_VECTOR_DRAWABLE_ALPHA",
+          "STYLEABLE_VECTOR_DRAWABLE_HEIGHT",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_FILL_ALPHA",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_MITER_LIMIT",
+          "STYLEABLE_PATH_INTERPOLATOR_CONTROL_X_2",
+          "STYLEABLE_PATH_INTERPOLATOR_CONTROL_X_1",
+          "LINEAR_OUT_SLOW_IN",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_FILL_COLOR",
+          "STYLEABLE_PROPERTY_VALUES_HOLDER_VALUE_TO",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH",
+          "STYLEABLE_ANIMATOR_REMOVE_BEFORE_M_RELEASE",
+          "STYLEABLE_PATH_INTERPOLATOR_CONTROL_Y_1",
+          "STYLEABLE_PATH_INTERPOLATOR_CONTROL_Y_2",
+          "FAST_OUT_SLOW_IN",
+          "STYLEABLE_ANIMATOR_VALUE_FROM",
+          "STYLEABLE_ANIMATOR_REPEAT_COUNT",
+          "STYLEABLE_ANIMATOR_SET",
+          "STYLEABLE_PROPERTY_ANIMATOR_PATH_DATA",
+          "STYLEABLE_ANIMATOR_VALUE_TO",
+          "STYLEABLE_VECTOR_DRAWABLE_VIEWPORT_HEIGHT",
+          "STYLEABLE_KEYFRAME",
+          "STYLEABLE_VECTOR_DRAWABLE_TYPE_ARRAY",
+          "STYLEABLE_ANIMATOR_VALUE_TYPE",
+          "STYLEABLE_PROPERTY_VALUES_HOLDER",
+          "STYLEABLE_VECTOR_DRAWABLE_GROUP_PIVOT_X",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_OFFSET",
+          "STYLEABLE_VECTOR_DRAWABLE_GROUP_PIVOT_Y",
+          "STYLEABLE_VECTOR_DRAWABLE_GROUP_TRANSLATE_X",
+          "STYLEABLE_VECTOR_DRAWABLE_GROUP_TRANSLATE_Y",
+          "STYLEABLE_VECTOR_DRAWABLE_AUTO_MIRRORED",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_START",
+          "STYLEABLE_KEYFRAME_VALUE",
+          "STYLEABLE_PROPERTY_VALUES_HOLDER_VALUE_TYPE",
+          "STYLEABLE_PROPERTY_ANIMATOR_PROPERTY_NAME",
+          "STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH",
+          "STYLEABLE_VECTOR_DRAWABLE_NAME",
+          "STYLEABLE_PROPERTY_VALUES_HOLDER_VALUE_FROM",
+          "STYLEABLE_VECTOR_DRAWABLE_GROUP_SCALE_Y",
+          "STYLEABLE_VECTOR_DRAWABLE_GROUP_SCALE_X",
+          "STYLEABLE_ANIMATOR",
+          "STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH_PATH_DATA",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_LINE_CAP",
+          "STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_FILLTYPE",
+          "STYLEABLE_PROPERTY_ANIMATOR",
+          "STYLEABLE_PROPERTY_ANIMATOR_PROPERTY_X_NAME"
+        ]
+      },
+      "android/support/v7/app/ActionBar$LayoutParams": {
+        "androidx/app/ActionBar$LayoutParams": [
+          "gravity"
+        ]
+      },
+      "android/support/v7/widget/LinearLayoutCompat": {
+        "androidx/widget/LinearLayoutCompat": [
+          "VERTICAL_GRAVITY_COUNT",
+          "SHOW_DIVIDER_BEGINNING",
+          "HORIZONTAL",
+          "SHOW_DIVIDER_MIDDLE",
+          "SHOW_DIVIDER_NONE",
+          "INDEX_CENTER_VERTICAL",
+          "INDEX_TOP",
+          "INDEX_FILL",
+          "VERTICAL",
+          "INDEX_BOTTOM",
+          "SHOW_DIVIDER_END"
+        ]
+      },
+      "android/support/percent/PercentLayoutHelper$PercentMarginLayoutParams": {
+        "androidx/PercentLayoutHelper$PercentMarginLayoutParams": [
+          "topMargin",
+          "leftMargin",
+          "rightMargin",
+          "height",
+          "width",
+          "bottomMargin"
+        ]
+      },
+      "android/support/v17/leanback/widget/StreamingTextView": {
+        "androidx/leanback/widget/StreamingTextView": [
+          "STREAM_POSITION_PROPERTY",
+          "DOTS_FOR_STABLE",
+          "ANIMATE_DOTS_FOR_PENDING",
+          "STREAM_UPDATE_DELAY_MILLIS",
+          "DEBUG",
+          "TEXT_DOT_SCALE",
+          "DOTS_FOR_PENDING",
+          "SPLIT_PATTERN",
+          "TAG"
+        ]
+      },
+      "android/support/v7/view/SupportMenuInflater$MenuState": {
+        "androidx/view/SupportMenuInflater$MenuState": [
+          "itemListenerMethodName",
+          "itemActionViewClassName",
+          "itemContentDescription",
+          "itemEnabled",
+          "defaultItemChecked",
+          "itemCategoryOrder",
+          "itemTitle",
+          "groupCategory",
+          "itemIconTintMode",
+          "itemAdded",
+          "groupCheckable",
+          "itemNumericShortcut",
+          "groupVisible",
+          "itemNumericModifiers",
+          "itemTitleCondensed",
+          "defaultItemVisible",
+          "itemAlphabeticShortcut",
+          "itemShowAsAction",
+          "menu",
+          "defaultItemCheckable",
+          "itemActionProvider",
+          "itemCheckable",
+          "itemActionViewLayout",
+          "itemIconResId",
+          "itemVisible",
+          "itemTooltipText",
+          "defaultItemCategory",
+          "defaultGroupId",
+          "groupOrder",
+          "defaultItemId",
+          "itemActionProviderClassName",
+          "itemId",
+          "itemIconTintList",
+          "itemChecked",
+          "groupId",
+          "defaultItemEnabled",
+          "defaultItemOrder",
+          "itemAlphabeticModifiers",
+          "groupEnabled"
+        ]
+      },
+      "android/support/v4/view/InputDeviceCompat": {
+        "androidx/view/InputDeviceCompat": [
+          "SOURCE_CLASS_JOYSTICK",
+          "SOURCE_KEYBOARD",
+          "SOURCE_CLASS_MASK",
+          "SOURCE_CLASS_POINTER",
+          "SOURCE_ROTARY_ENCODER",
+          "SOURCE_TOUCHSCREEN",
+          "SOURCE_TOUCHPAD",
+          "SOURCE_STYLUS",
+          "SOURCE_CLASS_POSITION",
+          "SOURCE_UNKNOWN",
+          "SOURCE_DPAD",
+          "SOURCE_CLASS_BUTTON",
+          "SOURCE_JOYSTICK",
+          "SOURCE_ANY",
+          "SOURCE_TOUCH_NAVIGATION",
+          "SOURCE_TRACKBALL",
+          "SOURCE_MOUSE",
+          "SOURCE_HDMI",
+          "SOURCE_GAMEPAD",
+          "SOURCE_CLASS_TRACKBALL",
+          "SOURCE_CLASS_NONE"
+        ]
+      },
+      "android/support/v17/leanback/R$styleable": {
+        "androidx/leanback/R$styleable": [
+          "lbImageCardView_lbImageCardViewType",
+          "LeanbackTheme_browseRowsMarginTop",
+          "lbPlaybackControlsActionIcons_thumb_down_outline",
+          "lbSlide_android_interpolator",
+          "lbBaseCardView_cardType",
+          "lbResizingTextView_resizedPaddingAdjustmentBottom",
+          "lbBaseGridView_android_horizontalSpacing",
+          "lbResizingTextView_maintainLineSpacing",
+          "lbBaseGridView_verticalMargin",
+          "lbPlaybackControlsActionIcons_repeat_one",
+          "lbBaseGridView_horizontalMargin",
+          "lbHorizontalGridView_rowHeight",
+          "lbHorizontalGridView_numberOfRows",
+          "LeanbackTheme_browseRowsFadingEdgeLength",
+          "PagingIndicator_dotToDotGap",
+          "PagingIndicator_arrowColor",
+          "PagingIndicator",
+          "lbSearchOrbView_searchOrbColor",
+          "lbTimePicker_is24HourFormat",
+          "lbDatePicker",
+          "lbSearchOrbView_searchOrbBrightColor",
+          "lbDatePicker_android_maxDate",
+          "lbVerticalGridView_columnWidth",
+          "PagingIndicator_arrowRadius",
+          "lbTimePicker_useCurrentTime",
+          "LeanbackGuidedStepTheme",
+          "lbPlaybackControlsActionIcons_shuffle",
+          "lbBaseCardView_cardBackground",
+          "lbPlaybackControlsActionIcons",
+          "lbBaseCardView",
+          "lbPlaybackControlsActionIcons_play",
+          "lbSlide_lb_slideEdge",
+          "lbBaseCardView_extraVisibility",
+          "LeanbackTheme_overlayDimActiveLevel",
+          "lbResizingTextView_resizeTrigger",
+          "lbPlaybackControlsActionIcons_picture_in_picture",
+          "lbBaseGridView_android_gravity",
+          "lbBaseGridView_focusOutEnd",
+          "LeanbackTheme",
+          "lbPlaybackControlsActionIcons_thumb_up",
+          "PagingIndicator_dotBgColor",
+          "lbSearchOrbView_searchOrbIconColor",
+          "lbSearchOrbView",
+          "lbBaseGridView_focusOutFront",
+          "lbBaseCardView_infoVisibility",
+          "lbResizingTextView_resizedTextSize",
+          "lbPlaybackControlsActionIcons_skip_previous",
+          "PagingIndicator_dotToArrowGap",
+          "lbHorizontalGridView",
+          "lbDatePicker_datePickerFormat",
+          "lbVerticalGridView_numberOfColumns",
+          "lbSlide_android_duration",
+          "PagingIndicator_lbDotRadius",
+          "lbPlaybackControlsActionIcons_skip_next",
+          "lbSlide",
+          "lbSlide_android_startDelay",
+          "lbPlaybackControlsActionIcons_fast_forward",
+          "lbImageCardView",
+          "LeanbackTheme_browseRowsMarginStart",
+          "lbBaseCardView_Layout_layout_viewType",
+          "lbTimePicker",
+          "lbResizingTextView",
+          "lbImageCardView_infoAreaBackground",
+          "lbBaseCardView_Layout",
+          "lbPlaybackControlsActionIcons_repeat",
+          "lbPlaybackControlsActionIcons_rewind",
+          "lbBaseCardView_selectedAnimationDelay",
+          "lbBaseGridView_focusOutSideStart",
+          "lbBaseCardView_selectedAnimationDuration",
+          "lbBaseGridView_android_verticalSpacing",
+          "lbSearchOrbView_searchOrbIcon",
+          "lbPlaybackControlsActionIcons_pause",
+          "lbBaseGridView",
+          "PagingIndicator_arrowBgColor",
+          "lbVerticalGridView",
+          "lbDatePicker_android_minDate",
+          "lbPlaybackControlsActionIcons_thumb_up_outline",
+          "LeanbackTheme_overlayDimDimmedLevel",
+          "lbBaseGridView_focusOutSideEnd",
+          "lbPlaybackControlsActionIcons_high_quality",
+          "lbResizingTextView_resizedPaddingAdjustmentTop",
+          "lbBaseCardView_activatedAnimationDuration",
+          "lbPlaybackControlsActionIcons_closed_captioning",
+          "LeanbackTheme_overlayDimMaskColor",
+          "lbPlaybackControlsActionIcons_thumb_down",
+          "LeanbackGuidedStepTheme_guidedStepKeyline",
+          "lbBaseCardView_cardForeground"
+        ]
+      },
+      "android/support/v17/leanback/R$drawable": {
+        "androidx/leanback/R$drawable": [
+          "lb_ic_in_app_search",
+          "lb_text_dot_one",
+          "lb_ic_search_mic_out",
+          "lb_ic_search_mic",
+          "lb_background",
+          "lb_text_dot_two",
+          "lb_ic_nav_arrow",
+          "lb_ic_more"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView$ViewHolder": {
+        "androidx/widget/RecyclerView$ViewHolder": [
+          "FLAG_NOT_RECYCLABLE",
+          "FLAG_INVALID",
+          "FULLUPDATE_PAYLOADS",
+          "FLAG_RETURNED_FROM_SCRAP",
+          "PENDING_ACCESSIBILITY_STATE_NOT_SET",
+          "FLAG_REMOVED",
+          "FLAG_TMP_DETACHED",
+          "FLAG_ADAPTER_POSITION_UNKNOWN",
+          "FLAG_SET_A11Y_ITEM_DELEGATE",
+          "itemView",
+          "FLAG_APPEARED_IN_PRE_LAYOUT",
+          "FLAG_ADAPTER_FULLUPDATE",
+          "FLAG_BOUNCED_FROM_HIDDEN_LIST",
+          "FLAG_IGNORE",
+          "FLAG_BOUND",
+          "FLAG_UPDATE",
+          "FLAG_MOVED"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompat$Token": {
+        "androidx/media/session/MediaSessionCompat$Token": [
+          "CREATOR"
+        ]
+      },
+      "android/support/v17/leanback/app/BrowseFragment$ExpandPreLayout": {
+        "androidx/leanback/app/BrowseFragment$ExpandPreLayout": [
+          "STATE_SECOND_DRAW",
+          "STATE_INIT",
+          "mainFragmentAdapter",
+          "STATE_FIRST_DRAW"
+        ]
+      },
+      "android/support/v13/app/FragmentTabHost$TabInfo": {
+        "androidx/app/FragmentTabHost$TabInfo": [
+          "fragment",
+          "args",
+          "tag",
+          "clss"
+        ]
+      },
+      "android/support/media/tv/Channel": {
+        "androidx/media/tv/Channel": [
+          "IS_SEARCHABLE",
+          "IS_SYSTEM_APPROVED",
+          "INVALID_INT_VALUE",
+          "INVALID_CHANNEL_ID",
+          "PROJECTION",
+          "IS_TRANSIENT",
+          "IS_BROWSABLE",
+          "IS_LOCKED"
+        ]
+      },
+      "android/support/v4/text/BidiFormatter$DirectionalityEstimator": {
+        "androidx/text/BidiFormatter$DirectionalityEstimator": [
+          "lastChar",
+          "DIR_TYPE_CACHE_SIZE",
+          "DIR_TYPE_CACHE",
+          "charIndex",
+          "isHtml",
+          "text",
+          "length"
+        ]
+      },
+      "android/support/v7/widget/AppCompatDrawableManager": {
+        "androidx/widget/AppCompatDrawableManager": [
+          "COLOR_FILTER_CACHE",
+          "TINT_COLOR_CONTROL_NORMAL",
+          "TAG",
+          "COLORFILTER_TINT_COLOR_CONTROL_NORMAL",
+          "COLORFILTER_COLOR_CONTROL_ACTIVATED",
+          "TINT_CHECKABLE_BUTTON_LIST",
+          "INSTANCE",
+          "TINT_COLOR_CONTROL_STATE_LIST",
+          "DEFAULT_MODE",
+          "DEBUG",
+          "COLORFILTER_COLOR_BACKGROUND_MULTIPLY",
+          "PLATFORM_VD_CLAZZ",
+          "SKIP_DRAWABLE_TAG"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat": {
+        "androidx/media/tv/TvContractCompat": [
+          "PARAM_INPUT",
+          "PATH_CHANNEL",
+          "ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED",
+          "ACTION_REQUEST_CHANNEL_BROWSABLE",
+          "EXTRA_PREVIEW_PROGRAM_ID",
+          "PATH_RECORDED_PROGRAM",
+          "PATH_PASSTHROUGH",
+          "PARAM_CHANNEL",
+          "AUTHORITY",
+          "PARAM_START_TIME",
+          "PARAM_BROWSABLE_ONLY",
+          "EXTRA_DATA_TYPE",
+          "EXTRA_DEFAULT_VALUE",
+          "PARAM_END_TIME",
+          "EXTRA_WATCH_NEXT_PROGRAM_ID",
+          "PARAM_CANONICAL_GENRE",
+          "METHOD_GET_COLUMNS",
+          "PATH_PROGRAM",
+          "METHOD_ADD_COLUMN",
+          "PATH_PREVIEW_PROGRAM",
+          "PATH_WATCH_NEXT_PROGRAM",
+          "EXTRA_COLUMN_NAME",
+          "ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED",
+          "PERMISSION_READ_TV_LISTINGS",
+          "EXTRA_EXISTING_COLUMN_NAMES",
+          "ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT",
+          "EXTRA_PACKAGE_NAME",
+          "ACTION_CHANNEL_BROWSABLE_REQUESTED",
+          "EXTRA_CHANNEL_ID",
+          "ACTION_INITIALIZE_PROGRAMS"
+        ]
+      },
+      "android/support/v17/leanback/widget/GridLayoutManager$PendingMoveSmoothScroller": {
+        "androidx/leanback/widget/GridLayoutManager$PendingMoveSmoothScroller": [
+          "TARGET_UNDEFINED"
+        ]
+      },
+      "android/support/v7/media/RemoteControlClientCompat$PlaybackInfo": {
+        "androidx/media/RemoteControlClientCompat$PlaybackInfo": [
+          "volumeMax",
+          "playbackType",
+          "volume",
+          "volumeHandling",
+          "playbackStream"
+        ]
+      },
+      "android/support/v4/util/ArraySet": {
+        "androidx/util/ArraySet": [
+          "OBJECT",
+          "TAG",
+          "sTwiceBaseCacheSize",
+          "CACHE_SIZE",
+          "sBaseCacheSize",
+          "sTwiceBaseCache",
+          "BASE_SIZE",
+          "INT",
+          "sBaseCache",
+          "DEBUG"
+        ]
+      },
+      "android/support/v17/leanback/app/OnboardingFragment": {
+        "androidx/leanback/app/OnboardingFragment": [
+          "DESCRIPTION_START_DELAY_MS",
+          "TAG",
+          "HEADER_ANIMATION_DURATION_MS",
+          "HEADER_APPEAR_DELAY_MS",
+          "KEY_LOGO_ANIMATION_FINISHED",
+          "HEADER_DISAPPEAR_INTERPOLATOR",
+          "DEBUG",
+          "HEADER_APPEAR_INTERPOLATOR",
+          "KEY_ENTER_ANIMATION_FINISHED",
+          "KEY_CURRENT_PAGE_INDEX",
+          "sSlideDistance",
+          "LOGO_SPLASH_PAUSE_DURATION_MS",
+          "SLIDE_DISTANCE"
+        ]
+      },
+      "android/support/v17/leanback/R$string": {
+        "androidx/leanback/R$string": [
+          "lb_control_display_fast_forward_multiplier",
+          "lb_playback_controls_repeat_one",
+          "lb_playback_controls_thumb_up_outline",
+          "lb_playback_controls_thumb_up",
+          "lb_playback_controls_repeat_none",
+          "lb_guidedaction_finish_title",
+          "lb_control_display_rewind_multiplier",
+          "lb_playback_controls_closed_captioning_disable",
+          "lb_playback_controls_repeat_all",
+          "lb_playback_controls_pause",
+          "lb_playback_controls_thumb_down",
+          "lb_playback_controls_shuffle_enable",
+          "lb_playback_controls_rewind_multiplier",
+          "lb_guidedaction_continue_title",
+          "lb_playback_controls_shuffle_disable",
+          "lb_media_player_error",
+          "lb_playback_controls_hidden",
+          "lb_playback_controls_play",
+          "lb_guidedactions_item_unselected_description_text_alpha",
+          "lb_playback_controls_skip_next",
+          "lb_playback_controls_fast_forward",
+          "lb_playback_controls_high_quality_enable",
+          "lb_search_bar_hint_speech",
+          "lb_search_bar_hint_with_title_speech",
+          "lb_playback_controls_closed_captioning_enable",
+          "lb_playback_controls_shown",
+          "lb_guidedactions_item_disabled_description_text_alpha",
+          "lb_search_bar_hint",
+          "lb_playback_controls_fast_forward_multiplier",
+          "lb_playback_controls_picture_in_picture",
+          "lb_playback_controls_thumb_down_outline",
+          "lb_playback_controls_high_quality_disable",
+          "lb_playback_controls_rewind",
+          "lb_playback_controls_more_actions",
+          "lb_guidedactions_item_unselected_text_alpha",
+          "lb_guidedactions_item_disabled_text_alpha",
+          "lb_playback_controls_skip_previous",
+          "lb_search_bar_hint_with_title"
+        ]
+      },
+      "android/support/v7/preference/PreferenceInflater": {
+        "androidx/preference/PreferenceInflater": [
+          "EXTRA_TAG_NAME",
+          "INTENT_TAG_NAME",
+          "CONSTRUCTOR_MAP",
+          "TAG",
+          "CONSTRUCTOR_SIGNATURE"
+        ]
+      },
+      "android/support/constraint/R$styleable": {
+        "androidx/constraint/R$styleable": [
+          "ConstraintLayout_Layout_layout_constraintWidth_max",
+          "ConstraintLayout_Layout_layout_constraintWidth_min",
+          "ConstraintSet_layout_constraintDimensionRatio",
+          "ConstraintSet_android_transformPivotY",
+          "ConstraintSet_android_transformPivotX",
+          "ConstraintSet_layout_goneMarginRight",
+          "ConstraintLayout_Layout_layout_constraintGuide_percent",
+          "ConstraintLayout_Layout_layout_constraintLeft_toLeftOf",
+          "ConstraintSet_layout_goneMarginStart",
+          "ConstraintSet_android_orientation",
+          "ConstraintLayout_Layout_layout_constraintRight_toLeftOf",
+          "ConstraintSet_android_layout_marginBottom",
+          "ConstraintSet_layout_constraintBaseline_toBaselineOf",
+          "ConstraintSet_android_layout_height",
+          "ConstraintSet_layout_constraintRight_creator",
+          "ConstraintSet_layout_constraintWidth_max",
+          "ConstraintSet_layout_constraintEnd_toStartOf",
+          "ConstraintLayout_Layout_layout_constraintBottom_creator",
+          "ConstraintSet_android_visibility",
+          "ConstraintLayout_Layout_layout_constraintTop_toBottomOf",
+          "ConstraintSet_layout_constraintGuide_begin",
+          "ConstraintSet_layout_constraintWidth_min",
+          "ConstraintLayout_Layout_android_maxHeight",
+          "ConstraintSet_android_id",
+          "ConstraintSet_layout_constraintBottom_creator",
+          "ConstraintLayout_Layout_layout_optimizationLevel",
+          "ConstraintLayout_Layout_layout_constraintVertical_bias",
+          "ConstraintSet_layout_constraintHorizontal_bias",
+          "ConstraintSet_layout_constraintHeight_default",
+          "ConstraintSet",
+          "ConstraintLayout_Layout_layout_constraintBottom_toBottomOf",
+          "ConstraintLayout_Layout",
+          "ConstraintLayout_Layout_layout_constraintBaseline_creator",
+          "ConstraintLayout_Layout_layout_constraintVertical_chainStyle",
+          "ConstraintSet_android_rotationY",
+          "ConstraintSet_android_rotationX",
+          "ConstraintSet_android_alpha",
+          "ConstraintLayout_Layout_layout_constraintDimensionRatio",
+          "ConstraintLayout_Layout_android_orientation",
+          "ConstraintSet_layout_constraintLeft_creator",
+          "ConstraintSet_layout_goneMarginLeft",
+          "ConstraintSet_layout_constraintLeft_toLeftOf",
+          "ConstraintLayout_Layout_layout_constraintVertical_weight",
+          "ConstraintSet_layout_constraintStart_toStartOf",
+          "ConstraintLayout_Layout_layout_constraintHorizontal_chainStyle",
+          "ConstraintLayout_Layout_layout_constraintEnd_toEndOf",
+          "ConstraintSet_layout_editor_absoluteY",
+          "ConstraintSet_layout_editor_absoluteX",
+          "ConstraintLayout_Layout_layout_constraintEnd_toStartOf",
+          "ConstraintLayout_Layout_layout_constraintTop_toTopOf",
+          "ConstraintSet_android_layout_marginEnd",
+          "ConstraintLayout_Layout_layout_goneMarginLeft",
+          "ConstraintLayout_Layout_layout_constraintGuide_begin",
+          "ConstraintSet_layout_constraintGuide_end",
+          "ConstraintSet_android_translationZ",
+          "ConstraintSet_android_translationY",
+          "ConstraintSet_android_translationX",
+          "ConstraintSet_layout_constraintStart_toEndOf",
+          "ConstraintSet_layout_constraintRight_toRightOf",
+          "ConstraintSet_layout_constraintHeight_max",
+          "ConstraintSet_android_layout_marginTop",
+          "ConstraintSet_layout_constraintHeight_min",
+          "ConstraintSet_layout_constraintTop_creator",
+          "ConstraintLayout_Layout_layout_editor_absoluteX",
+          "ConstraintLayout_Layout_layout_editor_absoluteY",
+          "ConstraintLayout_Layout_layout_goneMarginTop",
+          "ConstraintSet_layout_goneMarginEnd",
+          "ConstraintSet_layout_constraintLeft_toRightOf",
+          "ConstraintLayout_Layout_layout_goneMarginBottom",
+          "ConstraintLayout_Layout_android_minHeight",
+          "ConstraintLayout_Layout_layout_constraintBaseline_toBaselineOf",
+          "ConstraintSet_android_layout_marginLeft",
+          "ConstraintSet_layout_constraintHorizontal_weight",
+          "ConstraintLayout_Layout_layout_goneMarginEnd",
+          "ConstraintSet_layout_constraintVertical_weight",
+          "ConstraintSet_layout_constraintBaseline_creator",
+          "ConstraintSet_layout_constraintVertical_bias",
+          "ConstraintSet_layout_goneMarginTop",
+          "ConstraintLayout_Layout_layout_constraintRight_creator",
+          "ConstraintSet_layout_constraintBottom_toTopOf",
+          "ConstraintLayout_Layout_layout_constraintWidth_default",
+          "ConstraintSet_android_layout_marginStart",
+          "ConstraintSet_android_layout_width",
+          "ConstraintSet_layout_constraintWidth_default",
+          "ConstraintLayout_Layout_layout_constraintBottom_toTopOf",
+          "ConstraintLayout_Layout_layout_constraintStart_toEndOf",
+          "ConstraintLayout_Layout_layout_constraintHorizontal_weight",
+          "ConstraintSet_android_layout_marginRight",
+          "ConstraintSet_layout_constraintBottom_toBottomOf",
+          "ConstraintSet_android_scaleX",
+          "ConstraintSet_android_scaleY",
+          "ConstraintLayout_Layout_layout_constraintRight_toRightOf",
+          "ConstraintSet_layout_constraintGuide_percent",
+          "ConstraintLayout_Layout_layout_constraintLeft_creator",
+          "ConstraintLayout_Layout_layout_constraintTop_creator",
+          "ConstraintSet_layout_constraintTop_toTopOf",
+          "ConstraintLayout_Layout_layout_goneMarginRight",
+          "ConstraintSet_layout_constraintEnd_toEndOf",
+          "ConstraintLayout_Layout_layout_constraintHeight_max",
+          "ConstraintLayout_Layout_constraintSet",
+          "ConstraintLayout_Layout_layout_constraintHeight_min",
+          "ConstraintLayout_Layout_layout_goneMarginStart",
+          "ConstraintSet_android_elevation",
+          "ConstraintSet_layout_constraintTop_toBottomOf",
+          "ConstraintLayout_Layout_layout_constraintLeft_toRightOf",
+          "ConstraintLayout_Layout_layout_constraintStart_toStartOf",
+          "ConstraintSet_layout_constraintHorizontal_chainStyle",
+          "ConstraintLayout_Layout_android_maxWidth",
+          "ConstraintLayout_Layout_layout_constraintHorizontal_bias",
+          "ConstraintLayout_Layout_layout_constraintHeight_default",
+          "ConstraintSet_layout_constraintRight_toLeftOf",
+          "ConstraintLayout_Layout_android_minWidth",
+          "ConstraintSet_layout_constraintVertical_chainStyle",
+          "ConstraintLayout_Layout_layout_constraintGuide_end",
+          "ConstraintSet_layout_goneMarginBottom"
+        ]
+      },
+      "android/support/v4/view/ViewPager": {
+        "androidx/widget/ViewPager": [
+          "SCROLL_STATE_DRAGGING",
+          "MIN_FLING_VELOCITY",
+          "LAYOUT_ATTRS",
+          "DRAW_ORDER_DEFAULT",
+          "DEFAULT_OFFSCREEN_PAGES",
+          "USE_CACHE",
+          "INVALID_POINTER",
+          "sPositionComparator",
+          "SCROLL_STATE_IDLE",
+          "TAG",
+          "DEBUG",
+          "MAX_SETTLE_DURATION",
+          "SCROLL_STATE_SETTLING",
+          "DEFAULT_GUTTER_SIZE",
+          "sInterpolator",
+          "MIN_DISTANCE_FOR_FLING",
+          "DRAW_ORDER_REVERSE",
+          "CLOSE_ENOUGH",
+          "DRAW_ORDER_FORWARD",
+          "COMPARATOR"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplBase$MessageHandler": {
+        "androidx/media/session/MediaSessionCompat$MediaSessionImplBase$MessageHandler": [
+          "MSG_CUSTOM_ACTION",
+          "MSG_SET_VOLUME",
+          "MSG_SET_SHUFFLE_MODE",
+          "MSG_PREPARE",
+          "MSG_COMMAND",
+          "MSG_REMOVE_QUEUE_ITEM",
+          "MSG_RATE_EXTRA",
+          "MSG_PREPARE_SEARCH",
+          "MSG_FAST_FORWARD",
+          "MSG_PREPARE_URI",
+          "MSG_PAUSE",
+          "MSG_PLAY_URI",
+          "MSG_STOP",
+          "MSG_SKIP_TO_ITEM",
+          "MSG_ADD_QUEUE_ITEM",
+          "MSG_RATE",
+          "MSG_PLAY",
+          "MSG_NEXT",
+          "MSG_REMOVE_QUEUE_ITEM_AT",
+          "MSG_SET_REPEAT_MODE",
+          "MSG_PREVIOUS",
+          "MSG_SEEK_TO",
+          "MSG_PLAY_SEARCH",
+          "MSG_PLAY_MEDIA_ID",
+          "MSG_MEDIA_BUTTON",
+          "KEYCODE_MEDIA_PAUSE",
+          "MSG_PREPARE_MEDIA_ID",
+          "KEYCODE_MEDIA_PLAY",
+          "MSG_ADD_QUEUE_ITEM_AT",
+          "MSG_SET_CAPTIONING_ENABLED",
+          "MSG_ADJUST_VOLUME",
+          "MSG_REWIND"
+        ]
+      },
+      "android/support/design/R$dimen": {
+        "androidx/design/R$dimen": [
+          "design_bottom_navigation_item_min_width",
+          "design_tab_scrollable_min_width",
+          "design_tab_text_size_2line",
+          "design_bottom_sheet_peek_height_min",
+          "design_fab_size_mini",
+          "design_snackbar_padding_vertical_2lines",
+          "design_snackbar_padding_vertical",
+          "design_bottom_navigation_item_max_width",
+          "design_bottom_navigation_active_text_size",
+          "design_navigation_separator_vertical_padding",
+          "design_navigation_icon_size",
+          "design_bottom_navigation_text_size",
+          "design_fab_image_size",
+          "design_bottom_navigation_height",
+          "design_bottom_navigation_margin",
+          "design_fab_size_normal",
+          "design_bottom_navigation_active_item_max_width",
+          "design_bottom_navigation_shadow_height"
+        ]
+      },
+      "android/support/multidex/MultiDex": {
+        "androidx/multidex/MultiDex": [
+          "installedApk",
+          "CODE_CACHE_SECONDARY_FOLDER_NAME",
+          "CODE_CACHE_NAME",
+          "VM_WITH_MULTIDEX_VERSION_MAJOR",
+          "TAG",
+          "NO_KEY_PREFIX",
+          "IS_VM_MULTIDEX_CAPABLE",
+          "VM_WITH_MULTIDEX_VERSION_MINOR",
+          "MIN_SDK_VERSION",
+          "MAX_SUPPORTED_SDK_VERSION",
+          "OLD_SECONDARY_FOLDER_NAME"
+        ]
+      },
+      "android/support/constraint/ConstraintSet$Constraint": {
+        "androidx/constraint/ConstraintSet$Constraint": [
+          "guidePercent",
+          "topToTop",
+          "guideEnd",
+          "heightDefault",
+          "topMargin",
+          "goneRightMargin",
+          "goneTopMargin",
+          "visibility",
+          "elevation",
+          "dimensionRatio",
+          "startToStart",
+          "widthMax",
+          "applyElevation",
+          "widthMin",
+          "verticalWeight",
+          "endToStart",
+          "bottomToTop",
+          "rotationY",
+          "rotationX",
+          "horizontalBias",
+          "translationY",
+          "translationZ",
+          "translationX",
+          "transformPivotX",
+          "transformPivotY",
+          "leftMargin",
+          "horizontalChainStyle",
+          "orientation",
+          "leftToRight",
+          "endMargin",
+          "verticalBias",
+          "heightMax",
+          "scaleX",
+          "scaleY",
+          "rightMargin",
+          "leftToLeft",
+          "heightMin",
+          "endToEnd",
+          "topToBottom",
+          "startMargin",
+          "goneLeftMargin",
+          "bottomToBottom",
+          "editorAbsoluteY",
+          "editorAbsoluteX",
+          "baselineToBaseline",
+          "horizontalWeight",
+          "guideBegin",
+          "bottomMargin",
+          "widthDefault",
+          "startToEnd",
+          "rightToRight",
+          "alpha",
+          "UNSET",
+          "goneStartMargin",
+          "rightToLeft",
+          "goneBottomMargin",
+          "verticalChainStyle",
+          "goneEndMargin"
+        ]
+      },
+      "android/support/compat/R$id": {
+        "androidx/compat/R$id": [
+          "right_icon",
+          "action_container",
+          "icon",
+          "notification_background",
+          "line1",
+          "line3",
+          "text",
+          "action_divider",
+          "time",
+          "action_text",
+          "right_side",
+          "notification_main_column",
+          "action_image",
+          "tag_transition_group",
+          "title",
+          "text2",
+          "actions",
+          "notification_main_column_container",
+          "info",
+          "chronometer"
+        ]
+      },
+      "android/support/v7/widget/helper/ItemTouchHelper": {
+        "androidx/widget/helper/ItemTouchHelper": [
+          "DOWN",
+          "DEBUG",
+          "PIXELS_PER_SECOND",
+          "ACTION_STATE_SWIPE",
+          "ANIMATION_TYPE_SWIPE_CANCEL",
+          "END",
+          "UP",
+          "START",
+          "ANIMATION_TYPE_SWIPE_SUCCESS",
+          "ANIMATION_TYPE_DRAG",
+          "LEFT",
+          "ACTIVE_POINTER_ID_NONE",
+          "RIGHT",
+          "TAG",
+          "ACTION_STATE_DRAG",
+          "ACTION_MODE_IDLE_MASK",
+          "ACTION_MODE_SWIPE_MASK",
+          "DIRECTION_FLAG_COUNT",
+          "ACTION_MODE_DRAG_MASK",
+          "ACTION_STATE_IDLE"
+        ]
+      },
+      "android/support/graphics/drawable/VectorDrawableCompat": {
+        "androidx/graphics/drawable/VectorDrawableCompat": [
+          "LINECAP_ROUND",
+          "SHAPE_VECTOR",
+          "LOGTAG",
+          "DEFAULT_TINT_MODE",
+          "SHAPE_CLIP_PATH",
+          "LINECAP_SQUARE",
+          "LINEJOIN_MITER",
+          "LINEJOIN_ROUND",
+          "LINEJOIN_BEVEL",
+          "LINECAP_BUTT",
+          "SHAPE_PATH",
+          "MAX_CACHED_BITMAP_SIZE",
+          "DBG_VECTOR_DRAWABLE",
+          "SHAPE_GROUP"
+        ]
+      },
+      "android/support/v14/preference/R$styleable": {
+        "androidx/preference/R$styleable": [
+          "SwitchPreference_switchTextOff",
+          "SwitchPreference_switchTextOn",
+          "SwitchPreference_disableDependentsState",
+          "PreferenceFragment",
+          "SwitchPreference_android_summaryOn",
+          "PreferenceFragment_android_dividerHeight",
+          "SwitchPreference_android_switchTextOff",
+          "SwitchPreference_android_summaryOff",
+          "PreferenceFragment_allowDividerAfterLastItem",
+          "SwitchPreference",
+          "SwitchPreference_summaryOff",
+          "SwitchPreference_summaryOn",
+          "SwitchPreference_android_switchTextOn",
+          "PreferenceFragment_android_divider",
+          "SwitchPreference_android_disableDependentsState",
+          "PreferenceFragment_android_layout"
+        ]
+      },
+      "android/support/v7/app/MediaRouteControllerDialog": {
+        "androidx/app/MediaRouteControllerDialog": [
+          "BUTTON_DISCONNECT_RES_ID",
+          "DEBUG",
+          "BUTTON_NEUTRAL_RES_ID",
+          "VOLUME_UPDATE_DELAY_MILLIS",
+          "CONNECTION_TIMEOUT_MILLIS",
+          "BUTTON_STOP_RES_ID",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/picker/PickerUtility": {
+        "androidx/leanback/widget/picker/PickerUtility": [
+          "SUPPORTS_BEST_DATE_TIME_PATTERN"
+        ]
+      },
+      "android/support/wear/widget/drawer/WearableActionDrawerView$TitleViewHolder": {
+        "androidx/wear/widget/drawer/WearableActionDrawerView$TitleViewHolder": [
+          "textView",
+          "view"
+        ]
+      },
+      "android/support/customtabs/CustomTabsIntent": {
+        "androidx/browser/customtabs/CustomTabsIntent": [
+          "TOOLBAR_ACTION_BUTTON_ID",
+          "EXTRA_ACTION_BUTTON_BUNDLE",
+          "EXTRA_EXIT_ANIMATION_BUNDLE",
+          "EXTRA_MENU_ITEMS",
+          "EXTRA_CLOSE_BUTTON_ICON",
+          "startAnimationBundle",
+          "KEY_ICON",
+          "EXTRA_SESSION",
+          "EXTRA_DEFAULT_SHARE_MENU_ITEM",
+          "MAX_TOOLBAR_ITEMS",
+          "intent",
+          "EXTRA_SECONDARY_TOOLBAR_COLOR",
+          "KEY_ID",
+          "EXTRA_TOOLBAR_COLOR",
+          "SHOW_PAGE_TITLE",
+          "EXTRA_TITLE_VISIBILITY_STATE",
+          "EXTRA_TOOLBAR_ITEMS",
+          "EXTRA_TINT_ACTION_BUTTON",
+          "NO_TITLE",
+          "KEY_DESCRIPTION",
+          "EXTRA_ENABLE_INSTANT_APPS",
+          "EXTRA_REMOTEVIEWS_PENDINGINTENT",
+          "EXTRA_REMOTEVIEWS_CLICKED_ID",
+          "KEY_MENU_ITEM_TITLE",
+          "EXTRA_ENABLE_URLBAR_HIDING",
+          "KEY_PENDING_INTENT",
+          "EXTRA_REMOTEVIEWS",
+          "EXTRA_USER_OPT_OUT_FROM_CUSTOM_TABS",
+          "EXTRA_REMOTEVIEWS_VIEW_IDS"
+        ]
+      },
+      "android/support/wear/R$styleable": {
+        "androidx/wear/R$styleable": [
+          "PageIndicatorView_wsPageIndicatorDotFadeInDuration",
+          "CircularProgressLayout_strokeWidth",
+          "WearableActionDrawerView",
+          "WearableRecyclerView_circularScrollingGestureEnabled",
+          "PageIndicatorView_wsPageIndicatorDotColor",
+          "PageIndicatorView",
+          "WearableActionDrawerView_actionMenu",
+          "PageIndicatorView_wsPageIndicatorDotFadeOutDelay",
+          "PageIndicatorView_wsPageIndicatorDotRadius",
+          "PageIndicatorView_wsPageIndicatorDotRadiusSelected",
+          "RoundedDrawable",
+          "WearableNavigationDrawerView_navigationStyle",
+          "CircledImageView_img_horizontal_offset_percentage",
+          "CircularProgressLayout",
+          "CircledImageView_img_tint",
+          "WearableActionDrawerView_showOverflowInPeek",
+          "CircledImageView_background_border_cap",
+          "CircledImageView_img_circle_percentage",
+          "BoxInsetLayout_Layout",
+          "CircledImageView_background_radius_pressed_percent",
+          "WearableActionDrawerView_drawerTitle",
+          "WearableRecyclerView",
+          "PageIndicatorView_wsPageIndicatorDotColorSelected",
+          "CircledImageView_img_padding",
+          "WearableDrawerView_android_elevation",
+          "RoundedDrawable_backgroundColor",
+          "PageIndicatorView_wsPageIndicatorDotShadowDx",
+          "PageIndicatorView_wsPageIndicatorDotShadowDy",
+          "CircularProgressLayout_backgroundColor",
+          "CircledImageView_background_radius_pressed",
+          "WearableDrawerView",
+          "BoxInsetLayout_Layout_boxedEdges",
+          "RoundedDrawable_radius",
+          "CircularProgressLayout_indeterminate",
+          "WearableDrawerView_peekView",
+          "WearableDrawerView_android_background",
+          "WearableDrawerView_enableAutoPeek",
+          "CircledImageView",
+          "PageIndicatorView_wsPageIndicatorDotFadeOutDuration",
+          "CircledImageView_background_shadow_width",
+          "CircledImageView_android_src",
+          "CircledImageView_background_radius_percent",
+          "PageIndicatorView_wsPageIndicatorDotShadowRadius",
+          "WearableRecyclerView_scrollDegreesPerScreen",
+          "CircledImageView_background_color",
+          "CircledImageView_clip_dimen",
+          "CircledImageView_background_radius",
+          "PageIndicatorView_wsPageIndicatorDotShadowColor",
+          "RoundedDrawable_clipEnabled",
+          "RoundedDrawable_android_src",
+          "WearableRecyclerView_bezelWidth",
+          "CircularProgressLayout_colorSchemeColors",
+          "WearableDrawerView_drawerContent",
+          "CircledImageView_background_border_color",
+          "WearableNavigationDrawerView",
+          "PageIndicatorView_wsPageIndicatorDotSpacing",
+          "CircledImageView_background_border_width",
+          "PageIndicatorView_wsPageIndicatorDotFadeWhenIdle"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsRow$ShuffleAction": {
+        "androidx/leanback/widget/PlaybackControlsRow$ShuffleAction": [
+          "INDEX_ON",
+          "INDEX_OFF",
+          "ON",
+          "OFF"
+        ]
+      },
+      "android/support/v7/widget/TooltipCompatHandler": {
+        "androidx/widget/TooltipCompatHandler": [
+          "LONG_CLICK_HIDE_TIMEOUT_MS",
+          "sActiveHandler",
+          "HOVER_HIDE_TIMEOUT_MS",
+          "TAG",
+          "HOVER_HIDE_TIMEOUT_SHORT_MS"
+        ]
+      },
+      "android/support/v7/appcompat/BuildConfig": {
+        "androidx/appcompat/BuildConfig": [
+          "APPLICATION_ID",
+          "FLAVOR",
+          "DEBUG",
+          "VERSION_CODE",
+          "VERSION_NAME",
+          "BUILD_TYPE"
+        ]
+      },
+      "android/support/v4/media/AudioAttributesCompat$AudioManagerHidden": {
+        "androidx/media/AudioAttributesCompat$AudioManagerHidden": [
+          "STREAM_TTS",
+          "STREAM_BLUETOOTH_SCO",
+          "STREAM_SYSTEM_ENFORCED",
+          "STREAM_ACCESSIBILITY"
+        ]
+      },
+      "android/support/v17/leanback/widget/CursorObjectAdapter": {
+        "androidx/leanback/widget/CursorObjectAdapter": [
+          "CACHE_SIZE"
+        ]
+      },
+      "android/support/v7/mediarouter/R$dimen": {
+        "androidx/mediarouter/R$dimen": [
+          "mr_controller_volume_group_list_padding_top",
+          "mr_controller_volume_group_list_max_height",
+          "mr_controller_volume_group_list_item_height",
+          "mr_controller_volume_group_list_item_icon_size",
+          "mr_dialog_fixed_width_major",
+          "mr_dialog_fixed_width_minor"
+        ]
+      },
+      "android/support/transition/Transition": {
+        "androidx/transition/Transition": [
+          "MATCH_INSTANCE",
+          "MATCH_LAST",
+          "MATCH_FIRST",
+          "sRunningAnimators",
+          "MATCH_ID_STR",
+          "DBG",
+          "MATCH_INSTANCE_STR",
+          "MATCH_ITEM_ID",
+          "DEFAULT_MATCH_ORDER",
+          "MATCH_NAME_STR",
+          "MATCH_NAME",
+          "STRAIGHT_PATH_MOTION",
+          "MATCH_ITEM_ID_STR",
+          "MATCH_ID",
+          "LOG_TAG"
+        ]
+      },
+      "android/support/design/widget/CoordinatorLayout": {
+        "androidx/widget/CoordinatorLayout": [
+          "EVENT_VIEW_REMOVED",
+          "sConstructors",
+          "TOP_SORTED_CHILDREN_COMPARATOR",
+          "TYPE_ON_TOUCH",
+          "sRectPool",
+          "CONSTRUCTOR_PARAMS",
+          "TAG",
+          "EVENT_NESTED_SCROLL",
+          "WIDGET_PACKAGE_NAME",
+          "EVENT_PRE_DRAW",
+          "TYPE_ON_INTERCEPT"
+        ]
+      },
+      "android/support/constraint/ConstraintSet": {
+        "androidx/constraint/ConstraintSet": [
+          "CHAIN_SPREAD_INSIDE",
+          "UNUSED",
+          "GONE_LEFT_MARGIN",
+          "WIDTH_MAX",
+          "DIMENSION_RATIO",
+          "WIDTH_MIN",
+          "GUIDE_BEGIN",
+          "START_TO_START",
+          "ORIENTATION",
+          "RIGHT_TO_LEFT",
+          "VERTICAL",
+          "GUIDE_PERCENT",
+          "GONE_END_MARGIN",
+          "CHAIN_SPREAD",
+          "LAYOUT_HEIGHT",
+          "HORIZONTAL_STYLE",
+          "TOP_MARGIN",
+          "TRANSLATION_X",
+          "TRANSLATION_Z",
+          "TRANSLATION_Y",
+          "ELEVATION",
+          "EDITOR_ABSOLUTE_Y",
+          "EDITOR_ABSOLUTE_X",
+          "END_TO_START",
+          "DEBUG",
+          "MATCH_CONSTRAINT",
+          "BOTTOM_TO_TOP",
+          "RIGHT_MARGIN",
+          "TRANSFORM_PIVOT_Y",
+          "TRANSFORM_PIVOT_X",
+          "WRAP_CONTENT",
+          "BASELINE",
+          "HORIZONTAL_BIAS",
+          "SCALE_Y",
+          "SCALE_X",
+          "VISIBILITY_FLAGS",
+          "CHAIN_PACKED",
+          "VERTICAL_STYLE",
+          "mapToConstant",
+          "HORIZONTAL_GUIDELINE",
+          "LEFT",
+          "START_MARGIN",
+          "PARENT_ID",
+          "GUIDE_END",
+          "END_TO_END",
+          "TOP",
+          "LAYOUT_VISIBILITY",
+          "GONE_BOTTOM_MARGIN",
+          "LEFT_MARGIN",
+          "RIGHT",
+          "GONE_TOP_MARGIN",
+          "VERTICAL_GUIDELINE",
+          "START",
+          "GONE_RIGHT_MARGIN",
+          "TAG",
+          "GONE_START_MARGIN",
+          "HEIGHT_MIN",
+          "MATCH_CONSTRAINT_WRAP",
+          "UNSET",
+          "HEIGHT_MAX",
+          "END",
+          "BASELINE_TO_BASELINE",
+          "LAYOUT_WIDTH",
+          "VERTICAL_BIAS",
+          "HORIZONTAL",
+          "MATCH_CONSTRAINT_SPREAD",
+          "ALPHA",
+          "TOP_TO_TOP",
+          "RIGHT_TO_RIGHT",
+          "TOP_TO_BOTTOM",
+          "BOTTOM",
+          "LEFT_TO_LEFT",
+          "VIEW_ID",
+          "INVISIBLE",
+          "VERTICAL_WEIGHT",
+          "VISIBLE",
+          "HEIGHT_DEFAULT",
+          "WIDTH_DEFAULT",
+          "LEFT_TO_RIGHT",
+          "END_MARGIN",
+          "BOTTOM_MARGIN",
+          "HORIZONTAL_WEIGHT",
+          "START_TO_END",
+          "BOTTOM_TO_BOTTOM",
+          "GONE",
+          "ROTATION_X",
+          "ROTATION_Y"
+        ]
+      },
+      "android/support/v4/app/FrameMetricsAggregator$FrameMetricsApi24Impl": {
+        "androidx/app/FrameMetricsAggregator$FrameMetricsApi24Impl": [
+          "NANOS_PER_MS",
+          "NANOS_ROUNDING_VALUE",
+          "sHandlerThread",
+          "sHandler"
+        ]
+      },
+      "android/support/v4/view/GestureDetectorCompat$GestureDetectorCompatImplBase": {
+        "androidx/view/GestureDetectorCompat$GestureDetectorCompatImplBase": [
+          "LONGPRESS_TIMEOUT",
+          "TAP_TIMEOUT",
+          "DOUBLE_TAP_TIMEOUT",
+          "LONG_PRESS",
+          "TAP",
+          "SHOW_PRESS"
+        ]
+      },
+      "android/support/multidex/MultiDexExtractor": {
+        "androidx/multidex/MultiDexExtractor": [
+          "KEY_DEX_TIME",
+          "MAX_EXTRACT_ATTEMPTS",
+          "TAG",
+          "DEX_PREFIX",
+          "DEX_SUFFIX",
+          "EXTRACTED_NAME_EXT",
+          "KEY_CRC",
+          "KEY_DEX_CRC",
+          "NO_VALUE",
+          "LOCK_FILENAME",
+          "KEY_TIME_STAMP",
+          "EXTRACTED_SUFFIX",
+          "BUFFER_SIZE",
+          "KEY_DEX_NUMBER",
+          "PREFS_FILE"
+        ]
+      },
+      "android/support/v4/view/accessibility/AccessibilityNodeInfoCompat$AccessibilityActionCompat": {
+        "androidx/view/accessibility/AccessibilityNodeInfoCompat$AccessibilityActionCompat": [
+          "ACTION_FOCUS",
+          "ACTION_SCROLL_BACKWARD",
+          "ACTION_SCROLL_DOWN",
+          "ACTION_CONTEXT_CLICK",
+          "ACTION_CLEAR_FOCUS",
+          "ACTION_ACCESSIBILITY_FOCUS",
+          "ACTION_PASTE",
+          "ACTION_SET_PROGRESS",
+          "ACTION_EXPAND",
+          "ACTION_NEXT_HTML_ELEMENT",
+          "ACTION_SCROLL_UP",
+          "ACTION_SCROLL_FORWARD",
+          "ACTION_CLEAR_SELECTION",
+          "ACTION_LONG_CLICK",
+          "ACTION_SET_TEXT",
+          "ACTION_NEXT_AT_MOVEMENT_GRANULARITY",
+          "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY",
+          "ACTION_SHOW_ON_SCREEN",
+          "ACTION_COLLAPSE",
+          "ACTION_COPY",
+          "ACTION_SCROLL_LEFT",
+          "ACTION_PREVIOUS_HTML_ELEMENT",
+          "ACTION_SET_SELECTION",
+          "ACTION_CLEAR_ACCESSIBILITY_FOCUS",
+          "ACTION_SCROLL_TO_POSITION",
+          "ACTION_DISMISS",
+          "ACTION_CLICK",
+          "ACTION_CUT",
+          "ACTION_SCROLL_RIGHT",
+          "ACTION_SELECT"
+        ]
+      },
+      "android/support/v4/graphics/drawable/DrawableWrapperApi21": {
+        "androidx/graphics/drawable/DrawableWrapperApi21": [
+          "sIsProjectedDrawableMethod",
+          "TAG"
+        ]
+      },
+      "android/support/v7/media/MediaRouter$RouteInfo": {
+        "androidx/media/MediaRouter$RouteInfo": [
+          "PRESENTATION_DISPLAY_ID_NONE",
+          "SYSTEM_MEDIA_ROUTE_PROVIDER_PACKAGE_NAME",
+          "PLAYBACK_TYPE_REMOTE",
+          "CHANGE_VOLUME",
+          "DEVICE_TYPE_BLUETOOTH",
+          "CHANGE_PRESENTATION_DISPLAY",
+          "CHANGE_GENERAL",
+          "CONNECTION_STATE_DISCONNECTED",
+          "DEVICE_TYPE_TV",
+          "PLAYBACK_VOLUME_VARIABLE",
+          "CONNECTION_STATE_CONNECTING",
+          "PLAYBACK_TYPE_LOCAL",
+          "DEVICE_TYPE_UNKNOWN",
+          "CONNECTION_STATE_CONNECTED",
+          "PLAYBACK_VOLUME_FIXED",
+          "DEVICE_TYPE_SPEAKER"
+        ]
+      },
+      "android/support/v17/leanback/widget/picker/TimePicker": {
+        "androidx/leanback/widget/picker/TimePicker": [
+          "TAG",
+          "HOURS_IN_HALF_DAY",
+          "AM_INDEX",
+          "PM_INDEX"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView": {
+        "androidx/widget/RecyclerView": [
+          "LAYOUT_MANAGER_CONSTRUCTOR_SIGNATURE",
+          "TRACE_ON_DATA_SET_CHANGE_LAYOUT_TAG",
+          "NO_ID",
+          "NO_POSITION",
+          "DISPATCH_TEMP_DETACH",
+          "TRACE_SCROLL_TAG",
+          "SCROLL_STATE_DRAGGING",
+          "TRACE_PREFETCH_TAG",
+          "INVALID_POINTER",
+          "MAX_SCROLL_DURATION",
+          "TOUCH_SLOP_PAGING",
+          "TOUCH_SLOP_DEFAULT",
+          "VERBOSE_TRACING",
+          "TRACE_CREATE_VIEW_TAG",
+          "ALLOW_SIZE_IN_UNSPECIFIED_SPEC",
+          "FORCE_ABS_FOCUS_SEARCH_DIRECTION",
+          "TRACE_BIND_VIEW_TAG",
+          "HORIZONTAL",
+          "ALLOW_THREAD_GAP_WORK",
+          "DEBUG",
+          "TRACE_NESTED_PREFETCH_TAG",
+          "SCROLL_STATE_SETTLING",
+          "POST_UPDATES_ON_ANIMATION",
+          "sQuinticInterpolator",
+          "VERTICAL",
+          "CLIP_TO_PADDING_ATTR",
+          "FOREVER_NS",
+          "IGNORE_DETACHED_FOCUSED_CHILD",
+          "INVALID_TYPE",
+          "SCROLL_STATE_IDLE",
+          "NESTED_SCROLLING_ATTRS",
+          "TAG",
+          "TRACE_ON_LAYOUT_TAG",
+          "FORCE_INVALIDATE_DISPLAY_LIST",
+          "TRACE_HANDLE_ADAPTER_UPDATES_TAG"
+        ]
+      },
+      "android/support/v4/view/PagerAdapter": {
+        "androidx/widget/PagerAdapter": [
+          "POSITION_NONE",
+          "POSITION_UNCHANGED"
+        ]
+      },
+      "android/support/compat/BuildConfig": {
+        "androidx/compat/BuildConfig": [
+          "FLAVOR",
+          "APPLICATION_ID",
+          "VERSION_CODE",
+          "DEBUG",
+          "VERSION_NAME",
+          "BUILD_TYPE"
+        ]
+      },
+      "android/support/v4/view/accessibility/AccessibilityNodeInfoCompat": {
+        "androidx/view/accessibility/AccessibilityNodeInfoCompat": [
+          "ACTION_PREVIOUS_HTML_ELEMENT",
+          "ACTION_ARGUMENT_SELECTION_END_INT",
+          "ACTION_SET_SELECTION",
+          "MOVEMENT_GRANULARITY_CHARACTER",
+          "MOVEMENT_GRANULARITY_LINE",
+          "ACTION_SET_TEXT",
+          "MOVEMENT_GRANULARITY_PARAGRAPH",
+          "ACTION_SELECT",
+          "FOCUS_ACCESSIBILITY",
+          "ACTION_DISMISS",
+          "ACTION_EXPAND",
+          "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE",
+          "ACTION_CLEAR_ACCESSIBILITY_FOCUS",
+          "ACTION_CUT",
+          "ACTION_PASTE",
+          "ACTION_ARGUMENT_ROW_INT",
+          "FOCUS_INPUT",
+          "ACTION_ARGUMENT_HTML_ELEMENT_STRING",
+          "MOVEMENT_GRANULARITY_PAGE",
+          "ACTION_ARGUMENT_PROGRESS_VALUE",
+          "ACTION_CLEAR_FOCUS",
+          "MOVEMENT_GRANULARITY_WORD",
+          "ACTION_SCROLL_BACKWARD",
+          "ROLE_DESCRIPTION_KEY",
+          "ACTION_FOCUS",
+          "ACTION_NEXT_HTML_ELEMENT",
+          "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN",
+          "ACTION_CLEAR_SELECTION",
+          "ACTION_ARGUMENT_COLUMN_INT",
+          "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY",
+          "ACTION_NEXT_AT_MOVEMENT_GRANULARITY",
+          "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT",
+          "ACTION_ACCESSIBILITY_FOCUS",
+          "ACTION_CLICK",
+          "ACTION_ARGUMENT_SELECTION_START_INT",
+          "ACTION_SCROLL_FORWARD",
+          "ACTION_COPY",
+          "ACTION_COLLAPSE",
+          "ACTION_LONG_CLICK"
+        ]
+      },
+      "android/support/v7/preference/R$styleable": {
+        "androidx/preference/R$styleable": [
+          "SeekBarPreference",
+          "CheckBoxPreference_summaryOn",
+          "DialogPreference_android_dialogLayout",
+          "Preference_summary",
+          "Preference_widgetLayout",
+          "CheckBoxPreference_android_disableDependentsState",
+          "Preference_android_layout",
+          "Preference_android_selectable",
+          "Preference_android_enabled",
+          "DialogPreference_dialogLayout",
+          "Preference_dependency",
+          "Preference_iconSpaceReserved",
+          "Preference_fragment",
+          "ListPreference_android_entries",
+          "PreferenceGroup",
+          "SeekBarPreference_seekBarIncrement",
+          "Preference_android_iconSpaceReserved",
+          "Preference_selectable",
+          "PreferenceFragmentCompat",
+          "Preference_allowDividerAbove",
+          "PreferenceImageView",
+          "SwitchPreferenceCompat_switchTextOn",
+          "DialogPreference_android_dialogMessage",
+          "Preference",
+          "CheckBoxPreference_summaryOff",
+          "Preference_shouldDisableView",
+          "Preference_title",
+          "Preference_enabled",
+          "SwitchPreferenceCompat_android_switchTextOff",
+          "DialogPreference_android_dialogIcon",
+          "ListPreference_entries",
+          "MultiSelectListPreference",
+          "SeekBarPreference_adjustable",
+          "PreferenceImageView_maxHeight",
+          "SwitchPreferenceCompat_android_summaryOn",
+          "PreferenceFragmentCompat_allowDividerAfterLastItem",
+          "SwitchPreferenceCompat_disableDependentsState",
+          "DialogPreference",
+          "DialogPreference_positiveButtonText",
+          "PreferenceFragmentCompat_android_layout",
+          "Preference_android_icon",
+          "SwitchPreferenceCompat_summaryOff",
+          "DialogPreference_dialogMessage",
+          "DialogPreference_android_negativeButtonText",
+          "MultiSelectListPreference_entries",
+          "ListPreference_android_entryValues",
+          "Preference_defaultValue",
+          "CheckBoxPreference_android_summaryOff",
+          "PreferenceFragmentCompat_android_divider",
+          "Preference_android_shouldDisableView",
+          "SwitchPreferenceCompat_switchTextOff",
+          "SwitchPreferenceCompat",
+          "Preference_allowDividerBelow",
+          "Preference_android_persistent",
+          "BackgroundStyle",
+          "ListPreference",
+          "Preference_android_widgetLayout",
+          "SwitchPreferenceCompat_android_summaryOff",
+          "SwitchPreferenceCompat_android_switchTextOn",
+          "Preference_android_order",
+          "MultiSelectListPreference_android_entries",
+          "Preference_layout",
+          "SwitchPreferenceCompat_android_disableDependentsState",
+          "SwitchPreferenceCompat_summaryOn",
+          "Preference_android_summary",
+          "DialogPreference_dialogTitle",
+          "Preference_android_dependency",
+          "DialogPreference_android_dialogTitle",
+          "Preference_persistent",
+          "MultiSelectListPreference_android_entryValues",
+          "Preference_android_key",
+          "DialogPreference_android_positiveButtonText",
+          "Preference_android_title",
+          "Preference_android_singleLineTitle",
+          "DialogPreference_negativeButtonText",
+          "MultiSelectListPreference_entryValues",
+          "PreferenceFragmentCompat_android_dividerHeight",
+          "CheckBoxPreference_android_summaryOn",
+          "SeekBarPreference_min",
+          "BackgroundStyle_android_selectableItemBackground",
+          "Preference_android_fragment",
+          "DialogPreference_dialogIcon",
+          "Preference_icon",
+          "CheckBoxPreference_disableDependentsState",
+          "Preference_key",
+          "CheckBoxPreference",
+          "SeekBarPreference_android_max",
+          "Preference_singleLineTitle",
+          "SeekBarPreference_showSeekBarValue",
+          "PreferenceImageView_maxWidth",
+          "Preference_android_defaultValue",
+          "ListPreference_entryValues",
+          "PreferenceGroup_orderingFromXml",
+          "Preference_order"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat$RecordedPrograms": {
+        "androidx/media/tv/TvContractCompat$RecordedPrograms": [
+          "CONTENT_URI",
+          "COLUMN_RECORDING_DURATION_MILLIS",
+          "COLUMN_CHANNEL_ID",
+          "COLUMN_BROADCAST_GENRE",
+          "COLUMN_RECORDING_DATA_BYTES",
+          "COLUMN_END_TIME_UTC_MILLIS",
+          "CONTENT_TYPE",
+          "COLUMN_RECORDING_DATA_URI",
+          "COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS",
+          "COLUMN_INPUT_ID",
+          "COLUMN_START_TIME_UTC_MILLIS",
+          "CONTENT_ITEM_TYPE"
+        ]
+      },
+      "android/support/v17/leanback/app/PlaybackSupportFragment": {
+        "androidx/leanback/app/PlaybackSupportFragment": [
+          "IDLE",
+          "ANIMATION_MULTIPLIER",
+          "ANIMATING",
+          "BG_LIGHT",
+          "START_FADE_OUT",
+          "TAG",
+          "BG_DARK",
+          "BG_NONE",
+          "BUNDLE_CONTROL_VISIBLE_ON_CREATEVIEW",
+          "DEBUG"
+        ]
+      },
+      "android/support/v17/leanback/widget/ShadowOverlayHelper$Options": {
+        "androidx/leanback/widget/ShadowOverlayHelper$Options": [
+          "DEFAULT",
+          "roundedCornerRadius",
+          "dynamicShadowUnfocusedZ",
+          "dynamicShadowFocusedZ"
+        ]
+      },
+      "android/support/v17/leanback/widget/ShadowOverlayHelper": {
+        "androidx/leanback/widget/ShadowOverlayHelper": [
+          "SHADOW_NONE",
+          "SHADOW_STATIC",
+          "SHADOW_DYNAMIC"
+        ]
+      },
+      "android/support/v4/media/MediaBrowserServiceCompat": {
+        "androidx/media/MediaBrowserServiceCompat": [
+          "EPSILON",
+          "RESULT_ERROR",
+          "DEBUG",
+          "RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED",
+          "RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED",
+          "KEY_MEDIA_ITEM",
+          "TAG",
+          "SERVICE_INTERFACE",
+          "KEY_SEARCH_RESULTS",
+          "RESULT_OK",
+          "RESULT_PROGRESS_UPDATE",
+          "RESULT_FLAG_OPTION_NOT_HANDLED"
+        ]
+      },
+      "android/support/v13/app/FragmentPagerAdapter": {
+        "androidx/app/FragmentPagerAdapter": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/design/widget/BaseTransientBottomBar$BaseCallback": {
+        "androidx/design/widget/BaseTransientBottomBar$BaseCallback": [
+          "DISMISS_EVENT_MANUAL",
+          "DISMISS_EVENT_SWIPE",
+          "DISMISS_EVENT_TIMEOUT",
+          "DISMISS_EVENT_ACTION",
+          "DISMISS_EVENT_CONSECUTIVE"
+        ]
+      },
+      "android/support/v7/widget/GapWorker": {
+        "androidx/widget/GapWorker": [
+          "sGapWorker",
+          "sTaskComparator"
+        ]
+      },
+      "android/support/v7/preference/PreferenceManager": {
+        "androidx/preference/PreferenceManager": [
+          "STORAGE_DEFAULT",
+          "KEY_HAS_SET_DEFAULT_VALUES",
+          "STORAGE_DEVICE_PROTECTED"
+        ]
+      },
+      "android/support/v4/widget/SlidingPaneLayout$LayoutParams": {
+        "androidx/widget/SlidingPaneLayout$LayoutParams": [
+          "width",
+          "ATTRS",
+          "height",
+          "dimPaint",
+          "leftMargin",
+          "weight",
+          "slideable",
+          "rightMargin",
+          "dimWhenOffset"
+        ]
+      },
+      "android/support/v17/leanback/widget/GuidedAction": {
+        "androidx/leanback/widget/GuidedAction": [
+          "ACTION_ID_CONTINUE",
+          "PF_ENABLED",
+          "ACTION_ID_YES",
+          "ACTION_ID_OK",
+          "ACTION_ID_NO",
+          "PF_INFO_ONLY",
+          "ACTION_ID_FINISH",
+          "TAG",
+          "EDITING_TITLE",
+          "EDITING_DESCRIPTION",
+          "PF_MULTI_lINE_DESCRIPTION",
+          "PF_CHECKED",
+          "DEFAULT_CHECK_SET_ID",
+          "ACTION_ID_CURRENT",
+          "CHECKBOX_CHECK_SET_ID",
+          "EDITING_NONE",
+          "PF_AUTORESTORE",
+          "EDITING_ACTIVATOR_VIEW",
+          "PF_HAS_NEXT",
+          "ACTION_ID_NEXT",
+          "ACTION_ID_CANCEL",
+          "PF_FOCUSABLE",
+          "NO_CHECK_SET"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat$PreviewPrograms": {
+        "androidx/media/tv/TvContractCompat$PreviewPrograms": [
+          "COLUMN_CHANNEL_ID",
+          "CONTENT_ITEM_TYPE",
+          "CONTENT_URI",
+          "CONTENT_TYPE",
+          "COLUMN_WEIGHT"
+        ]
+      },
+      "android/support/v17/leanback/widget/BaseCardView": {
+        "androidx/leanback/widget/BaseCardView": [
+          "CARD_TYPE_INFO_OVER",
+          "CARD_TYPE_INVALID",
+          "DEBUG",
+          "CARD_TYPE_INFO_UNDER",
+          "CARD_TYPE_MAIN_ONLY",
+          "LB_PRESSED_STATE_SET",
+          "CARD_REGION_VISIBLE_ALWAYS",
+          "CARD_REGION_VISIBLE_SELECTED",
+          "TAG",
+          "CARD_TYPE_INFO_UNDER_WITH_EXTRA",
+          "CARD_REGION_VISIBLE_ACTIVATED"
+        ]
+      },
+      "android/support/v7/mediarouter/R$string": {
+        "androidx/mediarouter/R$string": [
+          "mr_user_route_category_name",
+          "mr_controller_no_info_available",
+          "mr_system_route_name",
+          "mr_controller_disconnect",
+          "mr_cast_button_disconnected",
+          "mr_controller_casting_screen",
+          "mr_button_content_description",
+          "mr_controller_no_media_selected",
+          "mr_controller_expand_group",
+          "mr_controller_play",
+          "mr_controller_stop",
+          "mr_cast_button_connected",
+          "mr_controller_pause",
+          "mr_controller_collapse_group",
+          "mr_cast_button_connecting",
+          "mr_controller_stop_casting"
+        ]
+      },
+      "android/support/multidex/BuildConfig": {
+        "androidx/multidex/BuildConfig": [
+          "DEBUG",
+          "APPLICATION_ID",
+          "FLAVOR",
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "VERSION_CODE"
+        ]
+      },
+      "android/support/v4/text/util/LinkifyCompat$LinkSpec": {
+        "androidx/text/util/LinkifyCompat$LinkSpec": [
+          "end",
+          "url",
+          "frameworkAddedSpan",
+          "start"
+        ]
+      },
+      "android/support/transition/ArcMotion": {
+        "androidx/transition/ArcMotion": [
+          "DEFAULT_MIN_ANGLE_DEGREES",
+          "DEFAULT_MAX_ANGLE_DEGREES",
+          "DEFAULT_MAX_TANGENT"
+        ]
+      },
+      "android/support/v17/leanback/widget/TitleViewAdapter": {
+        "androidx/leanback/widget/TitleViewAdapter": [
+          "BRANDING_VIEW_VISIBLE",
+          "FULL_VIEW_VISIBLE",
+          "SEARCH_VIEW_VISIBLE"
+        ]
+      },
+      "android/support/v17/leanback/app/DetailsFragment": {
+        "androidx/leanback/app/DetailsFragment": [
+          "EVT_ON_CREATE",
+          "EVT_SWITCH_TO_VIDEO",
+          "STATE_ENTRANCE_INIT",
+          "STATE_SWITCH_TO_VIDEO_IN_ON_CREATE",
+          "STATE_START",
+          "EVT_DETAILS_ROW_LOADED",
+          "STATE_ENTER_TRANSITION_INIT",
+          "STATE_ENTER_TRANSITION_CANCEL",
+          "COND_TRANSITION_NOT_SUPPORTED",
+          "STATE_ENTRANCE_ON_PREPARED",
+          "EVT_NO_ENTER_TRANSITION",
+          "EVT_ON_CREATEVIEW",
+          "STATE_ENTER_TRANSITION_PENDING",
+          "EVT_ONSTART",
+          "STATE_ON_SAFE_START",
+          "DEBUG",
+          "EVT_ENTER_TRANSIITON_DONE",
+          "STATE_SET_ENTRANCE_START_STATE",
+          "STATE_ENTRANCE_PERFORM",
+          "STATE_ENTRANCE_COMPLETE",
+          "STATE_ENTER_TRANSITION_COMPLETE",
+          "STATE_ENTER_TRANSITION_ADDLISTENER",
+          "TAG"
+        ]
+      },
+      "android/support/v7/widget/FastScroller": {
+        "androidx/widget/FastScroller": [
+          "ANIMATION_STATE_OUT",
+          "ANIMATION_STATE_IN",
+          "SHOW_DURATION_MS",
+          "STATE_VISIBLE",
+          "DRAG_NONE",
+          "STATE_HIDDEN",
+          "ANIMATION_STATE_FADING_IN",
+          "STATE_DRAGGING",
+          "HIDE_DELAY_AFTER_VISIBLE_MS",
+          "DRAG_X",
+          "DRAG_Y",
+          "HIDE_DELAY_AFTER_DRAGGING_MS",
+          "HIDE_DURATION_MS",
+          "SCROLLBAR_FULL_OPAQUE",
+          "ANIMATION_STATE_FADING_OUT",
+          "PRESSED_STATE_SET",
+          "EMPTY_STATE_SET"
+        ]
+      },
+      "android/support/v7/media/MediaRouteDescriptor": {
+        "androidx/media/MediaRouteDescriptor": [
+          "KEY_VOLUME",
+          "KEY_PLAYBACK_TYPE",
+          "KEY_SETTINGS_INTENT",
+          "KEY_ID",
+          "KEY_ENABLED",
+          "KEY_MAX_CLIENT_VERSION",
+          "KEY_ICON_URI",
+          "KEY_DESCRIPTION",
+          "KEY_PLAYBACK_STREAM",
+          "KEY_GROUP_MEMBER_IDS",
+          "KEY_CONNECTION_STATE",
+          "KEY_EXTRAS",
+          "KEY_VOLUME_HANDLING",
+          "KEY_PRESENTATION_DISPLAY_ID",
+          "KEY_MIN_CLIENT_VERSION",
+          "KEY_CONTROL_FILTERS",
+          "KEY_CAN_DISCONNECT",
+          "KEY_DEVICE_TYPE",
+          "KEY_NAME",
+          "KEY_VOLUME_MAX",
+          "KEY_CONNECTING"
+        ]
+      },
+      "android/support/design/widget/BottomNavigationView": {
+        "androidx/design/widget/BottomNavigationView": [
+          "DISABLED_STATE_SET",
+          "CHECKED_STATE_SET",
+          "EMPTY_STATE_SET",
+          "MENU_PRESENTER_ID"
+        ]
+      },
+      "android/support/multidex/instrumentation/BuildConfig": {
+        "androidx/multidex/instrumentation/BuildConfig": [
+          "VERSION_NAME",
+          "VERSION_CODE",
+          "APPLICATION_ID",
+          "BUILD_TYPE",
+          "FLAVOR",
+          "DEBUG"
+        ]
+      },
+      "android/support/wear/widget/drawer/WearableActionDrawerView": {
+        "androidx/wear/widget/drawer/WearableActionDrawerView": [
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/media/PlaybackBaseControlGlue": {
+        "androidx/leanback/media/PlaybackBaseControlGlue": [
+          "ACTION_FAST_FORWARD",
+          "DEBUG",
+          "ACTION_CUSTOM_LEFT_FIRST",
+          "ACTION_SKIP_TO_PREVIOUS",
+          "TAG",
+          "ACTION_SKIP_TO_NEXT",
+          "ACTION_CUSTOM_RIGHT_FIRST",
+          "ACTION_PLAY_PAUSE",
+          "ACTION_REPEAT",
+          "ACTION_REWIND",
+          "ACTION_SHUFFLE"
+        ]
+      },
+      "android/support/v4/app/AppLaunchChecker": {
+        "androidx/app/AppLaunchChecker": [
+          "KEY_STARTED_FROM_LAUNCHER",
+          "SHARED_PREFS_NAME"
+        ]
+      },
+      "android/support/transition/Styleable$ArcMotion": {
+        "androidx/transition/Styleable$ArcMotion": [
+          "MAXIMUM_ANGLE",
+          "MINIMUM_VERTICAL_ANGLE",
+          "MINIMUM_HORIZONTAL_ANGLE"
+        ]
+      },
+      "android/support/v7/cardview/R$color": {
+        "androidx/cardview/R$color": [
+          "cardview_shadow_end_color",
+          "cardview_light_background",
+          "cardview_dark_background",
+          "cardview_shadow_start_color"
+        ]
+      },
+      "android/support/v17/leanback/app/BrowseFragment": {
+        "androidx/leanback/app/BrowseFragment": [
+          "TAG",
+          "EVT_SCREEN_DATA_READY",
+          "LB_HEADERS_BACKSTACK",
+          "STATE_ENTRANCE_PERFORM",
+          "IS_PAGE_ROW",
+          "ARG_TITLE",
+          "HEADERS_HIDDEN",
+          "HEADER_SHOW",
+          "EVT_MAIN_FRAGMENT_VIEW_CREATED",
+          "CURRENT_SELECTED_POSITION",
+          "DEBUG",
+          "EVT_HEADER_VIEW_CREATED",
+          "STATE_ENTRANCE_ON_PREPARED",
+          "HEADERS_ENABLED",
+          "ARG_HEADERS_STATE",
+          "STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW",
+          "STATE_SET_ENTRANCE_START_STATE",
+          "HEADERS_DISABLED",
+          "HEADER_STACK_INDEX"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat$ProgramColumns": {
+        "androidx/media/tv/TvContractCompat$ProgramColumns": [
+          "COLUMN_SHORT_DESCRIPTION",
+          "COLUMN_SEASON_DISPLAY_NUMBER",
+          "COLUMN_SEASON_TITLE",
+          "COLUMN_VIDEO_WIDTH",
+          "COLUMN_AUDIO_LANGUAGE",
+          "REVIEW_RATING_STYLE_STARS",
+          "COLUMN_EPISODE_TITLE",
+          "REVIEW_RATING_STYLE_THUMBS_UP_DOWN",
+          "COLUMN_INTERNAL_PROVIDER_FLAG2",
+          "COLUMN_INTERNAL_PROVIDER_FLAG3",
+          "COLUMN_INTERNAL_PROVIDER_FLAG4",
+          "COLUMN_INTERNAL_PROVIDER_FLAG1",
+          "COLUMN_TITLE",
+          "COLUMN_POSTER_ART_URI",
+          "COLUMN_VERSION_NUMBER",
+          "COLUMN_THUMBNAIL_URI",
+          "REVIEW_RATING_STYLE_PERCENTAGE",
+          "COLUMN_EPISODE_DISPLAY_NUMBER",
+          "COLUMN_SEARCHABLE",
+          "COLUMN_VIDEO_HEIGHT",
+          "COLUMN_CANONICAL_GENRE",
+          "COLUMN_CONTENT_RATING",
+          "COLUMN_REVIEW_RATING",
+          "COLUMN_REVIEW_RATING_STYLE",
+          "COLUMN_LONG_DESCRIPTION",
+          "COLUMN_INTERNAL_PROVIDER_DATA"
+        ]
+      },
+      "android/support/v4/graphics/PaintCompat": {
+        "androidx/graphics/PaintCompat": [
+          "TOFU_STRING",
+          "sRectThreadLocal",
+          "EM_STRING"
+        ]
+      },
+      "android/support/v4/view/accessibility/AccessibilityEventCompat": {
+        "androidx/view/accessibility/AccessibilityEventCompat": [
+          "CONTENT_CHANGE_TYPE_UNDEFINED",
+          "TYPE_ANNOUNCEMENT",
+          "TYPE_TOUCH_INTERACTION_END",
+          "CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION",
+          "TYPE_TOUCH_INTERACTION_START",
+          "TYPE_TOUCH_EXPLORATION_GESTURE_END",
+          "TYPE_VIEW_HOVER_ENTER",
+          "TYPE_VIEW_ACCESSIBILITY_FOCUSED",
+          "CONTENT_CHANGE_TYPE_TEXT",
+          "TYPE_WINDOW_CONTENT_CHANGED",
+          "TYPES_ALL_MASK",
+          "TYPE_TOUCH_EXPLORATION_GESTURE_START",
+          "TYPE_WINDOWS_CHANGED",
+          "TYPE_VIEW_CONTEXT_CLICKED",
+          "TYPE_VIEW_HOVER_EXIT",
+          "CONTENT_CHANGE_TYPE_SUBTREE",
+          "TYPE_ASSIST_READING_CONTEXT",
+          "TYPE_VIEW_TEXT_SELECTION_CHANGED",
+          "TYPE_GESTURE_DETECTION_START",
+          "TYPE_VIEW_SCROLLED",
+          "TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY",
+          "TYPE_GESTURE_DETECTION_END",
+          "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED"
+        ]
+      },
+      "android/support/v17/leanback/R$attr": {
+        "androidx/leanback/R$attr": [
+          "guidedActionContentWidthWeightTwoPanels",
+          "onboardingTheme",
+          "playbackProgressPrimaryColor",
+          "guidedActionTitleMaxLines",
+          "guidedActionPressedAnimation",
+          "playbackMediaItemNumberViewFlipperLayout",
+          "imageCardViewStyle",
+          "playbackControlsActionIcons",
+          "browseTitleViewLayout",
+          "playbackControlsIconHighlightColor",
+          "guidedStepTheme",
+          "guidedActionTitleMinLines",
+          "defaultBrandColorDark",
+          "baseCardViewStyle",
+          "browseTitleViewStyle",
+          "guidedActionVerticalPadding",
+          "guidedActionDisabledChevronAlpha",
+          "searchOrbViewStyle",
+          "defaultBrandColor",
+          "guidedStepThemeFlag",
+          "rowHeaderStyle",
+          "guidedActionDescriptionMinLines",
+          "guidedActionUnpressedAnimation",
+          "guidedActionEnabledChevronAlpha"
+        ]
+      },
+      "android/support/media/ExifInterface$ExifTag": {
+        "androidx/media/ExifInterface$ExifTag": [
+          "number",
+          "primaryFormat",
+          "name",
+          "secondaryFormat"
+        ]
+      },
+      "android/support/v4/widget/ContentLoadingProgressBar": {
+        "androidx/widget/ContentLoadingProgressBar": [
+          "MIN_DELAY",
+          "MIN_SHOW_TIME"
+        ]
+      },
+      "android/support/transition/ViewGroupUtilsApi14": {
+        "androidx/transition/ViewGroupUtilsApi14": [
+          "TAG",
+          "LAYOUT_TRANSITION_CHANGING",
+          "sEmptyLayoutTransition",
+          "sCancelMethod",
+          "sLayoutSuppressedField",
+          "sCancelMethodFetched",
+          "sLayoutSuppressedFieldFetched"
+        ]
+      },
+      "android/support/design/internal/NavigationMenuPresenter$NavigationMenuAdapter": {
+        "androidx/design/internal/NavigationMenuPresenter$NavigationMenuAdapter": [
+          "STATE_ACTION_VIEWS",
+          "VIEW_TYPE_SEPARATOR",
+          "VIEW_TYPE_HEADER",
+          "VIEW_TYPE_SUBHEADER",
+          "VIEW_TYPE_NORMAL",
+          "STATE_CHECKED_ITEM"
+        ]
+      },
+      "android/support/v4/os/LocaleListHelper": {
+        "androidx/os/LocaleListHelper": [
+          "EN_LATN",
+          "LOCALE_EN_XA",
+          "sDefaultAdjustedLocaleList",
+          "sLock",
+          "sLastExplicitlySetLocaleList",
+          "sEmptyLocaleList",
+          "sEmptyList",
+          "NUM_PSEUDO_LOCALES",
+          "STRING_AR_XB",
+          "sDefaultLocaleList",
+          "sLastDefaultLocale",
+          "STRING_EN_XA",
+          "LOCALE_AR_XB"
+        ]
+      },
+      "android/support/v4/app/NotificationCompat$CarExtender": {
+        "androidx/app/NotificationCompat$CarExtender": [
+          "KEY_TIMESTAMP",
+          "EXTRA_LARGE_ICON",
+          "KEY_ON_READ",
+          "KEY_PARTICIPANTS",
+          "KEY_ON_REPLY",
+          "KEY_AUTHOR",
+          "KEY_REMOTE_INPUT",
+          "KEY_TEXT",
+          "KEY_MESSAGES",
+          "EXTRA_CAR_EXTENDER",
+          "EXTRA_COLOR",
+          "EXTRA_CONVERSATION"
+        ]
+      },
+      "android/support/wear/R$layout": {
+        "androidx/wear/R$layout": [
+          "ws_navigation_drawer_item_view",
+          "ws_single_page_nav_drawer_7_item",
+          "ws_single_page_nav_drawer_4_item",
+          "ws_action_drawer_item_view",
+          "ws_single_page_nav_drawer_2_item",
+          "ws_navigation_drawer_view",
+          "ws_single_page_nav_drawer_5_item",
+          "ws_wearable_drawer_view",
+          "ws_single_page_nav_drawer_3_item",
+          "ws_single_page_nav_drawer_peek_view",
+          "ws_action_drawer_title_view",
+          "ws_action_drawer_peek_view",
+          "ws_single_page_nav_drawer_1_item",
+          "ws_single_page_nav_drawer_6_item"
+        ]
+      },
+      "android/support/v4/content/pm/ActivityInfoCompat": {
+        "androidx/content/pm/ActivityInfoCompat": [
+          "CONFIG_UI_MODE"
+        ]
+      },
+      "android/support/v7/mediarouter/R$layout": {
+        "androidx/mediarouter/R$layout": [
+          "mr_chooser_dialog",
+          "mr_controller_material_dialog_b",
+          "mr_chooser_list_item",
+          "mr_controller_volume_item"
+        ]
+      },
+      "android/support/v7/app/AppCompatDelegateImplV9$PanelFeatureState": {
+        "androidx/app/AppCompatDelegateImplV9$PanelFeatureState": [
+          "x",
+          "y",
+          "frozenActionViewState",
+          "refreshDecorView",
+          "createdPanelView",
+          "frozenMenuState",
+          "qwertyMode",
+          "featureId",
+          "listPresenterContext",
+          "listMenuPresenter",
+          "decorView",
+          "isPrepared",
+          "wasLastOpen",
+          "isOpen",
+          "gravity",
+          "background",
+          "isHandled",
+          "windowAnimations",
+          "refreshMenuContent",
+          "shownPanelView",
+          "menu"
+        ]
+      },
+      "android/support/v4/graphics/TypefaceCompatBaseImpl": {
+        "androidx/graphics/TypefaceCompatBaseImpl": [
+          "TAG",
+          "CACHE_FILE_PREFIX"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat$PreviewProgramColumns": {
+        "androidx/media/tv/TvContractCompat$PreviewProgramColumns": [
+          "COLUMN_DURATION_MILLIS",
+          "COLUMN_LIVE",
+          "COLUMN_OFFER_PRICE",
+          "AVAILABILITY_PURCHASED",
+          "COLUMN_INTERACTION_COUNT",
+          "INTERACTION_TYPE_FOLLOWERS",
+          "INTERACTION_TYPE_FANS",
+          "COLUMN_GENRE",
+          "INTERACTION_TYPE_LISTENS",
+          "AVAILABILITY_PAID_CONTENT",
+          "COLUMN_START_TIME_UTC_MILLIS",
+          "COLUMN_INTERACTION_TYPE",
+          "TYPE_MOVIE",
+          "TYPE_GAME",
+          "TYPE_ALBUM",
+          "TYPE_TRACK",
+          "COLUMN_POSTER_ART_ASPECT_RATIO",
+          "TYPE_EVENT",
+          "COLUMN_AVAILABILITY",
+          "COLUMN_BROWSABLE",
+          "COLUMN_INTENT_URI",
+          "COLUMN_LOGO_URI",
+          "TYPE_TV_SERIES",
+          "COLUMN_ITEM_COUNT",
+          "INTERACTION_TYPE_VIEWS",
+          "COLUMN_PREVIEW_AUDIO_URI",
+          "AVAILABILITY_FREE_WITH_SUBSCRIPTION",
+          "COLUMN_PREVIEW_VIDEO_URI",
+          "COLUMN_LAST_PLAYBACK_POSITION_MILLIS",
+          "COLUMN_END_TIME_UTC_MILLIS",
+          "ASPECT_RATIO_4_3",
+          "INTERACTION_TYPE_THUMBS",
+          "INTERACTION_TYPE_VIEWERS",
+          "COLUMN_TYPE",
+          "ASPECT_RATIO_3_2",
+          "COLUMN_AUTHOR",
+          "TYPE_TV_EPISODE",
+          "ASPECT_RATIO_1_1",
+          "ASPECT_RATIO_2_3",
+          "COLUMN_INTERNAL_PROVIDER_ID",
+          "ASPECT_RATIO_MOVIE_POSTER",
+          "TYPE_CHANNEL",
+          "COLUMN_LOGO_CONTENT_DESCRIPTION",
+          "AVAILABILITY_FREE",
+          "COLUMN_TRANSIENT",
+          "TYPE_STATION",
+          "INTERACTION_TYPE_LIKES",
+          "TYPE_TV_SEASON",
+          "AVAILABILITY_AVAILABLE",
+          "TYPE_PLAYLIST",
+          "ASPECT_RATIO_16_9",
+          "COLUMN_RELEASE_DATE",
+          "COLUMN_CONTENT_ID",
+          "TYPE_ARTIST",
+          "COLUMN_THUMBNAIL_ASPECT_RATIO",
+          "COLUMN_STARTING_PRICE",
+          "TYPE_CLIP"
+        ]
+      },
+      "android/support/wear/widget/BoxInsetLayout": {
+        "androidx/wear/widget/BoxInsetLayout": [
+          "FACTOR",
+          "DEFAULT_CHILD_GRAVITY"
+        ]
+      },
+      "android/support/v7/graphics/ColorCutQuantizer": {
+        "androidx/graphics/palette/ColorCutQuantizer": [
+          "LOG_TAG",
+          "COMPONENT_GREEN",
+          "VBOX_COMPARATOR_VOLUME",
+          "LOG_TIMINGS",
+          "COMPONENT_RED",
+          "COMPONENT_BLUE",
+          "QUANTIZE_WORD_WIDTH",
+          "QUANTIZE_WORD_MASK"
+        ]
+      },
+      "android/support/text/emoji/flatbuffer/Struct": {
+        "androidx/text/emoji/flatbuffer/Struct": [
+          "bb",
+          "bb_pos"
+        ]
+      },
+      "android/support/media/instantvideo/BuildConfig": {
+        "androidx/media/instantvideo/BuildConfig": [
+          "VERSION_CODE",
+          "DEBUG",
+          "FLAVOR",
+          "APPLICATION_ID",
+          "BUILD_TYPE",
+          "VERSION_NAME"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompat": {
+        "androidx/media/session/MediaSessionCompat": [
+          "TAG",
+          "EXTRA_BINDER",
+          "ARGUMENT_MEDIA_ATTRIBUTE_VALUE",
+          "ACTION_PREPARE_FROM_MEDIA_ID",
+          "ACTION_FLAG_AS_INAPPROPRIATE",
+          "ACTION_SET_CAPTIONING_ENABLED",
+          "MEDIA_ATTRIBUTE_PLAYLIST",
+          "sMaxBitmapSize",
+          "MAX_BITMAP_SIZE_IN_DP",
+          "FLAG_HANDLES_MEDIA_BUTTONS",
+          "ACTION_ARGUMENT_CAPTIONING_ENABLED",
+          "ACTION_SET_SHUFFLE_MODE",
+          "ACTION_ARGUMENT_EXTRAS",
+          "ACTION_SKIP_AD",
+          "ACTION_ARGUMENT_REPEAT_MODE",
+          "FLAG_HANDLES_TRANSPORT_CONTROLS",
+          "ACTION_ARGUMENT_QUERY",
+          "ACTION_ARGUMENT_MEDIA_ID",
+          "ACTION_PREPARE_FROM_SEARCH",
+          "FLAG_HANDLES_QUEUE_COMMANDS",
+          "ACTION_UNFOLLOW",
+          "ACTION_ARGUMENT_RATING",
+          "ACTION_ARGUMENT_URI",
+          "ACTION_PLAY_FROM_URI",
+          "MEDIA_ATTRIBUTE_ALBUM",
+          "ACTION_SET_RATING",
+          "ACTION_SET_REPEAT_MODE",
+          "ACTION_ARGUMENT_SHUFFLE_MODE",
+          "ACTION_FOLLOW",
+          "ACTION_PREPARE_FROM_URI",
+          "ACTION_PREPARE",
+          "ARGUMENT_MEDIA_ATTRIBUTE",
+          "MEDIA_ATTRIBUTE_ARTIST"
+        ]
+      },
+      "android/support/v17/leanback/widget/GridLayoutManager": {
+        "androidx/leanback/widget/GridLayoutManager": [
+          "PREV_ROW",
+          "NEXT_ITEM",
+          "DEBUG",
+          "DEFAULT_MAX_PENDING_MOVES",
+          "TRACE",
+          "MIN_MS_SMOOTH_SCROLL_MAIN_SCREEN",
+          "sTempRect",
+          "NEXT_ROW",
+          "TAG",
+          "PREV_ITEM",
+          "sTwoInts"
+        ]
+      },
+      "android/support/v14/preference/BuildConfig": {
+        "androidx/preference/BuildConfig": [
+          "APPLICATION_ID",
+          "DEBUG",
+          "VERSION_CODE",
+          "FLAVOR",
+          "BUILD_TYPE",
+          "VERSION_NAME"
+        ]
+      },
+      "android/support/v4/util/TimeUtils": {
+        "androidx/util/TimeUtils": [
+          "HUNDRED_DAY_FIELD_LEN",
+          "SECONDS_PER_MINUTE",
+          "sFormatSync",
+          "sFormatStr",
+          "SECONDS_PER_DAY",
+          "SECONDS_PER_HOUR"
+        ]
+      },
+      "android/support/v4/view/accessibility/AccessibilityWindowInfoCompat": {
+        "androidx/view/accessibility/AccessibilityWindowInfoCompat": [
+          "TYPE_APPLICATION",
+          "TYPE_SYSTEM",
+          "TYPE_ACCESSIBILITY_OVERLAY",
+          "TYPE_INPUT_METHOD",
+          "UNDEFINED",
+          "TYPE_SPLIT_SCREEN_DIVIDER"
+        ]
+      },
+      "android/support/v17/leanback/app/VerticalGridFragment": {
+        "androidx/leanback/app/VerticalGridFragment": [
+          "STATE_SET_ENTRANCE_START_STATE",
+          "EVT_ON_CREATEVIEW",
+          "STATE_ENTRANCE_ON_PREPARED",
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v4/app/FrameMetricsAggregator": {
+        "androidx/app/FrameMetricsAggregator": [
+          "COMMAND_INDEX",
+          "SWAP_DURATION",
+          "SYNC_INDEX",
+          "ANIMATION_INDEX",
+          "LAYOUT_MEASURE_DURATION",
+          "INPUT_INDEX",
+          "TOTAL_INDEX",
+          "LAST_INDEX",
+          "LAYOUT_MEASURE_INDEX",
+          "DELAY_DURATION",
+          "COMMAND_DURATION",
+          "DBG",
+          "INPUT_DURATION",
+          "SWAP_INDEX",
+          "SYNC_DURATION",
+          "TOTAL_DURATION",
+          "TAG",
+          "ANIMATION_DURATION",
+          "DRAW_DURATION",
+          "DRAW_INDEX",
+          "EVERY_DURATION",
+          "DELAY_INDEX"
+        ]
+      },
+      "android/support/design/widget/FloatingActionButtonImpl": {
+        "androidx/design/widget/FloatingActionButtonImpl": [
+          "PRESSED_ENABLED_STATE_SET",
+          "PRESSED_ANIM_DURATION",
+          "PRESSED_ANIM_DELAY",
+          "FOCUSED_ENABLED_STATE_SET",
+          "ANIM_STATE_NONE",
+          "EMPTY_STATE_SET",
+          "ANIM_INTERPOLATOR",
+          "ENABLED_STATE_SET",
+          "ANIM_STATE_SHOWING",
+          "SHOW_HIDE_ANIM_DURATION",
+          "ANIM_STATE_HIDING"
+        ]
+      },
+      "android/support/transition/R$id": {
+        "androidx/transition/R$id": [
+          "transition_transform",
+          "ghost_view",
+          "transition_scene_layoutid_cache",
+          "save_image_matrix",
+          "save_scale_type",
+          "transition_current_scene",
+          "transition_layout_save",
+          "parent_matrix",
+          "transition_position",
+          "save_non_transition_alpha"
+        ]
+      },
+      "android/support/v7/app/ResourcesFlusher": {
+        "androidx/app/ResourcesFlusher": [
+          "sDrawableCacheField",
+          "sThemedResourceCacheClazz",
+          "sResourcesImplFieldFetched",
+          "sDrawableCacheFieldFetched",
+          "TAG",
+          "sThemedResourceCacheClazzFetched",
+          "sResourcesImplField",
+          "sThemedResourceCache_mUnthemedEntriesFieldFetched",
+          "sThemedResourceCache_mUnthemedEntriesField"
+        ]
+      },
+      "android/support/v4/app/RemoteInput": {
+        "androidx/app/RemoteInput": [
+          "EXTRA_RESULTS_DATA",
+          "TAG",
+          "RESULTS_CLIP_LABEL",
+          "EXTRA_DATA_TYPE_RESULTS_DATA"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat$Programs$Genres": {
+        "androidx/media/tv/TvContractCompat$Programs$Genres": [
+          "EDUCATION",
+          "DELIMITER",
+          "LIFE_STYLE",
+          "SPORTS",
+          "GAMING",
+          "TECH_SCIENCE",
+          "DOUBLE_QUOTE",
+          "TRAVEL",
+          "CANONICAL_GENRES",
+          "MOVIES",
+          "FAMILY_KIDS",
+          "NEWS",
+          "ENTERTAINMENT",
+          "PREMIER",
+          "ARTS",
+          "EMPTY_STRING_ARRAY",
+          "DRAMA",
+          "MUSIC",
+          "COMMA",
+          "COMEDY",
+          "SHOPPING",
+          "ANIMAL_WILDLIFE"
+        ]
+      },
+      "android/support/v4/view/GravityCompat": {
+        "androidx/view/GravityCompat": [
+          "START",
+          "END",
+          "RELATIVE_LAYOUT_DIRECTION",
+          "RELATIVE_HORIZONTAL_GRAVITY_MASK"
+        ]
+      },
+      "android/support/design/R$color": {
+        "androidx/design/R$color": [
+          "design_fab_shadow_start_color",
+          "design_bottom_navigation_shadow_color",
+          "design_fab_stroke_end_outer_color",
+          "design_fab_shadow_mid_color",
+          "design_fab_stroke_end_inner_color",
+          "design_fab_shadow_end_color",
+          "design_fab_stroke_top_inner_color",
+          "design_fab_stroke_top_outer_color"
+        ]
+      },
+      "android/support/v4/view/LayoutInflaterCompat": {
+        "androidx/view/LayoutInflaterCompat": [
+          "sLayoutInflaterFactory2Field",
+          "TAG",
+          "sCheckedField",
+          "IMPL"
+        ]
+      },
+      "android/support/v13/view/inputmethod/EditorInfoCompat": {
+        "androidx/view/inputmethod/EditorInfoCompat": [
+          "IMPL",
+          "IME_FLAG_NO_PERSONALIZED_LEARNING",
+          "EMPTY_STRING_ARRAY",
+          "IME_FLAG_FORCE_ASCII"
+        ]
+      },
+      "android/support/v17/leanback/app/OnboardingSupportFragment": {
+        "androidx/leanback/app/OnboardingSupportFragment": [
+          "KEY_ENTER_ANIMATION_FINISHED",
+          "KEY_CURRENT_PAGE_INDEX",
+          "DEBUG",
+          "HEADER_DISAPPEAR_INTERPOLATOR",
+          "sSlideDistance",
+          "LOGO_SPLASH_PAUSE_DURATION_MS",
+          "HEADER_APPEAR_DELAY_MS",
+          "HEADER_ANIMATION_DURATION_MS",
+          "TAG",
+          "HEADER_APPEAR_INTERPOLATOR",
+          "DESCRIPTION_START_DELAY_MS",
+          "SLIDE_DISTANCE",
+          "KEY_LOGO_ANIMATION_FINISHED"
+        ]
+      },
+      "android/support/v4/app/BackStackRecord": {
+        "androidx/app/BackStackRecord": [
+          "TAG",
+          "OP_SET_PRIMARY_NAV",
+          "OP_DETACH",
+          "OP_NULL",
+          "OP_UNSET_PRIMARY_NAV",
+          "OP_REMOVE",
+          "OP_HIDE",
+          "OP_SHOW",
+          "OP_ADD",
+          "OP_REPLACE",
+          "OP_ATTACH"
+        ]
+      },
+      "android/support/v7/util/DiffUtil$DiffResult": {
+        "androidx/util/DiffUtil$DiffResult": [
+          "FLAG_MOVED_CHANGED",
+          "FLAG_IGNORE",
+          "FLAG_MASK",
+          "FLAG_OFFSET",
+          "FLAG_MOVED_NOT_CHANGED",
+          "FLAG_CHANGED",
+          "FLAG_NOT_CHANGED"
+        ]
+      },
+      "android/support/wear/widget/drawer/WearableDrawerView": {
+        "androidx/wear/widget/drawer/WearableDrawerView": [
+          "STATE_DRAGGING",
+          "STATE_SETTLING",
+          "STATE_IDLE"
+        ]
+      },
+      "android/support/wear/R$string": {
+        "androidx/wear/R$string": [
+          "ws_action_drawer_content_description",
+          "ws_navigation_drawer_content_description"
+        ]
+      },
+      "android/support/design/widget/SwipeDismissBehavior": {
+        "androidx/design/widget/SwipeDismissBehavior": [
+          "DEFAULT_ALPHA_START_DISTANCE",
+          "STATE_IDLE",
+          "STATE_DRAGGING",
+          "SWIPE_DIRECTION_START_TO_END",
+          "DEFAULT_ALPHA_END_DISTANCE",
+          "DEFAULT_DRAG_DISMISS_THRESHOLD",
+          "SWIPE_DIRECTION_ANY",
+          "STATE_SETTLING",
+          "SWIPE_DIRECTION_END_TO_START"
+        ]
+      },
+      "android/support/v17/leanback/widget/FullWidthDetailsOverviewSharedElementHelper": {
+        "androidx/leanback/widget/FullWidthDetailsOverviewSharedElementHelper": [
+          "DEFAULT_TIMEOUT",
+          "TAG",
+          "DEBUG"
+        ]
+      },
+      "android/support/transition/Styleable$TransitionTarget": {
+        "androidx/transition/Styleable$TransitionTarget": [
+          "EXCLUDE_CLASS",
+          "EXCLUDE_ID",
+          "TARGET_CLASS",
+          "EXCLUDE_NAME",
+          "TARGET_ID",
+          "TARGET_NAME"
+        ]
+      },
+      "android/support/v4/media/MediaDescriptionCompat": {
+        "androidx/media/MediaDescriptionCompat": [
+          "BT_FOLDER_TYPE_MIXED",
+          "CREATOR",
+          "STATUS_DOWNLOADED",
+          "STATUS_NOT_DOWNLOADED",
+          "EXTRA_BT_FOLDER_TYPE",
+          "BT_FOLDER_TYPE_GENRES",
+          "EXTRA_DOWNLOAD_STATUS",
+          "DESCRIPTION_KEY_MEDIA_URI",
+          "BT_FOLDER_TYPE_ARTISTS",
+          "DESCRIPTION_KEY_NULL_BUNDLE_FLAG",
+          "BT_FOLDER_TYPE_TITLES",
+          "STATUS_DOWNLOADING",
+          "BT_FOLDER_TYPE_YEARS",
+          "BT_FOLDER_TYPE_PLAYLISTS",
+          "BT_FOLDER_TYPE_ALBUMS"
+        ]
+      },
+      "android/support/v4/graphics/ColorUtils": {
+        "androidx/graphics/ColorUtils": [
+          "MIN_ALPHA_SEARCH_MAX_ITERATIONS",
+          "XYZ_KAPPA",
+          "MIN_ALPHA_SEARCH_PRECISION",
+          "TEMP_ARRAY",
+          "XYZ_WHITE_REFERENCE_Z",
+          "XYZ_WHITE_REFERENCE_Y",
+          "XYZ_WHITE_REFERENCE_X",
+          "XYZ_EPSILON"
+        ]
+      },
+      "android/support/v7/widget/AppCompatTextViewAutoSizeHelper": {
+        "androidx/widget/AppCompatTextViewAutoSizeHelper": [
+          "TAG",
+          "DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX",
+          "UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE",
+          "DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP",
+          "VERY_WIDE",
+          "sTextViewMethodByNameCache",
+          "DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP",
+          "TEMP_RECTF"
+        ]
+      },
+      "android/support/design/R$style": {
+        "androidx/design/R$style": [
+          "Widget_Design_ScrimInsetsFrameLayout",
+          "Widget_Design_TextInputLayout",
+          "Widget_Design_TabLayout",
+          "Widget_Design_CollapsingToolbar",
+          "Widget_Design_NavigationView",
+          "TextAppearance_Design_Tab",
+          "Widget_Design_CoordinatorLayout",
+          "Theme_Design_Light_BottomSheetDialog",
+          "Widget_Design_FloatingActionButton",
+          "Widget_Design_AppBarLayout",
+          "Widget_Design_BottomNavigationView",
+          "TextAppearance_Design_CollapsingToolbar_Expanded"
+        ]
+      },
+      "android/support/v7/widget/GridLayoutManager": {
+        "androidx/widget/GridLayoutManager": [
+          "TAG",
+          "DEFAULT_SPAN_COUNT",
+          "DEBUG"
+        ]
+      },
+      "android/support/v7/appcompat/R$dimen": {
+        "androidx/appcompat/R$dimen": [
+          "tooltip_precise_anchor_extra_offset",
+          "abc_dropdownitem_icon_width",
+          "tooltip_precise_anchor_threshold",
+          "tooltip_y_offset_non_touch",
+          "abc_config_prefDialogWidth",
+          "abc_dropdownitem_text_padding_left",
+          "abc_action_bar_stacked_max_height",
+          "abc_search_view_preferred_height",
+          "abc_cascading_menus_min_smallest_width",
+          "abc_action_bar_stacked_tab_max_width",
+          "tooltip_y_offset_touch",
+          "abc_search_view_preferred_width"
+        ]
+      },
+      "android/support/wear/internal/widget/drawer/SinglePageUi": {
+        "androidx/wear/internal/widget/drawer/SinglePageUi": [
+          "SINGLE_PAGE_LAYOUT_RES",
+          "SINGLE_PAGE_BUTTON_IDS"
+        ]
+      },
+      "android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat": {
+        "androidx/accessibilityservice/AccessibilityServiceInfoCompat": [
+          "FLAG_REQUEST_TOUCH_EXPLORATION_MODE",
+          "CAPABILITY_CAN_FILTER_KEY_EVENTS",
+          "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS",
+          "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY",
+          "CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT",
+          "FEEDBACK_BRAILLE",
+          "FEEDBACK_ALL_MASK",
+          "FLAG_REPORT_VIEW_IDS",
+          "CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION",
+          "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY",
+          "FLAG_REQUEST_FILTER_KEY_EVENTS"
+        ]
+      },
+      "android/support/graphics/drawable/AnimatorInflaterCompat": {
+        "androidx/graphics/drawable/AnimatorInflaterCompat": [
+          "MAX_NUM_POINTS",
+          "VALUE_TYPE_INT",
+          "VALUE_TYPE_FLOAT",
+          "VALUE_TYPE_COLOR",
+          "TAG",
+          "DBG_ANIMATOR_INFLATER",
+          "VALUE_TYPE_PATH",
+          "TOGETHER",
+          "VALUE_TYPE_UNDEFINED"
+        ]
+      },
+      "android/support/wear/R$id": {
+        "androidx/wear/R$id": [
+          "ws_navigation_drawer_item_icon",
+          "ws_drawer_view_peek_container",
+          "ws_navigation_drawer_item_text",
+          "ws_action_drawer_item_text",
+          "ws_drawer_view_peek_icon",
+          "ws_nav_drawer_icon_4",
+          "ws_nav_drawer_icon_5",
+          "ws_nav_drawer_icon_6",
+          "ws_nav_drawer_icon_0",
+          "ws_nav_drawer_icon_1",
+          "ws_nav_drawer_icon_2",
+          "ws_nav_drawer_icon_3",
+          "ws_navigation_drawer_page_indicator",
+          "ws_navigation_drawer_view_pager",
+          "ws_nav_drawer_text",
+          "ws_action_drawer_expand_icon",
+          "ws_action_drawer_item_icon",
+          "ws_action_drawer_title",
+          "ws_action_drawer_peek_action_icon"
+        ]
+      },
+      "android/support/v4/view/animation/LinearOutSlowInInterpolator": {
+        "androidx/view/animation/LinearOutSlowInInterpolator": [
+          "VALUES"
+        ]
+      },
+      "android/support/v4/graphics/TypefaceCompatApi24Impl": {
+        "androidx/graphics/TypefaceCompatApi24Impl": [
+          "FONT_FAMILY_CLASS",
+          "sFontFamily",
+          "TAG",
+          "sAddFontWeightStyle",
+          "sFontFamilyCtor",
+          "sCreateFromFamiliesWithDefault",
+          "ADD_FONT_WEIGHT_STYLE_METHOD",
+          "CREATE_FROM_FAMILIES_WITH_DEFAULT_METHOD"
+        ]
+      },
+      "android/support/v7/widget/AdapterHelper": {
+        "androidx/widget/AdapterHelper": [
+          "TAG",
+          "POSITION_TYPE_NEW_OR_LAID_OUT",
+          "DEBUG",
+          "POSITION_TYPE_INVISIBLE"
+        ]
+      },
+      "android/support/wear/BuildConfig": {
+        "androidx/wear/BuildConfig": [
+          "VERSION_CODE",
+          "DEBUG",
+          "FLAVOR",
+          "BUILD_TYPE",
+          "APPLICATION_ID",
+          "VERSION_NAME"
+        ]
+      },
+      "android/support/v4/media/session/ParcelableVolumeInfo": {
+        "androidx/media/session/ParcelableVolumeInfo": [
+          "audioStream",
+          "currentVolume",
+          "maxVolume",
+          "volumeType",
+          "CREATOR",
+          "controlType"
+        ]
+      },
+      "android/support/text/emoji/EmojiCompat": {
+        "androidx/text/emoji/EmojiCompat": [
+          "EDITOR_INFO_REPLACE_ALL_KEY",
+          "sInstanceLock",
+          "EMOJI_COUNT_UNLIMITED",
+          "LOAD_STATE_SUCCEEDED",
+          "EDITOR_INFO_METAVERSION_KEY",
+          "sInstance",
+          "REPLACE_STRATEGY_ALL",
+          "LOAD_STATE_FAILED",
+          "REPLACE_STRATEGY_NON_EXISTENT",
+          "LOAD_STATE_LOADING",
+          "REPLACE_STRATEGY_DEFAULT"
+        ]
+      },
+      "android/support/v7/graphics/Target": {
+        "androidx/graphics/palette/Target": [
+          "TARGET_MUTED_SATURATION",
+          "MUTED",
+          "MIN_NORMAL_LUMA",
+          "MAX_DARK_LUMA",
+          "VIBRANT",
+          "TARGET_LIGHT_LUMA",
+          "TARGET_NORMAL_LUMA",
+          "MAX_NORMAL_LUMA",
+          "WEIGHT_LUMA",
+          "INDEX_WEIGHT_LUMA",
+          "TARGET_VIBRANT_SATURATION",
+          "DARK_MUTED",
+          "DARK_VIBRANT",
+          "INDEX_MAX",
+          "INDEX_MIN",
+          "MAX_MUTED_SATURATION",
+          "MIN_LIGHT_LUMA",
+          "LIGHT_VIBRANT",
+          "LIGHT_MUTED",
+          "INDEX_TARGET",
+          "INDEX_WEIGHT_POP",
+          "TARGET_DARK_LUMA",
+          "WEIGHT_POPULATION",
+          "INDEX_WEIGHT_SAT",
+          "WEIGHT_SATURATION",
+          "MIN_VIBRANT_SATURATION"
+        ]
+      },
+      "android/support/v17/leanback/media/PlaybackControlGlue": {
+        "androidx/leanback/media/PlaybackControlGlue": [
+          "MSG_UPDATE_PLAYBACK_STATE",
+          "PLAYBACK_SPEED_INVALID",
+          "ACTION_REWIND",
+          "sHandler",
+          "ACTION_FAST_FORWARD",
+          "PLAYBACK_SPEED_FAST_L2",
+          "PLAYBACK_SPEED_FAST_L3",
+          "PLAYBACK_SPEED_FAST_L4",
+          "PLAYBACK_SPEED_FAST_L0",
+          "PLAYBACK_SPEED_FAST_L1",
+          "DEBUG",
+          "PLAYBACK_SPEED_PAUSED",
+          "UPDATE_PLAYBACK_STATE_DELAY_MS",
+          "PLAYBACK_SPEED_NORMAL",
+          "TAG",
+          "ACTION_SKIP_TO_NEXT",
+          "ACTION_SKIP_TO_PREVIOUS",
+          "ACTION_CUSTOM_LEFT_FIRST",
+          "ACTION_PLAY_PAUSE",
+          "NUMBER_OF_SEEK_SPEEDS",
+          "ACTION_CUSTOM_RIGHT_FIRST"
+        ]
+      },
+      "android/support/v7/widget/GridLayout$LayoutParams": {
+        "androidx/widget/GridLayout$LayoutParams": [
+          "bottomMargin",
+          "DEFAULT_SPAN",
+          "COLUMN_WEIGHT",
+          "leftMargin",
+          "GRAVITY",
+          "ROW_SPAN",
+          "ROW",
+          "COLUMN",
+          "topMargin",
+          "RIGHT_MARGIN",
+          "height",
+          "COLUMN_SPAN",
+          "rightMargin",
+          "width",
+          "ROW_WEIGHT",
+          "BOTTOM_MARGIN",
+          "DEFAULT_SPAN_SIZE",
+          "columnSpec",
+          "DEFAULT_ROW",
+          "DEFAULT_WIDTH",
+          "MARGIN",
+          "rowSpec",
+          "TOP_MARGIN",
+          "DEFAULT_HEIGHT",
+          "LEFT_MARGIN",
+          "DEFAULT_COLUMN",
+          "DEFAULT_MARGIN"
+        ]
+      },
+      "android/support/v17/leanback/app/DetailsSupportFragment": {
+        "androidx/leanback/app/DetailsSupportFragment": [
+          "EVT_ONSTART",
+          "STATE_ENTER_TRANSITION_CANCEL",
+          "DEBUG",
+          "STATE_SWITCH_TO_VIDEO_IN_ON_CREATE",
+          "STATE_ENTRANCE_COMPLETE",
+          "STATE_ENTER_TRANSITION_COMPLETE",
+          "STATE_ENTER_TRANSITION_ADDLISTENER",
+          "STATE_ENTRANCE_INIT",
+          "EVT_SWITCH_TO_VIDEO",
+          "STATE_START",
+          "STATE_ON_SAFE_START",
+          "STATE_ENTRANCE_PERFORM",
+          "EVT_ON_CREATEVIEW",
+          "STATE_SET_ENTRANCE_START_STATE",
+          "COND_TRANSITION_NOT_SUPPORTED",
+          "TAG",
+          "STATE_ENTER_TRANSITION_PENDING",
+          "EVT_ENTER_TRANSIITON_DONE",
+          "STATE_ENTRANCE_ON_PREPARED",
+          "EVT_ON_CREATE",
+          "EVT_DETAILS_ROW_LOADED",
+          "STATE_ENTER_TRANSITION_INIT",
+          "EVT_NO_ENTER_TRANSITION"
+        ]
+      },
+      "android/support/v17/leanback/app/ListRowDataAdapter": {
+        "androidx/leanback/app/ListRowDataAdapter": [
+          "ON_ITEM_RANGE_INSERTED",
+          "ON_ITEM_RANGE_CHANGED",
+          "ON_ITEM_RANGE_REMOVED",
+          "ON_CHANGED"
+        ]
+      },
+      "android/support/percent/PercentLayoutHelper$PercentLayoutInfo": {
+        "androidx/PercentLayoutHelper$PercentLayoutInfo": [
+          "topMarginPercent",
+          "endMarginPercent",
+          "aspectRatio",
+          "rightMarginPercent",
+          "heightPercent",
+          "leftMarginPercent",
+          "startMarginPercent",
+          "bottomMarginPercent",
+          "widthPercent"
+        ]
+      },
+      "android/support/v17/leanback/system/Settings": {
+        "androidx/leanback/system/Settings": [
+          "OUTLINE_CLIPPING_DISABLED",
+          "PREFER_STATIC_SHADOWS",
+          "DEBUG",
+          "sInstance",
+          "ACTION_PARTNER_CUSTOMIZATION",
+          "TAG"
+        ]
+      },
+      "android/support/v4/util/SimpleArrayMap": {
+        "androidx/util/SimpleArrayMap": [
+          "BASE_SIZE",
+          "CONCURRENT_MODIFICATION_EXCEPTIONS",
+          "DEBUG",
+          "TAG",
+          "CACHE_SIZE"
+        ]
+      },
+      "android/support/v4/widget/AutoScrollHelper": {
+        "androidx/widget/AutoScrollHelper": [
+          "EDGE_TYPE_OUTSIDE",
+          "NO_MIN",
+          "NO_MAX",
+          "HORIZONTAL",
+          "EDGE_TYPE_INSIDE_EXTEND",
+          "DEFAULT_MAXIMUM_EDGE",
+          "VERTICAL",
+          "EDGE_TYPE_INSIDE",
+          "RELATIVE_UNSPECIFIED",
+          "DEFAULT_MAXIMUM_VELOCITY_DIPS",
+          "DEFAULT_RAMP_DOWN_DURATION",
+          "DEFAULT_RELATIVE_VELOCITY",
+          "DEFAULT_ACTIVATION_DELAY",
+          "DEFAULT_MINIMUM_VELOCITY_DIPS",
+          "DEFAULT_RAMP_UP_DURATION",
+          "DEFAULT_EDGE_TYPE",
+          "DEFAULT_RELATIVE_EDGE"
+        ]
+      },
+      "android/support/v7/widget/ViewInfoStore$InfoRecord": {
+        "androidx/widget/ViewInfoStore$InfoRecord": [
+          "FLAG_PRE",
+          "postInfo",
+          "FLAG_APPEAR_AND_DISAPPEAR",
+          "FLAG_PRE_AND_POST",
+          "FLAG_DISAPPEARED",
+          "preInfo",
+          "flags",
+          "FLAG_APPEAR",
+          "FLAG_APPEAR_PRE_AND_POST",
+          "FLAG_POST",
+          "sPool"
+        ]
+      },
+      "android/support/design/widget/AnimationUtils": {
+        "androidx/design/widget/AnimationUtils": [
+          "LINEAR_OUT_SLOW_IN_INTERPOLATOR",
+          "LINEAR_INTERPOLATOR",
+          "FAST_OUT_LINEAR_IN_INTERPOLATOR",
+          "FAST_OUT_SLOW_IN_INTERPOLATOR",
+          "DECELERATE_INTERPOLATOR"
+        ]
+      },
+      "android/support/design/widget/SnackbarManager$SnackbarRecord": {
+        "androidx/design/widget/SnackbarManager$SnackbarRecord": [
+          "duration",
+          "callback",
+          "paused"
+        ]
+      },
+      "android/support/transition/ChangeScroll": {
+        "androidx/transition/ChangeScroll": [
+          "PROPNAME_SCROLL_X",
+          "PROPNAME_SCROLL_Y",
+          "PROPERTIES"
+        ]
+      },
+      "android/support/design/widget/FloatingActionButtonLollipop": {
+        "androidx/design/widget/FloatingActionButtonLollipop": [
+          "EMPTY_STATE_SET",
+          "ENABLED_STATE_SET",
+          "PRESSED_ENABLED_STATE_SET",
+          "ANIM_INTERPOLATOR",
+          "FOCUSED_ENABLED_STATE_SET"
+        ]
+      },
+      "android/support/v4/graphics/TypefaceCompat": {
+        "androidx/graphics/TypefaceCompat": [
+          "sTypefaceCompatImpl",
+          "TAG",
+          "sTypefaceCache"
+        ]
+      },
+      "android/support/v7/widget/LinearSmoothScroller": {
+        "androidx/widget/LinearSmoothScroller": [
+          "MILLISECONDS_PER_PX",
+          "SNAP_TO_ANY",
+          "SNAP_TO_END",
+          "DEBUG",
+          "TAG",
+          "MILLISECONDS_PER_INCH",
+          "TARGET_SEEK_SCROLL_DISTANCE_PX",
+          "TARGET_SEEK_EXTRA_SCROLL_RATIO",
+          "SNAP_TO_START"
+        ]
+      },
+      "android/support/transition/Styleable$ChangeTransform": {
+        "androidx/transition/Styleable$ChangeTransform": [
+          "REPARENT_WITH_OVERLAY",
+          "REPARENT"
+        ]
+      },
+      "android/support/animation/DynamicAnimation": {
+        "androidx/animation/DynamicAnimation": [
+          "MIN_VISIBLE_CHANGE_ALPHA",
+          "MIN_VISIBLE_CHANGE_ROTATION_DEGREES",
+          "UNSET",
+          "ROTATION_Y",
+          "ROTATION_X",
+          "ALPHA",
+          "Z",
+          "X",
+          "Y",
+          "SCROLL_Y",
+          "SCROLL_X",
+          "TRANSLATION_Z",
+          "TRANSLATION_X",
+          "TRANSLATION_Y",
+          "THRESHOLD_MULTIPLIER",
+          "ROTATION",
+          "MIN_VISIBLE_CHANGE_SCALE",
+          "SCALE_Y",
+          "SCALE_X",
+          "MIN_VISIBLE_CHANGE_PIXELS"
+        ]
+      },
+      "android/support/constraint/solver/widgets/ConstraintWidget$DimensionBehaviour": {
+        "androidx/constraint/solver/widgets/ConstraintWidget$DimensionBehaviour": [
+          "FIXED",
+          "MATCH_PARENT",
+          "WRAP_CONTENT",
+          "MATCH_CONSTRAINT"
+        ]
+      },
+      "android/support/v17/leanback/media/PlaybackBannerControlGlue": {
+        "androidx/leanback/media/PlaybackBannerControlGlue": [
+          "PLAYBACK_SPEED_PAUSED",
+          "ACTION_SKIP_TO_PREVIOUS",
+          "ACTION_SKIP_TO_NEXT",
+          "ACTION_CUSTOM_LEFT_FIRST",
+          "TAG",
+          "ACTION_PLAY_PAUSE",
+          "PLAYBACK_SPEED_NORMAL",
+          "ACTION_CUSTOM_RIGHT_FIRST",
+          "NUMBER_OF_SEEK_SPEEDS",
+          "ACTION_REWIND",
+          "PLAYBACK_SPEED_INVALID",
+          "PLAYBACK_SPEED_FAST_L1",
+          "PLAYBACK_SPEED_FAST_L0",
+          "PLAYBACK_SPEED_FAST_L4",
+          "PLAYBACK_SPEED_FAST_L3",
+          "PLAYBACK_SPEED_FAST_L2",
+          "ACTION_FAST_FORWARD"
+        ]
+      },
+      "android/support/transition/ChangeTransform": {
+        "androidx/transition/ChangeTransform": [
+          "PROPNAME_PARENT",
+          "TRANSLATIONS_PROPERTY",
+          "PROPNAME_INTERMEDIATE_PARENT_MATRIX",
+          "PROPNAME_TRANSFORMS",
+          "PROPNAME_INTERMEDIATE_MATRIX",
+          "sTransitionProperties",
+          "PROPNAME_MATRIX",
+          "PROPNAME_PARENT_MATRIX",
+          "NON_TRANSLATIONS_PROPERTY",
+          "SUPPORTS_VIEW_REMOVAL_SUPPRESSION"
+        ]
+      },
+      "android/support/v17/leanback/R$fraction": {
+        "androidx/leanback/R$fraction": [
+          "lb_focus_zoom_factor_xsmall",
+          "lb_focus_zoom_factor_medium",
+          "lb_browse_rows_scale",
+          "lb_search_orb_focused_zoom",
+          "lb_view_active_level",
+          "lb_focus_zoom_factor_large",
+          "lb_focus_zoom_factor_small",
+          "lb_browse_header_unselect_alpha",
+          "lb_view_dimmed_level",
+          "lb_search_bar_speech_orb_max_level_zoom"
+        ]
+      },
+      "android/support/v7/widget/LinearLayoutCompat$LayoutParams": {
+        "androidx/widget/LinearLayoutCompat$LayoutParams": [
+          "height",
+          "gravity",
+          "rightMargin",
+          "width",
+          "bottomMargin",
+          "leftMargin",
+          "topMargin",
+          "weight"
+        ]
+      },
+      "android/support/v7/preference/PreferenceViewHolder": {
+        "androidx/preference/PreferenceViewHolder": [
+          "itemView"
+        ]
+      },
+      "android/support/v7/util/MessageThreadUtil$SyncQueueItem": {
+        "androidx/util/MessageThreadUtil$SyncQueueItem": [
+          "sPoolLock",
+          "what",
+          "sPool",
+          "arg2",
+          "arg1",
+          "arg4",
+          "arg3",
+          "arg5",
+          "next",
+          "data"
+        ]
+      },
+      "android/support/v14/preference/PreferenceFragment": {
+        "androidx/preference/PreferenceFragment": [
+          "PREFERENCES_TAG",
+          "DIALOG_FRAGMENT_TAG",
+          "ARG_PREFERENCE_ROOT",
+          "MSG_BIND_PREFERENCES"
+        ]
+      },
+      "android/support/v7/gridlayout/R$styleable": {
+        "androidx/gridlayout/R$styleable": [
+          "GridLayout_Layout_android_layout_margin",
+          "GridLayout_Layout_layout_gravity",
+          "GridLayout_Layout_layout_column",
+          "GridLayout_Layout_layout_columnSpan",
+          "GridLayout_Layout_layout_row",
+          "GridLayout_Layout_layout_columnWeight",
+          "GridLayout_Layout_layout_rowWeight",
+          "GridLayout_Layout",
+          "GridLayout_Layout_android_layout_marginBottom",
+          "GridLayout_rowCount",
+          "GridLayout_columnCount",
+          "GridLayout_Layout_android_layout_marginRight",
+          "GridLayout",
+          "GridLayout_useDefaultMargins",
+          "GridLayout_rowOrderPreserved",
+          "GridLayout_columnOrderPreserved",
+          "GridLayout_Layout_android_layout_marginLeft",
+          "GridLayout_alignmentMode",
+          "GridLayout_Layout_layout_rowSpan",
+          "GridLayout_orientation",
+          "GridLayout_Layout_android_layout_marginTop"
+        ]
+      },
+      "android/support/v17/leanback/app/BackgroundManager": {
+        "androidx/leanback/app/BackgroundManager": [
+          "FULL_ALPHA",
+          "DEBUG",
+          "FRAGMENT_TAG",
+          "FADE_DURATION",
+          "CHANGE_BG_DELAY_MS",
+          "TAG"
+        ]
+      },
+      "android/support/customtabs/ICustomTabsService$Stub": {
+        "androidx/browser/customtabs/ICustomTabsService$Stub": [
+          "TRANSACTION_extraCommand",
+          "TRANSACTION_requestPostMessageChannel",
+          "TRANSACTION_postMessage",
+          "TRANSACTION_validateRelationship",
+          "TRANSACTION_warmup",
+          "TRANSACTION_updateVisuals",
+          "TRANSACTION_mayLaunchUrl",
+          "TRANSACTION_newSession",
+          "DESCRIPTOR"
+        ]
+      },
+      "android/support/v7/widget/Toolbar$SavedState": {
+        "androidx/widget/Toolbar$SavedState": [
+          "isOverflowOpen",
+          "expandedMenuItemId",
+          "CREATOR"
+        ]
+      },
+      "android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter": {
+        "androidx/leanback/widget/FullWidthDetailsOverviewRowPresenter": [
+          "ALIGN_MODE_START",
+          "sTmpRect",
+          "STATE_HALF",
+          "TAG",
+          "STATE_SMALL",
+          "sHandler",
+          "ALIGN_MODE_MIDDLE",
+          "STATE_FULL",
+          "DEBUG"
+        ]
+      },
+      "android/support/v4/app/FragmentTabHost$SavedState": {
+        "androidx/app/FragmentTabHost$SavedState": [
+          "CREATOR",
+          "curTab"
+        ]
+      },
+      "android/support/recommendation/BuildConfig": {
+        "androidx/recommendation/BuildConfig": [
+          "DEBUG",
+          "APPLICATION_ID",
+          "FLAVOR",
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "VERSION_CODE"
+        ]
+      },
+      "android/support/v4/app/ActivityOptionsCompat": {
+        "androidx/app/ActivityOptionsCompat": [
+          "EXTRA_USAGE_TIME_REPORT",
+          "EXTRA_USAGE_TIME_REPORT_PACKAGES"
+        ]
+      },
+      "android/support/v4/widget/NestedScrollView": {
+        "androidx/widget/NestedScrollView": [
+          "MAX_SCROLL_FACTOR",
+          "SCROLLVIEW_STYLEABLE",
+          "TAG",
+          "ANIMATED_SCROLL_GAP",
+          "INVALID_POINTER",
+          "ACCESSIBILITY_DELEGATE"
+        ]
+      },
+      "android/support/v4/app/BackStackRecord$Op": {
+        "androidx/app/BackStackRecord$Op": [
+          "enterAnim",
+          "fragment",
+          "popEnterAnim",
+          "exitAnim",
+          "popExitAnim",
+          "cmd"
+        ]
+      },
+      "android/support/v17/leanback/graphics/BoundsRule": {
+        "androidx/leanback/graphics/BoundsRule": [
+          "bottom",
+          "right",
+          "left",
+          "top"
+        ]
+      },
+      "android/support/v17/leanback/app/SearchSupportFragment": {
+        "androidx/leanback/app/SearchSupportFragment": [
+          "SPEECH_RECOGNITION_DELAY_MS",
+          "TAG",
+          "AUDIO_PERMISSION_REQUEST_CODE",
+          "ARG_QUERY",
+          "RESULTS_CHANGED",
+          "ARG_TITLE",
+          "EXTRA_LEANBACK_BADGE_PRESENT",
+          "ARG_PREFIX",
+          "QUERY_COMPLETE",
+          "DEBUG"
+        ]
+      },
+      "android/support/v7/util/SortedList": {
+        "androidx/util/SortedList": [
+          "INSERTION",
+          "DELETION",
+          "MIN_CAPACITY",
+          "INVALID_POSITION",
+          "CAPACITY_GROWTH",
+          "LOOKUP"
+        ]
+      },
+      "android/support/v4/view/ViewCompat": {
+        "androidx/view/ViewCompat": [
+          "IMPL",
+          "SCROLL_AXIS_VERTICAL",
+          "SCROLL_INDICATOR_END",
+          "MEASURED_HEIGHT_STATE_SHIFT",
+          "OVER_SCROLL_ALWAYS",
+          "SCROLL_INDICATOR_RIGHT",
+          "IMPORTANT_FOR_ACCESSIBILITY_AUTO",
+          "SCROLL_INDICATOR_START",
+          "LAYOUT_DIRECTION_LOCALE",
+          "ACCESSIBILITY_LIVE_REGION_ASSERTIVE",
+          "IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS",
+          "SCROLL_INDICATOR_TOP",
+          "MEASURED_STATE_MASK",
+          "SCROLL_INDICATOR_BOTTOM",
+          "LAYOUT_DIRECTION_LTR",
+          "OVER_SCROLL_IF_CONTENT_SCROLLS",
+          "SCROLL_AXIS_NONE",
+          "OVER_SCROLL_NEVER",
+          "ACCESSIBILITY_LIVE_REGION_POLITE",
+          "TYPE_TOUCH",
+          "MEASURED_STATE_TOO_SMALL",
+          "ACCESSIBILITY_LIVE_REGION_NONE",
+          "LAYOUT_DIRECTION_INHERIT",
+          "IMPORTANT_FOR_ACCESSIBILITY_NO",
+          "LAYER_TYPE_NONE",
+          "MEASURED_SIZE_MASK",
+          "SCROLL_INDICATOR_LEFT",
+          "TAG",
+          "SCROLL_AXIS_HORIZONTAL",
+          "TYPE_NON_TOUCH",
+          "LAYER_TYPE_HARDWARE",
+          "LAYER_TYPE_SOFTWARE",
+          "IMPORTANT_FOR_ACCESSIBILITY_YES",
+          "LAYOUT_DIRECTION_RTL"
+        ]
+      },
+      "android/support/v7/media/MediaRouter": {
+        "androidx/media/MediaRouter": [
+          "AVAILABILITY_FLAG_REQUIRE_MATCH",
+          "CALLBACK_FLAG_PERFORM_ACTIVE_SCAN",
+          "CALLBACK_FLAG_FORCE_DISCOVERY",
+          "UNSELECT_REASON_DISCONNECTED",
+          "AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE",
+          "UNSELECT_REASON_ROUTE_CHANGED",
+          "sGlobal",
+          "UNSELECT_REASON_UNKNOWN",
+          "TAG",
+          "CALLBACK_FLAG_REQUEST_DISCOVERY",
+          "DEBUG",
+          "UNSELECT_REASON_STOPPED",
+          "CALLBACK_FLAG_UNFILTERED_EVENTS"
+        ]
+      },
+      "android/support/v17/leanback/graphics/CompositeDrawable$ChildDrawable": {
+        "androidx/leanback/graphics/CompositeDrawable$ChildDrawable": [
+          "adjustedBounds",
+          "BOTTOM_FRACTION",
+          "RIGHT_FRACTION",
+          "BOTTOM_ABSOLUTE",
+          "RIGHT_ABSOLUTE",
+          "LEFT_ABSOLUTE",
+          "LEFT_FRACTION",
+          "TOP_FRACTION",
+          "TOP_ABSOLUTE"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsRow$RepeatAction": {
+        "androidx/leanback/widget/PlaybackControlsRow$RepeatAction": [
+          "INDEX_NONE",
+          "INDEX_ALL",
+          "ALL",
+          "NONE",
+          "ONE",
+          "INDEX_ONE"
+        ]
+      },
+      "android/support/design/R$id": {
+        "androidx/design/R$id": [
+          "touch_outside",
+          "largeLabel",
+          "textinput_error",
+          "textinput_counter",
+          "snackbar_text",
+          "snackbar_action",
+          "icon",
+          "smallLabel",
+          "view_offset_helper",
+          "design_bottom_sheet",
+          "coordinator",
+          "design_menu_item_action_area_stub",
+          "design_menu_item_text"
+        ]
+      },
+      "android/support/v7/widget/ActivityChooserModel$HistoricalRecord": {
+        "androidx/widget/ActivityChooserModel$HistoricalRecord": [
+          "activity",
+          "weight",
+          "time"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat$BaseTvColumns": {
+        "androidx/media/tv/TvContractCompat$BaseTvColumns": [
+          "COLUMN_PACKAGE_NAME"
+        ]
+      },
+      "android/support/v17/leanback/media/MediaPlayerGlue": {
+        "androidx/leanback/media/MediaPlayerGlue": [
+          "FAST_FORWARD_REWIND_STEP",
+          "TAG",
+          "REPEAT_ONE",
+          "FAST_FORWARD_REWIND_REPEAT_DELAY",
+          "NO_REPEAT",
+          "REPEAT_ALL"
+        ]
+      },
+      "android/support/text/emoji/EmojiProcessor$GlyphChecker": {
+        "androidx/text/emoji/EmojiProcessor$GlyphChecker": [
+          "PAINT_TEXT_SIZE",
+          "sStringBuilder"
+        ]
+      },
+      "android/support/v4/app/FragmentManager": {
+        "androidx/app/FragmentManager": [
+          "POP_BACK_STACK_INCLUSIVE"
+        ]
+      },
+      "android/support/v4/content/LocalBroadcastManager$ReceiverRecord": {
+        "androidx/content/LocalBroadcastManager$ReceiverRecord": [
+          "broadcasting",
+          "receiver",
+          "filter",
+          "dead"
+        ]
+      },
+      "android/support/percent/R$styleable": {
+        "androidx/R$styleable": [
+          "PercentLayout_Layout_layout_marginEndPercent",
+          "PercentLayout_Layout",
+          "PercentLayout_Layout_layout_marginBottomPercent",
+          "PercentLayout_Layout_layout_aspectRatio",
+          "PercentLayout_Layout_layout_widthPercent",
+          "PercentLayout_Layout_layout_heightPercent",
+          "PercentLayout_Layout_layout_marginLeftPercent",
+          "PercentLayout_Layout_layout_marginRightPercent",
+          "PercentLayout_Layout_layout_marginStartPercent",
+          "PercentLayout_Layout_layout_marginPercent",
+          "PercentLayout_Layout_layout_marginTopPercent"
+        ]
+      },
+      "android/support/v17/leanback/app/BrowseSupportFragment": {
+        "androidx/leanback/app/BrowseSupportFragment": [
+          "STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW",
+          "STATE_SET_ENTRANCE_START_STATE",
+          "HEADERS_ENABLED",
+          "STATE_ENTRANCE_ON_PREPARED",
+          "HEADERS_HIDDEN",
+          "ARG_HEADERS_STATE",
+          "TAG",
+          "STATE_ENTRANCE_PERFORM",
+          "HEADER_SHOW",
+          "IS_PAGE_ROW",
+          "ARG_TITLE",
+          "LB_HEADERS_BACKSTACK",
+          "DEBUG",
+          "EVT_SCREEN_DATA_READY",
+          "CURRENT_SELECTED_POSITION",
+          "EVT_HEADER_VIEW_CREATED",
+          "EVT_MAIN_FRAGMENT_VIEW_CREATED",
+          "HEADERS_DISABLED",
+          "HEADER_STACK_INDEX"
+        ]
+      },
+      "android/support/v17/leanback/app/SearchFragment": {
+        "androidx/leanback/app/SearchFragment": [
+          "TAG",
+          "QUERY_COMPLETE",
+          "ARG_QUERY",
+          "RESULTS_CHANGED",
+          "ARG_TITLE",
+          "SPEECH_RECOGNITION_DELAY_MS",
+          "EXTRA_LEANBACK_BADGE_PRESENT",
+          "AUDIO_PERMISSION_REQUEST_CODE",
+          "DEBUG",
+          "ARG_PREFIX"
+        ]
+      },
+      "android/support/media/tv/BuildConfig": {
+        "androidx/media/tv/BuildConfig": [
+          "VERSION_NAME",
+          "VERSION_CODE",
+          "BUILD_TYPE",
+          "FLAVOR",
+          "APPLICATION_ID",
+          "DEBUG"
+        ]
+      },
+      "android/support/v4/graphics/drawable/IconCompat": {
+        "androidx/graphics/drawable/IconCompat": [
+          "ADAPTIVE_ICON_INSET_FACTOR",
+          "TYPE_RESOURCE",
+          "TYPE_BITMAP",
+          "ICON_DIAMETER_FACTOR",
+          "KEY_SHADOW_ALPHA",
+          "DEFAULT_VIEW_PORT_SCALE",
+          "AMBIENT_SHADOW_ALPHA",
+          "TYPE_DATA",
+          "BLUR_FACTOR",
+          "TYPE_URI",
+          "KEY_SHADOW_OFFSET_FACTOR",
+          "TYPE_ADAPTIVE_BITMAP"
+        ]
+      },
+      "android/support/v4/internal/view/SupportMenuItem": {
+        "androidx/internal/view/SupportMenuItem": [
+          "SHOW_AS_ACTION_ALWAYS",
+          "SHOW_AS_ACTION_NEVER",
+          "SHOW_AS_ACTION_WITH_TEXT",
+          "SHOW_AS_ACTION_IF_ROOM",
+          "SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW"
+        ]
+      },
+      "android/support/v7/cardview/R$dimen": {
+        "androidx/cardview/R$dimen": [
+          "cardview_compat_inset_shadow"
+        ]
+      },
+      "android/support/v4/widget/CompoundButtonCompat$CompoundButtonCompatBaseImpl": {
+        "androidx/widget/CompoundButtonCompat$CompoundButtonCompatBaseImpl": [
+          "sButtonDrawableField",
+          "sButtonDrawableFieldFetched",
+          "TAG"
+        ]
+      },
+      "android/support/v7/widget/StaggeredGridLayoutManager$LayoutParams": {
+        "androidx/widget/StaggeredGridLayoutManager$LayoutParams": [
+          "width",
+          "leftMargin",
+          "INVALID_SPAN_ID",
+          "bottomMargin",
+          "height",
+          "topMargin",
+          "rightMargin"
+        ]
+      },
+      "android/support/v17/leanback/widget/ItemAlignmentFacetHelper": {
+        "androidx/leanback/widget/ItemAlignmentFacetHelper": [
+          "sRect"
+        ]
+      },
+      "android/support/media/ExifInterface$ExifAttribute": {
+        "androidx/media/ExifInterface$ExifAttribute": [
+          "format",
+          "numberOfComponents",
+          "bytes"
+        ]
+      },
+      "android/support/compat/R$styleable": {
+        "androidx/compat/R$styleable": [
+          "FontFamily_fontProviderCerts",
+          "FontFamily_fontProviderAuthority",
+          "FontFamilyFont_fontWeight",
+          "FontFamilyFont_android_font",
+          "FontFamilyFont_android_fontStyle",
+          "FontFamilyFont_android_fontWeight",
+          "FontFamilyFont_fontStyle",
+          "FontFamilyFont",
+          "FontFamily_fontProviderFetchTimeout",
+          "FontFamily_fontProviderFetchStrategy",
+          "FontFamilyFont_font",
+          "FontFamily_fontProviderQuery",
+          "FontFamily",
+          "FontFamily_fontProviderPackage"
+        ]
+      },
+      "android/support/v7/widget/ButtonBarLayout": {
+        "androidx/widget/ButtonBarLayout": [
+          "PEEK_BUTTON_DP",
+          "ALLOW_STACKING_MIN_HEIGHT_DP"
+        ]
+      },
+      "android/support/v7/app/ActionBarDrawerToggleHoneycomb": {
+        "androidx/app/ActionBarDrawerToggleHoneycomb": [
+          "THEME_ATTRS",
+          "TAG"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView$LayoutParams": {
+        "androidx/widget/RecyclerView$LayoutParams": [
+          "topMargin",
+          "bottomMargin",
+          "width",
+          "height",
+          "rightMargin",
+          "leftMargin"
+        ]
+      },
+      "android/support/v7/util/DiffUtil$Snake": {
+        "androidx/util/DiffUtil$Snake": [
+          "size",
+          "x",
+          "y",
+          "reverse",
+          "removal"
+        ]
+      },
+      "android/support/v4/print/PrintHelper": {
+        "androidx/print/PrintHelper": [
+          "COLOR_MODE_MONOCHROME",
+          "SCALE_MODE_FILL",
+          "ORIENTATION_PORTRAIT",
+          "SCALE_MODE_FIT",
+          "COLOR_MODE_COLOR",
+          "ORIENTATION_LANDSCAPE"
+        ]
+      },
+      "android/support/v4/widget/CompoundButtonCompat": {
+        "androidx/widget/CompoundButtonCompat": [
+          "IMPL"
+        ]
+      },
+      "android/support/v7/widget/DefaultItemAnimator$MoveInfo": {
+        "androidx/widget/DefaultItemAnimator$MoveInfo": [
+          "toY",
+          "toX",
+          "fromY",
+          "fromX",
+          "holder"
+        ]
+      },
+      "android/support/v7/widget/ActionMenuView": {
+        "androidx/widget/ActionMenuView": [
+          "MIN_CELL_SIZE",
+          "TAG",
+          "GENERATED_ITEM_PADDING"
+        ]
+      },
+      "android/support/v7/widget/GapWorker$Task": {
+        "androidx/widget/GapWorker$Task": [
+          "viewVelocity",
+          "position",
+          "view",
+          "immediate",
+          "distanceToItem"
+        ]
+      },
+      "android/support/v7/util/DiffUtil": {
+        "androidx/util/DiffUtil": [
+          "SNAKE_COMPARATOR"
+        ]
+      },
+      "android/support/v4/content/res/ResourcesCompat": {
+        "androidx/content/res/ResourcesCompat": [
+          "TAG"
+        ]
+      },
+      "android/support/v7/widget/ActionMenuView$LayoutParams": {
+        "androidx/widget/ActionMenuView$LayoutParams": [
+          "expandable",
+          "extraPixels",
+          "isOverflowButton",
+          "gravity",
+          "rightMargin",
+          "cellsUsed",
+          "expanded",
+          "leftMargin",
+          "preventEdgeOffset"
+        ]
+      },
+      "android/support/transition/Visibility": {
+        "androidx/transition/Visibility": [
+          "PROPNAME_PARENT",
+          "PROPNAME_VISIBILITY",
+          "MODE_OUT",
+          "PROPNAME_SCREEN_LOCATION",
+          "sTransitionProperties",
+          "MODE_IN"
+        ]
+      },
+      "android/support/v4/view/ViewPager$LayoutParams": {
+        "androidx/view/ViewPager$LayoutParams": [
+          "needsMeasure",
+          "height",
+          "width",
+          "childIndex",
+          "position",
+          "widthFactor",
+          "gravity",
+          "isDecor"
+        ]
+      },
+      "android/support/v17/preference/R$layout": {
+        "androidx/leanback/preference/R$layout": [
+          "leanback_list_preference_item_multi",
+          "leanback_list_preference_fragment",
+          "leanback_settings_fragment",
+          "leanback_list_preference_item_single",
+          "leanback_preferences_list",
+          "leanback_preference_fragment"
+        ]
+      },
+      "android/support/v4/widget/CircularProgressDrawable": {
+        "androidx/widget/CircularProgressDrawable": [
+          "ANIMATION_DURATION",
+          "CENTER_RADIUS",
+          "COLOR_CHANGE_OFFSET",
+          "ARROW_WIDTH",
+          "STROKE_WIDTH",
+          "MAX_PROGRESS_ARC",
+          "GROUP_FULL_ROTATION",
+          "MIN_PROGRESS_ARC",
+          "RING_ROTATION",
+          "DEFAULT",
+          "ARROW_WIDTH_LARGE",
+          "ARROW_HEIGHT_LARGE",
+          "CENTER_RADIUS_LARGE",
+          "COLORS",
+          "STROKE_WIDTH_LARGE",
+          "MATERIAL_INTERPOLATOR",
+          "ARROW_HEIGHT",
+          "SHRINK_OFFSET",
+          "LARGE",
+          "LINEAR_INTERPOLATOR"
+        ]
+      },
+      "android/support/v7/mediarouter/R$integer": {
+        "androidx/mediarouter/R$integer": [
+          "mr_controller_volume_group_list_animation_duration_ms",
+          "mr_controller_volume_group_list_fade_in_duration_ms",
+          "mr_controller_volume_group_list_fade_out_duration_ms"
+        ]
+      },
+      "android/support/v17/leanback/widget/ShadowOverlayContainer": {
+        "androidx/leanback/widget/ShadowOverlayContainer": [
+          "SHADOW_DYNAMIC",
+          "sTempRect",
+          "SHADOW_NONE",
+          "SHADOW_STATIC"
+        ]
+      },
+      "android/support/v4/widget/SwipeRefreshLayout": {
+        "androidx/widget/SwipeRefreshLayout": [
+          "LAYOUT_ATTRS",
+          "CIRCLE_DIAMETER_LARGE",
+          "ALPHA_ANIMATION_DURATION",
+          "MAX_ALPHA",
+          "ANIMATE_TO_START_DURATION",
+          "LOG_TAG",
+          "MAX_PROGRESS_ANGLE",
+          "ANIMATE_TO_TRIGGER_DURATION",
+          "DEFAULT",
+          "SCALE_DOWN_DURATION",
+          "CIRCLE_DIAMETER",
+          "INVALID_POINTER",
+          "DRAG_RATE",
+          "CIRCLE_BG_LIGHT",
+          "DECELERATE_INTERPOLATION_FACTOR",
+          "LARGE",
+          "DEFAULT_CIRCLE_TARGET",
+          "STARTING_PROGRESS_ALPHA"
+        ]
+      },
+      "android/support/annotation/Dimension": {
+        "androidx/annotation/Dimension": [
+          "DP",
+          "SP",
+          "PX"
+        ]
+      },
+      "android/support/v7/widget/AppCompatSpinner": {
+        "androidx/widget/AppCompatSpinner": [
+          "MAX_ITEMS_MEASURED",
+          "MODE_DIALOG",
+          "ATTRS_ANDROID_SPINNERMODE",
+          "TAG",
+          "MODE_THEME",
+          "MODE_DROPDOWN"
+        ]
+      },
+      "android/support/v13/view/inputmethod/InputConnectionCompat$InputContentInfoCompatBaseImpl": {
+        "androidx/view/inputmethod/InputConnectionCompat$InputContentInfoCompatBaseImpl": [
+          "COMMIT_CONTENT_RESULT_RECEIVER",
+          "COMMIT_CONTENT_OPTS_KEY",
+          "COMMIT_CONTENT_FLAGS_KEY",
+          "COMMIT_CONTENT_LINK_URI_KEY",
+          "COMMIT_CONTENT_DESCRIPTION_KEY",
+          "COMMIT_CONTENT_ACTION",
+          "COMMIT_CONTENT_CONTENT_URI_KEY"
+        ]
+      },
+      "android/support/v7/app/TwilightCalculator": {
+        "androidx/app/TwilightCalculator": [
+          "OBLIQUITY",
+          "ALTIDUTE_CORRECTION_CIVIL_TWILIGHT",
+          "UTC_2000",
+          "DEGREES_TO_RADIANS",
+          "NIGHT",
+          "sunrise",
+          "state",
+          "DAY",
+          "J0",
+          "C1",
+          "C2",
+          "C3",
+          "sunset",
+          "sInstance"
+        ]
+      },
+      "android/support/v7/widget/LinearLayoutManager$LayoutState": {
+        "androidx/widget/LinearLayoutManager$LayoutState": [
+          "TAG",
+          "SCROLLING_OFFSET_NaN",
+          "LAYOUT_START",
+          "ITEM_DIRECTION_TAIL",
+          "INVALID_LAYOUT",
+          "LAYOUT_END",
+          "ITEM_DIRECTION_HEAD"
+        ]
+      },
+      "android/support/wear/R$drawable": {
+        "androidx/wear/R$drawable": [
+          "ws_ic_more_horiz_24dp_wht",
+          "ws_ic_more_vert_24dp_wht"
+        ]
+      },
+      "android/support/v17/leanback/widget/ControlBarPresenter$BoundData": {
+        "androidx/leanback/widget/ControlBarPresenter$BoundData": [
+          "adapter",
+          "presenter"
+        ]
+      },
+      "android/support/v4/media/MediaBrowserServiceCompat$ConnectionRecord": {
+        "androidx/media/MediaBrowserServiceCompat$ConnectionRecord": [
+          "callbacks",
+          "pkg",
+          "subscriptions",
+          "rootHints",
+          "root"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplApi18": {
+        "androidx/media/session/MediaSessionCompat$MediaSessionImplApi18": [
+          "sIsMbrPendingIntentSupported"
+        ]
+      },
+      "android/support/v4/util/PatternsCompat": {
+        "androidx/util/PatternsCompat": [
+          "TLD_CHAR",
+          "USER_INFO",
+          "WEB_URL",
+          "AUTOLINK_WEB_URL",
+          "LABEL_CHAR",
+          "PATH_AND_QUERY",
+          "PUNYCODE_TLD",
+          "EMAIL_CHAR",
+          "STRICT_DOMAIN_NAME",
+          "STRICT_HOST_NAME",
+          "IP_ADDRESS",
+          "STRICT_TLD",
+          "WEB_URL_WITHOUT_PROTOCOL",
+          "PROTOCOL",
+          "EMAIL_ADDRESS",
+          "EMAIL_ADDRESS_LOCAL_PART",
+          "UCS_CHAR",
+          "TLD",
+          "IRI_LABEL",
+          "WEB_URL_WITH_PROTOCOL",
+          "AUTOLINK_EMAIL_ADDRESS",
+          "PORT_NUMBER",
+          "EMAIL_ADDRESS_DOMAIN",
+          "DOMAIN_NAME",
+          "HOST_NAME",
+          "IANA_TOP_LEVEL_DOMAINS",
+          "RELAXED_DOMAIN_NAME",
+          "WORD_BOUNDARY"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsRow$ClosedCaptioningAction": {
+        "androidx/leanback/widget/PlaybackControlsRow$ClosedCaptioningAction": [
+          "INDEX_OFF",
+          "INDEX_ON",
+          "OFF",
+          "ON"
+        ]
+      },
+      "android/support/v4/widget/ExploreByTouchHelper": {
+        "androidx/widget/ExploreByTouchHelper": [
+          "INVALID_ID",
+          "NODE_ADAPTER",
+          "DEFAULT_CLASS_NAME",
+          "INVALID_PARENT_BOUNDS",
+          "HOST_ID",
+          "SPARSE_VALUES_ADAPTER"
+        ]
+      },
+      "android/support/v7/widget/OrientationHelper": {
+        "androidx/widget/OrientationHelper": [
+          "INVALID_SIZE",
+          "HORIZONTAL",
+          "VERTICAL"
+        ]
+      },
+      "android/support/animation/SpringForce": {
+        "androidx/animation/SpringForce": [
+          "DAMPING_RATIO_NO_BOUNCY",
+          "UNSET",
+          "DAMPING_RATIO_HIGH_BOUNCY",
+          "VELOCITY_THRESHOLD_MULTIPLIER",
+          "STIFFNESS_LOW",
+          "DAMPING_RATIO_LOW_BOUNCY",
+          "STIFFNESS_HIGH",
+          "STIFFNESS_MEDIUM",
+          "DAMPING_RATIO_MEDIUM_BOUNCY",
+          "STIFFNESS_VERY_LOW"
+        ]
+      },
+      "android/support/v7/view/menu/MenuAdapter": {
+        "androidx/view/menu/MenuAdapter": [
+          "ITEM_LAYOUT"
+        ]
+      },
+      "android/support/design/widget/ViewGroupUtils": {
+        "androidx/widget/ViewGroupUtils": [
+          "sMatrix",
+          "sRectF"
+        ]
+      },
+      "android/support/multidex/ZipUtil": {
+        "androidx/multidex/ZipUtil": [
+          "ENDSIG",
+          "ENDHDR",
+          "BUFFER_SIZE"
+        ]
+      },
+      "android/support/v7/media/MediaItemStatus": {
+        "androidx/media/MediaItemStatus": [
+          "KEY_EXTRAS",
+          "PLAYBACK_STATE_PLAYING",
+          "KEY_TIMESTAMP",
+          "KEY_CONTENT_POSITION",
+          "PLAYBACK_STATE_PENDING",
+          "PLAYBACK_STATE_FINISHED",
+          "PLAYBACK_STATE_BUFFERING",
+          "PLAYBACK_STATE_PAUSED",
+          "PLAYBACK_STATE_INVALIDATED",
+          "KEY_CONTENT_DURATION",
+          "PLAYBACK_STATE_ERROR",
+          "PLAYBACK_STATE_CANCELED",
+          "EXTRA_HTTP_RESPONSE_HEADERS",
+          "KEY_PLAYBACK_STATE",
+          "EXTRA_HTTP_STATUS_CODE"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView$Recycler": {
+        "androidx/widget/RecyclerView$Recycler": [
+          "DEFAULT_CACHE_SIZE"
+        ]
+      },
+      "android/support/transition/ViewUtilsApi19": {
+        "androidx/transition/ViewUtilsApi19": [
+          "sSetTransitionAlphaMethod",
+          "sSetTransitionAlphaMethodFetched",
+          "TAG",
+          "sGetTransitionAlphaMethod",
+          "sGetTransitionAlphaMethodFetched"
+        ]
+      },
+      "android/support/v4/media/MediaBrowserCompat": {
+        "androidx/media/MediaBrowserCompat": [
+          "EXTRA_PAGE",
+          "DEBUG",
+          "EXTRA_MEDIA_ID",
+          "EXTRA_PAGE_SIZE",
+          "CUSTOM_ACTION_DOWNLOAD",
+          "CUSTOM_ACTION_REMOVE_DOWNLOADED_FILE",
+          "TAG",
+          "EXTRA_DOWNLOAD_PROGRESS"
+        ]
+      },
+      "android/support/v4/app/FragmentTransition$FragmentContainerTransition": {
+        "androidx/app/FragmentTransition$FragmentContainerTransition": [
+          "lastInTransaction",
+          "lastIn",
+          "lastInIsPop",
+          "firstOut",
+          "firstOutIsPop",
+          "firstOutTransaction"
+        ]
+      },
+      "android/support/v4/text/util/LinkifyCompat": {
+        "androidx/text/util/LinkifyCompat": [
+          "COMPARATOR",
+          "EMPTY_STRING"
+        ]
+      },
+      "android/support/v7/app/TwilightManager$TwilightState": {
+        "androidx/app/TwilightManager$TwilightState": [
+          "todaySunrise",
+          "todaySunset",
+          "yesterdaySunset",
+          "nextUpdate",
+          "tomorrowSunrise",
+          "isNight"
+        ]
+      },
+      "android/support/constraint/BuildConfig": {
+        "androidx/constraint/BuildConfig": [
+          "VERSION_NAME",
+          "DEBUG",
+          "FLAVOR",
+          "VERSION_CODE",
+          "APPLICATION_ID",
+          "BUILD_TYPE"
+        ]
+      },
+      "android/support/v4/content/res/FontResourcesParserCompat": {
+        "androidx/content/res/FontResourcesParserCompat": [
+          "NORMAL_WEIGHT",
+          "FETCH_STRATEGY_ASYNC",
+          "INFINITE_TIMEOUT_VALUE",
+          "DEFAULT_TIMEOUT_MILLIS",
+          "FETCH_STRATEGY_BLOCKING",
+          "ITALIC"
+        ]
+      },
+      "android/support/v7/widget/ListPopupWindow": {
+        "androidx/widget/ListPopupWindow": [
+          "sSetEpicenterBoundsMethod",
+          "WRAP_CONTENT",
+          "MATCH_PARENT",
+          "POSITION_PROMPT_BELOW",
+          "DEBUG",
+          "sGetMaxAvailableHeightMethod",
+          "INPUT_METHOD_FROM_FOCUSABLE",
+          "INPUT_METHOD_NEEDED",
+          "EXPAND_LIST_TIMEOUT",
+          "sClipToWindowEnabledMethod",
+          "POSITION_PROMPT_ABOVE",
+          "TAG",
+          "INPUT_METHOD_NOT_NEEDED"
+        ]
+      },
+      "android/support/v7/media/MediaRouteProviderProtocol": {
+        "androidx/media/MediaRouteProviderProtocol": [
+          "SERVICE_INTERFACE",
+          "CLIENT_MSG_RELEASE_ROUTE_CONTROLLER",
+          "CLIENT_DATA_ROUTE_ID",
+          "CLIENT_VERSION_CURRENT",
+          "CLIENT_VERSION_START",
+          "CLIENT_DATA_ROUTE_LIBRARY_GROUP",
+          "CLIENT_VERSION_1",
+          "CLIENT_VERSION_2",
+          "SERVICE_VERSION_CURRENT",
+          "SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED",
+          "CLIENT_MSG_SELECT_ROUTE",
+          "CLIENT_MSG_UNREGISTER",
+          "CLIENT_MSG_UPDATE_ROUTE_VOLUME",
+          "SERVICE_MSG_REGISTERED",
+          "CLIENT_MSG_CREATE_ROUTE_CONTROLLER",
+          "CLIENT_MSG_ROUTE_CONTROL_REQUEST",
+          "CLIENT_DATA_UNSELECT_REASON",
+          "CLIENT_MSG_SET_DISCOVERY_REQUEST",
+          "SERVICE_MSG_CONTROL_REQUEST_FAILED",
+          "CLIENT_MSG_REGISTER",
+          "CLIENT_MSG_UNSELECT_ROUTE",
+          "SERVICE_MSG_GENERIC_FAILURE",
+          "SERVICE_MSG_GENERIC_SUCCESS",
+          "SERVICE_VERSION_1",
+          "CLIENT_DATA_VOLUME",
+          "SERVICE_DATA_ERROR",
+          "SERVICE_MSG_DESCRIPTOR_CHANGED",
+          "CLIENT_MSG_SET_ROUTE_VOLUME"
+        ]
+      },
+      "android/support/v4/app/Fragment": {
+        "androidx/app/Fragment": [
+          "CREATED",
+          "STARTED",
+          "ACTIVITY_CREATED",
+          "USE_DEFAULT_TRANSITION",
+          "RESUMED",
+          "sClassMap",
+          "INITIALIZING",
+          "STOPPED"
+        ]
+      },
+      "android/support/v7/app/AlertController$ButtonHandler": {
+        "androidx/app/AlertController$ButtonHandler": [
+          "MSG_DISMISS_DIALOG"
+        ]
+      },
+      "android/support/v4/text/BidiFormatter": {
+        "androidx/text/BidiFormatter": [
+          "DIR_LTR",
+          "DIR_UNKNOWN",
+          "DEFAULT_FLAGS",
+          "DEFAULT_LTR_INSTANCE",
+          "PDF",
+          "FLAG_STEREO_RESET",
+          "LRM_STRING",
+          "LRE",
+          "LRM",
+          "DEFAULT_TEXT_DIRECTION_HEURISTIC",
+          "DIR_RTL",
+          "DEFAULT_RTL_INSTANCE",
+          "RLM",
+          "RLE",
+          "EMPTY_STRING",
+          "RLM_STRING"
+        ]
+      },
+      "android/support/v17/leanback/widget/BaseGridView": {
+        "androidx/leanback/widget/BaseGridView": [
+          "WINDOW_ALIGN_NO_EDGE",
+          "SAVE_ALL_CHILD",
+          "WINDOW_ALIGN_BOTH_EDGE",
+          "FOCUS_SCROLL_PAGE",
+          "WINDOW_ALIGN_HIGH_EDGE",
+          "ITEM_ALIGN_OFFSET_PERCENT_DISABLED",
+          "WINDOW_ALIGN_LOW_EDGE",
+          "SAVE_ON_SCREEN_CHILD",
+          "SAVE_NO_CHILD",
+          "FOCUS_SCROLL_ALIGNED",
+          "WINDOW_ALIGN_OFFSET_PERCENT_DISABLED",
+          "FOCUS_SCROLL_ITEM",
+          "SAVE_LIMITED_CHILD"
+        ]
+      },
+      "android/support/v4/app/FragmentActivity": {
+        "androidx/app/FragmentActivity": [
+          "MSG_REALLY_STOPPED",
+          "NEXT_CANDIDATE_REQUEST_INDEX_TAG",
+          "MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS",
+          "FRAGMENTS_TAG",
+          "TAG",
+          "ALLOCATED_REQUEST_INDICIES_TAG",
+          "MSG_RESUME_PENDING",
+          "REQUEST_FRAGMENT_WHO_TAG"
+        ]
+      },
+      "android/support/v7/gridlayout/R$dimen": {
+        "androidx/gridlayout/R$dimen": [
+          "default_gap"
+        ]
+      },
+      "android/support/content/ContentPager$Stats": {
+        "androidx/content/ContentPager$Stats": [
+          "EXTRA_COMPAT_PAGED",
+          "EXTRA_PROVIDER_PAGED",
+          "EXTRA_RESOLVED_QUERIES",
+          "EXTRA_TOTAL_QUERIES"
+        ]
+      },
+      "android/support/design/widget/BaseTransientBottomBar": {
+        "androidx/design/widget/BaseTransientBottomBar": [
+          "ANIMATION_DURATION",
+          "USE_OFFSET_API",
+          "LENGTH_SHORT",
+          "MSG_SHOW",
+          "MSG_DISMISS",
+          "LENGTH_LONG",
+          "sHandler",
+          "ANIMATION_FADE_DURATION",
+          "LENGTH_INDEFINITE"
+        ]
+      },
+      "android/support/v17/leanback/widget/ArrayObjectAdapter": {
+        "androidx/leanback/widget/ArrayObjectAdapter": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v4/view/AsyncLayoutInflater$InflateRequest": {
+        "androidx/view/AsyncLayoutInflater$InflateRequest": [
+          "inflater",
+          "callback",
+          "view",
+          "parent",
+          "resid"
+        ]
+      },
+      "android/support/transition/Styleable": {
+        "androidx/transition/Styleable": [
+          "TRANSITION",
+          "VISIBILITY_TRANSITION",
+          "CHANGE_TRANSFORM",
+          "SLIDE",
+          "TRANSITION_MANAGER",
+          "CHANGE_BOUNDS",
+          "TRANSITION_SET",
+          "FADE",
+          "TRANSITION_TARGET",
+          "ARC_MOTION",
+          "PATTERN_PATH_MOTION"
+        ]
+      },
+      "android/support/design/widget/Snackbar$Callback": {
+        "androidx/design/widget/Snackbar$Callback": [
+          "DISMISS_EVENT_ACTION",
+          "DISMISS_EVENT_TIMEOUT",
+          "DISMISS_EVENT_SWIPE",
+          "DISMISS_EVENT_CONSECUTIVE",
+          "DISMISS_EVENT_MANUAL"
+        ]
+      },
+      "android/support/v4/content/ModernAsyncTask$Status": {
+        "androidx/content/ModernAsyncTask$Status": [
+          "PENDING",
+          "FINISHED",
+          "RUNNING"
+        ]
+      },
+      "android/support/wear/widget/drawer/WearableActionDrawerView$ActionListAdapter": {
+        "androidx/wear/widget/drawer/WearableActionDrawerView$ActionListAdapter": [
+          "TYPE_TITLE",
+          "TYPE_ACTION"
+        ]
+      },
+      "android/support/design/widget/AppBarLayout$Behavior": {
+        "androidx/design/widget/AppBarLayout$Behavior": [
+          "INVALID_POSITION",
+          "MAX_OFFSET_ANIMATION_DURATION"
+        ]
+      },
+      "android/support/v17/leanback/app/BaseSupportFragment": {
+        "androidx/leanback/app/BaseSupportFragment": [
+          "STATE_ENTRANCE_INIT",
+          "EVT_PREPARE_ENTRANCE",
+          "EVT_ON_CREATE",
+          "COND_TRANSITION_NOT_SUPPORTED",
+          "STATE_ENTRANCE_PERFORM",
+          "EVT_ENTRANCE_END",
+          "EVT_ON_CREATEVIEW",
+          "STATE_ENTRANCE_ON_PREPARED",
+          "STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW",
+          "EVT_START_ENTRANCE",
+          "STATE_ENTRANCE_ON_ENDED",
+          "STATE_START",
+          "STATE_ENTRANCE_COMPLETE"
+        ]
+      },
+      "android/support/annotation/VisibleForTesting": {
+        "androidx/annotation/VisibleForTesting": [
+          "PROTECTED",
+          "PACKAGE_PRIVATE",
+          "NONE",
+          "PRIVATE"
+        ]
+      },
+      "android/support/v17/leanback/widget/Parallax$IntProperty": {
+        "androidx/leanback/widget/Parallax$IntProperty": [
+          "UNKNOWN_AFTER",
+          "UNKNOWN_BEFORE"
+        ]
+      },
+      "android/support/v7/media/SystemMediaRouteProvider$JellybeanImpl": {
+        "androidx/media/SystemMediaRouteProvider$JellybeanImpl": [
+          "LIVE_AUDIO_CONTROL_FILTERS",
+          "LIVE_VIDEO_CONTROL_FILTERS"
+        ]
+      },
+      "android/support/constraint/ConstraintLayout": {
+        "androidx/constraint/ConstraintLayout": [
+          "VERSION",
+          "ALLOWS_EMBEDDED",
+          "SIMPLE_LAYOUT",
+          "TAG"
+        ]
+      },
+      "android/support/v4/widget/TextViewCompat": {
+        "androidx/widget/TextViewCompat": [
+          "AUTO_SIZE_TEXT_TYPE_UNIFORM",
+          "IMPL",
+          "AUTO_SIZE_TEXT_TYPE_NONE"
+        ]
+      },
+      "android/support/content/ContentPager": {
+        "androidx/content/ContentPager": [
+          "DEBUG",
+          "CURSOR_DISPOSITION",
+          "EXTRA_TOTAL_COUNT",
+          "EXTRA_HONORED_ARGS",
+          "CURSOR_DISPOSITION_REPAGED",
+          "QUERY_ARG_LIMIT",
+          "QUERY_ARG_OFFSET",
+          "EXTRA_SUGGESTED_LIMIT",
+          "EXTRA_REQUESTED_LIMIT",
+          "CURSOR_DISPOSITION_PAGED",
+          "TAG",
+          "CURSOR_DISPOSITION_WRAPPED",
+          "DEFAULT_CURSOR_CACHE_SIZE",
+          "CURSOR_DISPOSITION_COPIED"
+        ]
+      },
+      "android/support/v13/app/FragmentTabHost$SavedState": {
+        "androidx/app/FragmentTabHost$SavedState": [
+          "curTab",
+          "CREATOR"
+        ]
+      },
+      "android/support/design/widget/CollapsingToolbarLayout$LayoutParams": {
+        "androidx/design/widget/CollapsingToolbarLayout$LayoutParams": [
+          "DEFAULT_PARALLAX_MULTIPLIER",
+          "bottomMargin",
+          "COLLAPSE_MODE_PARALLAX",
+          "COLLAPSE_MODE_PIN",
+          "COLLAPSE_MODE_OFF"
+        ]
+      },
+      "android/support/v7/app/WindowDecorActionBar": {
+        "androidx/app/WindowDecorActionBar": [
+          "FADE_OUT_DURATION_MS",
+          "FADE_IN_DURATION_MS",
+          "sShowInterpolator",
+          "INVALID_POSITION",
+          "sHideInterpolator",
+          "TAG"
+        ]
+      },
+      "android/support/v4/view/PointerIconCompat": {
+        "androidx/view/PointerIconCompat": [
+          "TYPE_ZOOM_IN",
+          "TYPE_HELP",
+          "TYPE_WAIT",
+          "TYPE_VERTICAL_TEXT",
+          "TYPE_GRAB",
+          "TYPE_NULL",
+          "TYPE_CELL",
+          "TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW",
+          "TYPE_ARROW",
+          "TYPE_TEXT",
+          "TYPE_HORIZONTAL_DOUBLE_ARROW",
+          "TYPE_HAND",
+          "TYPE_DEFAULT",
+          "TYPE_VERTICAL_DOUBLE_ARROW",
+          "TYPE_NO_DROP",
+          "TYPE_COPY",
+          "TYPE_ALL_SCROLL",
+          "TYPE_GRABBING",
+          "TYPE_ALIAS",
+          "TYPE_CROSSHAIR",
+          "TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW",
+          "TYPE_ZOOM_OUT",
+          "TYPE_CONTEXT_MENU"
+        ]
+      },
+      "android/support/v7/widget/GridLayout$Bounds": {
+        "androidx/widget/GridLayout$Bounds": [
+          "after",
+          "flexibility",
+          "before"
+        ]
+      },
+      "android/support/v4/internal/view/SupportMenu": {
+        "androidx/internal/view/SupportMenu": [
+          "USER_SHIFT",
+          "SUPPORTED_MODIFIERS_MASK",
+          "USER_MASK",
+          "CATEGORY_SHIFT",
+          "FLAG_KEEP_OPEN_ON_SUBMENU_OPENED",
+          "CATEGORY_MASK"
+        ]
+      },
+      "android/support/multidex/ZipUtil$CentralDirectory": {
+        "androidx/multidex/ZipUtil$CentralDirectory": [
+          "offset",
+          "size"
+        ]
+      },
+      "android/support/app/recommendation/ContentRecommendation": {
+        "androidx/app/recommendation/ContentRecommendation": [
+          "CONTENT_TYPE_SERIAL",
+          "CONTENT_TYPE_SPORTS",
+          "CONTENT_TYPE_APP",
+          "CONTENT_MATURITY_LOW",
+          "CONTENT_MATURITY_ALL",
+          "CONTENT_PRICING_PREORDER",
+          "INTENT_TYPE_BROADCAST",
+          "CONTENT_STATUS_AVAILABLE",
+          "CONTENT_PRICING_SUBSCRIPTION",
+          "CONTENT_TYPE_MAGAZINE",
+          "CONTENT_TYPE_VIDEO",
+          "CONTENT_MATURITY_MEDIUM",
+          "CONTENT_PRICING_PURCHASE",
+          "CONTENT_TYPE_RADIO",
+          "CONTENT_TYPE_WEBSITE",
+          "CONTENT_TYPE_MUSIC",
+          "INTENT_TYPE_ACTIVITY",
+          "CONTENT_STATUS_UNAVAILABLE",
+          "CONTENT_PRICING_FREE",
+          "CONTENT_TYPE_TRAILER",
+          "CONTENT_TYPE_GAME",
+          "CONTENT_MATURITY_HIGH",
+          "CONTENT_TYPE_NEWS",
+          "CONTENT_STATUS_READY",
+          "CONTENT_TYPE_MOVIE",
+          "CONTENT_STATUS_PENDING",
+          "INTENT_TYPE_SERVICE",
+          "CONTENT_TYPE_PODCAST",
+          "CONTENT_PRICING_RENTAL",
+          "CONTENT_TYPE_COMIC",
+          "CONTENT_TYPE_BOOK"
+        ]
+      },
+      "android/support/v4/media/app/NotificationCompat$MediaStyle": {
+        "androidx/media/app/NotificationCompat$MediaStyle": [
+          "MAX_MEDIA_BUTTONS",
+          "MAX_MEDIA_BUTTONS_IN_COMPACT"
+        ]
+      },
+      "android/support/v4/media/session/MediaControllerCompat$Callback$MessageHandler": {
+        "androidx/media/session/MediaControllerCompat$Callback$MessageHandler": [
+          "MSG_EVENT",
+          "MSG_UPDATE_QUEUE_TITLE",
+          "MSG_UPDATE_EXTRAS",
+          "MSG_UPDATE_METADATA",
+          "MSG_UPDATE_VOLUME",
+          "MSG_UPDATE_SHUFFLE_MODE",
+          "MSG_DESTROYED",
+          "MSG_SESSION_READY",
+          "MSG_UPDATE_REPEAT_MODE",
+          "MSG_UPDATE_CAPTIONING_ENABLED",
+          "MSG_UPDATE_QUEUE",
+          "MSG_UPDATE_PLAYBACK_STATE"
+        ]
+      },
+      "android/support/v7/widget/LinearLayoutManager": {
+        "androidx/widget/LinearLayoutManager": [
+          "TAG",
+          "MAX_SCROLL_FACTOR",
+          "VERTICAL",
+          "INVALID_OFFSET",
+          "DEBUG",
+          "HORIZONTAL"
+        ]
+      },
+      "android/support/percent/BuildConfig": {
+        "androidx/BuildConfig": [
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "VERSION_CODE",
+          "APPLICATION_ID",
+          "FLAVOR",
+          "DEBUG"
+        ]
+      },
+      "android/support/graphics/drawable/BuildConfig": {
+        "androidx/graphics/drawable/BuildConfig": [
+          "VERSION_NAME",
+          "DEBUG",
+          "APPLICATION_ID",
+          "BUILD_TYPE",
+          "VERSION_CODE",
+          "FLAVOR"
+        ]
+      },
+      "android/support/v4/view/ViewParentCompat": {
+        "androidx/view/ViewParentCompat": [
+          "IMPL",
+          "TAG"
+        ]
+      },
+      "android/support/v4/widget/DrawerLayout$LayoutParams": {
+        "androidx/widget/DrawerLayout$LayoutParams": [
+          "gravity",
+          "width",
+          "FLAG_IS_OPENED",
+          "openState",
+          "onScreen",
+          "isPeeking",
+          "leftMargin",
+          "bottomMargin",
+          "FLAG_IS_OPENING",
+          "topMargin",
+          "FLAG_IS_CLOSING",
+          "height",
+          "rightMargin"
+        ]
+      },
+      "android/support/v4/graphics/drawable/DrawableWrapperApi14": {
+        "androidx/graphics/drawable/DrawableWrapperApi14": [
+          "DEFAULT_TINT_MODE"
+        ]
+      },
+      "android/support/v7/widget/GridLayoutManager$LayoutParams": {
+        "androidx/widget/GridLayoutManager$LayoutParams": [
+          "bottomMargin",
+          "rightMargin",
+          "height",
+          "topMargin",
+          "width",
+          "INVALID_SPAN_ID",
+          "leftMargin"
+        ]
+      },
+      "android/support/v4/app/NotificationManagerCompat$SideChannelManager$ListenerRecord": {
+        "androidx/app/NotificationManagerCompat$SideChannelManager$ListenerRecord": [
+          "taskQueue",
+          "service",
+          "componentName",
+          "retryCount",
+          "bound"
+        ]
+      },
+      "android/support/v17/leanback/widget/picker/DatePicker": {
+        "androidx/leanback/widget/picker/DatePicker": [
+          "DATE_FORMAT",
+          "LOG_TAG",
+          "DATE_FIELDS"
+        ]
+      },
+      "android/support/v7/widget/DrawableUtils": {
+        "androidx/widget/DrawableUtils": [
+          "INSETS_NONE",
+          "VECTOR_DRAWABLE_CLAZZ_NAME",
+          "TAG",
+          "sInsetsClazz"
+        ]
+      },
+      "android/support/v4/media/session/MediaControllerCompat$PlaybackInfo": {
+        "androidx/media/session/MediaControllerCompat$PlaybackInfo": [
+          "PLAYBACK_TYPE_LOCAL",
+          "PLAYBACK_TYPE_REMOTE"
+        ]
+      },
+      "android/support/v17/leanback/widget/SearchOrbView$Colors": {
+        "androidx/leanback/widget/SearchOrbView$Colors": [
+          "sBrightnessAlpha",
+          "brightColor",
+          "iconColor",
+          "color"
+        ]
+      },
+      "android/support/v7/widget/LayoutState": {
+        "androidx/widget/LayoutState": [
+          "TAG",
+          "LAYOUT_END",
+          "INVALID_LAYOUT",
+          "ITEM_DIRECTION_HEAD",
+          "ITEM_DIRECTION_TAIL",
+          "LAYOUT_START"
+        ]
+      },
+      "android/support/v17/leanback/app/BaseFragment": {
+        "androidx/leanback/app/BaseFragment": [
+          "STATE_ENTRANCE_COMPLETE",
+          "EVT_ON_CREATEVIEW",
+          "COND_TRANSITION_NOT_SUPPORTED",
+          "STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW",
+          "STATE_ENTRANCE_ON_ENDED",
+          "EVT_START_ENTRANCE",
+          "EVT_PREPARE_ENTRANCE",
+          "STATE_ENTRANCE_INIT",
+          "STATE_START",
+          "STATE_ENTRANCE_ON_PREPARED",
+          "EVT_ENTRANCE_END",
+          "STATE_ENTRANCE_PERFORM",
+          "EVT_ON_CREATE"
+        ]
+      },
+      "android/support/v7/widget/ActivityChooserView": {
+        "androidx/widget/ActivityChooserView": [
+          "LOG_TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/picker/PickerUtility$TimeConstant": {
+        "androidx/leanback/widget/picker/PickerUtility$TimeConstant": [
+          "ampm",
+          "minutes",
+          "locale",
+          "hours12",
+          "hours24"
+        ]
+      },
+      "android/support/design/widget/DrawableUtils": {
+        "androidx/design/widget/DrawableUtils": [
+          "LOG_TAG",
+          "sSetConstantStateMethod",
+          "sSetConstantStateMethodFetched"
+        ]
+      },
+      "android/support/v7/util/AsyncListUtil": {
+        "androidx/util/AsyncListUtil": [
+          "TAG",
+          "DEBUG"
+        ]
+      },
+      "android/support/v7/widget/ActivityChooserView$ActivityChooserViewAdapter": {
+        "androidx/widget/ActivityChooserView$ActivityChooserViewAdapter": [
+          "ITEM_VIEW_TYPE_COUNT",
+          "MAX_ACTIVITY_COUNT_DEFAULT",
+          "ITEM_VIEW_TYPE_ACTIVITY",
+          "ITEM_VIEW_TYPE_FOOTER",
+          "MAX_ACTIVITY_COUNT_UNLIMITED"
+        ]
+      },
+      "android/support/v17/leanback/widget/ControlBarPresenter": {
+        "androidx/leanback/widget/ControlBarPresenter": [
+          "sChildMarginDefault",
+          "MAX_CONTROLS",
+          "sControlIconWidth"
+        ]
+      },
+      "android/support/v4/app/FragmentTransaction": {
+        "androidx/app/FragmentTransaction": [
+          "TRANSIT_FRAGMENT_CLOSE",
+          "TRANSIT_EXIT_MASK",
+          "TRANSIT_FRAGMENT_OPEN",
+          "TRANSIT_UNSET",
+          "TRANSIT_FRAGMENT_FADE",
+          "TRANSIT_NONE",
+          "TRANSIT_ENTER_MASK"
+        ]
+      },
+      "android/support/design/widget/BottomSheetBehavior": {
+        "androidx/design/widget/BottomSheetBehavior": [
+          "STATE_COLLAPSED",
+          "HIDE_THRESHOLD",
+          "STATE_SETTLING",
+          "STATE_HIDDEN",
+          "STATE_DRAGGING",
+          "HIDE_FRICTION",
+          "STATE_EXPANDED",
+          "PEEK_HEIGHT_AUTO"
+        ]
+      },
+      "android/support/v17/leanback/app/VerticalGridSupportFragment": {
+        "androidx/leanback/app/VerticalGridSupportFragment": [
+          "DEBUG",
+          "STATE_ENTRANCE_ON_PREPARED",
+          "EVT_ON_CREATEVIEW",
+          "STATE_SET_ENTRANCE_START_STATE",
+          "TAG"
+        ]
+      },
+      "android/support/v7/media/MediaItemMetadata": {
+        "androidx/media/MediaItemMetadata": [
+          "KEY_ALBUM_TITLE",
+          "KEY_DURATION",
+          "KEY_YEAR",
+          "KEY_TRACK_NUMBER",
+          "KEY_AUTHOR",
+          "KEY_DISC_NUMBER",
+          "KEY_ALBUM_ARTIST",
+          "KEY_COMPOSER",
+          "KEY_ARTIST",
+          "KEY_ARTWORK_URI",
+          "KEY_TITLE"
+        ]
+      },
+      "android/support/v7/appcompat/R$bool": {
+        "androidx/appcompat/R$bool": [
+          "abc_config_showMenuShortcutsWhenKeyboardPresent",
+          "abc_action_bar_embed_tabs"
+        ]
+      },
+      "android/support/transition/ViewUtilsApi21": {
+        "androidx/transition/ViewUtilsApi21": [
+          "sTransformMatrixToGlobalMethodFetched",
+          "sTransformMatrixToLocalMethodFetched",
+          "TAG",
+          "sSetAnimationMatrixMethod",
+          "sTransformMatrixToGlobalMethod",
+          "sTransformMatrixToLocalMethod",
+          "sSetAnimationMatrixMethodFetched"
+        ]
+      },
+      "android/support/v4/util/Pair": {
+        "androidx/util/Pair": [
+          "first",
+          "second"
+        ]
+      },
+      "android/support/v7/preference/SeekBarPreference$SavedState": {
+        "androidx/preference/SeekBarPreference$SavedState": [
+          "min",
+          "max",
+          "CREATOR",
+          "seekBarValue"
+        ]
+      },
+      "android/support/v7/mediarouter/R$attr": {
+        "androidx/mediarouter/R$attr": [
+          "mediaRouteTheme",
+          "mediaRouteTvIconDrawable",
+          "mediaRouteButtonStyle",
+          "mediaRouteStopDrawable",
+          "mediaRoutePauseDrawable",
+          "mediaRouteSpeakerGroupIconDrawable",
+          "mediaRouteSpeakerIconDrawable",
+          "mediaRouteDefaultIconDrawable",
+          "mediaRoutePlayDrawable"
+        ]
+      },
+      "android/support/v7/view/SupportMenuInflater": {
+        "androidx/view/SupportMenuInflater": [
+          "XML_ITEM",
+          "XML_GROUP",
+          "LOG_TAG",
+          "ACTION_VIEW_CONSTRUCTOR_SIGNATURE",
+          "XML_MENU",
+          "ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE",
+          "NO_ID"
+        ]
+      },
+      "android/support/v4/view/AsyncLayoutInflater$InflateThread": {
+        "androidx/view/AsyncLayoutInflater$InflateThread": [
+          "sInstance"
+        ]
+      },
+      "android/support/design/widget/CollapsingTextHelper": {
+        "androidx/design/widget/CollapsingTextHelper": [
+          "DEBUG_DRAW",
+          "USE_SCALING_TEXTURE",
+          "DEBUG_DRAW_PAINT"
+        ]
+      },
+      "android/support/v4/app/FragmentTabHost$TabInfo": {
+        "androidx/app/FragmentTabHost$TabInfo": [
+          "tag",
+          "fragment",
+          "args",
+          "clss"
+        ]
+      },
+      "android/support/v17/leanback/app/VideoFragment": {
+        "androidx/leanback/app/VideoFragment": [
+          "SURFACE_NOT_CREATED",
+          "SURFACE_CREATED"
+        ]
+      },
+      "android/support/text/emoji/bundled/BundledEmojiCompatConfig$InitRunnable": {
+        "androidx/text/emoji/bundled/BundledEmojiCompatConfig$InitRunnable": [
+          "FONT_NAME"
+        ]
+      },
+      "android/support/mediacompat/R$layout": {
+        "androidx/mediacompat/R$layout": [
+          "notification_template_big_media_custom",
+          "notification_template_media",
+          "notification_media_action",
+          "notification_template_big_media_narrow_custom",
+          "notification_template_media_custom",
+          "notification_template_big_media",
+          "notification_template_big_media_narrow"
+        ]
+      },
+      "android/support/v4/app/NotificationCompat$MessagingStyle$Message": {
+        "androidx/app/NotificationCompat$MessagingStyle$Message": [
+          "KEY_DATA_URI",
+          "KEY_EXTRAS_BUNDLE",
+          "KEY_DATA_MIME_TYPE",
+          "KEY_TIMESTAMP",
+          "KEY_SENDER",
+          "KEY_TEXT"
+        ]
+      },
+      "android/support/v4/media/session/MediaControllerCompat": {
+        "androidx/media/session/MediaControllerCompat": [
+          "COMMAND_GET_EXTRA_BINDER",
+          "COMMAND_REMOVE_QUEUE_ITEM_AT",
+          "COMMAND_ARGUMENT_INDEX",
+          "COMMAND_ARGUMENT_MEDIA_DESCRIPTION",
+          "COMMAND_ADD_QUEUE_ITEM_AT",
+          "COMMAND_ADD_QUEUE_ITEM",
+          "COMMAND_REMOVE_QUEUE_ITEM",
+          "TAG"
+        ]
+      },
+      "android/support/v4/text/TextDirectionHeuristicsCompat$AnyStrong": {
+        "androidx/text/TextDirectionHeuristicsCompat$AnyStrong": [
+          "INSTANCE_RTL",
+          "INSTANCE_LTR"
+        ]
+      },
+      "android/support/wear/widget/ProgressDrawable": {
+        "androidx/wear/widget/ProgressDrawable": [
+          "FULL_CIRCLE",
+          "LEVEL",
+          "CORRECTION_ANGLE",
+          "GROW_SHRINK_RATIO",
+          "MAX_LEVEL",
+          "sInterpolator",
+          "NUMBER_OF_SEGMENTS",
+          "STARTING_ANGLE",
+          "MAX_SWEEP",
+          "ANIMATION_DURATION",
+          "LEVELS_PER_SEGMENT"
+        ]
+      },
+      "android/support/v7/app/MediaRouteControllerDialog$FetchArtTask": {
+        "androidx/app/MediaRouteControllerDialog$FetchArtTask": [
+          "SHOW_ANIM_TIME_THRESHOLD_MILLIS"
+        ]
+      },
+      "android/support/v17/leanback/transition/SlideKitkat": {
+        "androidx/leanback/transition/SlideKitkat": [
+          "sCalculateRight",
+          "sCalculateStart",
+          "sAccelerate",
+          "sDecelerate",
+          "sCalculateTop",
+          "sCalculateEnd",
+          "sCalculateLeft",
+          "sCalculateBottom",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/ImageCardView": {
+        "androidx/leanback/widget/ImageCardView": [
+          "CARD_TYPE_FLAG_CONTENT",
+          "ALPHA",
+          "CARD_TYPE_FLAG_ICON_RIGHT",
+          "CARD_TYPE_FLAG_TITLE",
+          "CARD_TYPE_FLAG_IMAGE_ONLY",
+          "CARD_TYPE_FLAG_ICON_LEFT"
+        ]
+      },
+      "android/support/v17/leanback/app/VideoSupportFragment": {
+        "androidx/leanback/app/VideoSupportFragment": [
+          "SURFACE_NOT_CREATED",
+          "SURFACE_CREATED"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsRow$PlayPauseAction": {
+        "androidx/leanback/widget/PlaybackControlsRow$PlayPauseAction": [
+          "INDEX_PAUSE",
+          "PLAY",
+          "INDEX_PLAY",
+          "PAUSE"
+        ]
+      },
+      "android/support/v7/widget/SearchView$AutoCompleteTextViewReflector": {
+        "androidx/widget/SearchView$AutoCompleteTextViewReflector": [
+          "showSoftInputUnchecked",
+          "doAfterTextChanged",
+          "ensureImeVisible",
+          "doBeforeTextChanged"
+        ]
+      },
+      "android/support/text/emoji/R$styleable": {
+        "androidx/text/emoji/R$styleable": [
+          "EmojiExtractTextLayout",
+          "EmojiEditText_maxEmojiCount",
+          "EmojiExtractTextLayout_emojiReplaceStrategy",
+          "EmojiEditText"
+        ]
+      },
+      "android/support/v4/view/animation/PathInterpolatorApi14": {
+        "androidx/view/animation/PathInterpolatorApi14": [
+          "PRECISION"
+        ]
+      },
+      "android/support/v4/app/FragmentTransition": {
+        "androidx/app/FragmentTransition": [
+          "PLATFORM_IMPL",
+          "INVERSE_OPS",
+          "SUPPORT_IMPL"
+        ]
+      },
+      "android/support/v7/widget/GridLayout$Spec": {
+        "androidx/widget/GridLayout$Spec": [
+          "weight",
+          "alignment",
+          "UNDEFINED",
+          "startDefined",
+          "span",
+          "DEFAULT_WEIGHT"
+        ]
+      },
+      "android/support/v4/BuildConfig": {
+        "androidx/BuildConfig": [
+          "BUILD_TYPE",
+          "DEBUG",
+          "APPLICATION_ID",
+          "FLAVOR",
+          "VERSION_CODE",
+          "VERSION_NAME"
+        ]
+      },
+      "android/support/v4/app/INotificationSideChannel$Stub": {
+        "androidx/app/INotificationSideChannel$Stub": [
+          "TRANSACTION_notify",
+          "TRANSACTION_cancel",
+          "TRANSACTION_cancelAll",
+          "DESCRIPTOR"
+        ]
+      },
+      "android/support/v4/app/FragmentManagerImpl": {
+        "androidx/app/FragmentManagerImpl": [
+          "sAnimationListenerField",
+          "TAG",
+          "ANIM_DUR",
+          "ANIM_STYLE_FADE_EXIT",
+          "DEBUG",
+          "ACCELERATE_QUINT",
+          "TARGET_REQUEST_CODE_STATE_TAG",
+          "ANIM_STYLE_OPEN_EXIT",
+          "ANIM_STYLE_OPEN_ENTER",
+          "TARGET_STATE_TAG",
+          "USER_VISIBLE_HINT_TAG",
+          "ANIM_STYLE_FADE_ENTER",
+          "VIEW_STATE_TAG",
+          "DECELERATE_QUINT",
+          "DECELERATE_CUBIC",
+          "ANIM_STYLE_CLOSE_ENTER",
+          "ACCELERATE_CUBIC",
+          "ANIM_STYLE_CLOSE_EXIT"
+        ]
+      },
+      "android/support/v7/app/MediaRouteButton": {
+        "androidx/app/MediaRouteButton": [
+          "TAG",
+          "sRemoteIndicatorCache",
+          "CHECKED_STATE_SET",
+          "CHECKABLE_STATE_SET",
+          "CONTROLLER_FRAGMENT_TAG",
+          "CHOOSER_FRAGMENT_TAG"
+        ]
+      },
+      "android/support/v7/widget/VectorEnabledTintResources": {
+        "androidx/widget/VectorEnabledTintResources": [
+          "MAX_SDK_WHERE_REQUIRED"
+        ]
+      },
+      "android/support/v7/view/menu/MenuItemImpl": {
+        "androidx/view/menu/MenuItemImpl": [
+          "NO_ICON",
+          "HIDDEN",
+          "sEnterShortcutLabel",
+          "CHECKABLE",
+          "SHOW_AS_ACTION_MASK",
+          "sSpaceShortcutLabel",
+          "EXCLUSIVE",
+          "CHECKED",
+          "TAG",
+          "sDeleteShortcutLabel",
+          "IS_ACTION",
+          "ENABLED",
+          "sPrependShortcutLabel"
+        ]
+      },
+      "android/support/content/InMemoryCursor": {
+        "androidx/content/InMemoryCursor": [
+          "NUM_TYPES"
+        ]
+      },
+      "android/support/v4/app/FragmentPagerAdapter": {
+        "androidx/app/FragmentPagerAdapter": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v4/text/ICUCompat": {
+        "androidx/text/ICUCompat": [
+          "TAG",
+          "sAddLikelySubtagsMethod",
+          "sGetScriptMethod"
+        ]
+      },
+      "android/support/v4/media/session/MediaControllerCompatApi21$PlaybackInfo": {
+        "androidx/media/session/MediaControllerCompatApi21$PlaybackInfo": [
+          "FLAG_SCO",
+          "STREAM_BLUETOOTH_SCO",
+          "STREAM_SYSTEM_ENFORCED"
+        ]
+      },
+      "android/support/text/emoji/R$id": {
+        "androidx/text/emoji/R$id": [
+          "inputExtractAccessories",
+          "inputExtractAction"
+        ]
+      },
+      "android/support/v17/leanback/R$animator": {
+        "androidx/leanback/R$animator": [
+          "lb_onboarding_page_indicator_fade_in",
+          "lb_onboarding_page_indicator_fade_out",
+          "lb_onboarding_start_button_fade_in",
+          "lb_playback_controls_fade_in",
+          "lb_playback_controls_fade_out",
+          "lb_onboarding_logo_enter",
+          "lb_onboarding_start_button_fade_out",
+          "lb_onboarding_page_indicator_enter",
+          "lb_playback_bg_fade_out",
+          "lb_onboarding_title_enter",
+          "lb_onboarding_description_enter",
+          "lb_playback_bg_fade_in",
+          "lb_onboarding_logo_exit"
+        ]
+      },
+      "android/support/transition/TransitionInflater": {
+        "androidx/transition/TransitionInflater": [
+          "CONSTRUCTOR_SIGNATURE",
+          "CONSTRUCTORS"
+        ]
+      },
+      "android/support/v4/media/RatingCompat": {
+        "androidx/media/RatingCompat": [
+          "RATING_THUMB_UP_DOWN",
+          "RATING_5_STARS",
+          "RATING_HEART",
+          "RATING_PERCENTAGE",
+          "CREATOR",
+          "RATING_4_STARS",
+          "RATING_NONE",
+          "RATING_NOT_RATED",
+          "TAG",
+          "RATING_3_STARS"
+        ]
+      },
+      "android/support/v17/leanback/transition/FadeAndShortSlide": {
+        "androidx/leanback/transition/FadeAndShortSlide": [
+          "sCalculateTopBottom",
+          "sCalculateStartEnd",
+          "sCalculateEnd",
+          "sCalculateBottom",
+          "PROPNAME_SCREEN_POSITION",
+          "sDecelerate",
+          "sCalculateStart",
+          "sCalculateTop"
+        ]
+      },
+      "android/support/design/R$attr": {
+        "androidx/design/R$attr": [
+          "state_collapsible",
+          "state_collapsed",
+          "bottomSheetDialogTheme"
+        ]
+      },
+      "android/support/graphics/drawable/PathInterpolatorCompat": {
+        "androidx/graphics/drawable/PathInterpolatorCompat": [
+          "EPSILON",
+          "PRECISION",
+          "MAX_NUM_POINTS"
+        ]
+      },
+      "android/support/animation/SpringAnimation": {
+        "androidx/animation/SpringAnimation": [
+          "UNSET"
+        ]
+      },
+      "android/support/v7/app/AppCompatDelegateImplV9$PanelFeatureState$SavedState": {
+        "androidx/app/AppCompatDelegateImplV9$PanelFeatureState$SavedState": [
+          "featureId",
+          "menuState",
+          "CREATOR",
+          "isOpen"
+        ]
+      },
+      "android/support/v7/view/menu/MenuBuilder": {
+        "androidx/view/menu/MenuBuilder": [
+          "EXPANDED_ACTION_VIEW_ID",
+          "TAG",
+          "PRESENTER_KEY",
+          "ACTION_VIEW_STATES_KEY",
+          "sCategoryToOrder"
+        ]
+      },
+      "android/support/v4/view/ViewGroupCompat": {
+        "androidx/view/ViewGroupCompat": [
+          "LAYOUT_MODE_OPTICAL_BOUNDS",
+          "LAYOUT_MODE_CLIP_BOUNDS",
+          "IMPL"
+        ]
+      },
+      "android/support/v14/preference/MultiSelectListPreferenceDialogFragment": {
+        "androidx/preference/MultiSelectListPreferenceDialogFragment": [
+          "SAVE_STATE_ENTRY_VALUES",
+          "SAVE_STATE_VALUES",
+          "SAVE_STATE_ENTRIES",
+          "SAVE_STATE_CHANGED"
+        ]
+      },
+      "android/support/exifinterface/BuildConfig": {
+        "androidx/exifinterface/BuildConfig": [
+          "VERSION_NAME",
+          "DEBUG",
+          "APPLICATION_ID",
+          "BUILD_TYPE",
+          "VERSION_CODE",
+          "FLAVOR"
+        ]
+      },
+      "android/support/v4/print/PrintHelper$PrintHelperApi19": {
+        "androidx/print/PrintHelper$PrintHelperApi19": [
+          "MAX_PRINT_SIZE",
+          "LOG_TAG"
+        ]
+      },
+      "android/support/v7/preference/R$layout": {
+        "androidx/preference/R$layout": [
+          "preference_list_fragment",
+          "preference_recyclerview",
+          "preference"
+        ]
+      },
+      "android/support/v7/widget/AdapterHelper$UpdateOp": {
+        "androidx/widget/AdapterHelper$UpdateOp": [
+          "positionStart",
+          "payload",
+          "MOVE",
+          "REMOVE",
+          "ADD",
+          "UPDATE",
+          "cmd",
+          "POOL_SIZE",
+          "itemCount"
+        ]
+      },
+      "android/support/v17/leanback/app/BrowseFragment$SetSelectionRunnable": {
+        "androidx/leanback/app/BrowseFragment$SetSelectionRunnable": [
+          "TYPE_INTERNAL_SYNC",
+          "TYPE_USER_REQUEST",
+          "TYPE_INVALID"
+        ]
+      },
+      "android/support/v17/leanback/app/BrowseSupportFragment$ExpandPreLayout": {
+        "androidx/leanback/app/BrowseSupportFragment$ExpandPreLayout": [
+          "STATE_SECOND_DRAW",
+          "STATE_INIT",
+          "STATE_FIRST_DRAW",
+          "mainFragmentAdapter"
+        ]
+      },
+      "android/support/v4/widget/PopupWindowCompat$PopupWindowCompatBaseImpl": {
+        "androidx/widget/PopupWindowCompat$PopupWindowCompatBaseImpl": [
+          "sGetWindowLayoutTypeMethodAttempted",
+          "sGetWindowLayoutTypeMethod",
+          "sSetWindowLayoutTypeMethod",
+          "sSetWindowLayoutTypeMethodAttempted"
+        ]
+      },
+      "android/support/v7/widget/SwitchCompat": {
+        "androidx/widget/SwitchCompat": [
+          "MONOSPACE",
+          "CHECKED_STATE_SET",
+          "TOUCH_MODE_DRAGGING",
+          "TOUCH_MODE_DOWN",
+          "THUMB_POS",
+          "TOUCH_MODE_IDLE",
+          "SERIF",
+          "THUMB_ANIMATION_DURATION",
+          "ACCESSIBILITY_EVENT_CLASS_NAME",
+          "SANS"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView$LayoutManager$Properties": {
+        "androidx/widget/RecyclerView$LayoutManager$Properties": [
+          "reverseLayout",
+          "stackFromEnd",
+          "spanCount",
+          "orientation"
+        ]
+      },
+      "android/support/v4/app/NotificationManagerCompat$SideChannelManager": {
+        "androidx/app/NotificationManagerCompat$SideChannelManager": [
+          "MSG_QUEUE_TASK",
+          "MSG_RETRY_LISTENER_QUEUE",
+          "MSG_SERVICE_CONNECTED",
+          "MSG_SERVICE_DISCONNECTED"
+        ]
+      },
+      "android/support/v17/leanback/app/BrowseSupportFragment$MainFragmentAdapterRegistry": {
+        "androidx/leanback/app/BrowseSupportFragment$MainFragmentAdapterRegistry": [
+          "sDefaultFragmentFactory"
+        ]
+      },
+      "android/support/v7/preference/PreferenceFragmentCompat": {
+        "androidx/preference/PreferenceFragmentCompat": [
+          "MSG_BIND_PREFERENCES",
+          "PREFERENCES_TAG",
+          "ARG_PREFERENCE_ROOT",
+          "DIALOG_FRAGMENT_TAG"
+        ]
+      },
+      "android/support/v7/widget/SearchView": {
+        "androidx/widget/SearchView": [
+          "ENABLED_STATE_SET",
+          "EMPTY_STATE_SET",
+          "FOCUSED_STATE_SET",
+          "DBG",
+          "IME_OPTION_NO_MICROPHONE",
+          "LOG_TAG",
+          "HIDDEN_METHOD_INVOKER"
+        ]
+      },
+      "android/support/v4/view/AsyncLayoutInflater$BasicInflater": {
+        "androidx/view/AsyncLayoutInflater$BasicInflater": [
+          "sClassPrefixList"
+        ]
+      },
+      "android/support/v7/widget/DividerItemDecoration": {
+        "androidx/widget/DividerItemDecoration": [
+          "VERTICAL",
+          "HORIZONTAL",
+          "ATTRS",
+          "TAG"
+        ]
+      },
+      "android/support/wear/widget/SwipeDismissFrameLayout": {
+        "androidx/wear/widget/SwipeDismissFrameLayout": [
+          "DEFAULT_INTERPOLATION_FACTOR",
+          "TRANSLATION_MIN_ALPHA",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/app/HeadersFragment": {
+        "androidx/leanback/app/HeadersFragment": [
+          "sHeaderPresenter",
+          "sLayoutChangeListener"
+        ]
+      },
+      "android/support/customtabs/CustomTabsService": {
+        "androidx/browser/customtabs/CustomTabsService": [
+          "RESULT_FAILURE_MESSAGING_ERROR",
+          "RESULT_SUCCESS",
+          "RESULT_FAILURE_REMOTE_ERROR",
+          "ACTION_CUSTOM_TABS_CONNECTION",
+          "KEY_URL",
+          "RESULT_FAILURE_DISALLOWED",
+          "RELATION_HANDLE_ALL_URLS",
+          "RELATION_USE_AS_ORIGIN"
+        ]
+      },
+      "android/support/v17/leanback/app/GuidedStepFragment": {
+        "androidx/leanback/app/GuidedStepFragment": [
+          "IS_FRAMEWORK_FRAGMENT",
+          "entranceTransitionType",
+          "ENTRY_NAME_ENTRANCE",
+          "TAG_LEAN_BACK_ACTIONS_FRAGMENT",
+          "UI_STYLE_REPLACE",
+          "EXTRA_BUTTON_ACTION_PREFIX",
+          "UI_STYLE_DEFAULT",
+          "DEBUG",
+          "SLIDE_FROM_BOTTOM",
+          "UI_STYLE_ENTRANCE",
+          "SLIDE_FROM_SIDE",
+          "TAG",
+          "EXTRA_UI_STYLE",
+          "EXTRA_ACTION_PREFIX",
+          "ENTRY_NAME_REPLACE",
+          "UI_STYLE_ACTIVITY_ROOT"
+        ]
+      },
+      "android/support/v17/leanback/util/StateMachine": {
+        "androidx/leanback/util/StateMachine": [
+          "STATUS_ZERO",
+          "STATUS_INVOKED",
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/compat/R$drawable": {
+        "androidx/compat/R$drawable": [
+          "notification_template_icon_bg",
+          "notification_bg",
+          "notification_icon_background",
+          "notification_template_icon_low_bg",
+          "notification_bg_low"
+        ]
+      },
+      "android/support/v4/provider/DocumentsContractApi19": {
+        "androidx/provider/DocumentsContractApi19": [
+          "TAG",
+          "FLAG_VIRTUAL_DOCUMENT"
+        ]
+      },
+      "android/support/v4/app/JobIntentService": {
+        "androidx/app/JobIntentService": [
+          "TAG",
+          "sClassWorkEnqueuer",
+          "DEBUG",
+          "sLock"
+        ]
+      },
+      "android/support/v4/graphics/TypefaceCompatUtil": {
+        "androidx/graphics/TypefaceCompatUtil": [
+          "CACHE_FILE_PREFIX",
+          "TAG"
+        ]
+      },
+      "android/support/transition/Explode": {
+        "androidx/transition/Explode": [
+          "PROPNAME_SCREEN_BOUNDS",
+          "sDecelerate",
+          "sAccelerate"
+        ]
+      },
+      "android/support/v4/view/AccessibilityDelegateCompat": {
+        "androidx/view/AccessibilityDelegateCompat": [
+          "DEFAULT_DELEGATE",
+          "IMPL"
+        ]
+      },
+      "android/support/v4/view/MenuItemCompat": {
+        "androidx/view/MenuItemCompat": [
+          "IMPL",
+          "SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW",
+          "SHOW_AS_ACTION_WITH_TEXT",
+          "SHOW_AS_ACTION_NEVER",
+          "SHOW_AS_ACTION_ALWAYS",
+          "SHOW_AS_ACTION_IF_ROOM",
+          "TAG"
+        ]
+      },
+      "android/support/v4/widget/CircleImageView": {
+        "androidx/widget/CircleImageView": [
+          "SHADOW_RADIUS",
+          "Y_OFFSET",
+          "X_OFFSET",
+          "KEY_SHADOW_COLOR",
+          "SHADOW_ELEVATION",
+          "FILL_SHADOW_COLOR"
+        ]
+      },
+      "android/support/v7/widget/SuggestionsAdapter": {
+        "androidx/widget/SuggestionsAdapter": [
+          "REFINE_NONE",
+          "LOG_TAG",
+          "REFINE_ALL",
+          "INVALID_INDEX",
+          "DBG",
+          "QUERY_LIMIT",
+          "REFINE_BY_ENTRY"
+        ]
+      },
+      "android/support/wear/widget/drawer/WearableActionDrawerView$ActionItemViewHolder": {
+        "androidx/wear/widget/drawer/WearableActionDrawerView$ActionItemViewHolder": [
+          "view",
+          "iconView",
+          "textView"
+        ]
+      },
+      "android/support/v14/preference/PreferenceDialogFragment": {
+        "androidx/preference/PreferenceDialogFragment": [
+          "SAVE_STATE_POSITIVE_TEXT",
+          "SAVE_STATE_TITLE",
+          "SAVE_STATE_ICON",
+          "ARG_KEY",
+          "SAVE_STATE_MESSAGE",
+          "SAVE_STATE_NEGATIVE_TEXT",
+          "SAVE_STATE_LAYOUT"
+        ]
+      },
+      "android/support/v4/media/session/IMediaControllerCallback$Stub": {
+        "androidx/media/session/IMediaControllerCallback$Stub": [
+          "TRANSACTION_onSessionDestroyed",
+          "TRANSACTION_onMetadataChanged",
+          "TRANSACTION_onEvent",
+          "TRANSACTION_onQueueChanged",
+          "TRANSACTION_onSessionReady",
+          "TRANSACTION_onCaptioningEnabledChanged",
+          "TRANSACTION_onVolumeInfoChanged",
+          "TRANSACTION_onShuffleModeChangedRemoved",
+          "TRANSACTION_onRepeatModeChanged",
+          "TRANSACTION_onPlaybackStateChanged",
+          "TRANSACTION_onQueueTitleChanged",
+          "TRANSACTION_onShuffleModeChanged",
+          "DESCRIPTOR",
+          "TRANSACTION_onExtrasChanged"
+        ]
+      },
+      "android/support/v7/preference/EditTextPreference$SavedState": {
+        "androidx/preference/EditTextPreference$SavedState": [
+          "text",
+          "CREATOR"
+        ]
+      },
+      "android/support/v17/leanback/widget/PagingIndicator$Dot": {
+        "androidx/leanback/widget/PagingIndicator$Dot": [
+          "LEFT",
+          "LTR",
+          "RIGHT",
+          "RTL"
+        ]
+      },
+      "android/support/v7/widget/ScrollingTabContainerView$TabView": {
+        "androidx/widget/ScrollingTabContainerView$TabView": [
+          "BG_ATTRS"
+        ]
+      },
+      "android/support/wear/ambient/SharedLibraryVersion$PresenceHolder": {
+        "androidx/wear/ambient/SharedLibraryVersion$PresenceHolder": [
+          "PRESENT"
+        ]
+      },
+      "android/support/v4/graphics/BitmapCompat": {
+        "androidx/graphics/BitmapCompat": [
+          "IMPL"
+        ]
+      },
+      "android/support/wear/R$fraction": {
+        "androidx/wear/R$fraction": [
+          "ws_action_drawer_item_right_padding",
+          "ws_action_drawer_item_last_item_bottom_padding",
+          "ws_action_drawer_item_left_padding",
+          "ws_action_drawer_item_first_item_top_padding"
+        ]
+      },
+      "android/support/v7/media/MediaSessionStatus": {
+        "androidx/media/MediaSessionStatus": [
+          "KEY_TIMESTAMP",
+          "SESSION_STATE_INVALIDATED",
+          "KEY_EXTRAS",
+          "KEY_QUEUE_PAUSED",
+          "KEY_SESSION_STATE",
+          "SESSION_STATE_ENDED",
+          "SESSION_STATE_ACTIVE"
+        ]
+      },
+      "android/support/v4/app/NotificationManagerCompat$CancelTask": {
+        "androidx/app/NotificationManagerCompat$CancelTask": [
+          "tag",
+          "all",
+          "id",
+          "packageName"
+        ]
+      },
+      "android/support/v4/media/MediaBrowserCompat$MediaBrowserImplBase": {
+        "androidx/media/MediaBrowserCompat$MediaBrowserImplBase": [
+          "CONNECT_STATE_DISCONNECTED",
+          "CONNECT_STATE_CONNECTED",
+          "CONNECT_STATE_CONNECTING",
+          "CONNECT_STATE_SUSPENDED",
+          "CONNECT_STATE_DISCONNECTING"
+        ]
+      },
+      "android/support/wear/widget/WearableRecyclerView": {
+        "androidx/wear/widget/WearableRecyclerView": [
+          "TAG",
+          "NO_VALUE"
+        ]
+      },
+      "android/support/app/recommendation/RecommendationExtender": {
+        "androidx/app/recommendation/RecommendationExtender": [
+          "KEY_CONTENT_RUN_LENGTH",
+          "KEY_CONTENT_GENRES",
+          "KEY_CONTENT_TYPE",
+          "TAG",
+          "EXTRA_CONTENT_INFO_EXTENDER",
+          "KEY_CONTENT_MATURITY_RATING",
+          "KEY_CONTENT_STATUS",
+          "KEY_CONTENT_PRICING_VALUE",
+          "KEY_CONTENT_PRICING_TYPE"
+        ]
+      },
+      "android/support/v7/widget/ThemeUtils": {
+        "androidx/widget/ThemeUtils": [
+          "TEMP_ARRAY",
+          "DISABLED_STATE_SET",
+          "ACTIVATED_STATE_SET",
+          "NOT_PRESSED_OR_FOCUSED_STATE_SET",
+          "FOCUSED_STATE_SET",
+          "SELECTED_STATE_SET",
+          "CHECKED_STATE_SET",
+          "PRESSED_STATE_SET",
+          "EMPTY_STATE_SET",
+          "TL_TYPED_VALUE"
+        ]
+      },
+      "android/support/media/ExifInterface$ByteOrderedDataInputStream": {
+        "androidx/media/ExifInterface$ByteOrderedDataInputStream": [
+          "BIG_ENDIAN",
+          "LITTLE_ENDIAN"
+        ]
+      },
+      "android/support/v7/widget/helper/ItemTouchHelper$Callback": {
+        "androidx/widget/helper/ItemTouchHelper$Callback": [
+          "ABS_HORIZONTAL_DIR_FLAGS",
+          "sDragScrollInterpolator",
+          "DRAG_SCROLL_ACCELERATION_LIMIT_TIME_MS",
+          "DEFAULT_DRAG_ANIMATION_DURATION",
+          "RELATIVE_DIR_FLAGS",
+          "DEFAULT_SWIPE_ANIMATION_DURATION",
+          "sDragViewScrollCapInterpolator",
+          "sUICallback"
+        ]
+      },
+      "android/support/v4/media/MediaBrowserServiceCompat$BrowserRoot": {
+        "androidx/media/MediaBrowserServiceCompat$BrowserRoot": [
+          "EXTRA_SUGGESTION_KEYWORDS",
+          "EXTRA_SUGGESTED",
+          "EXTRA_OFFLINE",
+          "EXTRA_RECENT"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsPresenter": {
+        "androidx/leanback/widget/PlaybackControlsPresenter": [
+          "sChildMarginBigger",
+          "sChildMarginBiggest"
+        ]
+      },
+      "android/support/v7/preference/PreferenceDialogFragmentCompat": {
+        "androidx/preference/PreferenceDialogFragmentCompat": [
+          "SAVE_STATE_LAYOUT",
+          "ARG_KEY",
+          "SAVE_STATE_ICON",
+          "SAVE_STATE_MESSAGE",
+          "SAVE_STATE_TITLE",
+          "SAVE_STATE_NEGATIVE_TEXT",
+          "SAVE_STATE_POSITIVE_TEXT"
+        ]
+      },
+      "android/support/v7/app/TwilightManager": {
+        "androidx/app/TwilightManager": [
+          "SUNRISE",
+          "SUNSET",
+          "TAG",
+          "sInstance"
+        ]
+      },
+      "android/support/v4/graphics/drawable/DrawableCompat": {
+        "androidx/graphics/drawable/DrawableCompat": [
+          "sSetLayoutDirectionMethod",
+          "sGetLayoutDirectionMethodFetched",
+          "sGetLayoutDirectionMethod",
+          "TAG",
+          "sSetLayoutDirectionMethodFetched"
+        ]
+      },
+      "android/support/coreutils/BuildConfig": {
+        "androidx/coreutils/BuildConfig": [
+          "FLAVOR",
+          "APPLICATION_ID",
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "VERSION_CODE",
+          "DEBUG"
+        ]
+      },
+      "android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory": {
+        "androidx/graphics/drawable/RoundedBitmapDrawableFactory": [
+          "TAG"
+        ]
+      },
+      "android/support/transition/GhostViewApi21": {
+        "androidx/transition/GhostViewApi21": [
+          "sAddGhostMethod",
+          "TAG",
+          "sRemoveGhostMethod",
+          "sAddGhostMethodFetched",
+          "sRemoveGhostMethodFetched",
+          "sGhostViewClassFetched",
+          "sGhostViewClass"
+        ]
+      },
+      "android/support/v7/app/ActionBar": {
+        "androidx/app/ActionBar": [
+          "NAVIGATION_MODE_TABS",
+          "NAVIGATION_MODE_LIST",
+          "DISPLAY_SHOW_TITLE",
+          "DISPLAY_SHOW_CUSTOM",
+          "DISPLAY_USE_LOGO",
+          "NAVIGATION_MODE_STANDARD",
+          "DISPLAY_HOME_AS_UP",
+          "DISPLAY_SHOW_HOME"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat$WatchNextPrograms": {
+        "androidx/media/tv/TvContractCompat$WatchNextPrograms": [
+          "WATCH_NEXT_TYPE_WATCHLIST",
+          "WATCH_NEXT_TYPE_CONTINUE",
+          "WATCH_NEXT_TYPE_NEXT",
+          "COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS",
+          "CONTENT_URI",
+          "WATCH_NEXT_TYPE_NEW",
+          "CONTENT_TYPE",
+          "COLUMN_WATCH_NEXT_TYPE",
+          "CONTENT_ITEM_TYPE"
+        ]
+      },
+      "android/support/v4/view/accessibility/AccessibilityNodeInfoCompat$CollectionInfoCompat": {
+        "androidx/view/accessibility/AccessibilityNodeInfoCompat$CollectionInfoCompat": [
+          "SELECTION_MODE_MULTIPLE",
+          "SELECTION_MODE_SINGLE",
+          "SELECTION_MODE_NONE"
+        ]
+      },
+      "android/support/v17/preference/R$id": {
+        "androidx/leanback/preference/R$id": [
+          "button",
+          "settings_preference_fragment_container",
+          "main_frame",
+          "container",
+          "decor_title",
+          "settings_dialog_container"
+        ]
+      },
+      "android/support/wear/R$style": {
+        "androidx/wear/R$style": [
+          "Widget_Wear_WearableDrawerView",
+          "WsPageIndicatorViewStyle"
+        ]
+      },
+      "android/support/v17/leanback/widget/GuidedActionAdapterGroup": {
+        "androidx/leanback/widget/GuidedActionAdapterGroup": [
+          "TAG_EDIT",
+          "DEBUG_EDIT"
+        ]
+      },
+      "android/support/v7/widget/GridLayout$PackedMap": {
+        "androidx/widget/GridLayout$PackedMap": [
+          "values",
+          "index",
+          "keys"
+        ]
+      },
+      "android/support/v7/widget/ActionBarOverlayLayout": {
+        "androidx/widget/ActionBarOverlayLayout": [
+          "TAG",
+          "ATTRS",
+          "ACTION_BAR_ANIMATE_DELAY"
+        ]
+      },
+      "android/support/fragment/BuildConfig": {
+        "androidx/fragment/BuildConfig": [
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "VERSION_CODE",
+          "DEBUG",
+          "APPLICATION_ID",
+          "FLAVOR"
+        ]
+      },
+      "android/support/v4/app/NavUtils": {
+        "androidx/app/NavUtils": [
+          "TAG",
+          "PARENT_ACTIVITY"
+        ]
+      },
+      "android/support/v7/media/RemotePlaybackClient$ActionReceiver": {
+        "androidx/media/RemotePlaybackClient$ActionReceiver": [
+          "ACTION_ITEM_STATUS_CHANGED",
+          "ACTION_MESSAGE_RECEIVED",
+          "ACTION_SESSION_STATUS_CHANGED"
+        ]
+      },
+      "android/support/v4/app/JobIntentService$JobServiceEngineImpl": {
+        "androidx/app/JobIntentService$JobServiceEngineImpl": [
+          "TAG",
+          "DEBUG"
+        ]
+      },
+      "android/support/v4/app/FragmentActivity$NonConfigurationInstances": {
+        "androidx/app/FragmentActivity$NonConfigurationInstances": [
+          "custom",
+          "fragments",
+          "loaders"
+        ]
+      },
+      "android/support/text/emoji/flatbuffer/FlatBufferBuilder": {
+        "androidx/text/emoji/flatbuffer/FlatBufferBuilder": [
+          "encoder",
+          "vtable_in_use",
+          "minalign",
+          "vtables",
+          "num_vtables",
+          "force_defaults",
+          "space",
+          "bb",
+          "object_start",
+          "vtable",
+          "dst",
+          "vector_num_elems",
+          "nested",
+          "finished",
+          "utf8charset"
+        ]
+      },
+      "android/support/v7/mediarouter/R$interpolator": {
+        "androidx/mediarouter/R$interpolator": [
+          "mr_fast_out_slow_in",
+          "mr_linear_out_slow_in"
+        ]
+      },
+      "android/support/v7/recyclerview/R$dimen": {
+        "androidx/recyclerview/R$dimen": [
+          "item_touch_helper_max_drag_scroll_per_frame",
+          "fastscroll_minimum_range",
+          "item_touch_helper_swipe_escape_max_velocity",
+          "fastscroll_default_thickness",
+          "item_touch_helper_swipe_escape_velocity",
+          "fastscroll_margin"
+        ]
+      },
+      "android/support/v4/app/ShareCompat": {
+        "androidx/app/ShareCompat": [
+          "EXTRA_CALLING_PACKAGE",
+          "HISTORY_FILENAME_PREFIX",
+          "EXTRA_CALLING_ACTIVITY"
+        ]
+      },
+      "android/support/v4/media/AudioAttributesCompatApi21": {
+        "androidx/media/AudioAttributesCompatApi21": [
+          "TAG",
+          "sAudioAttributesToLegacyStreamType"
+        ]
+      },
+      "android/support/customtabs/CustomTabsCallback": {
+        "androidx/browser/customtabs/CustomTabsCallback": [
+          "NAVIGATION_FINISHED",
+          "NAVIGATION_ABORTED",
+          "NAVIGATION_FAILED",
+          "NAVIGATION_STARTED",
+          "TAB_HIDDEN",
+          "TAB_SHOWN"
+        ]
+      },
+      "android/support/wear/widget/CircularProgressLayout": {
+        "androidx/wear/widget/CircularProgressLayout": [
+          "DEFAULT_ROTATION",
+          "DEFAULT_UPDATE_INTERVAL"
+        ]
+      },
+      "android/support/v17/leanback/widget/ListRowPresenter": {
+        "androidx/leanback/widget/ListRowPresenter": [
+          "DEBUG",
+          "TAG",
+          "sExpandedSelectedRowTopPadding",
+          "DEFAULT_RECYCLED_POOL_SIZE",
+          "sExpandedRowNoHovercardBottomPadding",
+          "sSelectedRowTopPadding"
+        ]
+      },
+      "android/support/v7/preference/PreferenceGroupAdapter$PreferenceLayout": {
+        "androidx/preference/PreferenceGroupAdapter$PreferenceLayout": [
+          "widgetResId",
+          "resId",
+          "name"
+        ]
+      },
+      "android/support/transition/BuildConfig": {
+        "androidx/transition/BuildConfig": [
+          "FLAVOR",
+          "DEBUG",
+          "BUILD_TYPE",
+          "VERSION_CODE",
+          "APPLICATION_ID",
+          "VERSION_NAME"
+        ]
+      },
+      "android/support/transition/Styleable$Transition": {
+        "androidx/transition/Styleable$Transition": [
+          "MATCH_ORDER",
+          "START_DELAY",
+          "DURATION",
+          "INTERPOLATOR"
+        ]
+      },
+      "android/support/v4/view/accessibility/AccessibilityNodeInfoCompat$RangeInfoCompat": {
+        "androidx/view/accessibility/AccessibilityNodeInfoCompat$RangeInfoCompat": [
+          "RANGE_TYPE_PERCENT",
+          "RANGE_TYPE_INT",
+          "RANGE_TYPE_FLOAT"
+        ]
+      },
+      "android/support/transition/Styleable$Fade": {
+        "androidx/transition/Styleable$Fade": [
+          "FADING_MODE"
+        ]
+      },
+      "android/support/v4/app/SharedElementCallback": {
+        "androidx/app/SharedElementCallback": [
+          "BUNDLE_SNAPSHOT_BITMAP",
+          "BUNDLE_SNAPSHOT_IMAGE_MATRIX",
+          "BUNDLE_SNAPSHOT_IMAGE_SCALETYPE",
+          "MAX_IMAGE_SIZE"
+        ]
+      },
+      "android/support/design/widget/ThemeUtils": {
+        "androidx/design/widget/ThemeUtils": [
+          "APPCOMPAT_CHECK_ATTRS"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat$Programs": {
+        "androidx/media/tv/TvContractCompat$Programs": [
+          "COLUMN_BROADCAST_GENRE",
+          "COLUMN_CHANNEL_ID",
+          "COLUMN_START_TIME_UTC_MILLIS",
+          "CONTENT_ITEM_TYPE",
+          "CONTENT_TYPE",
+          "COLUMN_EPISODE_NUMBER",
+          "COLUMN_END_TIME_UTC_MILLIS",
+          "COLUMN_RECORDING_PROHIBITED",
+          "CONTENT_URI",
+          "COLUMN_SEASON_NUMBER"
+        ]
+      },
+      "android/support/v17/leanback/R$integer": {
+        "androidx/leanback/R$integer": [
+          "lb_details_description_body_min_lines",
+          "lb_search_orb_pulse_duration_ms",
+          "lb_search_bar_speech_mode_background_alpha",
+          "lb_search_bar_text_mode_background_alpha",
+          "lb_details_description_body_max_lines",
+          "lb_card_activated_animation_duration",
+          "lb_card_selected_animation_duration",
+          "lb_search_orb_scale_duration_ms",
+          "lb_browse_rows_anim_duration",
+          "lb_playback_controls_show_time_ms",
+          "lb_card_selected_animation_delay"
+        ]
+      },
+      "android/support/mediacompat/R$id": {
+        "androidx/mediacompat/R$id": [
+          "action0",
+          "media_actions",
+          "cancel_action",
+          "status_bar_latest_event_content",
+          "end_padder"
+        ]
+      },
+      "android/support/v17/leanback/widget/Row": {
+        "androidx/leanback/widget/Row": [
+          "FLAG_ID_USE_HEADER",
+          "FLAG_ID_USE_ID",
+          "FLAG_ID_USE_MASK"
+        ]
+      },
+      "android/support/compat/R$layout": {
+        "androidx/compat/R$layout": [
+          "notification_action_tombstone",
+          "notification_template_custom_big",
+          "notification_action"
+        ]
+      },
+      "android/support/v4/app/FragmentManagerImpl$AnimationOrAnimator": {
+        "androidx/app/FragmentManagerImpl$AnimationOrAnimator": [
+          "animator",
+          "animation"
+        ]
+      },
+      "android/support/transition/VisibilityPropagation": {
+        "androidx/transition/VisibilityPropagation": [
+          "PROPNAME_VISIBILITY",
+          "PROPNAME_VIEW_CENTER",
+          "VISIBILITY_PROPAGATION_VALUES"
+        ]
+      },
+      "android/support/v13/BuildConfig": {
+        "androidx/BuildConfig": [
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "VERSION_CODE",
+          "DEBUG",
+          "APPLICATION_ID",
+          "FLAVOR"
+        ]
+      },
+      "android/support/v4/app/NotificationCompat$Action$WearableExtender": {
+        "androidx/app/NotificationCompat$Action$WearableExtender": [
+          "KEY_FLAGS",
+          "KEY_CONFIRM_LABEL",
+          "KEY_CANCEL_LABEL",
+          "FLAG_HINT_LAUNCHES_ACTIVITY",
+          "KEY_IN_PROGRESS_LABEL",
+          "EXTRA_WEARABLE_EXTENSIONS",
+          "FLAG_AVAILABLE_OFFLINE",
+          "FLAG_HINT_DISPLAY_INLINE",
+          "DEFAULT_FLAGS"
+        ]
+      },
+      "android/support/v4/view/ViewPager$ItemInfo": {
+        "androidx/view/ViewPager$ItemInfo": [
+          "offset",
+          "object",
+          "position",
+          "widthFactor",
+          "scrolling"
+        ]
+      },
+      "android/support/v17/leanback/transition/TransitionHelper": {
+        "androidx/leanback/transition/TransitionHelper": [
+          "SLIDE_RIGHT",
+          "sImpl",
+          "SLIDE_BOTTOM",
+          "FADE_OUT",
+          "SLIDE_TOP",
+          "FADE_IN",
+          "SLIDE_LEFT"
+        ]
+      },
+      "android/support/v4/widget/AutoSizeableTextView": {
+        "androidx/widget/AutoSizeableTextView": [
+          "PLATFORM_SUPPORTS_AUTOSIZE"
+        ]
+      },
+      "android/support/v7/widget/SimpleItemAnimator": {
+        "androidx/widget/SimpleItemAnimator": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/transition/TransitionManager": {
+        "androidx/transition/TransitionManager": [
+          "sPendingTransitions",
+          "sRunningTransitions",
+          "sDefaultTransition",
+          "LOG_TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/WindowAlignment$Axis": {
+        "androidx/leanback/widget/WindowAlignment$Axis": [
+          "PF_KEYLINE_OVER_HIGH_EDGE",
+          "PF_KEYLINE_OVER_LOW_EDGE"
+        ]
+      },
+      "android/support/v7/widget/AppCompatPopupWindow": {
+        "androidx/widget/AppCompatPopupWindow": [
+          "COMPAT_OVERLAP_ANCHOR"
+        ]
+      },
+      "android/support/constraint/solver/widgets/ConstraintAnchor$Type": {
+        "androidx/constraint/solver/widgets/ConstraintAnchor$Type": [
+          "RIGHT",
+          "TOP",
+          "BOTTOM",
+          "LEFT",
+          "BASELINE"
+        ]
+      },
+      "android/support/wear/widget/drawer/WearableDrawerLayout": {
+        "androidx/wear/widget/drawer/WearableDrawerLayout": [
+          "TAG",
+          "UP",
+          "OPENED_PERCENT_THRESHOLD",
+          "NESTED_SCROLL_SLOP_DP",
+          "GRAVITY_UNDEFINED",
+          "DOWN",
+          "PEEK_FADE_DURATION_MS",
+          "PEEK_AUTO_CLOSE_DELAY_MS"
+        ]
+      },
+      "android/support/v17/leanback/widget/ShadowOverlayHelper$Builder": {
+        "androidx/leanback/widget/ShadowOverlayHelper$Builder": [
+          "options",
+          "needsRoundedCorner",
+          "keepForegroundDrawable",
+          "preferZOrder",
+          "needsOverlay",
+          "needsShadow"
+        ]
+      },
+      "android/support/v7/media/MediaRouteProvider": {
+        "androidx/media/MediaRouteProvider": [
+          "MSG_DELIVER_DESCRIPTOR_CHANGED",
+          "MSG_DELIVER_DISCOVERY_REQUEST_CHANGED"
+        ]
+      },
+      "android/support/design/widget/AppBarLayout$LayoutParams": {
+        "androidx/design/widget/AppBarLayout$LayoutParams": [
+          "SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED",
+          "bottomMargin",
+          "topMargin",
+          "SCROLL_FLAG_EXIT_UNTIL_COLLAPSED",
+          "SCROLL_FLAG_SCROLL",
+          "COLLAPSIBLE_FLAGS",
+          "FLAG_SNAP",
+          "SCROLL_FLAG_SNAP",
+          "FLAG_QUICK_RETURN",
+          "SCROLL_FLAG_ENTER_ALWAYS"
+        ]
+      },
+      "android/support/v7/media/MediaRouterJellybean": {
+        "androidx/media/MediaRouterJellybean": [
+          "TAG",
+          "DEVICE_OUT_BLUETOOTH",
+          "ROUTE_TYPE_LIVE_AUDIO",
+          "ROUTE_TYPE_USER",
+          "ROUTE_TYPE_LIVE_VIDEO",
+          "ALL_ROUTE_TYPES"
+        ]
+      },
+      "android/support/content/LoaderQueryRunner": {
+        "androidx/content/LoaderQueryRunner": [
+          "TAG",
+          "CONTENT_URI_KEY",
+          "DEBUG"
+        ]
+      },
+      "android/support/v17/preference/BuildConfig": {
+        "androidx/leanback/preference/BuildConfig": [
+          "BUILD_TYPE",
+          "VERSION_NAME",
+          "FLAVOR",
+          "DEBUG",
+          "VERSION_CODE",
+          "APPLICATION_ID"
+        ]
+      },
+      "android/support/v17/leanback/app/BackgroundManager$BackgroundContinuityService": {
+        "androidx/leanback/app/BackgroundManager$BackgroundContinuityService": [
+          "DEBUG",
+          "TAG",
+          "sService"
+        ]
+      },
+      "android/support/design/internal/NavigationMenuPresenter": {
+        "androidx/design/internal/NavigationMenuPresenter": [
+          "STATE_HEADER",
+          "STATE_ADAPTER",
+          "STATE_HIERARCHY"
+        ]
+      },
+      "android/support/v17/leanback/widget/RowPresenter$ViewHolder": {
+        "androidx/leanback/widget/RowPresenter$ViewHolder": [
+          "ACTIVATED_NOT_ASSIGNED",
+          "NOT_ACTIVATED",
+          "ACTIVATED",
+          "view"
+        ]
+      },
+      "android/support/v7/widget/AppCompatCheckedTextView": {
+        "androidx/widget/AppCompatCheckedTextView": [
+          "TINT_ATTRS"
+        ]
+      },
+      "android/support/transition/ChangeImageTransform": {
+        "androidx/transition/ChangeImageTransform": [
+          "PROPNAME_BOUNDS",
+          "NULL_MATRIX_EVALUATOR",
+          "ANIMATED_TRANSFORM_PROPERTY",
+          "sTransitionProperties",
+          "PROPNAME_MATRIX"
+        ]
+      },
+      "android/support/design/widget/AppBarLayout$Behavior$SavedState": {
+        "androidx/design/widget/AppBarLayout$Behavior$SavedState": [
+          "firstVisibleChildIndex",
+          "firstVisibleChildPercentageShown",
+          "firstVisibleChildAtMinimumHeight",
+          "CREATOR"
+        ]
+      },
+      "android/support/design/widget/Snackbar": {
+        "androidx/design/widget/Snackbar": [
+          "LENGTH_SHORT",
+          "LENGTH_INDEFINITE",
+          "LENGTH_LONG"
+        ]
+      },
+      "android/support/v7/app/ActionBarDrawerToggleHoneycomb$SetIndicatorInfo": {
+        "androidx/app/ActionBarDrawerToggleHoneycomb$SetIndicatorInfo": [
+          "setHomeActionContentDescription",
+          "setHomeAsUpIndicator",
+          "upIndicatorView"
+        ]
+      },
+      "android/support/v17/leanback/widget/Grid": {
+        "androidx/leanback/widget/Grid": [
+          "START_DEFAULT"
+        ]
+      },
+      "android/support/media/tv/WatchNextProgram": {
+        "androidx/media/tv/WatchNextProgram": [
+          "PROJECTION",
+          "INVALID_INT_VALUE",
+          "INVALID_LONG_VALUE"
+        ]
+      },
+      "android/support/v7/widget/TintContextWrapper": {
+        "androidx/widget/TintContextWrapper": [
+          "CACHE_LOCK",
+          "sCache"
+        ]
+      },
+      "android/support/text/emoji/flatbuffer/Constants": {
+        "androidx/text/emoji/flatbuffer/Constants": [
+          "SIZEOF_INT",
+          "SIZEOF_FLOAT",
+          "SIZEOF_LONG",
+          "FILE_IDENTIFIER_LENGTH",
+          "SIZEOF_SHORT",
+          "SIZEOF_BYTE",
+          "SIZEOF_DOUBLE"
+        ]
+      },
+      "android/support/wear/widget/CurvingLayoutCallback": {
+        "androidx/wear/widget/CurvingLayoutCallback": [
+          "EPSILON"
+        ]
+      },
+      "android/support/v4/app/AppOpsManagerCompat": {
+        "androidx/app/AppOpsManagerCompat": [
+          "MODE_IGNORED",
+          "MODE_DEFAULT",
+          "MODE_ALLOWED"
+        ]
+      },
+      "android/support/v4/widget/CursorAdapter": {
+        "androidx/widget/CursorAdapter": [
+          "FLAG_AUTO_REQUERY",
+          "FLAG_REGISTER_CONTENT_OBSERVER"
+        ]
+      },
+      "android/support/v17/leanback/app/DetailsBackgroundVideoHelper": {
+        "androidx/leanback/app/DetailsBackgroundVideoHelper": [
+          "NO_VIDEO",
+          "CROSSFADE_DELAY",
+          "INITIAL",
+          "BACKGROUND_CROSS_FADE_DURATION",
+          "PLAY_VIDEO"
+        ]
+      },
+      "android/support/transition/ChangeBounds": {
+        "androidx/transition/ChangeBounds": [
+          "PROPNAME_BOUNDS",
+          "POSITION_PROPERTY",
+          "sRectEvaluator",
+          "BOTTOM_RIGHT_PROPERTY",
+          "BOTTOM_RIGHT_ONLY_PROPERTY",
+          "DRAWABLE_ORIGIN_PROPERTY",
+          "sTransitionProperties",
+          "TOP_LEFT_ONLY_PROPERTY",
+          "PROPNAME_PARENT",
+          "TOP_LEFT_PROPERTY",
+          "PROPNAME_CLIP",
+          "PROPNAME_WINDOW_X",
+          "PROPNAME_WINDOW_Y"
+        ]
+      },
+      "android/support/v4/widget/SwipeProgressBar": {
+        "androidx/widget/SwipeProgressBar": [
+          "INTERPOLATOR",
+          "ANIMATION_DURATION_MS",
+          "FINISH_ANIMATION_DURATION_MS",
+          "COLOR2",
+          "COLOR1",
+          "COLOR4",
+          "COLOR3"
+        ]
+      },
+      "android/support/v17/leanback/media/PlaybackTransportControlGlue": {
+        "androidx/leanback/media/PlaybackTransportControlGlue": [
+          "UPDATE_PLAYBACK_STATE_DELAY_MS",
+          "sHandler",
+          "TAG",
+          "DEBUG",
+          "MSG_UPDATE_PLAYBACK_STATE"
+        ]
+      },
+      "android/support/media/tv/BasePreviewProgram": {
+        "androidx/media/tv/BasePreviewProgram": [
+          "IS_LIVE",
+          "IS_TRANSIENT",
+          "PROJECTION",
+          "INVALID_LONG_VALUE",
+          "INVALID_INT_VALUE",
+          "IS_BROWSABLE"
+        ]
+      },
+      "android/support/v4/widget/TextViewCompat$TextViewCompatBaseImpl": {
+        "androidx/widget/TextViewCompat$TextViewCompatBaseImpl": [
+          "sMaxModeFieldFetched",
+          "sMinimumFieldFetched",
+          "sMinModeField",
+          "sMaximumField",
+          "sMinModeFieldFetched",
+          "sMaxModeField",
+          "sMinimumField",
+          "LOG_TAG",
+          "sMaximumFieldFetched",
+          "LINES"
+        ]
+      },
+      "android/support/v7/media/SystemMediaRouteProvider$LegacyImpl$VolumeChangeReceiver": {
+        "androidx/media/SystemMediaRouteProvider$LegacyImpl$VolumeChangeReceiver": [
+          "EXTRA_VOLUME_STREAM_TYPE",
+          "VOLUME_CHANGED_ACTION",
+          "EXTRA_VOLUME_STREAM_VALUE"
+        ]
+      },
+      "android/support/transition/Styleable$ChangeBounds": {
+        "androidx/transition/Styleable$ChangeBounds": [
+          "RESIZE_CLIP"
+        ]
+      },
+      "android/support/v7/widget/ActivityChooserModel": {
+        "androidx/widget/ActivityChooserModel": [
+          "DEFAULT_ACTIVITY_INFLATION",
+          "ATTRIBUTE_TIME",
+          "TAG_HISTORICAL_RECORD",
+          "DEFAULT_HISTORY_FILE_NAME",
+          "HISTORY_FILE_EXTENSION",
+          "TAG_HISTORICAL_RECORDS",
+          "ATTRIBUTE_ACTIVITY",
+          "ATTRIBUTE_WEIGHT",
+          "DEBUG",
+          "INVALID_INDEX",
+          "DEFAULT_HISTORICAL_RECORD_WEIGHT",
+          "sDataModelRegistry",
+          "sRegistryLock",
+          "DEFAULT_HISTORY_MAX_LENGTH",
+          "LOG_TAG"
+        ]
+      },
+      "android/support/v7/widget/ViewUtils": {
+        "androidx/widget/ViewUtils": [
+          "TAG",
+          "sComputeFitSystemWindowsMethod"
+        ]
+      },
+      "android/support/v14/preference/ListPreferenceDialogFragment": {
+        "androidx/preference/ListPreferenceDialogFragment": [
+          "SAVE_STATE_ENTRIES",
+          "SAVE_STATE_INDEX",
+          "SAVE_STATE_ENTRY_VALUES"
+        ]
+      },
+      "android/support/v17/leanback/widget/RoundedRectHelper": {
+        "androidx/leanback/widget/RoundedRectHelper": [
+          "sInstance"
+        ]
+      },
+      "android/support/transition/Styleable$TransitionManager": {
+        "androidx/transition/Styleable$TransitionManager": [
+          "FROM_SCENE",
+          "TRANSITION",
+          "TO_SCENE"
+        ]
+      },
+      "android/support/v17/leanback/R$style": {
+        "androidx/leanback/R$style": [
+          "TextAppearance_Leanback_SearchTextEdit",
+          "Widget_Leanback_ImageCardView"
+        ]
+      },
+      "android/support/v7/widget/ShareActionProvider": {
+        "androidx/widget/ShareActionProvider": [
+          "DEFAULT_SHARE_HISTORY_FILE_NAME",
+          "DEFAULT_INITIAL_ACTIVITY_COUNT"
+        ]
+      },
+      "android/support/v4/app/ListFragment": {
+        "androidx/app/ListFragment": [
+          "INTERNAL_EMPTY_ID",
+          "INTERNAL_PROGRESS_CONTAINER_ID",
+          "INTERNAL_LIST_CONTAINER_ID"
+        ]
+      },
+      "android/support/design/widget/BottomSheetBehavior$SavedState": {
+        "androidx/design/widget/BottomSheetBehavior$SavedState": [
+          "state",
+          "CREATOR"
+        ]
+      },
+      "android/support/v7/appcompat/R$color": {
+        "androidx/appcompat/R$color": [
+          "abc_tint_switch_track",
+          "abc_tint_edittext",
+          "abc_tint_btn_checkable",
+          "abc_tint_default",
+          "abc_tint_spinner",
+          "abc_tint_seek_thumb",
+          "error_color_material",
+          "abc_input_method_navigation_guard"
+        ]
+      },
+      "android/support/v17/leanback/R$raw": {
+        "androidx/leanback/R$raw": [
+          "lb_voice_no_input",
+          "lb_voice_failure",
+          "lb_voice_success",
+          "lb_voice_open"
+        ]
+      },
+      "android/support/v7/util/DiffUtil$PostponedUpdate": {
+        "androidx/util/DiffUtil$PostponedUpdate": [
+          "posInOwnerList",
+          "removal",
+          "currentPos"
+        ]
+      },
+      "android/support/v7/graphics/drawable/DrawerArrowDrawable": {
+        "androidx/graphics/drawable/DrawerArrowDrawable": [
+          "ARROW_DIRECTION_LEFT",
+          "ARROW_HEAD_ANGLE",
+          "ARROW_DIRECTION_RIGHT",
+          "ARROW_DIRECTION_END",
+          "ARROW_DIRECTION_START"
+        ]
+      },
+      "android/support/v4/os/IResultReceiver$Stub": {
+        "androidx/os/IResultReceiver$Stub": [
+          "TRANSACTION_send",
+          "DESCRIPTOR"
+        ]
+      },
+      "android/support/v7/util/DiffUtil$Range": {
+        "androidx/util/DiffUtil$Range": [
+          "newListEnd",
+          "oldListEnd",
+          "newListStart",
+          "oldListStart"
+        ]
+      },
+      "android/support/v7/widget/ActionMenuPresenter$SavedState": {
+        "androidx/widget/ActionMenuPresenter$SavedState": [
+          "CREATOR",
+          "openSubMenuId"
+        ]
+      },
+      "android/support/v17/leanback/widget/GuidedActionAdapter": {
+        "androidx/leanback/widget/GuidedActionAdapter": [
+          "DEBUG",
+          "DEBUG_EDIT",
+          "TAG_EDIT",
+          "TAG"
+        ]
+      },
+      "android/support/v7/widget/AppCompatMultiAutoCompleteTextView": {
+        "androidx/widget/AppCompatMultiAutoCompleteTextView": [
+          "TINT_ATTRS"
+        ]
+      },
+      "android/support/compat/R$dimen": {
+        "androidx/compat/R$dimen": [
+          "notification_small_icon_background_padding",
+          "notification_top_pad_large_text",
+          "notification_large_icon_width",
+          "notification_small_icon_size_as_large",
+          "notification_big_circle_margin",
+          "notification_subtext_size",
+          "notification_top_pad",
+          "notification_right_icon_size"
+        ]
+      },
+      "android/support/customtabs/CustomTabsSessionToken": {
+        "androidx/browser/customtabs/CustomTabsSessionToken": [
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/StaggeredGrid$Location": {
+        "androidx/leanback/widget/StaggeredGrid$Location": [
+          "row",
+          "offset",
+          "size"
+        ]
+      },
+      "android/support/compat/R$color": {
+        "androidx/compat/R$color": [
+          "notification_action_color_filter"
+        ]
+      },
+      "android/support/v7/widget/DefaultItemAnimator$ChangeInfo": {
+        "androidx/widget/DefaultItemAnimator$ChangeInfo": [
+          "toY",
+          "toX",
+          "oldHolder",
+          "newHolder",
+          "fromY",
+          "fromX"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsPresenter$ViewHolder": {
+        "androidx/leanback/widget/PlaybackControlsPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/v4/app/DialogFragment": {
+        "androidx/app/DialogFragment": [
+          "SAVED_SHOWS_DIALOG",
+          "STYLE_NORMAL",
+          "STYLE_NO_INPUT",
+          "SAVED_CANCELABLE",
+          "SAVED_THEME",
+          "SAVED_DIALOG_STATE_TAG",
+          "STYLE_NO_TITLE",
+          "SAVED_BACK_STACK_ID",
+          "STYLE_NO_FRAME",
+          "SAVED_STYLE"
+        ]
+      },
+      "android/support/v7/palette/BuildConfig": {
+        "androidx/palette/BuildConfig": [
+          "VERSION_CODE",
+          "DEBUG",
+          "FLAVOR",
+          "BUILD_TYPE",
+          "APPLICATION_ID",
+          "VERSION_NAME"
+        ]
+      },
+      "android/support/v7/preference/R$attr": {
+        "androidx/preference/R$attr": [
+          "dialogPreferenceStyle",
+          "dropdownPreferenceStyle",
+          "preferenceScreenStyle",
+          "editTextPreferenceStyle",
+          "preferenceTheme",
+          "preferenceCategoryStyle",
+          "seekBarPreferenceStyle",
+          "switchPreferenceStyle",
+          "preferenceStyle",
+          "preferenceFragmentStyle",
+          "switchPreferenceCompatStyle",
+          "checkBoxPreferenceStyle",
+          "preferenceFragmentCompatStyle"
+        ]
+      },
+      "android/support/v17/leanback/widget/BaseCardView$LayoutParams": {
+        "androidx/leanback/widget/BaseCardView$LayoutParams": [
+          "VIEW_TYPE_INFO",
+          "VIEW_TYPE_MAIN",
+          "VIEW_TYPE_EXTRA",
+          "viewType"
+        ]
+      },
+      "android/support/wear/ambient/WearableControllerProvider": {
+        "androidx/wear/ambient/WearableControllerProvider": [
+          "TAG",
+          "sAmbientCallbacksVerifiedPresent"
+        ]
+      },
+      "android/support/design/R$anim": {
+        "androidx/design/R$anim": [
+          "design_snackbar_out",
+          "design_snackbar_in"
+        ]
+      },
+      "android/support/wear/ambient/AmbientMode": {
+        "androidx/wear/ambient/AmbientMode": [
+          "FRAGMENT_TAG",
+          "EXTRA_BURN_IN_PROTECTION",
+          "EXTRA_LOWBIT_AMBIENT"
+        ]
+      },
+      "android/support/text/emoji/flatbuffer/MetadataItem": {
+        "androidx/text/emoji/flatbuffer/MetadataItem": [
+          "bb_pos",
+          "bb"
+        ]
+      },
+      "android/support/v13/app/FragmentStatePagerAdapter": {
+        "androidx/app/FragmentStatePagerAdapter": [
+          "TAG",
+          "DEBUG"
+        ]
+      },
+      "android/support/v17/leanback/transition/LeanbackTransitionHelper": {
+        "androidx/leanback/transition/LeanbackTransitionHelper": [
+          "sImpl"
+        ]
+      },
+      "android/support/v7/view/menu/MenuItemWrapperICS": {
+        "androidx/view/menu/MenuItemWrapperICS": [
+          "LOG_TAG"
+        ]
+      },
+      "android/support/v4/content/IntentCompat": {
+        "androidx/content/IntentCompat": [
+          "EXTRA_HTML_TEXT",
+          "CATEGORY_LEANBACK_LAUNCHER",
+          "EXTRA_START_PLAYBACK"
+        ]
+      },
+      "android/support/graphics/drawable/AnimatedVectorDrawableCompat": {
+        "androidx/graphics/drawable/AnimatedVectorDrawableCompat": [
+          "LOGTAG",
+          "TARGET",
+          "ANIMATED_VECTOR",
+          "DBG_ANIMATION_VECTOR_DRAWABLE"
+        ]
+      },
+      "android/support/v7/appcompat/R$style": {
+        "androidx/appcompat/R$style": [
+          "Base_Widget_AppCompat_DrawerArrowToggle",
+          "Theme_AppCompat_Light",
+          "TextAppearance_AppCompat_Caption",
+          "Theme_AppCompat_CompactMenu",
+          "TextAppearance_AppCompat_Widget_ActionBar_Title",
+          "Animation_AppCompat_Tooltip"
+        ]
+      },
+      "android/support/media/instantvideo/widget/InstantVideoView": {
+        "androidx/media/instantvideo/widget/InstantVideoView": [
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/transition/Scale": {
+        "androidx/leanback/transition/Scale": [
+          "PROPNAME_SCALE"
+        ]
+      },
+      "android/support/v4/content/WakefulBroadcastReceiver": {
+        "androidx/content/WakefulBroadcastReceiver": [
+          "EXTRA_WAKE_LOCK_ID",
+          "sActiveWakeLocks"
+        ]
+      },
+      "android/support/v17/leanback/widget/VerticalGridPresenter": {
+        "androidx/leanback/widget/VerticalGridPresenter": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/PersistentFocusWrapper": {
+        "androidx/leanback/widget/PersistentFocusWrapper": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v4/provider/SelfDestructiveThread": {
+        "androidx/provider/SelfDestructiveThread": [
+          "MSG_DESTRUCTION",
+          "MSG_INVOKE_RUNNABLE"
+        ]
+      },
+      "android/support/customtabs/TrustedWebUtils": {
+        "androidx/browser/customtabs/TrustedWebUtils": [
+          "EXTRA_LAUNCH_AS_TRUSTED_WEB_ACTIVITY"
+        ]
+      },
+      "android/support/v17/leanback/app/RowsSupportFragment": {
+        "androidx/leanback/app/RowsSupportFragment": [
+          "TAG",
+          "ALIGN_TOP_NOT_SET",
+          "DEBUG"
+        ]
+      },
+      "android/support/v17/leanback/widget/ScaleFrameLayout": {
+        "androidx/leanback/widget/ScaleFrameLayout": [
+          "DEFAULT_CHILD_GRAVITY"
+        ]
+      },
+      "android/support/v4/media/MediaBrowserCompat$MediaItem": {
+        "androidx/media/MediaBrowserCompat$MediaItem": [
+          "CREATOR",
+          "FLAG_PLAYABLE",
+          "FLAG_BROWSABLE"
+        ]
+      },
+      "android/support/v4/provider/FontsContractCompat$FontRequestCallback": {
+        "androidx/provider/FontsContractCompat$FontRequestCallback": [
+          "FAIL_REASON_WRONG_CERTIFICATES",
+          "FAIL_REASON_FONT_UNAVAILABLE",
+          "FAIL_REASON_MALFORMED_QUERY",
+          "FAIL_REASON_SECURITY_VIOLATION",
+          "FAIL_REASON_FONT_LOAD_ERROR",
+          "RESULT_OK",
+          "FAIL_REASON_FONT_NOT_FOUND",
+          "FAIL_REASON_PROVIDER_NOT_FOUND"
+        ]
+      },
+      "android/support/dynamicanimation/BuildConfig": {
+        "androidx/dynamicanimation/BuildConfig": [
+          "BUILD_TYPE",
+          "VERSION_NAME",
+          "FLAVOR",
+          "APPLICATION_ID",
+          "VERSION_CODE",
+          "DEBUG"
+        ]
+      },
+      "android/support/v4/widget/NestedScrollView$SavedState": {
+        "androidx/widget/NestedScrollView$SavedState": [
+          "CREATOR",
+          "scrollPosition"
+        ]
+      },
+      "android/support/text/emoji/R$layout": {
+        "androidx/text/emoji/R$layout": [
+          "input_method_extract_view"
+        ]
+      },
+      "android/support/v4/app/FragmentManagerImpl$FragmentTag": {
+        "androidx/app/FragmentManagerImpl$FragmentTag": [
+          "Fragment",
+          "Fragment_tag",
+          "Fragment_name",
+          "Fragment_id"
+        ]
+      },
+      "android/support/v7/widget/GridLayout$Assoc": {
+        "androidx/widget/GridLayout$Assoc": [
+          "keyType",
+          "valueType"
+        ]
+      },
+      "android/support/text/emoji/bundled/BuildConfig": {
+        "androidx/text/emoji/bundled/BuildConfig": [
+          "BUILD_TYPE",
+          "VERSION_NAME",
+          "APPLICATION_ID",
+          "DEBUG",
+          "VERSION_CODE",
+          "FLAVOR"
+        ]
+      },
+      "android/support/v4/app/LoaderManagerImpl": {
+        "androidx/app/LoaderManagerImpl": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v7/appcompat/R$string": {
+        "androidx/appcompat/R$string": [
+          "abc_action_bar_up_description",
+          "abc_searchview_description_search",
+          "abc_activity_chooser_view_see_all",
+          "abc_shareactionprovider_share_with",
+          "abc_shareactionprovider_share_with_application",
+          "abc_activitychooserview_choose_application"
+        ]
+      },
+      "android/support/v7/widget/AppCompatAutoCompleteTextView": {
+        "androidx/widget/AppCompatAutoCompleteTextView": [
+          "TINT_ATTRS"
+        ]
+      },
+      "android/support/graphics/drawable/animated/BuildConfig": {
+        "androidx/graphics/drawable/animated/BuildConfig": [
+          "BUILD_TYPE",
+          "FLAVOR",
+          "VERSION_NAME",
+          "APPLICATION_ID",
+          "VERSION_CODE",
+          "DEBUG"
+        ]
+      },
+      "android/support/v7/widget/ChildHelper": {
+        "androidx/widget/ChildHelper": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/wear/ambient/SharedLibraryVersion$VersionHolder": {
+        "androidx/wear/ambient/SharedLibraryVersion$VersionHolder": [
+          "VERSION"
+        ]
+      },
+      "android/support/media/tv/BaseProgram": {
+        "androidx/media/tv/BaseProgram": [
+          "INVALID_LONG_VALUE",
+          "PROJECTION",
+          "IS_SEARCHABLE",
+          "INVALID_INT_VALUE"
+        ]
+      },
+      "android/support/transition/TransitionUtils": {
+        "androidx/transition/TransitionUtils": [
+          "MAX_IMAGE_SIZE"
+        ]
+      },
+      "android/support/v17/leanback/widget/ItemAlignment": {
+        "androidx/leanback/widget/ItemAlignment": [
+          "horizontal",
+          "vertical"
+        ]
+      },
+      "android/support/design/widget/NavigationView$SavedState": {
+        "androidx/design/widget/NavigationView$SavedState": [
+          "CREATOR",
+          "menuState"
+        ]
+      },
+      "android/support/v17/leanback/widget/WindowAlignment": {
+        "androidx/leanback/widget/WindowAlignment": [
+          "horizontal",
+          "vertical"
+        ]
+      },
+      "android/support/design/internal/BottomNavigationMenuView": {
+        "androidx/design/internal/BottomNavigationMenuView": [
+          "ACTIVE_ANIMATION_DURATION_MS"
+        ]
+      },
+      "android/support/transition/Slide": {
+        "androidx/transition/Slide": [
+          "sDecelerate",
+          "PROPNAME_SCREEN_POSITION",
+          "sCalculateTop",
+          "sCalculateBottom",
+          "sCalculateRight",
+          "sAccelerate",
+          "sCalculateStart",
+          "sCalculateEnd",
+          "sCalculateLeft"
+        ]
+      },
+      "android/support/text/emoji/MetadataRepo": {
+        "androidx/text/emoji/MetadataRepo": [
+          "DEFAULT_ROOT_SIZE"
+        ]
+      },
+      "android/support/v7/app/AppCompatDelegateImplBase": {
+        "androidx/app/AppCompatDelegateImplBase": [
+          "EXCEPTION_HANDLER_MESSAGE_SUFFIX",
+          "sInstalledExceptionHandler",
+          "sWindowBackgroundStyleable",
+          "DEBUG",
+          "SHOULD_INSTALL_EXCEPTION_HANDLER"
+        ]
+      },
+      "android/support/v7/widget/StaggeredGridLayoutManager$LazySpanLookup$FullSpanItem": {
+        "androidx/widget/StaggeredGridLayoutManager$LazySpanLookup$FullSpanItem": [
+          "CREATOR"
+        ]
+      },
+      "android/support/v17/leanback/R$anim": {
+        "androidx/leanback/R$anim": [
+          "lb_decelerator_4"
+        ]
+      },
+      "android/support/v17/leanback/widget/PagingIndicator": {
+        "androidx/leanback/widget/PagingIndicator": [
+          "DURATION_DIAMETER",
+          "DURATION_TRANSLATION_X",
+          "DECELERATE_INTERPOLATOR",
+          "DOT_DIAMETER",
+          "DURATION_ALPHA",
+          "DOT_TRANSLATION_X",
+          "DOT_ALPHA"
+        ]
+      },
+      "android/support/v7/widget/ScrollingTabContainerView": {
+        "androidx/widget/ScrollingTabContainerView": [
+          "sAlphaInterpolator",
+          "TAG",
+          "FADE_DURATION"
+        ]
+      },
+      "android/support/v4/text/TextDirectionHeuristicsCompat$FirstStrong": {
+        "androidx/text/TextDirectionHeuristicsCompat$FirstStrong": [
+          "INSTANCE"
+        ]
+      },
+      "android/support/design/internal/NavigationMenuPresenter$NavigationMenuTextItem": {
+        "androidx/design/internal/NavigationMenuPresenter$NavigationMenuTextItem": [
+          "needsEmptyIcon"
+        ]
+      },
+      "android/support/v17/leanback/widget/Presenter$ViewHolder": {
+        "androidx/leanback/widget/Presenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/customtabs/IPostMessageService$Stub": {
+        "androidx/browser/customtabs/IPostMessageService$Stub": [
+          "TRANSACTION_onPostMessage",
+          "DESCRIPTOR",
+          "TRANSACTION_onMessageChannelReady"
+        ]
+      },
+      "android/support/v4/view/ViewPropertyAnimatorCompat": {
+        "androidx/view/ViewPropertyAnimatorCompat": [
+          "LISTENER_TAG_ID",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/AbstractMediaItemPresenter": {
+        "androidx/leanback/widget/AbstractMediaItemPresenter": [
+          "PLAY_STATE_PLAYING",
+          "PLAY_STATE_PAUSED",
+          "sTempRect",
+          "PLAY_STATE_INITIAL"
+        ]
+      },
+      "android/support/text/emoji/BuildConfig": {
+        "androidx/text/emoji/BuildConfig": [
+          "APPLICATION_ID",
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "VERSION_CODE",
+          "DEBUG",
+          "FLAVOR"
+        ]
+      },
+      "android/support/v4/media/session/MediaControllerCompat$TransportControls": {
+        "androidx/media/session/MediaControllerCompat$TransportControls": [
+          "EXTRA_LEGACY_STREAM_TYPE"
+        ]
+      },
+      "android/support/v4/view/WindowCompat": {
+        "androidx/view/WindowCompat": [
+          "FEATURE_ACTION_MODE_OVERLAY",
+          "FEATURE_ACTION_BAR",
+          "FEATURE_ACTION_BAR_OVERLAY"
+        ]
+      },
+      "android/support/v4/content/PermissionChecker": {
+        "androidx/content/PermissionChecker": [
+          "PERMISSION_GRANTED",
+          "PERMISSION_DENIED",
+          "PERMISSION_DENIED_APP_OP"
+        ]
+      },
+      "android/support/v4/text/TextUtilsCompat": {
+        "androidx/text/TextUtilsCompat": [
+          "ROOT",
+          "ARAB_SCRIPT_SUBTAG",
+          "HEBR_SCRIPT_SUBTAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/DetailsOverviewRowPresenter": {
+        "androidx/leanback/widget/DetailsOverviewRowPresenter": [
+          "MORE_ACTIONS_FADE_MS",
+          "DEBUG",
+          "TAG",
+          "DEFAULT_TIMEOUT"
+        ]
+      },
+      "android/support/design/widget/TextInputLayout": {
+        "androidx/design/widget/TextInputLayout": [
+          "LOG_TAG",
+          "INVALID_MAX_LENGTH",
+          "ANIMATION_DURATION"
+        ]
+      },
+      "android/support/v7/media/RemotePlaybackClient": {
+        "androidx/media/RemotePlaybackClient": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/ListRowPresenter$ViewHolder": {
+        "androidx/leanback/widget/ListRowPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/v7/content/res/AppCompatColorStateListInflater": {
+        "androidx/content/res/AppCompatColorStateListInflater": [
+          "DEFAULT_COLOR"
+        ]
+      },
+      "android/support/v7/view/menu/ExpandedMenuView": {
+        "androidx/view/menu/ExpandedMenuView": [
+          "TINT_ATTRS"
+        ]
+      },
+      "android/support/v7/widget/PositionMap$ContainerHelpers": {
+        "androidx/widget/PositionMap$ContainerHelpers": [
+          "EMPTY_BOOLEANS",
+          "EMPTY_INTS",
+          "EMPTY_OBJECTS",
+          "EMPTY_LONGS"
+        ]
+      },
+      "android/support/design/widget/TextInputLayout$SavedState": {
+        "androidx/design/widget/TextInputLayout$SavedState": [
+          "error",
+          "isPasswordToggledVisible",
+          "CREATOR"
+        ]
+      },
+      "android/support/v17/leanback/BuildConfig": {
+        "androidx/leanback/BuildConfig": [
+          "DEBUG",
+          "VERSION_CODE",
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "APPLICATION_ID",
+          "FLAVOR"
+        ]
+      },
+      "android/support/v7/widget/GridLayout$MutableInt": {
+        "androidx/widget/GridLayout$MutableInt": [
+          "value"
+        ]
+      },
+      "android/support/wear/R$dimen": {
+        "androidx/wear/R$dimen": [
+          "ws_action_drawer_item_icon_right_margin",
+          "ws_action_drawer_item_bottom_padding",
+          "ws_wearable_drawer_view_elevation",
+          "circular_progress_layout_stroke_width",
+          "ws_wrv_curve_default_x_offset",
+          "ws_action_drawer_item_top_padding"
+        ]
+      },
+      "android/support/wear/widget/drawer/WearableNavigationDrawerView": {
+        "androidx/wear/widget/drawer/WearableNavigationDrawerView": [
+          "MULTI_PAGE",
+          "SINGLE_PAGE",
+          "AUTO_CLOSE_DRAWER_DELAY_MS",
+          "TAG",
+          "DEFAULT_STYLE"
+        ]
+      },
+      "android/support/v7/graphics/Palette": {
+        "androidx/graphics/palette/Palette": [
+          "DEFAULT_CALCULATE_NUMBER_COLORS",
+          "MIN_CONTRAST_BODY_TEXT",
+          "LOG_TIMINGS",
+          "DEFAULT_FILTER",
+          "LOG_TAG",
+          "MIN_CONTRAST_TITLE_TEXT",
+          "DEFAULT_RESIZE_BITMAP_AREA"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView$State": {
+        "androidx/widget/RecyclerView$State": [
+          "STEP_ANIMATIONS",
+          "STEP_LAYOUT",
+          "STEP_START"
+        ]
+      },
+      "android/support/design/widget/AppBarLayout": {
+        "androidx/design/widget/AppBarLayout": [
+          "PENDING_ACTION_FORCE",
+          "PENDING_ACTION_NONE",
+          "PENDING_ACTION_COLLAPSED",
+          "INVALID_SCROLL_RANGE",
+          "PENDING_ACTION_EXPANDED",
+          "PENDING_ACTION_ANIMATE_ENABLED"
+        ]
+      },
+      "android/support/design/widget/ViewUtilsLollipop": {
+        "androidx/design/widget/ViewUtilsLollipop": [
+          "STATE_LIST_ANIM_ATTRS"
+        ]
+      },
+      "android/support/v4/provider/FontsContractCompat": {
+        "androidx/provider/FontsContractCompat": [
+          "sByteArrayComparator",
+          "sBackgroundThread",
+          "BACKGROUND_THREAD_KEEP_ALIVE_DURATION_MS",
+          "sTypefaceCache",
+          "RESULT_CODE_WRONG_CERTIFICATES",
+          "RESULT_CODE_PROVIDER_NOT_FOUND",
+          "PARCEL_FONT_RESULTS",
+          "sPendingReplies",
+          "TAG",
+          "sLock"
+        ]
+      },
+      "android/support/media/tv/TvContractUtils": {
+        "androidx/media/tv/TvContractUtils": [
+          "DEBUG",
+          "EMPTY",
+          "TAG",
+          "DELIMITER"
+        ]
+      },
+      "android/support/v17/leanback/widget/RoundedRectHelperApi21": {
+        "androidx/leanback/widget/RoundedRectHelperApi21": [
+          "sRoundedRectProvider",
+          "MAX_CACHED_PROVIDER"
+        ]
+      },
+      "android/support/v17/leanback/app/BrowseFragment$MainFragmentAdapterRegistry": {
+        "androidx/leanback/app/BrowseFragment$MainFragmentAdapterRegistry": [
+          "sDefaultFragmentFactory"
+        ]
+      },
+      "android/support/v7/util/BatchingListUpdateCallback": {
+        "androidx/util/BatchingListUpdateCallback": [
+          "TYPE_CHANGE",
+          "TYPE_REMOVE",
+          "TYPE_NONE",
+          "TYPE_ADD"
+        ]
+      },
+      "android/support/v4/widget/DrawerLayout$SavedState": {
+        "androidx/widget/DrawerLayout$SavedState": [
+          "lockModeLeft",
+          "lockModeEnd",
+          "CREATOR",
+          "lockModeStart",
+          "openDrawerGravity",
+          "lockModeRight"
+        ]
+      },
+      "android/support/design/internal/NavigationMenuItemView": {
+        "androidx/design/internal/NavigationMenuItemView": [
+          "CHECKED_STATE_SET",
+          "EMPTY_STATE_SET"
+        ]
+      },
+      "android/support/customtabs/BuildConfig": {
+        "androidx/browser/customtabs/BuildConfig": [
+          "FLAVOR",
+          "VERSION_CODE",
+          "DEBUG",
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "APPLICATION_ID"
+        ]
+      },
+      "android/support/text/emoji/EmojiProcessor$ProcessorSm": {
+        "androidx/text/emoji/EmojiProcessor$ProcessorSm": [
+          "STATE_DEFAULT",
+          "STATE_WALKING"
+        ]
+      },
+      "android/support/v7/widget/ActivityChooserModel$DefaultSorter": {
+        "androidx/widget/ActivityChooserModel$DefaultSorter": [
+          "WEIGHT_DECAY_COEFFICIENT"
+        ]
+      },
+      "android/support/design/BuildConfig": {
+        "androidx/design/BuildConfig": [
+          "APPLICATION_ID",
+          "FLAVOR",
+          "VERSION_NAME",
+          "BUILD_TYPE",
+          "VERSION_CODE",
+          "DEBUG"
+        ]
+      },
+      "android/support/v4/content/pm/ShortcutManagerCompat": {
+        "androidx/content/pm/ShortcutManagerCompat": [
+          "ACTION_INSTALL_SHORTCUT",
+          "INSTALL_SHORTCUT_PERMISSION"
+        ]
+      },
+      "android/support/media/tv/TvContractCompat$Channels$Logo": {
+        "androidx/media/tv/TvContractCompat$Channels$Logo": [
+          "CONTENT_DIRECTORY"
+        ]
+      },
+      "android/support/v4/view/ViewCompat$ViewCompatBaseImpl": {
+        "androidx/view/ViewCompat$ViewCompatBaseImpl": [
+          "sChildrenDrawingOrderMethod",
+          "sMinHeightField",
+          "sMinHeightFieldFetched",
+          "sTransitionNameMap",
+          "sAccessibilityDelegateCheckFailed",
+          "sMinWidthField",
+          "sMinWidthFieldFetched",
+          "sAccessibilityDelegateField"
+        ]
+      },
+      "android/support/v4/content/res/TypedArrayUtils": {
+        "androidx/content/res/TypedArrayUtils": [
+          "NAMESPACE"
+        ]
+      },
+      "android/support/annotation/RestrictTo$Scope": {
+        "androidx/annotation/RestrictTo$Scope": [
+          "GROUP_ID",
+          "TESTS",
+          "LIBRARY",
+          "SUBCLASSES",
+          "LIBRARY_GROUP"
+        ]
+      },
+      "android/support/media/tv/ChannelLogoUtils": {
+        "androidx/media/tv/ChannelLogoUtils": [
+          "TAG",
+          "CONNECTION_TIMEOUT_MS_FOR_URLCONNECTION",
+          "READ_TIMEOUT_MS_FOR_URLCONNECTION"
+        ]
+      },
+      "android/support/text/emoji/EmojiProcessor": {
+        "androidx/text/emoji/EmojiProcessor": [
+          "ACTION_FLUSH",
+          "ACTION_ADVANCE_BOTH",
+          "ACTION_ADVANCE_END"
+        ]
+      },
+      "android/support/design/R$layout": {
+        "androidx/design/R$layout": [
+          "design_navigation_item",
+          "design_navigation_menu_item",
+          "design_navigation_item_separator",
+          "design_navigation_item_subheader",
+          "design_navigation_item_header",
+          "design_bottom_navigation_item",
+          "design_text_input_password_icon",
+          "design_layout_snackbar_include",
+          "design_layout_tab_text",
+          "design_layout_snackbar",
+          "design_bottom_sheet_dialog",
+          "design_layout_tab_icon",
+          "design_navigation_menu"
+        ]
+      },
+      "android/support/v4/app/NotificationCompatExtras": {
+        "androidx/app/NotificationCompatExtras": [
+          "EXTRA_ACTION_EXTRAS",
+          "EXTRA_GROUP_KEY",
+          "EXTRA_SORT_KEY",
+          "EXTRA_REMOTE_INPUTS",
+          "EXTRA_LOCAL_ONLY",
+          "EXTRA_GROUP_SUMMARY"
+        ]
+      },
+      "android/support/v17/leanback/widget/GridLayoutManager$SavedState": {
+        "androidx/leanback/widget/GridLayoutManager$SavedState": [
+          "CREATOR",
+          "index",
+          "childStates"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView$ItemAnimator": {
+        "androidx/widget/RecyclerView$ItemAnimator": [
+          "FLAG_CHANGED",
+          "FLAG_REMOVED",
+          "FLAG_APPEARED_IN_PRE_LAYOUT",
+          "FLAG_INVALIDATED",
+          "FLAG_MOVED"
+        ]
+      },
+      "android/support/v17/leanback/widget/Grid$Location": {
+        "androidx/leanback/widget/Grid$Location": [
+          "row"
+        ]
+      },
+      "android/support/v17/leanback/media/MediaControllerGlue": {
+        "androidx/leanback/media/MediaControllerGlue": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v17/preference/LeanbackListPreferenceDialogFragment": {
+        "androidx/leanback/preference/LeanbackListPreferenceDialogFragment": [
+          "SAVE_STATE_ENTRY_VALUES",
+          "SAVE_STATE_TITLE",
+          "SAVE_STATE_INITIAL_SELECTIONS",
+          "SAVE_STATE_IS_MULTI",
+          "SAVE_STATE_ENTRIES",
+          "SAVE_STATE_INITIAL_SELECTION",
+          "SAVE_STATE_MESSAGE"
+        ]
+      },
+      "android/support/v4/app/ServiceCompat": {
+        "androidx/app/ServiceCompat": [
+          "STOP_FOREGROUND_DETACH",
+          "START_STICKY",
+          "STOP_FOREGROUND_REMOVE"
+        ]
+      },
+      "android/support/wear/widget/SwipeDismissLayout": {
+        "androidx/wear/widget/SwipeDismissLayout": [
+          "TAG",
+          "DEFAULT_DISMISS_DRAG_WIDTH_RATIO",
+          "EDGE_SWIPE_THRESHOLD"
+        ]
+      },
+      "android/support/v4/os/LocaleListCompat": {
+        "androidx/os/LocaleListCompat": [
+          "sEmptyLocaleList",
+          "IMPL"
+        ]
+      },
+      "android/support/v7/preference/Preference$BaseSavedState": {
+        "androidx/preference/Preference$BaseSavedState": [
+          "CREATOR",
+          "EMPTY_STATE"
+        ]
+      },
+      "android/support/v7/media/MediaRouteProviderService": {
+        "androidx/media/MediaRouteProviderService": [
+          "TAG",
+          "SERVICE_INTERFACE",
+          "DEBUG",
+          "PRIVATE_MSG_CLIENT_DIED"
+        ]
+      },
+      "android/support/v7/view/menu/CascadingMenuPopup$CascadingMenuInfo": {
+        "androidx/view/menu/CascadingMenuPopup$CascadingMenuInfo": [
+          "position",
+          "menu",
+          "window"
+        ]
+      },
+      "android/support/v7/widget/ToolbarWidgetWrapper": {
+        "androidx/widget/ToolbarWidgetWrapper": [
+          "DEFAULT_FADE_DURATION_MS",
+          "AFFECTS_LOGO_MASK",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackTransportRowPresenter$ViewHolder": {
+        "androidx/leanback/widget/PlaybackTransportRowPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/v7/widget/DefaultItemAnimator": {
+        "androidx/widget/DefaultItemAnimator": [
+          "DEBUG",
+          "sDefaultInterpolator"
+        ]
+      },
+      "android/support/v4/widget/PopupWindowCompat$PopupWindowCompatApi21Impl": {
+        "androidx/widget/PopupWindowCompat$PopupWindowCompatApi21Impl": [
+          "sOverlapAnchorField",
+          "TAG"
+        ]
+      },
+      "android/support/v17/preference/LeanbackSettingsFragment": {
+        "androidx/leanback/preference/LeanbackSettingsFragment": [
+          "PREFERENCE_FRAGMENT_TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/ParallaxTarget$PropertyValuesHolderTarget": {
+        "androidx/leanback/widget/ParallaxTarget$PropertyValuesHolderTarget": [
+          "PSEUDO_DURATION"
+        ]
+      },
+      "android/support/design/widget/SnackbarManager": {
+        "androidx/design/widget/SnackbarManager": [
+          "MSG_TIMEOUT",
+          "sSnackbarManager",
+          "LONG_DURATION_MS",
+          "SHORT_DURATION_MS"
+        ]
+      },
+      "android/support/v17/leanback/app/BaseRowSupportFragment": {
+        "androidx/leanback/app/BaseRowSupportFragment": [
+          "CURRENT_SELECTED_POSITION"
+        ]
+      },
+      "android/support/v7/app/MediaRouteVolumeSlider": {
+        "androidx/app/MediaRouteVolumeSlider": [
+          "TAG"
+        ]
+      },
+      "android/support/v7/util/AsyncListUtil$ViewCallback": {
+        "androidx/util/AsyncListUtil$ViewCallback": [
+          "HINT_SCROLL_DESC",
+          "HINT_SCROLL_NONE",
+          "HINT_SCROLL_ASC"
+        ]
+      },
+      "android/support/multidex/MultiDexExtractor$ExtractedDex": {
+        "androidx/multidex/MultiDexExtractor$ExtractedDex": [
+          "crc"
+        ]
+      },
+      "android/support/transition/AnimatorUtils": {
+        "androidx/transition/AnimatorUtils": [
+          "IMPL"
+        ]
+      },
+      "android/support/v7/app/AppCompatDelegateImplV14": {
+        "androidx/app/AppCompatDelegateImplV14": [
+          "KEY_LOCAL_NIGHT_MODE"
+        ]
+      },
+      "android/support/transition/Styleable$PatternPathMotion": {
+        "androidx/transition/Styleable$PatternPathMotion": [
+          "PATTERN_PATH_DATA"
+        ]
+      },
+      "android/support/v7/media/SystemMediaRouteProvider": {
+        "androidx/media/SystemMediaRouteProvider": [
+          "TAG",
+          "DEFAULT_ROUTE_ID",
+          "PACKAGE_NAME"
+        ]
+      },
+      "android/support/design/internal/BottomNavigationItemView": {
+        "androidx/design/internal/BottomNavigationItemView": [
+          "CHECKED_STATE_SET",
+          "INVALID_ITEM_POSITION"
+        ]
+      },
+      "android/support/wear/widget/ScrollManager": {
+        "androidx/wear/widget/ScrollManager": [
+          "ONE_SEC_IN_MS",
+          "FLING_EDGE_RATIO",
+          "VELOCITY_MULTIPLIER"
+        ]
+      },
+      "android/support/v7/widget/AppCompatTextHelper": {
+        "androidx/widget/AppCompatTextHelper": [
+          "MONOSPACE",
+          "SANS",
+          "SERIF"
+        ]
+      },
+      "android/support/v17/leanback/app/DetailsSupportFragment$WaitEnterTransitionTimeout": {
+        "androidx/leanback/app/DetailsSupportFragment$WaitEnterTransitionTimeout": [
+          "WAIT_ENTERTRANSITION_START"
+        ]
+      },
+      "android/support/v7/media/MediaRouteProviderDescriptor": {
+        "androidx/media/MediaRouteProviderDescriptor": [
+          "KEY_ROUTES"
+        ]
+      },
+      "android/support/v17/leanback/widget/TitleView": {
+        "androidx/leanback/widget/TitleView": [
+          "flags"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompat$QueueItem": {
+        "androidx/media/session/MediaSessionCompat$QueueItem": [
+          "CREATOR",
+          "UNKNOWN_ID"
+        ]
+      },
+      "android/support/v7/mediarouter/R$styleable": {
+        "androidx/mediarouter/R$styleable": [
+          "MediaRouteButton_android_minHeight",
+          "MediaRouteButton_mediaRouteButtonTint",
+          "MediaRouteButton_android_minWidth",
+          "MediaRouteButton_externalRouteEnabledDrawable",
+          "MediaRouteButton"
+        ]
+      },
+      "android/support/v7/view/menu/ActionMenuItemView": {
+        "androidx/view/menu/ActionMenuItemView": [
+          "TAG",
+          "MAX_ICON_SIZE"
+        ]
+      },
+      "android/support/v4/app/FragmentStatePagerAdapter": {
+        "androidx/app/FragmentStatePagerAdapter": [
+          "TAG",
+          "DEBUG"
+        ]
+      },
+      "android/support/wear/widget/drawer/ScrollViewFlingWatcher": {
+        "androidx/wear/widget/drawer/ScrollViewFlingWatcher": [
+          "MAX_WAIT_TIME_MS"
+        ]
+      },
+      "android/support/transition/MatrixUtils": {
+        "androidx/transition/MatrixUtils": [
+          "IDENTITY_MATRIX"
+        ]
+      },
+      "android/support/v4/app/NotificationCompat$Action": {
+        "androidx/app/NotificationCompat$Action": [
+          "icon",
+          "title",
+          "actionIntent"
+        ]
+      },
+      "android/support/v4/os/ResultReceiver": {
+        "androidx/os/ResultReceiver": [
+          "CREATOR"
+        ]
+      },
+      "android/support/v7/widget/AppCompatTextView": {
+        "androidx/widget/AppCompatTextView": [
+          "PLATFORM_SUPPORTS_AUTOSIZE"
+        ]
+      },
+      "android/support/v7/widget/StaggeredGridLayoutManager": {
+        "androidx/widget/StaggeredGridLayoutManager": [
+          "GAP_HANDLING_LAZY",
+          "GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS",
+          "TAG",
+          "VERTICAL",
+          "INVALID_OFFSET",
+          "MAX_SCROLL_FACTOR",
+          "GAP_HANDLING_NONE",
+          "DEBUG",
+          "HORIZONTAL"
+        ]
+      },
+      "android/support/design/widget/BottomNavigationView$SavedState": {
+        "androidx/design/widget/BottomNavigationView$SavedState": [
+          "CREATOR",
+          "menuPresenterState"
+        ]
+      },
+      "android/support/v7/widget/RoundRectDrawableWithShadow": {
+        "androidx/widget/RoundRectDrawableWithShadow": [
+          "sRoundRectHelper",
+          "COS_45",
+          "SHADOW_MULTIPLIER"
+        ]
+      },
+      "android/support/v7/preference/PreferenceCategory": {
+        "androidx/preference/PreferenceCategory": [
+          "TAG"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView$ItemAnimator$ItemHolderInfo": {
+        "androidx/widget/RecyclerView$ItemAnimator$ItemHolderInfo": [
+          "left",
+          "changeFlags",
+          "top",
+          "right",
+          "bottom"
+        ]
+      },
+      "android/support/v7/preference/ListPreference$SavedState": {
+        "androidx/preference/ListPreference$SavedState": [
+          "CREATOR",
+          "value"
+        ]
+      },
+      "android/support/v7/widget/TooltipPopup": {
+        "androidx/widget/TooltipPopup": [
+          "TAG"
+        ]
+      },
+      "android/support/v4/net/ConnectivityManagerCompat": {
+        "androidx/net/ConnectivityManagerCompat": [
+          "RESTRICT_BACKGROUND_STATUS_ENABLED",
+          "RESTRICT_BACKGROUND_STATUS_WHITELISTED",
+          "RESTRICT_BACKGROUND_STATUS_DISABLED"
+        ]
+      },
+      "android/support/v7/widget/MenuPopupWindow": {
+        "androidx/widget/MenuPopupWindow": [
+          "sSetTouchModalMethod",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/app/RowsFragment": {
+        "androidx/leanback/app/RowsFragment": [
+          "TAG",
+          "ALIGN_TOP_NOT_SET",
+          "DEBUG"
+        ]
+      },
+      "android/support/v17/leanback/app/ProgressBarManager": {
+        "androidx/leanback/app/ProgressBarManager": [
+          "runnable",
+          "rootView",
+          "DEFAULT_PROGRESS_BAR_DELAY"
+        ]
+      },
+      "android/support/v7/media/RegisteredMediaRouteProvider": {
+        "androidx/media/RegisteredMediaRouteProvider": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/design/widget/CheckableImageButton": {
+        "androidx/design/widget/CheckableImageButton": [
+          "DRAWABLE_STATE_CHECKED"
+        ]
+      },
+      "android/support/transition/ImageViewUtils": {
+        "androidx/transition/ImageViewUtils": [
+          "IMPL"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsRow$HighQualityAction": {
+        "androidx/leanback/widget/PlaybackControlsRow$HighQualityAction": [
+          "INDEX_OFF",
+          "INDEX_ON",
+          "OFF",
+          "ON"
+        ]
+      },
+      "android/support/wear/widget/drawer/PageIndicatorView": {
+        "androidx/wear/widget/drawer/PageIndicatorView": [
+          "TAG"
+        ]
+      },
+      "android/support/transition/TransitionValues": {
+        "androidx/transition/TransitionValues": [
+          "view",
+          "values"
+        ]
+      },
+      "android/support/v17/leanback/app/BaseRowFragment": {
+        "androidx/leanback/app/BaseRowFragment": [
+          "CURRENT_SELECTED_POSITION"
+        ]
+      },
+      "android/support/v7/mediarouter/R$drawable": {
+        "androidx/mediarouter/R$drawable": [
+          "mr_group_collapse",
+          "mr_group_expand"
+        ]
+      },
+      "android/support/transition/ViewUtils": {
+        "androidx/transition/ViewUtils": [
+          "sViewFlagsField",
+          "TRANSITION_ALPHA",
+          "IMPL",
+          "sViewFlagsFieldFetched",
+          "TAG",
+          "CLIP_BOUNDS",
+          "VISIBILITY_MASK"
+        ]
+      },
+      "android/support/v7/preference/AndroidResources": {
+        "androidx/preference/AndroidResources": [
+          "ANDROID_R_ICON_FRAME",
+          "ANDROID_R_SWITCH_WIDGET",
+          "ANDROID_R_PREFERENCE_FRAGMENT_STYLE",
+          "ANDROID_R_LIST_CONTAINER",
+          "ANDROID_R_EDITTEXT_PREFERENCE_STYLE"
+        ]
+      },
+      "android/support/v4/net/DatagramSocketWrapper$DatagramSocketImplWrapper": {
+        "androidx/net/DatagramSocketWrapper$DatagramSocketImplWrapper": [
+          "localport",
+          "fd"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsRowPresenter$BoundData": {
+        "androidx/leanback/widget/PlaybackControlsRowPresenter$BoundData": [
+          "secondaryActionsAdapter",
+          "presenter",
+          "adapter"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsRowPresenter$ViewHolder": {
+        "androidx/leanback/widget/PlaybackControlsRowPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/v17/leanback/widget/Parallax$FloatProperty": {
+        "androidx/leanback/widget/Parallax$FloatProperty": [
+          "UNKNOWN_AFTER",
+          "UNKNOWN_BEFORE"
+        ]
+      },
+      "android/support/v17/leanback/widget/AbstractDetailsDescriptionPresenter$ViewHolder": {
+        "androidx/leanback/widget/AbstractDetailsDescriptionPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/design/R$string": {
+        "androidx/design/R$string": [
+          "character_counter_pattern"
+        ]
+      },
+      "android/support/wear/ambient/AmbientDelegate": {
+        "androidx/wear/ambient/AmbientDelegate": [
+          "TAG",
+          "sInitAutoResumeEnabledMethod",
+          "sHasAutoResumeEnabledMethod"
+        ]
+      },
+      "android/support/v17/leanback/app/PlaybackFragment": {
+        "androidx/leanback/app/PlaybackFragment": [
+          "ANIMATION_MULTIPLIER",
+          "BG_DARK",
+          "BG_NONE",
+          "DEBUG",
+          "BUNDLE_CONTROL_VISIBLE_ON_CREATEVIEW",
+          "BG_LIGHT",
+          "TAG",
+          "ANIMATING",
+          "IDLE",
+          "START_FADE_OUT"
+        ]
+      },
+      "android/support/v7/widget/ActionBarOverlayLayout$LayoutParams": {
+        "androidx/widget/ActionBarOverlayLayout$LayoutParams": [
+          "topMargin",
+          "rightMargin",
+          "bottomMargin",
+          "leftMargin"
+        ]
+      },
+      "android/support/v4/os/EnvironmentCompat": {
+        "androidx/os/EnvironmentCompat": [
+          "MEDIA_UNKNOWN",
+          "TAG"
+        ]
+      },
+      "android/support/compat/R$string": {
+        "androidx/compat/R$string": [
+          "status_bar_notification_info_overflow"
+        ]
+      },
+      "android/support/v7/widget/PositionMap": {
+        "androidx/widget/PositionMap": [
+          "DELETED"
+        ]
+      },
+      "android/support/media/tv/Program": {
+        "androidx/media/tv/Program": [
+          "INVALID_LONG_VALUE",
+          "PROJECTION",
+          "IS_RECORDING_PROHIBITED"
+        ]
+      },
+      "android/support/v7/widget/ActionBarContextView": {
+        "androidx/widget/ActionBarContextView": [
+          "TAG"
+        ]
+      },
+      "android/support/v4/media/VolumeProviderCompat": {
+        "androidx/media/VolumeProviderCompat": [
+          "VOLUME_CONTROL_RELATIVE",
+          "VOLUME_CONTROL_FIXED",
+          "VOLUME_CONTROL_ABSOLUTE"
+        ]
+      },
+      "android/support/v7/view/menu/CascadingMenuPopup": {
+        "androidx/view/menu/CascadingMenuPopup": [
+          "SUBMENU_TIMEOUT_MS",
+          "HORIZ_POSITION_LEFT",
+          "HORIZ_POSITION_RIGHT"
+        ]
+      },
+      "android/support/v4/app/NotificationManagerCompat$ServiceConnectedEvent": {
+        "androidx/app/NotificationManagerCompat$ServiceConnectedEvent": [
+          "componentName",
+          "iBinder"
+        ]
+      },
+      "android/support/v7/app/AlertDialog": {
+        "androidx/app/AlertDialog": [
+          "LAYOUT_HINT_NONE",
+          "LAYOUT_HINT_SIDE"
+        ]
+      },
+      "android/support/v17/leanback/widget/picker/PickerUtility$DateConstant": {
+        "androidx/leanback/widget/picker/PickerUtility$DateConstant": [
+          "months",
+          "days",
+          "locale"
+        ]
+      },
+      "android/support/v7/app/MediaRouteChooserDialogFragment": {
+        "androidx/app/MediaRouteChooserDialogFragment": [
+          "ARGUMENT_SELECTOR"
+        ]
+      },
+      "android/support/design/widget/CoordinatorLayout$SavedState": {
+        "androidx/design/widget/CoordinatorLayout$SavedState": [
+          "behaviorStates",
+          "CREATOR"
+        ]
+      },
+      "android/support/v7/media/MediaRouteDiscoveryRequest": {
+        "androidx/media/MediaRouteDiscoveryRequest": [
+          "KEY_ACTIVE_SCAN",
+          "KEY_SELECTOR"
+        ]
+      },
+      "android/support/v17/leanback/widget/StaticShadowHelper": {
+        "androidx/leanback/widget/StaticShadowHelper": [
+          "sInstance"
+        ]
+      },
+      "android/support/design/widget/ShadowDrawableWrapper": {
+        "androidx/design/widget/ShadowDrawableWrapper": [
+          "SHADOW_MULTIPLIER",
+          "SHADOW_TOP_SCALE",
+          "COS_45",
+          "SHADOW_HORIZ_SCALE",
+          "SHADOW_BOTTOM_SCALE"
+        ]
+      },
+      "android/support/v13/app/FragmentCompat": {
+        "androidx/app/FragmentCompat": [
+          "sDelegate",
+          "IMPL"
+        ]
+      },
+      "android/support/v7/widget/GridLayout$Arc": {
+        "androidx/widget/GridLayout$Arc": [
+          "span",
+          "valid",
+          "value"
+        ]
+      },
+      "android/support/v4/content/AsyncTaskLoader": {
+        "androidx/content/AsyncTaskLoader": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v7/gridlayout/BuildConfig": {
+        "androidx/gridlayout/BuildConfig": [
+          "DEBUG",
+          "VERSION_CODE",
+          "BUILD_TYPE",
+          "VERSION_NAME",
+          "FLAVOR",
+          "APPLICATION_ID"
+        ]
+      },
+      "android/support/text/emoji/flatbuffer/MetadataList": {
+        "androidx/text/emoji/flatbuffer/MetadataList": [
+          "bb_pos",
+          "bb"
+        ]
+      },
+      "android/support/text/emoji/widget/EditTextAttributeHelper": {
+        "androidx/text/emoji/widget/EditTextAttributeHelper": [
+          "MAX_EMOJI_COUNT"
+        ]
+      },
+      "android/support/v7/widget/ChildHelper$Bucket": {
+        "androidx/widget/ChildHelper$Bucket": [
+          "LAST_BIT",
+          "BITS_PER_WORD"
+        ]
+      },
+      "android/support/v4/content/LocalBroadcastManager": {
+        "androidx/content/LocalBroadcastManager": [
+          "DEBUG",
+          "MSG_EXEC_PENDING_BROADCASTS",
+          "TAG"
+        ]
+      },
+      "android/support/v7/widget/TooltipCompat": {
+        "androidx/widget/TooltipCompat": [
+          "IMPL"
+        ]
+      },
+      "android/support/media/tv/PreviewProgram": {
+        "androidx/media/tv/PreviewProgram": [
+          "INVALID_INT_VALUE",
+          "PROJECTION",
+          "INVALID_LONG_VALUE"
+        ]
+      },
+      "android/support/v7/preference/ListPreferenceDialogFragmentCompat": {
+        "androidx/preference/ListPreferenceDialogFragmentCompat": [
+          "SAVE_STATE_INDEX",
+          "SAVE_STATE_ENTRIES",
+          "SAVE_STATE_ENTRY_VALUES"
+        ]
+      },
+      "android/support/v7/widget/ViewInfoStore": {
+        "androidx/widget/ViewInfoStore": [
+          "DEBUG"
+        ]
+      },
+      "android/support/v7/widget/ActivityChooserModel$ActivityResolveInfo": {
+        "androidx/widget/ActivityChooserModel$ActivityResolveInfo": [
+          "weight",
+          "resolveInfo"
+        ]
+      },
+      "android/support/v7/preference/SeekBarPreference": {
+        "androidx/preference/SeekBarPreference": [
+          "TAG"
+        ]
+      },
+      "android/support/v7/widget/ActivityChooserView$InnerLayout": {
+        "androidx/widget/ActivityChooserView$InnerLayout": [
+          "TINT_ATTRS"
+        ]
+      },
+      "android/support/v7/app/AppCompatDelegateImplV9": {
+        "androidx/app/AppCompatDelegateImplV9": [
+          "IS_PRE_LOLLIPOP"
+        ]
+      },
+      "android/support/v7/media/SystemMediaRouteProvider$LegacyImpl": {
+        "androidx/media/SystemMediaRouteProvider$LegacyImpl": [
+          "PLAYBACK_STREAM",
+          "CONTROL_FILTERS"
+        ]
+      },
+      "android/support/transition/ViewUtilsApi22": {
+        "androidx/transition/ViewUtilsApi22": [
+          "sSetLeftTopRightBottomMethod",
+          "TAG",
+          "sSetLeftTopRightBottomMethodFetched"
+        ]
+      },
+      "android/support/v17/leanback/widget/ObjectAdapter": {
+        "androidx/leanback/widget/ObjectAdapter": [
+          "NO_ID"
+        ]
+      },
+      "android/support/content/Query": {
+        "androidx/content/Query": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/media/MediaControllerAdapter": {
+        "androidx/leanback/media/MediaControllerAdapter": [
+          "TAG",
+          "DEBUG"
+        ]
+      },
+      "android/support/v7/recyclerview/R$id": {
+        "androidx/recyclerview/R$id": [
+          "item_touch_helper_previous_elevation"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompat$Callback$CallbackHandler": {
+        "androidx/media/session/MediaSessionCompat$Callback$CallbackHandler": [
+          "MSG_MEDIA_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT"
+        ]
+      },
+      "android/support/design/widget/FloatingActionButton": {
+        "androidx/design/widget/FloatingActionButton": [
+          "LOG_TAG",
+          "AUTO_MINI_LARGEST_SCREEN_WIDTH",
+          "SIZE_AUTO",
+          "SIZE_NORMAL",
+          "SIZE_MINI"
+        ]
+      },
+      "android/support/v17/leanback/widget/DetailsOverviewSharedElementHelper": {
+        "androidx/leanback/widget/DetailsOverviewSharedElementHelper": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v7/app/AlertDialog$Builder": {
+        "androidx/app/AlertDialog$Builder": [
+          "P"
+        ]
+      },
+      "android/support/wear/internal/widget/drawer/SinglePagePresenter": {
+        "androidx/wear/internal/widget/drawer/SinglePagePresenter": [
+          "DRAWER_CLOSE_DELAY_MS"
+        ]
+      },
+      "android/support/v17/leanback/app/BrowseSupportFragment$SetSelectionRunnable": {
+        "androidx/leanback/app/BrowseSupportFragment$SetSelectionRunnable": [
+          "TYPE_INTERNAL_SYNC",
+          "TYPE_USER_REQUEST",
+          "TYPE_INVALID"
+        ]
+      },
+      "android/support/v7/preference/R$id": {
+        "androidx/preference/R$id": [
+          "switchWidget",
+          "seekbar",
+          "seekbar_value",
+          "icon_frame",
+          "spinner"
+        ]
+      },
+      "android/support/media/tv/BasePreviewProgram$Builder": {
+        "androidx/media/tv/BasePreviewProgram$Builder": [
+          "sFormat"
+        ]
+      },
+      "android/support/v4/widget/SlidingPaneLayout": {
+        "androidx/widget/SlidingPaneLayout": [
+          "DEFAULT_OVERHANG_SIZE",
+          "IMPL",
+          "DEFAULT_FADE_COLOR",
+          "TAG",
+          "MIN_FLING_VELOCITY"
+        ]
+      },
+      "android/support/v7/app/MediaRouteChooserDialog": {
+        "androidx/app/MediaRouteChooserDialog": [
+          "UPDATE_ROUTES_DELAY_MS",
+          "TAG",
+          "MSG_UPDATE_ROUTES"
+        ]
+      },
+      "android/support/v4/app/ShareCompat$IntentReader": {
+        "androidx/app/ShareCompat$IntentReader": [
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/ItemBridgeAdapter$ViewHolder": {
+        "androidx/leanback/widget/ItemBridgeAdapter$ViewHolder": [
+          "itemView"
+        ]
+      },
+      "android/support/v17/leanback/app/BrandedFragment": {
+        "androidx/leanback/app/BrandedFragment": [
+          "TITLE_SHOW"
+        ]
+      },
+      "android/support/v17/leanback/widget/SearchEditText": {
+        "androidx/leanback/widget/SearchEditText": [
+          "DEBUG",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/PersistentFocusWrapper$SavedState": {
+        "androidx/leanback/widget/PersistentFocusWrapper$SavedState": [
+          "CREATOR"
+        ]
+      },
+      "android/support/percent/PercentFrameLayout$LayoutParams": {
+        "androidx/PercentFrameLayout$LayoutParams": [
+          "gravity"
+        ]
+      },
+      "android/support/text/emoji/widget/EmojiEditableFactory": {
+        "androidx/text/emoji/widget/EmojiEditableFactory": [
+          "sWatcherClass",
+          "sInstanceLock",
+          "sInstance"
+        ]
+      },
+      "android/support/v4/view/ViewPager$SavedState": {
+        "androidx/view/ViewPager$SavedState": [
+          "position",
+          "adapterState",
+          "CREATOR",
+          "loader"
+        ]
+      },
+      "android/support/v17/leanback/widget/RowPresenter": {
+        "androidx/leanback/widget/RowPresenter": [
+          "SYNC_ACTIVATED_TO_SELECTED",
+          "SYNC_ACTIVATED_TO_EXPANDED_AND_SELECTED",
+          "SYNC_ACTIVATED_CUSTOM",
+          "SYNC_ACTIVATED_TO_EXPANDED"
+        ]
+      },
+      "android/support/v7/preference/EditTextPreferenceDialogFragmentCompat": {
+        "androidx/preference/EditTextPreferenceDialogFragmentCompat": [
+          "SAVE_STATE_TEXT"
+        ]
+      },
+      "android/support/v17/leanback/graphics/ColorFilterCache": {
+        "androidx/leanback/graphics/ColorFilterCache": [
+          "sColorToFiltersMap"
+        ]
+      },
+      "android/support/v7/view/menu/ListMenuPresenter": {
+        "androidx/view/menu/ListMenuPresenter": [
+          "VIEWS_TAG",
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/VerticalGridPresenter$ViewHolder": {
+        "androidx/leanback/widget/VerticalGridPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/v4/app/TaskStackBuilder": {
+        "androidx/app/TaskStackBuilder": [
+          "TAG",
+          "IMPL"
+        ]
+      },
+      "android/support/v7/content/res/AppCompatResources": {
+        "androidx/content/res/AppCompatResources": [
+          "LOG_TAG",
+          "sColorStateCaches",
+          "TL_TYPED_VALUE",
+          "sColorStateCacheLock"
+        ]
+      },
+      "android/support/v7/recyclerview/BuildConfig": {
+        "androidx/recyclerview/BuildConfig": [
+          "DEBUG",
+          "FLAVOR",
+          "VERSION_CODE",
+          "BUILD_TYPE",
+          "VERSION_NAME",
+          "APPLICATION_ID"
+        ]
+      },
+      "android/support/v4/hardware/display/DisplayManagerCompat": {
+        "androidx/hardware/display/DisplayManagerCompat": [
+          "DISPLAY_CATEGORY_PRESENTATION",
+          "sInstances"
+        ]
+      },
+      "android/support/v7/widget/ActionMenuPresenter": {
+        "androidx/widget/ActionMenuPresenter": [
+          "TAG"
+        ]
+      },
+      "android/support/v4/app/NotificationManagerCompat$NotifyTask": {
+        "androidx/app/NotificationManagerCompat$NotifyTask": [
+          "notif",
+          "id",
+          "tag",
+          "packageName"
+        ]
+      },
+      "android/support/text/emoji/FontRequestEmojiCompatConfig": {
+        "androidx/text/emoji/FontRequestEmojiCompatConfig": [
+          "DEFAULT_FONTS_CONTRACT"
+        ]
+      },
+      "android/support/v17/leanback/widget/ShadowHelperApi21": {
+        "androidx/leanback/widget/ShadowHelperApi21": [
+          "sOutlineProvider"
+        ]
+      },
+      "android/support/v17/leanback/widget/ItemBridgeAdapter": {
+        "androidx/leanback/widget/ItemBridgeAdapter": [
+          "TAG",
+          "DEBUG"
+        ]
+      },
+      "android/support/wear/utils/MetadataConstants": {
+        "androidx/wear/utils/MetadataConstants": [
+          "STANDALONE_METADATA_NAME",
+          "WATCH_FACE_PREVIEW_CIRCULAR_METADATA_NAME",
+          "NOTIFICATION_BRIDGE_MODE_NO_BRIDGING",
+          "NOTIFICATION_BRIDGE_MODE_BRIDGING",
+          "WATCH_FACE_PREVIEW_METADATA_NAME",
+          "NOTIFICATION_BRIDGE_MODE_METADATA_NAME"
+        ]
+      },
+      "android/support/transition/GhostViewUtils": {
+        "androidx/transition/GhostViewUtils": [
+          "CREATOR"
+        ]
+      },
+      "android/support/v17/leanback/widget/AbstractMediaListHeaderPresenter$ViewHolder": {
+        "androidx/leanback/widget/AbstractMediaListHeaderPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsRowPresenter": {
+        "androidx/leanback/widget/PlaybackControlsRowPresenter": [
+          "sShadowZ"
+        ]
+      },
+      "android/support/v7/widget/CardView": {
+        "androidx/widget/CardView": [
+          "COLOR_BACKGROUND_ATTR",
+          "IMPL"
+        ]
+      },
+      "android/support/v7/app/ActionBar$Tab": {
+        "androidx/app/ActionBar$Tab": [
+          "INVALID_POSITION"
+        ]
+      },
+      "android/support/v7/app/MediaRouterThemeHelper": {
+        "androidx/app/MediaRouterThemeHelper": [
+          "MIN_CONTRAST",
+          "COLOR_WHITE_ON_DARK_BACKGROUND",
+          "COLOR_DARK_ON_LIGHT_BACKGROUND"
+        ]
+      },
+      "android/support/transition/ChangeClipBounds": {
+        "androidx/transition/ChangeClipBounds": [
+          "PROPNAME_CLIP",
+          "PROPNAME_BOUNDS",
+          "sTransitionProperties"
+        ]
+      },
+      "android/support/transition/Styleable$Slide": {
+        "androidx/transition/Styleable$Slide": [
+          "SLIDE_EDGE"
+        ]
+      },
+      "android/support/transition/TransitionSet": {
+        "androidx/transition/TransitionSet": [
+          "ORDERING_TOGETHER",
+          "ORDERING_SEQUENTIAL"
+        ]
+      },
+      "android/support/v7/widget/SearchView$SavedState": {
+        "androidx/widget/SearchView$SavedState": [
+          "CREATOR",
+          "isIconified"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackControlsPresenter$BoundData": {
+        "androidx/leanback/widget/PlaybackControlsPresenter$BoundData": [
+          "secondaryActionsAdapter"
+        ]
+      },
+      "android/support/v4/content/LocalBroadcastManager$BroadcastRecord": {
+        "androidx/content/LocalBroadcastManager$BroadcastRecord": [
+          "intent",
+          "receivers"
+        ]
+      },
+      "android/support/v7/preference/MultiSelectListPreferenceDialogFragmentCompat": {
+        "androidx/preference/MultiSelectListPreferenceDialogFragmentCompat": [
+          "SAVE_STATE_ENTRIES",
+          "SAVE_STATE_CHANGED",
+          "SAVE_STATE_ENTRY_VALUES",
+          "SAVE_STATE_VALUES"
+        ]
+      },
+      "android/support/transition/ViewGroupUtils": {
+        "androidx/transition/ViewGroupUtils": [
+          "IMPL"
+        ]
+      },
+      "android/support/v17/leanback/widget/ControlBarPresenter$ViewHolder": {
+        "androidx/leanback/widget/ControlBarPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/v7/mediarouter/BuildConfig": {
+        "androidx/mediarouter/BuildConfig": [
+          "DEBUG",
+          "VERSION_CODE",
+          "FLAVOR",
+          "BUILD_TYPE",
+          "APPLICATION_ID",
+          "VERSION_NAME"
+        ]
+      },
+      "android/support/v17/leanback/R$transition": {
+        "androidx/leanback/R$transition": [
+          "lb_title_in",
+          "lb_browse_headers_out",
+          "lb_title_out",
+          "lb_browse_entrance_transition",
+          "lb_details_enter_transition",
+          "lb_vertical_grid_entrance_transition",
+          "lb_browse_headers_in"
+        ]
+      },
+      "android/support/design/R$drawable": {
+        "androidx/design/R$drawable": [
+          "navigation_empty_icon",
+          "design_bottom_navigation_item_background"
+        ]
+      },
+      "android/support/wear/widget/drawer/NestedScrollViewFlingWatcher": {
+        "androidx/wear/widget/drawer/NestedScrollViewFlingWatcher": [
+          "MAX_WAIT_TIME_MS"
+        ]
+      },
+      "android/support/v17/leanback/app/HeadersSupportFragment": {
+        "androidx/leanback/app/HeadersSupportFragment": [
+          "sHeaderPresenter",
+          "sLayoutChangeListener"
+        ]
+      },
+      "android/support/v17/leanback/widget/ShadowHelper": {
+        "androidx/leanback/widget/ShadowHelper": [
+          "sInstance"
+        ]
+      },
+      "android/support/percent/PercentLayoutHelper": {
+        "androidx/PercentLayoutHelper": [
+          "TAG",
+          "VERBOSE",
+          "DEBUG"
+        ]
+      },
+      "android/support/design/internal/BottomNavigationMenu": {
+        "androidx/design/internal/BottomNavigationMenu": [
+          "MAX_ITEM_COUNT"
+        ]
+      },
+      "android/support/design/internal/TextScale": {
+        "androidx/design/internal/TextScale": [
+          "PROPNAME_SCALE"
+        ]
+      },
+      "android/support/v17/leanback/widget/PlaybackTransportRowPresenter$BoundData": {
+        "androidx/leanback/widget/PlaybackTransportRowPresenter$BoundData": [
+          "adapter",
+          "presenter"
+        ]
+      },
+      "android/support/v13/view/inputmethod/EditorInfoCompat$EditorInfoCompatBaseImpl": {
+        "androidx/view/inputmethod/EditorInfoCompat$EditorInfoCompatBaseImpl": [
+          "CONTENT_MIME_TYPES_KEY"
+        ]
+      },
+      "android/support/v17/leanback/widget/ViewsStateBundle": {
+        "androidx/leanback/widget/ViewsStateBundle": [
+          "UNLIMITED",
+          "LIMIT_DEFAULT"
+        ]
+      },
+      "android/support/v4/content/ContextCompat": {
+        "androidx/content/ContextCompat": [
+          "sLock",
+          "TAG",
+          "sTempValue"
+        ]
+      },
+      "android/support/v4/util/SparseArrayCompat": {
+        "androidx/util/SparseArrayCompat": [
+          "DELETED"
+        ]
+      },
+      "android/support/transition/Styleable$VisibilityTransition": {
+        "androidx/transition/Styleable$VisibilityTransition": [
+          "TRANSITION_VISIBILITY_MODE"
+        ]
+      },
+      "android/support/v14/preference/MultiSelectListPreference$SavedState": {
+        "androidx/preference/MultiSelectListPreference$SavedState": [
+          "CREATOR",
+          "values"
+        ]
+      },
+      "android/support/v17/leanback/app/DetailsFragment$WaitEnterTransitionTimeout": {
+        "androidx/leanback/app/DetailsFragment$WaitEnterTransitionTimeout": [
+          "WAIT_ENTERTRANSITION_START"
+        ]
+      },
+      "android/support/text/emoji/MetadataListReader$OpenTypeReader": {
+        "androidx/text/emoji/MetadataListReader$OpenTypeReader": [
+          "UINT16_BYTE_COUNT",
+          "UINT32_BYTE_COUNT"
+        ]
+      },
+      "android/support/v7/preference/TwoStatePreference$SavedState": {
+        "androidx/preference/TwoStatePreference$SavedState": [
+          "checked",
+          "CREATOR"
+        ]
+      },
+      "android/support/v17/leanback/widget/Action": {
+        "androidx/leanback/widget/Action": [
+          "NO_ID"
+        ]
+      },
+      "android/support/v7/widget/Toolbar": {
+        "androidx/widget/Toolbar": [
+          "TAG"
+        ]
+      },
+      "android/support/v17/preference/LeanbackPreferenceDialogFragment": {
+        "androidx/leanback/preference/LeanbackPreferenceDialogFragment": [
+          "ARG_KEY"
+        ]
+      },
+      "android/support/v4/content/SharedPreferencesCompat$EditorCompat": {
+        "androidx/content/SharedPreferencesCompat$EditorCompat": [
+          "sInstance"
+        ]
+      },
+      "android/support/v17/leanback/widget/RowPresenter$ContainerViewHolder": {
+        "androidx/leanback/widget/RowPresenter$ContainerViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/v7/app/MediaRouteChooserDialog$RouteComparator": {
+        "androidx/app/MediaRouteChooserDialog$RouteComparator": [
+          "sInstance"
+        ]
+      },
+      "android/support/v4/widget/PopupWindowCompat": {
+        "androidx/widget/PopupWindowCompat": [
+          "IMPL"
+        ]
+      },
+      "android/support/v4/widget/ImageViewCompat": {
+        "androidx/widget/ImageViewCompat": [
+          "IMPL"
+        ]
+      },
+      "android/support/v17/leanback/widget/GuidedActionsStylist$ViewHolder": {
+        "androidx/leanback/widget/GuidedActionsStylist$ViewHolder": [
+          "itemView"
+        ]
+      },
+      "android/support/v4/view/ActionProvider": {
+        "androidx/view/ActionProvider": [
+          "TAG"
+        ]
+      },
+      "android/support/v4/view/ViewConfigurationCompat": {
+        "androidx/view/ViewConfigurationCompat": [
+          "TAG",
+          "sGetScaledScrollFactorMethod"
+        ]
+      },
+      "android/support/customtabs/CustomTabsSession": {
+        "androidx/browser/customtabs/CustomTabsSession": [
+          "TAG"
+        ]
+      },
+      "android/support/v7/mediarouter/R$style": {
+        "androidx/mediarouter/R$style": [
+          "Theme_MediaRouter_LightControlPanel",
+          "Theme_MediaRouter_Light",
+          "Theme_MediaRouter_Light_DarkControlPanel",
+          "Theme_MediaRouter"
+        ]
+      },
+      "android/support/text/emoji/EmojiProcessor$CodepointIndexFinder": {
+        "androidx/text/emoji/EmojiProcessor$CodepointIndexFinder": [
+          "INVALID_INDEX"
+        ]
+      },
+      "android/support/v17/leanback/widget/NonOverlappingLinearLayoutWithForeground": {
+        "androidx/leanback/widget/NonOverlappingLinearLayoutWithForeground": [
+          "VERSION_M"
+        ]
+      },
+      "android/support/v4/view/ViewCompat$ViewCompatApi21Impl": {
+        "androidx/view/ViewCompat$ViewCompatApi21Impl": [
+          "sThreadLocalRect"
+        ]
+      },
+      "android/support/v4/app/NotificationCompat$DecoratedCustomViewStyle": {
+        "androidx/app/NotificationCompat$DecoratedCustomViewStyle": [
+          "MAX_ACTION_BUTTONS"
+        ]
+      },
+      "android/support/v7/widget/PagerSnapHelper": {
+        "androidx/widget/PagerSnapHelper": [
+          "MAX_SCROLL_ON_FLING_DURATION"
+        ]
+      },
+      "android/support/wear/widget/CircledImageView": {
+        "androidx/wear/widget/CircledImageView": [
+          "SQUARE_DIMEN_WIDTH",
+          "SQUARE_DIMEN_NONE",
+          "SQUARE_DIMEN_HEIGHT",
+          "ARGB_EVALUATOR"
+        ]
+      },
+      "android/support/v7/widget/RtlSpacingHelper": {
+        "androidx/widget/RtlSpacingHelper": [
+          "UNDEFINED"
+        ]
+      },
+      "android/support/v4/media/MediaBrowserServiceCompatApi26": {
+        "androidx/media/MediaBrowserServiceCompatApi26": [
+          "sResultFlags",
+          "TAG"
+        ]
+      },
+      "android/support/text/emoji/EmojiMetadata": {
+        "androidx/text/emoji/EmojiMetadata": [
+          "HAS_GLYPH_EXISTS",
+          "HAS_GLYPH_ABSENT",
+          "HAS_GLYPH_UNKNOWN",
+          "sMetadataItem"
+        ]
+      },
+      "android/support/mediacompat/R$integer": {
+        "androidx/mediacompat/R$integer": [
+          "cancel_button_image_alpha"
+        ]
+      },
+      "android/support/v7/content/res/AppCompatResources$ColorStateListCacheEntry": {
+        "androidx/content/res/AppCompatResources$ColorStateListCacheEntry": [
+          "value",
+          "configuration"
+        ]
+      },
+      "android/support/v17/leanback/widget/DetailsOverviewRowPresenter$ViewHolder": {
+        "androidx/leanback/widget/DetailsOverviewRowPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/wear/R$color": {
+        "androidx/wear/R$color": [
+          "circular_progress_layout_background_color"
+        ]
+      },
+      "android/support/v17/leanback/widget/ItemAlignmentFacet": {
+        "androidx/leanback/widget/ItemAlignmentFacet": [
+          "ITEM_ALIGN_OFFSET_PERCENT_DISABLED"
+        ]
+      },
+      "android/support/wear/ambient/AmbientMode$AmbientController": {
+        "androidx/wear/ambient/AmbientMode$AmbientController": [
+          "TAG"
+        ]
+      },
+      "android/support/v13/view/inputmethod/InputConnectionCompat": {
+        "androidx/view/inputmethod/InputConnectionCompat": [
+          "INPUT_CONTENT_GRANT_READ_URI_PERMISSION",
+          "IMPL"
+        ]
+      },
+      "android/support/wear/widget/BezierSCurveInterpolator": {
+        "androidx/wear/widget/BezierSCurveInterpolator": [
+          "STEP_SIZE",
+          "VALUES",
+          "INSTANCE"
+        ]
+      },
+      "android/support/v4/graphics/PathParser": {
+        "androidx/graphics/PathParser": [
+          "LOGTAG"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView$RecycledViewPool": {
+        "androidx/widget/RecyclerView$RecycledViewPool": [
+          "DEFAULT_MAX_SCRAP"
+        ]
+      },
+      "android/support/v7/media/MediaRouteSelector": {
+        "androidx/media/MediaRouteSelector": [
+          "KEY_CONTROL_CATEGORIES",
+          "EMPTY"
+        ]
+      },
+      "android/support/transition/PropertyValuesHolderUtils": {
+        "androidx/transition/PropertyValuesHolderUtils": [
+          "IMPL"
+        ]
+      },
+      "android/support/graphics/drawable/VectorDrawableCompat$VFullPath": {
+        "androidx/graphics/drawable/VectorDrawableCompat$VFullPath": [
+          "FILL_TYPE_WINDING"
+        ]
+      },
+      "android/support/mediacompat/R$color": {
+        "androidx/mediacompat/R$color": [
+          "notification_material_background_media_default_color"
+        ]
+      },
+      "android/support/v17/leanback/widget/RowHeaderPresenter$ViewHolder": {
+        "androidx/leanback/widget/RowHeaderPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/design/widget/CollapsingToolbarLayout": {
+        "androidx/design/widget/CollapsingToolbarLayout": [
+          "DEFAULT_SCRIM_ANIMATION_DURATION"
+        ]
+      },
+      "android/support/v17/leanback/app/BrandedSupportFragment": {
+        "androidx/leanback/app/BrandedSupportFragment": [
+          "TITLE_SHOW"
+        ]
+      },
+      "android/support/design/internal/BottomNavigationPresenter$SavedState": {
+        "androidx/design/internal/BottomNavigationPresenter$SavedState": [
+          "CREATOR",
+          "selectedItemId"
+        ]
+      },
+      "android/support/v4/app/BackStackState": {
+        "androidx/app/BackStackState": [
+          "CREATOR"
+        ]
+      },
+      "android/support/v4/provider/FontsContractCompat$FontFamilyResult": {
+        "androidx/provider/FontsContractCompat$FontFamilyResult": [
+          "STATUS_WRONG_CERTIFICATES",
+          "STATUS_OK",
+          "STATUS_UNEXPECTED_DATA_PROVIDED"
+        ]
+      },
+      "android/support/v4/app/FragmentManagerState": {
+        "androidx/app/FragmentManagerState": [
+          "CREATOR"
+        ]
+      },
+      "android/support/media/ExifInterface$Rational": {
+        "androidx/media/ExifInterface$Rational": [
+          "denominator",
+          "numerator"
+        ]
+      },
+      "android/support/text/emoji/TypefaceEmojiSpan": {
+        "androidx/text/emoji/TypefaceEmojiSpan": [
+          "sDebugPaint"
+        ]
+      },
+      "android/support/design/widget/FloatingActionButton$Behavior": {
+        "androidx/design/widget/FloatingActionButton$Behavior": [
+          "AUTO_HIDE_DEFAULT"
+        ]
+      },
+      "android/support/graphics/drawable/ArgbEvaluator": {
+        "androidx/graphics/drawable/ArgbEvaluator": [
+          "sInstance"
+        ]
+      },
+      "android/support/v4/util/ContainerHelpers": {
+        "androidx/util/ContainerHelpers": [
+          "EMPTY_INTS",
+          "EMPTY_LONGS",
+          "EMPTY_OBJECTS"
+        ]
+      },
+      "android/support/v7/media/MediaRouterJellybeanMr1": {
+        "androidx/media/MediaRouterJellybeanMr1": [
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/ActionPresenterSelector$ActionViewHolder": {
+        "androidx/leanback/widget/ActionPresenterSelector$ActionViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/v4/app/FragmentState": {
+        "androidx/app/FragmentState": [
+          "CREATOR"
+        ]
+      },
+      "android/support/v7/widget/LinearSnapHelper": {
+        "androidx/widget/LinearSnapHelper": [
+          "INVALID_DISTANCE"
+        ]
+      },
+      "android/support/v17/leanback/widget/FullWidthDetailsOverviewRowPresenter$ViewHolder": {
+        "androidx/leanback/widget/FullWidthDetailsOverviewRowPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/constraint/solver/widgets/ConstraintAnchor$Strength": {
+        "androidx/constraint/solver/widgets/ConstraintAnchor$Strength": [
+          "STRONG"
+        ]
+      },
+      "android/support/design/widget/HeaderBehavior": {
+        "androidx/design/widget/HeaderBehavior": [
+          "INVALID_POINTER"
+        ]
+      },
+      "android/support/v7/widget/LinearLayoutManager$SavedState": {
+        "androidx/widget/LinearLayoutManager$SavedState": [
+          "CREATOR"
+        ]
+      },
+      "android/support/v7/widget/GridLayout$Interval": {
+        "androidx/widget/GridLayout$Interval": [
+          "min",
+          "max"
+        ]
+      },
+      "android/support/v4/widget/SlidingPaneLayout$SavedState": {
+        "androidx/widget/SlidingPaneLayout$SavedState": [
+          "CREATOR",
+          "isOpen"
+        ]
+      },
+      "android/support/v17/leanback/widget/DetailsOverviewLogoPresenter$ViewHolder": {
+        "androidx/leanback/widget/DetailsOverviewLogoPresenter$ViewHolder": [
+          "view"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompatApi24": {
+        "androidx/media/session/MediaSessionCompatApi24": [
+          "TAG"
+        ]
+      },
+      "android/support/v7/app/MediaRouteActionProvider": {
+        "androidx/app/MediaRouteActionProvider": [
+          "TAG"
+        ]
+      },
+      "android/support/v4/media/session/MediaButtonReceiver": {
+        "androidx/media/session/MediaButtonReceiver": [
+          "TAG"
+        ]
+      },
+      "android/support/v4/content/AsyncTaskLoader$LoadTask": {
+        "androidx/content/AsyncTaskLoader$LoadTask": [
+          "waiting"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompatApi21": {
+        "androidx/media/session/MediaSessionCompatApi21": [
+          "TAG"
+        ]
+      },
+      "android/support/design/internal/NavigationMenuPresenter$ViewHolder": {
+        "androidx/design/internal/NavigationMenuPresenter$ViewHolder": [
+          "itemView"
+        ]
+      },
+      "android/support/v7/widget/AppCompatButton": {
+        "androidx/widget/AppCompatButton": [
+          "PLATFORM_SUPPORTS_AUTOSIZE"
+        ]
+      },
+      "android/support/v17/leanback/widget/CheckableImageView": {
+        "androidx/leanback/widget/CheckableImageView": [
+          "CHECKED_STATE_SET"
+        ]
+      },
+      "android/support/v4/view/animation/FastOutLinearInInterpolator": {
+        "androidx/view/animation/FastOutLinearInInterpolator": [
+          "VALUES"
+        ]
+      },
+      "android/support/v7/app/MediaRouteDiscoveryFragment": {
+        "androidx/app/MediaRouteDiscoveryFragment": [
+          "ARGUMENT_SELECTOR"
+        ]
+      },
+      "android/support/v4/graphics/TypefaceCompatApi21Impl": {
+        "androidx/graphics/TypefaceCompatApi21Impl": [
+          "TAG"
+        ]
+      },
+      "android/support/v17/leanback/widget/FocusHighlightHelper$BrowseItemFocusHighlight": {
+        "androidx/leanback/widget/FocusHighlightHelper$BrowseItemFocusHighlight": [
+          "DURATION_MS"
+        ]
+      },
+      "android/support/transition/ImageViewUtilsApi21": {
+        "androidx/transition/ImageViewUtilsApi21": [
+          "TAG",
+          "sAnimateTransformMethodFetched",
+          "sAnimateTransformMethod"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView$SmoothScroller$Action": {
+        "androidx/widget/RecyclerView$SmoothScroller$Action": [
+          "UNDEFINED_DURATION"
+        ]
+      },
+      "android/support/v4/media/session/PlaybackStateCompat$CustomAction": {
+        "androidx/media/session/PlaybackStateCompat$CustomAction": [
+          "CREATOR"
+        ]
+      },
+      "android/support/design/R$integer": {
+        "androidx/design/R$integer": [
+          "app_bar_elevation_anim_duration"
+        ]
+      },
+      "android/support/v4/provider/DocumentFile": {
+        "androidx/provider/DocumentFile": [
+          "TAG"
+        ]
+      },
+      "android/support/v7/widget/StaggeredGridLayoutManager$SavedState": {
+        "androidx/widget/StaggeredGridLayoutManager$SavedState": [
+          "CREATOR"
+        ]
+      },
+      "android/support/animation/FlingAnimation$DragForce": {
+        "androidx/animation/FlingAnimation$DragForce": [
+          "VELOCITY_THRESHOLD_MULTIPLIER",
+          "DEFAULT_FRICTION"
+        ]
+      },
+      "android/support/v17/leanback/transition/ParallaxTransition": {
+        "androidx/leanback/transition/ParallaxTransition": [
+          "sInterpolator"
+        ]
+      },
+      "android/support/v4/app/NotificationCompat$MessagingStyle": {
+        "androidx/app/NotificationCompat$MessagingStyle": [
+          "MAXIMUM_RETAINED_MESSAGES"
+        ]
+      },
+      "android/support/v7/widget/RecyclerView$SavedState": {
+        "androidx/widget/RecyclerView$SavedState": [
+          "CREATOR"
+        ]
+      },
+      "android/support/v17/leanback/widget/ResizingTextView": {
+        "androidx/leanback/widget/ResizingTextView": [
+          "TRIGGER_MAX_LINES"
+        ]
+      },
+      "android/support/v7/widget/StaggeredGridLayoutManager$LazySpanLookup": {
+        "androidx/widget/StaggeredGridLayoutManager$LazySpanLookup": [
+          "MIN_SIZE"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompat$MediaSessionImplBase": {
+        "androidx/media/session/MediaSessionCompat$MediaSessionImplBase": [
+          "RCC_PLAYSTATE_NONE"
+        ]
+      },
+      "android/support/v4/util/LongSparseArray": {
+        "androidx/util/LongSparseArray": [
+          "DELETED"
+        ]
+      },
+      "android/support/v4/view/accessibility/AccessibilityNodeProviderCompat": {
+        "androidx/view/accessibility/AccessibilityNodeProviderCompat": [
+          "HOST_VIEW_ID"
+        ]
+      },
+      "android/support/v4/view/AsyncLayoutInflater": {
+        "androidx/view/AsyncLayoutInflater": [
+          "TAG"
+        ]
+      },
+      "android/support/graphics/drawable/VectorDrawableCompat$VPathRenderer": {
+        "androidx/graphics/drawable/VectorDrawableCompat$VPathRenderer": [
+          "IDENTITY_MATRIX"
+        ]
+      },
+      "android/support/v13/view/DragAndDropPermissionsCompat": {
+        "androidx/view/DragAndDropPermissionsCompat": [
+          "IMPL"
+        ]
+      },
+      "android/support/v4/media/MediaBrowserCompatApi21": {
+        "androidx/media/MediaBrowserCompatApi21": [
+          "NULL_MEDIA_ITEM_ID"
+        ]
+      },
+      "android/support/v4/view/animation/FastOutSlowInInterpolator": {
+        "androidx/view/animation/FastOutSlowInInterpolator": [
+          "VALUES"
+        ]
+      },
+      "android/support/v7/widget/AppCompatProgressBarHelper": {
+        "androidx/widget/AppCompatProgressBarHelper": [
+          "TINT_ATTRS"
+        ]
+      },
+      "android/support/v4/media/ParceledListSliceAdapterApi21": {
+        "androidx/media/ParceledListSliceAdapterApi21": [
+          "sConstructor"
+        ]
+      },
+      "android/support/compat/R$integer": {
+        "androidx/compat/R$integer": [
+          "status_bar_notification_info_maxnum"
+        ]
+      },
+      "android/support/v14/preference/EditTextPreferenceDialogFragment": {
+        "androidx/preference/EditTextPreferenceDialogFragment": [
+          "SAVE_STATE_TEXT"
+        ]
+      },
+      "android/support/wear/R$array": {
+        "androidx/wear/R$array": [
+          "circular_progress_layout_color_scheme_colors"
+        ]
+      },
+      "android/support/v7/cardview/R$style": {
+        "androidx/cardview/R$style": [
+          "CardView"
+        ]
+      },
+      "android/support/design/internal/ParcelableSparseArray": {
+        "androidx/design/internal/ParcelableSparseArray": [
+          "CREATOR"
+        ]
+      },
+      "android/support/design/widget/CircularBorderDrawable": {
+        "androidx/design/widget/CircularBorderDrawable": [
+          "DRAW_STROKE_WIDTH_MULTIPLE"
+        ]
+      },
+      "android/support/transition/ObjectAnimatorUtils": {
+        "androidx/transition/ObjectAnimatorUtils": [
+          "IMPL"
+        ]
+      },
+      "android/support/v4/app/ActivityCompat": {
+        "androidx/app/ActivityCompat": [
+          "sDelegate"
+        ]
+      },
+      "android/support/wear/internal/widget/drawer/MultiPageUi": {
+        "androidx/wear/internal/widget/drawer/MultiPageUi": [
+          "TAG"
+        ]
+      },
+      "android/support/transition/ViewOverlayApi14$OverlayViewGroup": {
+        "androidx/transition/ViewOverlayApi14$OverlayViewGroup": [
+          "sInvalidateChildInParentFastMethod"
+        ]
+      },
+      "android/support/v4/text/TextDirectionHeuristicsCompat$TextDirectionHeuristicLocale": {
+        "androidx/text/TextDirectionHeuristicsCompat$TextDirectionHeuristicLocale": [
+          "INSTANCE"
+        ]
+      },
+      "android/support/v7/preference/Preference": {
+        "androidx/preference/Preference": [
+          "DEFAULT_ORDER"
+        ]
+      },
+      "android/support/v4/graphics/drawable/RoundedBitmapDrawable": {
+        "androidx/graphics/drawable/RoundedBitmapDrawable": [
+          "DEFAULT_PAINT_FLAGS"
+        ]
+      },
+      "android/support/design/widget/TabLayout$Tab": {
+        "androidx/design/widget/TabLayout$Tab": [
+          "INVALID_POSITION"
+        ]
+      },
+      "android/support/v7/widget/SnapHelper": {
+        "androidx/widget/SnapHelper": [
+          "MILLISECONDS_PER_INCH"
+        ]
+      },
+      "android/support/v7/widget/AbsActionBarView": {
+        "androidx/widget/AbsActionBarView": [
+          "FADE_DURATION"
+        ]
+      },
+      "android/support/v17/leanback/graphics/FitWidthBitmapDrawable": {
+        "androidx/leanback/graphics/FitWidthBitmapDrawable": [
+          "PROPERTY_VERTICAL_OFFSET"
+        ]
+      },
+      "android/support/v4/media/session/MediaSessionCompat$ResultReceiverWrapper": {
+        "androidx/media/session/MediaSessionCompat$ResultReceiverWrapper": [
+          "CREATOR"
+        ]
+      },
+      "android/support/v7/view/SupportMenuInflater$InflatedOnMenuItemClickListener": {
+        "androidx/view/SupportMenuInflater$InflatedOnMenuItemClickListener": [
+          "PARAM_TYPES"
+        ]
+      },
+      "android/support/v4/widget/EdgeEffectCompat": {
+        "androidx/widget/EdgeEffectCompat": [
+          "IMPL"
+        ]
+      },
+      "android/support/v7/app/MediaRouteDialogFactory": {
+        "androidx/app/MediaRouteDialogFactory": [
+          "sDefault"
+        ]
+      },
+      "android/support/v4/app/Fragment$SavedState": {
+        "androidx/app/Fragment$SavedState": [
+          "CREATOR"
+        ]
+      },
+      "android/support/transition/Styleable$TransitionSet": {
+        "androidx/transition/Styleable$TransitionSet": [
+          "TRANSITION_ORDERING"
+        ]
+      },
+      "android/support/v7/preference/PreferenceGroupAdapter": {
+        "androidx/preference/PreferenceGroupAdapter": [
+          "TAG"
+        ]
+      },
+      "android/support/v7/view/menu/MenuPopupHelper": {
+        "androidx/view/menu/MenuPopupHelper": [
+          "TOUCH_EPICENTER_SIZE_DP"
+        ]
+      },
+      "android/support/v4/app/NotificationCompat$Builder": {
+        "androidx/app/NotificationCompat$Builder": [
+          "MAX_CHARSEQUENCE_LENGTH"
+        ]
+      }
+    }
+  },
+  "proGuardMap": {
+    "rules": {}
+  }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/config/ConfigParserTest.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/config/ConfigParserTest.kt
new file mode 100644
index 0000000..4a03ef3
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/config/ConfigParserTest.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.config
+
+import com.google.common.truth.Truth
+import org.junit.Test
+
+class ConfigParserTest {
+
+    @Test fun parseConfig_validInput() {
+        val confStr =
+                "{\n" +
+                "    restrictToPackagePrefixes: [\"android/support/\"],\n" +
+                "    # Sample comment \n" +
+                "    rules: [\n" +
+                "        {\n" +
+                "            from: \"android/support/v14/preferences/(.*)\",\n" +
+                "            to: \"android/jetpack/prefs/main/{0}\"\n" +
+                "        },\n" +
+                "        {\n" +
+                "            from: \"android/support/v14/preferences/(.*)\",\n" +
+                "            to: \"android/jetpack/prefs/main/{0}\",\n" +
+                "            fieldSelectors: [\"dialog_(.*)\"]\n" +
+                "        }\n" +
+                "    ],\n" +
+                "    pomRules: [\n" +
+                "        {\n" +
+                "            from: {groupId: \"g\", artifactId: \"a\", version: \"1.0\"},\n" +
+                "            to: [\n" +
+                "                {groupId: \"g\", artifactId: \"a\", version: \"2.0\"} \n" +
+                "            ]\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}"
+
+        val config = ConfigParser.parseFromString(confStr)
+
+        Truth.assertThat(config).isNotNull()
+        Truth.assertThat(config!!.restrictToPackagePrefixes[0]).isEqualTo("android/support/")
+        Truth.assertThat(config.rewriteRules.size).isEqualTo(2)
+    }
+}
+
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/map/MapGenerationTest.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/map/MapGenerationTest.kt
new file mode 100644
index 0000000..e7f8570
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/map/MapGenerationTest.kt
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.map
+
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.rules.JavaField
+import android.support.tools.jetifier.core.rules.JavaType
+import android.support.tools.jetifier.core.rules.RewriteRule
+import android.support.tools.jetifier.core.transform.proguard.ProGuardTypesMap
+import com.google.common.truth.Truth
+import org.junit.Test
+
+
+class MapGenerationTest {
+
+    @Test fun fromOneType_toOneType() {
+        ScanTester
+            .testThatRules(
+                RewriteRule("android/support/v7/(.*)", "android/test/{0}")
+            )
+            .withAllowedPrefixes(
+                "android/support/"
+            )
+            .forGivenTypes(
+                JavaType("android/support/v7/pref/Preference")
+            )
+            .mapInto(
+                types = mapOf(
+                    "android/support/v7/pref/Preference" to "android/test/pref/Preference"
+                ),
+                fields = mapOf(
+                )
+            )
+            .andIsComplete()
+    }
+
+    @Test fun fromTwoTypes_toOneType_prefixRespected() {
+        ScanTester
+            .testThatRules(
+                RewriteRule("android/support/v7/(.*)", "android/test/{0}"),
+                RewriteRule("android/support/v14/(.*)", "android/test/{0}")
+            )
+            .withAllowedPrefixes(
+                "android/support/v7/"
+            )
+            .forGivenTypes(
+                JavaType("android/support/v7/pref/Preference"),
+                JavaType("android/support/v14/pref/PreferenceDialog")
+            )
+            .mapInto(
+                types = mapOf(
+                    "android/support/v7/pref/Preference" to "android/test/pref/Preference"
+                ),
+                fields = mapOf(
+                )
+            )
+            .andIsComplete()
+    }
+
+    @Test fun fromTwoTypes_toTwoTypes_distinctRules() {
+        ScanTester
+            .testThatRules(
+                RewriteRule("android/support/v7/(.*)", "android/test/{0}"),
+                RewriteRule("android/support/v14/(.*)", "android/test/{0}")
+            )
+            .withAllowedPrefixes(
+                "android/support/v7/",
+                "android/support/v14/"
+            )
+            .forGivenTypes(
+                JavaType("android/support/v7/pref/Preference"),
+                JavaType("android/support/v14/pref/PreferenceDialog")
+            )
+            .mapInto(
+                types = mapOf(
+                    "android/support/v7/pref/Preference" to "android/test/pref/Preference",
+                    "android/support/v14/pref/PreferenceDialog" to "android/test/pref/PreferenceDialog"
+                ),
+                fields = mapOf(
+                )
+            )
+            .andIsComplete()
+    }
+
+    @Test fun fromTwoTypes_toTwoTypes_respectsOrder() {
+        ScanTester
+            .testThatRules(
+                RewriteRule("android/support/v14/(.*)", "android/test/{0}"),
+                RewriteRule("android/support/(.*)", "android/fallback/{0}")
+            )
+            .withAllowedPrefixes(
+                "android/support/"
+            )
+            .forGivenTypes(
+                JavaType("android/support/v7/pref/Preference"),
+                JavaType("android/support/v14/pref/PreferenceDialog")
+            )
+            .mapInto(
+                types = mapOf(
+                    "android/support/v7/pref/Preference" to "android/fallback/v7/pref/Preference",
+                    "android/support/v14/pref/PreferenceDialog" to "android/test/pref/PreferenceDialog"
+                ),
+                fields = mapOf(
+                )
+            )
+            .andIsComplete()
+    }
+
+    @Test fun mapTwoFields_usingOneTypeRule() {
+        ScanTester
+            .testThatRules(
+                RewriteRule("android/support/v7/(.*)", "android/test/{0}")
+            )
+            .withAllowedPrefixes(
+                "android/support/"
+            )
+            .forGivenFields(
+                JavaField("android/support/v7/pref/Preference", "count"),
+                JavaField("android/support/v7/pref/Preference", "min")
+            )
+            .mapInto(
+                types = mapOf(
+                ),
+                fields = mapOf(
+                    "android/support/v7/pref/Preference" to mapOf(
+                        "android/test/pref/Preference" to listOf(
+                            "count",
+                            "min"
+                        )
+                    )
+                )
+            )
+            .andIsComplete()
+    }
+
+    @Test fun mapFieldInInnerClass_usingOneTypeRule() {
+        ScanTester
+            .testThatRules(
+                RewriteRule("android/support/v7/(.*)", "android/test/{0}")
+            )
+            .withAllowedPrefixes(
+                "android/support/"
+            )
+            .forGivenFields(
+                JavaField("android/support/v7/pref/R\$attr", "border")
+            )
+            .mapInto(
+                types = mapOf(
+                ),
+                fields = mapOf(
+                    "android/support/v7/pref/R\$attr" to mapOf(
+                        "android/test/pref/R\$attr" to listOf(
+                            "border"
+                        )
+                    )
+                )
+            )
+            .andIsComplete()
+    }
+
+    @Test fun mapPrivateFields_shouldIgnore() {
+        ScanTester
+            .testThatRules(
+                RewriteRule("android/support/v7/(.*)", "android/test/{0}")
+            )
+            .withAllowedPrefixes(
+                "android/support/"
+            )
+            .forGivenFields(
+                JavaField("android/support/v7/pref/Preference", "mCount"),
+                JavaField("android/support/v7/pref/Preference", "this$0")
+            )
+            .mapInto(
+                types = mapOf(
+                ),
+                fields = mapOf(
+                )
+            )
+            .andIsComplete()
+    }
+
+    @Test fun mapType_usingFieldSelector_shouldNotApply() {
+        ScanTester
+            .testThatRules(
+                RewriteRule("android/support/v7/(.*)", "android/test/{0}", listOf("count"))
+            )
+            .withAllowedPrefixes(
+                "android/support/"
+            )
+            .forGivenTypes(
+                JavaType("android/support/v7/pref/Preference")
+            )
+            .mapInto(
+                types = mapOf(
+                    "android/support/v7/pref/Preference" to "android/support/v7/pref/Preference"
+                ),
+                fields = mapOf(
+                )
+            )
+            .andIsNotComplete()
+    }
+
+    @Test fun mapField_noApplicableRule() {
+        ScanTester
+            .testThatRules(
+                RewriteRule("android/support/v7/(.*)", "android/test/{0}", listOf("count2"))
+            )
+            .withAllowedPrefixes(
+                "android/support/"
+            )
+            .forGivenFields(
+                JavaField("android/support/v7/pref/Preference", "count")
+            )
+            .mapInto(
+                types = mapOf(
+                ),
+                fields = mapOf(
+                    "android/support/v7/pref/Preference" to mapOf(
+                        "android/support/v7/pref/Preference" to listOf(
+                            "count"
+                        )
+                    )
+                )
+            )
+            .andIsNotComplete()
+    }
+
+    @Test fun mapTwoFields_usingTwoFieldsSelectors() {
+        ScanTester
+            .testThatRules(
+                RewriteRule("android/support/v7/(.*)", "android/test/{0}", listOf("count")),
+                RewriteRule("android/support/v7/(.*)", "android/test2/{0}", listOf("size"))
+            )
+            .withAllowedPrefixes(
+                "android/support/"
+            )
+            .forGivenFields(
+                JavaField("android/support/v7/pref/Preference", "count"),
+                JavaField("android/support/v7/pref/Preference", "size")
+            )
+            .mapInto(
+                types = mapOf(
+                ),
+                fields = mapOf(
+                    "android/support/v7/pref/Preference" to mapOf(
+                        "android/test/pref/Preference" to listOf(
+                            "count"
+                        ),
+                        "android/test2/pref/Preference" to listOf(
+                            "size"
+                        )
+                    )
+                )
+            )
+            .andIsComplete()
+    }
+
+
+    object ScanTester {
+
+        fun testThatRules(vararg rules: RewriteRule) = Step1(rules.toList())
+
+
+        class Step1(val rules: List<RewriteRule>) {
+
+            fun withAllowedPrefixes(vararg prefixes: String) = Step2(rules, prefixes.toList())
+
+
+            class Step2(val rules: List<RewriteRule>, val prefixes: List<String>) {
+
+                private val allTypes: MutableList<JavaType> = mutableListOf()
+                private val allFields: MutableList<JavaField> = mutableListOf()
+                private var wasMapIncomplete = false
+
+
+                fun forGivenTypes(vararg types: JavaType) : Step2 {
+                    allTypes.addAll(types)
+                    return this
+                }
+
+                fun forGivenFields(vararg fields: JavaField) : Step2 {
+                    allFields.addAll(fields)
+                    return this
+                }
+
+                fun mapInto(types: Map<String, String>,
+                            fields: Map<String, Map<String, List<String>>>) : Step2 {
+                    val config = Config(
+                        restrictToPackagePrefixes = prefixes,
+                        rewriteRules = rules,
+                        pomRewriteRules = emptyList(),
+                        typesMap = TypesMap.EMPTY,
+                        proGuardMap = ProGuardTypesMap.EMPTY)
+                    val scanner = MapGeneratorRemapper(config)
+
+                    allTypes.forEach { scanner.rewriteType(it) }
+                    allFields.forEach { scanner.rewriteField(it) }
+
+                    val typesMap = scanner.createTypesMap().toJson()
+                    wasMapIncomplete = scanner.isMapNotComplete
+
+                    Truth.assertThat(typesMap.types).containsExactlyEntriesIn(types)
+                    Truth.assertThat(typesMap.fields).containsExactlyEntriesIn(fields)
+                    return this
+                }
+
+                fun andIsNotComplete() {
+                    Truth.assertThat(wasMapIncomplete).isTrue()
+                }
+
+                fun andIsComplete() {
+                    Truth.assertThat(wasMapIncomplete).isFalse()
+                }
+            }
+
+        }
+
+    }
+}
+
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/RewriteRuleTest.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/RewriteRuleTest.kt
new file mode 100644
index 0000000..ca6288d
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/RewriteRuleTest.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform
+
+import android.support.tools.jetifier.core.rules.JavaField
+import android.support.tools.jetifier.core.rules.JavaType
+import android.support.tools.jetifier.core.rules.RewriteRule
+import com.google.common.truth.Truth
+import org.junit.Test
+
+
+class RewriteRuleTest {
+
+    @Test fun noRegEx_shouldRewrite() {
+        RuleTester
+            .testThatRule("A/B", "A/C")
+            .rewritesType("A/B")
+            .into("A/C")
+    }
+
+    @Test fun noRegEx_underscore_shouldRewrite() {
+        RuleTester
+            .testThatRule("A/B_B", "A/C")
+            .rewritesType("A/B_B")
+            .into("A/C")
+    }
+
+    @Test fun groupRegEx_shouldRewrite() {
+        RuleTester
+            .testThatRule("A/B/(.*)", "A/{0}")
+            .rewritesType("A/B/C/D")
+            .into("A/C/D")
+    }
+
+    @Test fun groupRegEx__innerClass_shouldRewrite() {
+        RuleTester
+            .testThatRule("A/B/(.*)", "A/{0}")
+            .rewritesType("A/B/C\$D")
+            .into("A/C\$D")
+    }
+
+    @Test fun fieldRule_noRegEx_shouldRewrite() {
+        RuleTester
+            .testThatRule("A/B", "A/C")
+            .withFieldSelector("MyField")
+            .rewritesField("A/B", "MyField")
+            .into("A/C", "MyField")
+    }
+
+    @Test fun fieldRule_innerClass_groupRegEx_shouldRewrite() {
+        RuleTester
+            .testThatRule("A/B$(.*)", "A/C\${0}")
+            .rewritesType("A/B\$D")
+            .into("A/C\$D")
+    }
+
+    @Test fun noFieldRule_shouldRewriteEvenWithField() {
+        RuleTester
+            .testThatRule("A/B", "A/C")
+            .rewritesField("A/B", "test")
+            .into("A/C", "test")
+    }
+
+
+    object RuleTester {
+
+        fun testThatRule(from: String, to: String) = RuleTesterStep1(from, to)
+
+        class RuleTesterStep1(val from: String, val to: String) {
+
+            val fieldSelectors: MutableList<String> = mutableListOf()
+
+            fun withFieldSelector(input: String) : RuleTesterStep1 {
+                fieldSelectors.add(input)
+                return this
+            }
+
+            fun rewritesField(inputType: String, inputField: String)
+                    = RuleTesterFinalFieldStep(from, to, inputType, inputField, fieldSelectors)
+
+            fun rewritesType(inputType: String)
+                    = RuleTesterFinalTypeStep(from, to, inputType, fieldSelectors)
+        }
+
+        class RuleTesterFinalFieldStep(val fromType: String,
+                                       val toType: String,
+                                       val inputType: String,
+                                       val inputField: String,
+                                       val fieldSelectors: List<String>) {
+
+            fun into(expectedTypeName: String, expectedFieldName: String) {
+                val fieldRule = RewriteRule(fromType, toType, fieldSelectors)
+                val result = fieldRule.apply(JavaField(inputType, inputField))
+                Truth.assertThat(result).isNotNull()
+
+                Truth.assertThat(result!!.owner.fullName).isEqualTo(expectedTypeName)
+                Truth.assertThat(result.name).isEqualTo(expectedFieldName)
+            }
+
+        }
+
+        class RuleTesterFinalTypeStep(val fromType: String,
+                                      val toType: String,
+                                      val inputType: String,
+                                      val fieldSelectors: List<String>) {
+
+            fun into(expectedResult: String) {
+                val fieldRule = RewriteRule(fromType, toType, fieldSelectors)
+                val result = fieldRule.apply(JavaType(inputType))
+                Truth.assertThat(result).isNotNull()
+
+                Truth.assertThat(result).isNotNull()
+                Truth.assertThat(result!!.fullName).isEqualTo(expectedResult)
+            }
+
+        }
+    }
+
+}
+
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/pom/PomDocumentTest.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/pom/PomDocumentTest.kt
new file mode 100644
index 0000000..d55687f
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/pom/PomDocumentTest.kt
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.pom
+
+import android.support.tools.jetifier.core.archive.ArchiveFile
+import com.google.common.truth.Truth
+import org.junit.Test
+import java.nio.charset.StandardCharsets
+import java.nio.file.Paths
+
+class PomDocumentTest {
+
+    @Test fun pom_noRules_noChange() {
+        testRewriteToTheSame(
+            givenAndExpectedXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>supportArtifact</artifactId>\n" +
+            "      <version>4.0</version>\n" +
+            "      <type>jar</type>\n" +
+            "      <scope>test</scope>\n" +
+            "      <optional>true</optional>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            rules = listOf()
+        )
+    }
+
+    @Test fun pom_oneRule_shouldApply() {
+        testRewrite(
+            givenXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>supportArtifact</artifactId>\n" +
+            "      <version>4.0</version>\n" +
+            "    </dependency>\n" +
+            "    <dependency>\n" +
+            "      <systemPath>test/test</systemPath>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            expectedXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>testGroup</groupId>\n" +
+            "      <artifactId>testArtifact</artifactId>\n" +
+            "      <version>1.0</version>\n" +
+            "    </dependency>\n" +
+            "    <dependency>\n" +
+            "      <systemPath>test/test</systemPath>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            rules = listOf(
+                PomRewriteRule(
+                    PomDependency(
+                        groupId = "supportGroup", artifactId = "supportArtifact",
+                        version =  "4.0"),
+                    listOf(
+                        PomDependency(
+                            groupId = "testGroup", artifactId = "testArtifact",
+                            version = "1.0")
+                    )
+                )
+            )
+        )
+    }
+
+    @Test fun pom_oneRule_shouldSkipTestScopedRule() {
+        testRewriteToTheSame(
+            givenAndExpectedXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>supportArtifact</artifactId>\n" +
+            "      <version>4.0</version>\n" +
+            "      <scope>test</scope>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            rules = listOf(
+                PomRewriteRule(
+                    PomDependency(
+                        groupId = "supportGroup", artifactId = "supportArtifact",
+                        version =  "4.0"),
+                    listOf(
+                        PomDependency(
+                            groupId = "testGroup", artifactId = "testArtifact",
+                            version = "1.0")
+                    )
+                )
+            )
+        )
+    }
+
+    @Test fun pom_oneRule_notApplicable() {
+        testRewriteToTheSame(
+            givenAndExpectedXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>supportArtifact</artifactId>\n" +
+            "      <version>4.0</version>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            rules = listOf(
+                PomRewriteRule(
+                    PomDependency(
+                        groupId = "supportGroup", artifactId = "supportArtifact2",
+                        version =  "4.0"),
+                    listOf(
+                        PomDependency(
+                            groupId = "testGroup", artifactId = "testArtifact",
+                            version = "1.0")
+                    )
+                )
+            )
+        )
+    }
+
+    @Test fun pom_oneRule_appliedForEachType() {
+        testRewrite(
+            givenXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>supportArtifact</artifactId>\n" +
+            "      <version>4.0</version>\n" +
+            "      <type>test</type>\n" +
+            "    </dependency>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>supportArtifact</artifactId>\n" +
+            "      <version>4.0</version>\n" +
+            "      <type>compile</type>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            expectedXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>testGroup</groupId>\n" +
+            "      <artifactId>testArtifact</artifactId>\n" +
+            "      <version>1.0</version>\n" +
+            "      <type>test</type>\n" +
+            "    </dependency>\n" +
+            "    <dependency>\n" +
+            "      <groupId>testGroup</groupId>\n" +
+            "      <artifactId>testArtifact</artifactId>\n" +
+            "      <version>1.0</version>\n" +
+            "      <type>compile</type>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            rules = listOf(
+                PomRewriteRule(
+                    PomDependency(
+                        groupId = "supportGroup", artifactId = "supportArtifact",
+                        version =  "4.0"),
+                    listOf(
+                        PomDependency(
+                            groupId = "testGroup", artifactId = "testArtifact",
+                            version = "1.0")
+                    )
+                )
+            )
+        )
+    }
+
+    @Test fun pom_multipleTargets_shouldApplyAll() {
+        testRewrite(
+            givenXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>supportArtifact</artifactId>\n" +
+            "      <version>4.0</version>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            expectedXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>testGroup</groupId>\n" +
+            "      <artifactId>testArtifact</artifactId>\n" +
+            "      <version>1.0</version>\n" +
+            "    </dependency>\n" +
+            "    <dependency>\n" +
+            "      <groupId>testGroup2</groupId>\n" +
+            "      <artifactId>testArtifact2</artifactId>\n" +
+            "      <version>2.0</version>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            rules = listOf(
+                PomRewriteRule(
+                    PomDependency(
+                        groupId = "supportGroup", artifactId = "supportArtifact",
+                        version =  "4.0"),
+                    listOf(
+                        PomDependency(
+                            groupId = "testGroup", artifactId = "testArtifact",
+                            version = "1.0"),
+                        PomDependency(
+                            groupId = "testGroup2", artifactId = "testArtifact2",
+                            version = "2.0"))
+                )
+            )
+        )
+    }
+
+    @Test fun pom_multipleRulesAndTargets_shouldApplyAll_distinct() {
+        testRewrite(
+            givenXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>supportArtifact</artifactId>\n" +
+            "      <version>4.0</version>\n" +
+            "    </dependency>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>supportArtifact2</artifactId>\n" +
+            "      <version>4.0</version>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            expectedXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>testGroup</groupId>\n" +
+            "      <artifactId>testArtifact</artifactId>\n" +
+            "      <version>1.0</version>\n" +
+            "    </dependency>\n" +
+            "    <dependency>\n" +
+            "      <groupId>testGroup2</groupId>\n" +
+            "      <artifactId>testArtifact2</artifactId>\n" +
+            "      <version>2.0</version>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            rules = listOf(
+                PomRewriteRule(
+                    PomDependency(
+                        groupId = "supportGroup", artifactId = "supportArtifact",
+                        version =  "4.0"),
+                    listOf(
+                        PomDependency(
+                            groupId = "testGroup", artifactId = "testArtifact",
+                            version = "1.0"),
+                        PomDependency(
+                            groupId = "testGroup2", artifactId = "testArtifact2",
+                            version = "2.0")
+                    )
+                ),
+                PomRewriteRule(
+                    PomDependency(
+                        groupId = "supportGroup", artifactId = "supportArtifact2",
+                        version =  "4.0"),
+                    listOf(
+                        PomDependency(
+                            groupId = "testGroup", artifactId = "testArtifact",
+                            version = "1.0"),
+                        PomDependency(
+                            groupId = "testGroup2", artifactId = "testArtifact2",
+                            version = "2.0"))
+                )
+            )
+        )
+    }
+
+    @Test fun pom_oneRule_hasToKeepExtraAttributesAndRewrite() {
+        testRewrite(
+            givenXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>supportArtifact</artifactId>\n" +
+            "      <version>4.0</version>\n" +
+            "      <classifier>hey</classifier>\n" +
+            "      <type>jar</type>\n" +
+            "      <scope>runtime</scope>\n" +
+            "      <systemPath>somePath</systemPath>\n" +
+            "      <optional>true</optional>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            expectedXml =
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>testGroup</groupId>\n" +
+            "      <artifactId>testArtifact</artifactId>\n" +
+            "      <version>1.0</version>\n" +
+            "      <classifier>hey</classifier>\n" +
+            "      <type>jar</type>\n" +
+            "      <scope>runtime</scope>\n" +
+            "      <systemPath>somePath</systemPath>\n" +
+            "      <optional>true</optional>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>",
+            rules = listOf(
+                PomRewriteRule(
+                    PomDependency(
+                        groupId = "supportGroup", artifactId = "supportArtifact",
+                        version =  "4.0"),
+                    listOf(
+                        PomDependency(
+                            groupId = "testGroup", artifactId = "testArtifact",
+                            version = "1.0")
+                    )
+                )
+            )
+        )
+    }
+
+    @Test fun pom_usingEmptyProperties_shouldNotCrash() {
+        val document = loadDocument(
+            "  <properties/>\n" +
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>\${groupId.version.property}</artifactId>\n" +
+            "      <version>\${groupId.version.property}</version>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>"
+        )
+
+        Truth.assertThat(document.dependencies).hasSize(1)
+    }
+
+    @Test fun pom_usingProperties_shouldResolve() {
+        val document = loadDocument(
+            "  <properties>\n" +
+            "    <groupId.version.property>1.0.0</groupId.version.property>\n" +
+            "    <groupId.artifactId.property>supportArtifact</groupId.artifactId.property>\n" +
+            "  </properties>\n" +
+            "  <dependencies>\n" +
+            "    <dependency>\n" +
+            "      <groupId>supportGroup</groupId>\n" +
+            "      <artifactId>\${groupId.artifactId.property}</artifactId>\n" +
+            "      <version>\${groupId.version.property}</version>\n" +
+            "    </dependency>\n" +
+            "  </dependencies>"
+        )
+
+        Truth.assertThat(document.dependencies).hasSize(1)
+
+        val dependency = document.dependencies.first()
+        Truth.assertThat(dependency.version).isEqualTo("1.0.0")
+        Truth.assertThat(dependency.artifactId).isEqualTo("supportArtifact")
+    }
+
+
+    private fun testRewriteToTheSame(givenAndExpectedXml: String, rules: List<PomRewriteRule>) {
+        testRewrite(givenAndExpectedXml, givenAndExpectedXml, rules)
+    }
+
+    private fun testRewrite(givenXml: String, expectedXml : String, rules: List<PomRewriteRule>) {
+        val given =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+            "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
+                "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
+                "xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
+            "  <!-- Some comment -->\n" +
+            "  <groupId>test.group</groupId>\n" +
+            "  <artifactId>test.artifact.id</artifactId>\n" +
+            "  <version>1.0</version>\n" +
+            "  $givenXml\n" +
+            "</project>\n"
+
+        var expected =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+            "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
+                "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
+                "xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
+            "  <!-- Some comment -->\n" +
+            "  <groupId>test.group</groupId>\n" +
+            "  <artifactId>test.artifact.id</artifactId>\n" +
+            "  <version>1.0</version>\n" +
+            "  $expectedXml\n" +
+            "</project>\n"
+
+        val file = ArchiveFile(Paths.get("pom.xml"), given.toByteArray())
+        val pomDocument = PomDocument.loadFrom(file)
+        pomDocument.applyRules(rules)
+        pomDocument.saveBackToFileIfNeeded()
+        var strResult = file.data.toString(StandardCharsets.UTF_8)
+
+        // Remove spaces in front of '<' and the back of '>'
+        expected = expected.replace(">[ ]+".toRegex(), ">")
+        expected = expected.replace("[ ]+<".toRegex(), "<")
+
+        strResult = strResult.replace(">[ ]+".toRegex(), ">")
+        strResult = strResult.replace("[ ]+<".toRegex(), "<")
+
+        // Replace newline characters to match the ones we are using in the expected string
+        strResult = strResult.replace("\\r\\n".toRegex(), "\n")
+
+        Truth.assertThat(strResult).isEqualTo(expected)
+    }
+
+    private fun loadDocument(givenXml : String) : PomDocument {
+        val given =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+            "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
+            "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
+            "xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
+            "  <!-- Some comment -->\n" +
+            "  <groupId>test.group</groupId>\n" +
+            "  <artifactId>test.artifact.id</artifactId>\n" +
+            "  <version>1.0</version>\n" +
+            "  $givenXml\n" +
+            "</project>\n"
+
+        val file = ArchiveFile(Paths.get("pom.xml"), given.toByteArray())
+        val pomDocument = PomDocument.loadFrom(file)
+        return pomDocument
+    }
+}
+
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/pom/PomRewriteRuleTest.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/pom/PomRewriteRuleTest.kt
new file mode 100644
index 0000000..34ebd04
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/pom/PomRewriteRuleTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.pom
+
+import com.google.common.truth.Truth
+import org.junit.Test
+
+class PomRewriteRuleTest {
+
+    @Test fun versions_nullInRule_match() {
+        testVersionsMatch(
+            ruleVersion = null,
+            pomVersion = "27.0.0"
+        )
+    }
+
+    @Test fun versions_nullInPom_match() {
+        testVersionsMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = null
+        )
+    }
+
+    @Test fun versions_nullBoth_match() {
+        testVersionsMatch(
+            ruleVersion = null,
+            pomVersion = null
+        )
+    }
+
+    @Test fun versions_same_match() {
+        testVersionsMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "27.0.0"
+        )
+    }
+
+    @Test fun versions_same_strict_match() {
+        testVersionsMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "[27.0.0]"
+        )
+    }
+
+    @Test fun versions_different_noMatch() {
+        testVersionsDoNotMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "26.0.0"
+        )
+    }
+
+    @Test fun versions_release_match() {
+        testVersionsMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "release"
+        )
+    }
+
+    @Test fun versions_latest_match() {
+        testVersionsMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "latest"
+        )
+    }
+
+    @Test fun versions_range_rightOpen_match() {
+        testVersionsMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "(26.0.0,]"
+        )
+    }
+
+    @Test fun versions_range_rightOpen2_match() {
+        testVersionsMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "(26.0.0,)"
+        )
+    }
+
+    @Test fun versions_range_inclusive_match() {
+        testVersionsMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "[21.0.0,27.0.0]"
+        )
+    }
+
+    @Test fun versions_range_inclusive_noMatch() {
+        testVersionsDoNotMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "[21.0.0,26.0.0]"
+        )
+    }
+
+    @Test fun versions_range_exclusive_noMatch() {
+        testVersionsDoNotMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "[21.0.0,27.0.0)"
+        )
+    }
+
+    @Test fun versions_exclusionRange_match() {
+        testVersionsMatch(
+            ruleVersion = "27.0.0",
+            pomVersion = "(,26.0.0),(26.0.0,)"
+        )
+    }
+
+    private fun testVersionsMatch(ruleVersion: String?, pomVersion: String?) {
+        val from = PomDependency(version = ruleVersion)
+        val pom = PomDependency(version = pomVersion)
+
+        val rule = PomRewriteRule(from, listOf(from))
+
+        Truth.assertThat(rule.validateVersion(pom)).isTrue()
+    }
+
+    private fun testVersionsDoNotMatch(ruleVersion: String?, pomVersion: String?) {
+        val from = PomDependency(version = ruleVersion)
+        val pom = PomDependency(version = pomVersion)
+
+        val rule = PomRewriteRule(from, listOf(from))
+
+        Truth.assertThat(rule.validateVersion(pom)).isFalse()
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassFilterTest.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassFilterTest.kt
new file mode 100644
index 0000000..2c7d7e2
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassFilterTest.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import org.junit.Test
+
+class ClassFilterTest {
+
+    @Test fun proGuard_classFilter() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-adaptclassstrings support.Activity, support.Fragment, keep.Me"
+            )
+            .rewritesTo(
+                "-adaptclassstrings test.Activity, test.Fragment, keep.Me"
+            )
+    }
+
+    @Test fun proGuard_classFilter_newLineIgnored() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-adaptclassstrings support.Activity, support.Fragment, keep.Me \n" +
+                " support.Activity"
+            )
+            .rewritesTo(
+                "-adaptclassstrings test.Activity, test.Fragment, keep.Me \n" +
+                " support.Activity"
+            )
+    }
+
+    @Test fun proGuard_classFilter_spacesRespected() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "  -adaptclassstrings  support.Activity ,  support.Fragment,keep.Me  "
+            )
+            .rewritesTo(
+                "  -adaptclassstrings  test.Activity, test.Fragment, keep.Me"
+            )
+    }
+
+    @Test fun proGuard_classFilter_negation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "  -adaptclassstrings !support.Activity, !support.Fragment, !keep.Me  "
+            )
+            .rewritesTo(
+                "  -adaptclassstrings !test.Activity, !test.Fragment, !keep.Me"
+            )
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest.kt
new file mode 100644
index 0000000..e64590f
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest.kt
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import org.junit.Test
+
+class ClassSpecTest {
+
+    @Test fun proGuard_classSpec_simple() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep class support.Activity"
+            )
+            .rewritesTo(
+                "-keep class test.Activity"
+            )
+    }
+
+    @Test fun proGuard_classSpec_allExistingRules() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep class support.Activity \n" +
+                "-keepclassmembers class support.Activity \n" +
+                "-keepclasseswithmembers class support.Activity \n" +
+                "-keepnames class support.Activity \n" +
+                "-keepclassmembernames class support.Activity \n" +
+                "-keepclasseswithmembernames class support.Activity \n" +
+                "-whyareyoukeeping class support.Activity \n" +
+                "-assumenosideeffects class support.Activity"
+            )
+            .rewritesTo(
+                "-keep class test.Activity \n" +
+                "-keepclassmembers class test.Activity \n" +
+                "-keepclasseswithmembers class test.Activity \n" +
+                "-keepnames class test.Activity \n" +
+                "-keepclassmembernames class test.Activity \n" +
+                "-keepclasseswithmembernames class test.Activity \n" +
+                "-whyareyoukeeping class test.Activity \n" +
+                "-assumenosideeffects class test.Activity"
+            )
+    }
+
+    @Test fun proGuard_classSpec_rulesModifiers() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep includedescriptorclasses class support.Activity \n" +
+                "-keep allowshrinking class support.Activity \n" +
+                "-keep allowoptimization class support.Activity \n" +
+                "-keep allowobfuscation class support.Activity \n" +
+                "-keep allowshrinking allowoptimization allowobfuscation class support.Activity \n" +
+                "-keep allowshrinking   allowoptimization   allowobfuscation  class support.Activity"
+            )
+            .rewritesTo(
+                "-keep includedescriptorclasses class test.Activity \n" +
+                "-keep allowshrinking class test.Activity \n" +
+                "-keep allowoptimization class test.Activity \n" +
+                "-keep allowobfuscation class test.Activity \n" +
+                "-keep allowshrinking allowoptimization allowobfuscation class test.Activity \n" +
+                "-keep allowshrinking   allowoptimization   allowobfuscation  class test.Activity"
+            )
+    }
+
+    @Test fun proGuard_classSpec_extends() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep class * extends support.Activity \n" +
+                "-keep class support.Fragment extends support.Activity"
+            )
+            .rewritesTo(
+                "-keep class * extends test.Activity \n" +
+                "-keep class test.Fragment extends test.Activity"
+            )
+    }
+
+    @Test fun proGuard_classSpec_modifiers_extends() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity"
+            )
+            .testThatGivenProGuard(
+                "-keep !public enum * extends support.Activity \n" +
+                "-keep public !final enum * extends support.Activity"
+            )
+            .rewritesTo(
+                "-keep !public enum * extends test.Activity \n" +
+                "-keep public !final enum * extends test.Activity"
+            )
+    }
+
+    @Test fun proGuard_classSpec_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep @support.Annotation public class support.Activity \n" +
+                "-keep @some.Annotation public class support.Activity"
+            )
+            .rewritesTo(
+                "-keep @test.Annotation public class test.Activity \n" +
+                "-keep @some.Annotation public class test.Activity"
+            )
+    }
+
+    @Test fun proGuard_classSpec_annotation_extends() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep @support.Annotation public class * extends support.Activity\n" +
+                "-keep @some.Annotation !public class * extends support.Activity"
+            )
+            .rewritesTo(
+                "-keep @test.Annotation public class * extends test.Activity\n" +
+                "-keep @some.Annotation !public class * extends test.Activity"
+            )
+    }
+
+    @Test fun proGuard_classSpec_annotation_extends_spaces() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep \t @support.Annotation \t public  class  *  extends support.Activity"
+            )
+            .rewritesTo(
+                "-keep \t @test.Annotation \t public  class  *  extends test.Activity"
+            )
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_FieldTypeSelector.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_FieldTypeSelector.kt
new file mode 100644
index 0000000..2832385
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_FieldTypeSelector.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import org.junit.Test
+
+class ClassSpecTest_FieldTypeSelector {
+
+    @Test fun proGuard_fieldTypeSelector() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  support.Activity height; \n" +
+                "  support.Fragment *; \n" +
+                "  keep.Me width; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  test.Activity height; \n" +
+                "  test.Fragment *; \n" +
+                "  keep.Me width; \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_fieldTypeSelector_modifiers() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  public support.Fragment height; \n" +
+                "  !public !static support.Fragment height; \n" +
+                "  !protected support.Fragment height; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  public test.Fragment height; \n" +
+                "  !public !static test.Fragment height; \n" +
+                "  !protected test.Fragment height; \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_fieldTypeSelector_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation support.Fragment height; \n" +
+                "  @some.Annotation support.Fragment height; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation test.Fragment height; \n" +
+                "  @some.Annotation test.Fragment height; \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_fieldTypeSelector_modifiers_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation public support.Fragment height; \n" +
+                "  @support.Annotation !public !static support.Fragment height; \n" +
+                "  @support.Annotation !protected volatile support.Fragment height; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation public test.Fragment height; \n" +
+                "  @test.Annotation !public !static test.Fragment height; \n" +
+                "  @test.Annotation !protected volatile test.Fragment height; \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_fieldTypeSelector_modifiers_annotation_spaces() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation  public  static \t support.Fragment  height ; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation  public  static \t test.Fragment  height ; \n" +
+                "}"
+            )
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_FieldsSelector.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_FieldsSelector.kt
new file mode 100644
index 0000000..6f6a1f9
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_FieldsSelector.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import org.junit.Test
+
+class ClassSpecTest_FieldsSelector {
+
+    @Test fun proGuard_fieldsSelector_minimal() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * extends support.Activity { \n" +
+                "  <fields>; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * extends test.Activity { \n" +
+                "  <fields>; \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_fieldsSelector_modifiers() {
+        ProGuardTester
+            .forGivenPrefixes(
+            )
+            .forGivenTypesMap(
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  public <fields>; \n" +
+                "  public static <fields>; \n" +
+                "  !private !protected <fields>; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  public <fields>; \n" +
+                "  public static <fields>; \n" +
+                "  !private !protected <fields>; \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_fieldsSelector_modifiers_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation public <fields>; \n" +
+                "  @support.Annotation public static <fields>; \n" +
+                "  @support.Annotation !private !protected <fields>; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation public <fields>; \n" +
+                "  @test.Annotation public static <fields>; \n" +
+                "  @test.Annotation !private !protected <fields>; \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_fieldsSelector_modifiers_annotation_spaces() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation  public \t  <fields> ; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation  public \t  <fields> ; \n" +
+                "}"
+            )
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_MethodInitSelector.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_MethodInitSelector.kt
new file mode 100644
index 0000000..9a792cf
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_MethodInitSelector.kt
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import org.junit.Test
+
+class ClassSpecTest_MethodInitSelector {
+
+    @Test fun proGuard_methodsInitSelector() {
+        ProGuardTester
+            .forGivenPrefixes(
+            )
+            .forGivenTypesMap(
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  <methods>; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  <methods>; \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodsInitSelector_modifiers() {
+        ProGuardTester
+            .forGivenPrefixes(
+            )
+            .forGivenTypesMap(
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  public <methods>; \n" +
+                "  public static <methods>; \n" +
+                "  public !static <methods>; \n" +
+                "  !private static <methods>; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  public <methods>; \n" +
+                "  public static <methods>; \n" +
+                "  public !static <methods>; \n" +
+                "  !private static <methods>; \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodsInitSelector_modifiers_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation public <methods>; \n" +
+                "  @support.Annotation public static <methods>; \n" +
+                "  @support.Annotation public !static <methods>; \n" +
+                "  @support.Annotation !private static <methods>; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation public <methods>; \n" +
+                "  @test.Annotation public static <methods>; \n" +
+                "  @test.Annotation public !static <methods>; \n" +
+                "  @test.Annotation !private static <methods>; \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodInitSelector() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  <init>(); \n" +
+                "  <init>(*); \n" +
+                "  <init>(...); \n" +
+                "  <init>(support.Activity); \n" +
+                "  <init>(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  <init>(); \n" +
+                "  <init>(*); \n" +
+                "  <init>(...); \n" +
+                "  <init>(test.Activity); \n" +
+                "  <init>(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodInitSelector_modifiers() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  public <init>(); \n" +
+                "  public static <init>(*); \n" +
+                "  !public !static <init>(...); \n" +
+                "  !private static <init>(support.Activity); \n" +
+                "  public !abstract <init>(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  public <init>(); \n" +
+                "  public static <init>(*); \n" +
+                "  !public !static <init>(...); \n" +
+                "  !private static <init>(test.Activity); \n" +
+                "  public !abstract <init>(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodInitSelector_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation <init>(); \n" +
+                "  @support.Annotation <init>(*); \n" +
+                "  @support.Annotation <init>(...); \n" +
+                "  @keep.Me <init>(support.Activity); \n" +
+                "  @support.Annotation <init>(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation <init>(); \n" +
+                "  @test.Annotation <init>(*); \n" +
+                "  @test.Annotation <init>(...); \n" +
+                "  @keep.Me <init>(test.Activity); \n" +
+                "  @test.Annotation <init>(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodInitSelector_modifiers_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation public <init>(); \n" +
+                "  @support.Annotation public static <init>(*); \n" +
+                "  @support.Annotation !public !static <init>(...); \n" +
+                "  @support.Annotation !private static <init>(support.Activity); \n" +
+                "  @support.Annotation public !abstract <init>(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation public <init>(); \n" +
+                "  @test.Annotation public static <init>(*); \n" +
+                "  @test.Annotation !public !static <init>(...); \n" +
+                "  @test.Annotation !private static <init>(test.Activity); \n" +
+                "  @test.Annotation public !abstract <init>(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodInitSelector_modifiers_annotation_test() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation  public  !abstract \t <init> ( support.Activity , support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation  public  !abstract \t <init> (test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_MethodSelectorWithReturnType.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_MethodSelectorWithReturnType.kt
new file mode 100644
index 0000000..d9960b4
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_MethodSelectorWithReturnType.kt
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import org.junit.Test
+
+class ClassSpecTest_MethodSelectorWithReturnType {
+
+    @Test fun proGuard_methodReturnTypeSelector() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  void get*(); \n" +
+                "  void get*(...); \n" +
+                "  void get*(*); \n" +
+                "  void get*(support.Activity); \n" +
+                "  void get?(support.Activity); \n" +
+                "  void get(support.Activity); \n" +
+                "  void *(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  void get*(); \n" +
+                "  void get*(...); \n" +
+                "  void get*(*); \n" +
+                "  void get*(test.Activity); \n" +
+                "  void get?(test.Activity); \n" +
+                "  void get(test.Activity); \n" +
+                "  void *(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodReturnTypeSelector_voidResult() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  void get(); \n" +
+                "  void get(...); \n" +
+                "  void get(*); \n" +
+                "  void get(support.Activity); \n" +
+                "  void get(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  void get(); \n" +
+                "  void get(...); \n" +
+                "  void get(*); \n" +
+                "  void get(test.Activity); \n" +
+                "  void get(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodReturnTypeSelector_starResult() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  * get(); \n" +
+                "  * get(...); \n" +
+                "  * get(*); \n" +
+                "  * get(support.Activity); \n" +
+                "  * get(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  * get(); \n" +
+                "  * get(...); \n" +
+                "  * get(*); \n" +
+                "  * get(test.Activity); \n" +
+                "  * get(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodReturnTypeSelector_typeResult() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  support.Fragment get(); \n" +
+                "  support.Fragment get(...); \n" +
+                "  support.Fragment get(*); \n" +
+                "  support.Fragment get(support.Activity); \n" +
+                "  support.Fragment get(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  test.Fragment get(); \n" +
+                "  test.Fragment get(...); \n" +
+                "  test.Fragment get(*); \n" +
+                "  test.Fragment get(test.Activity); \n" +
+                "  test.Fragment get(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodReturnTypeSelector_typeResult_wildcards() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  support.Fragment get*(); \n" +
+                "  support.Fragment get?(...); \n" +
+                "  support.Fragment *(*); \n" +
+                "  support.Fragment *(support.Activity); \n" +
+                "  support.Fragment *(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  test.Fragment get*(); \n" +
+                "  test.Fragment get?(...); \n" +
+                "  test.Fragment *(*); \n" +
+                "  test.Fragment *(test.Activity); \n" +
+                "  test.Fragment *(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodReturnTypeSelector_typeResult_modifiers() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  public support.Fragment get(); \n" +
+                "  public static support.Fragment get(...); \n" +
+                "  !public !static support.Fragment get(*); \n" +
+                "  private support.Fragment get(support.Activity); \n" +
+                "  public abstract support.Fragment get(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  public test.Fragment get(); \n" +
+                "  public static test.Fragment get(...); \n" +
+                "  !public !static test.Fragment get(*); \n" +
+                "  private test.Fragment get(test.Activity); \n" +
+                "  public abstract test.Fragment get(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodReturnTypeSelector_typeResult_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation support.Fragment get(); \n" +
+                "  @support.Annotation support.Fragment get(...); \n" +
+                "  @support.Annotation support.Fragment get(*); \n" +
+                "  @keep.Me support.Fragment get(support.Activity); \n" +
+                "  @support.Annotation support.Fragment get(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation test.Fragment get(); \n" +
+                "  @test.Annotation test.Fragment get(...); \n" +
+                "  @test.Annotation test.Fragment get(*); \n" +
+                "  @keep.Me test.Fragment get(test.Activity); \n" +
+                "  @test.Annotation test.Fragment get(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodReturnTypeSelector_typeResult_modifiers_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation public support.Fragment get(); \n" +
+                "  @support.Annotation public static support.Fragment get(...); \n" +
+                "  @support.Annotation !public !static support.Fragment get(*); \n" +
+                "  @support.Annotation private support.Fragment get(support.Activity); \n" +
+                "  @support.Annotation public abstract support.Fragment get(support.Activity, support.Fragment,  keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation public test.Fragment get(); \n" +
+                "  @test.Annotation public static test.Fragment get(...); \n" +
+                "  @test.Annotation !public !static test.Fragment get(*); \n" +
+                "  @test.Annotation private test.Fragment get(test.Activity); \n" +
+                "  @test.Annotation public abstract test.Fragment get(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_methodReturnTypeSelector_typeResult_modifiers_annotation_spaces() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation  support.Fragment \t get(support.Activity ,  support.Fragment ,  keep.Please) ; \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation  test.Fragment \t get(test.Activity, test.Fragment, keep.Please) ; \n" +
+                "}"
+            )
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_NamedCtorSelector.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_NamedCtorSelector.kt
new file mode 100644
index 0000000..21b8b8c
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ClassSpecTest_NamedCtorSelector.kt
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import org.junit.Test
+
+class ClassSpecTest_NamedCtorSelector {
+
+    @Test fun proGuard_ctorSelector() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  support.Activity(); \n" +
+                "  support.Activity(...); \n" +
+                "  support.Activity(*); \n" +
+                "  support.Activity(support.Activity); \n" +
+                "  support.Activity(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  test.Activity(); \n" +
+                "  test.Activity(...); \n" +
+                "  test.Activity(*); \n" +
+                "  test.Activity(test.Activity); \n" +
+                "  test.Activity(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_ctorSelector_modifiers() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  public support.Activity(); \n" +
+                "  public static support.Activity(...); \n" +
+                "  !private support.Activity(*); \n" +
+                "  !public !static support.Activity(support.Activity); \n" +
+                "  !protected support.Activity(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  public test.Activity(); \n" +
+                "  public static test.Activity(...); \n" +
+                "  !private test.Activity(*); \n" +
+                "  !public !static test.Activity(test.Activity); \n" +
+                "  !protected test.Activity(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_ctorSelector_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation support.Activity(); \n" +
+                "  @support.Annotation support.Activity(...); \n" +
+                "  @support.Annotation support.Activity(*); \n" +
+                "  @support.Annotation support.Activity(support.Activity); \n" +
+                "  @support.Annotation support.Activity(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation test.Activity(); \n" +
+                "  @test.Annotation test.Activity(...); \n" +
+                "  @test.Annotation test.Activity(*); \n" +
+                "  @test.Annotation test.Activity(test.Activity); \n" +
+                "  @test.Annotation test.Activity(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_ctorSelector_modifiers_annotation() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation public support.Activity(); \n" +
+                "  @support.Annotation public static support.Activity(...); \n" +
+                "  @support.Annotation !private support.Activity(*); \n" +
+                "  @support.Annotation !public !static support.Activity(support.Activity); \n" +
+                "  @support.Annotation !protected support.Activity(support.Activity, support.Fragment, keep.Please); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation public test.Activity(); \n" +
+                "  @test.Annotation public static test.Activity(...); \n" +
+                "  @test.Annotation !private test.Activity(*); \n" +
+                "  @test.Annotation !public !static test.Activity(test.Activity); \n" +
+                "  @test.Annotation !protected test.Activity(test.Activity, test.Fragment, keep.Please); \n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_ctorSelector_modifiers_annotation_spaces() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * { \n" +
+                "  @support.Annotation  !protected \t support.Activity( support.Activity ); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * { \n" +
+                "  @test.Annotation  !protected \t test.Activity(test.Activity); \n" +
+                "}"
+            )
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTester.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTester.kt
new file mode 100644
index 0000000..cae21d0
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTester.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import android.support.tools.jetifier.core.archive.ArchiveFile
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.map.TypesMap
+import android.support.tools.jetifier.core.rules.JavaType
+import android.support.tools.jetifier.core.transform.TransformationContext
+import com.google.common.truth.Truth
+import java.nio.charset.StandardCharsets
+import java.nio.file.Paths
+
+
+/**
+ * Helper to test ProGuard rewriting logic using lightweight syntax.
+ */
+object ProGuardTester {
+
+    private var javaTypes = emptyList<Pair<String, String>>()
+    private var proGuardTypes = emptyList<Pair<ProGuardType, ProGuardType>>()
+    private var prefixes = emptyList<String>()
+
+    fun forGivenPrefixes(vararg prefixes: String) : ProGuardTester {
+        this.prefixes = prefixes.toList()
+        return this
+    }
+
+    fun forGivenTypesMap(vararg rules: Pair<String, String>) : ProGuardTester {
+        this.javaTypes = rules.toList()
+        return this
+    }
+
+    fun forGivenProGuardMap(vararg rules: Pair<String, String>) : ProGuardTester {
+        this.proGuardTypes = rules.map {
+            ProGuardType.fromDotNotation(it.first) to ProGuardType.fromDotNotation(it.second) }
+            .toList()
+        return this
+    }
+
+    fun testThatGivenType(givenType: String) : ProGuardTesterForType {
+        return ProGuardTesterForType(createConfig(), givenType)
+    }
+
+    fun testThatGivenArguments(givenArgs: String) : ProGuardTesterForArgs {
+        return ProGuardTesterForArgs(createConfig(), givenArgs)
+    }
+
+    fun testThatGivenProGuard(given: String) : ProGuardTesterForFile {
+        return ProGuardTesterForFile(createConfig(), given)
+    }
+
+    private fun createConfig() : Config {
+        return Config(
+            restrictToPackagePrefixes = prefixes,
+            rewriteRules = emptyList(),
+            pomRewriteRules =  emptyList(),
+            typesMap = TypesMap(
+                types = javaTypes.map { JavaType(it.first) to JavaType(it.second) }.toMap(),
+                fields = emptyMap()),
+            proGuardMap = ProGuardTypesMap(proGuardTypes.toMap()))
+    }
+
+
+    class ProGuardTesterForFile(private val config: Config, private val given: String) {
+
+        fun rewritesTo(expected: String) {
+            val context = TransformationContext(config)
+            val transformer = ProGuardTransformer(context)
+            val file = ArchiveFile(Paths.get("proguard.txt"), given.toByteArray())
+            transformer.runTransform(file)
+
+            val result = file.data.toString(StandardCharsets.UTF_8)
+
+            Truth.assertThat(result).isEqualTo(expected)
+        }
+
+    }
+
+    class ProGuardTesterForType(private val config: Config, private val given: String) {
+
+        fun getsRewrittenTo(expectedType: String) {
+            val context = TransformationContext(config)
+            val mapper = ProGuardTypesMapper(context)
+            val result = mapper.replaceType(given)
+
+            Truth.assertThat(result).isEqualTo(expectedType)
+        }
+
+    }
+
+    class ProGuardTesterForArgs(private val config: Config, private val given: String) {
+
+        fun getRewrittenTo(expectedArguments: String) {
+            val context = TransformationContext(config)
+            val mapper = ProGuardTypesMapper(context)
+            val result = mapper.replaceMethodArgs(given)
+
+            Truth.assertThat(result).isEqualTo(expectedArguments)
+        }
+    }
+
+}
+
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTypesMapperTest.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTypesMapperTest.kt
new file mode 100644
index 0000000..5e12aff
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ProGuardTypesMapperTest.kt
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import org.junit.Test
+
+class ProGuardTypesMapperTest {
+
+    @Test fun proGuard_typeMapper_wildcard_simple() {
+        ProGuardTester
+            .testThatGivenType("*")
+            .getsRewrittenTo("*")
+    }
+
+    @Test fun proGuard_typeMapper_wildcard_double() {
+        ProGuardTester
+            .testThatGivenType("**")
+            .getsRewrittenTo("**")
+    }
+
+    @Test fun proGuard_typeMapper_wildcard_composed() {
+        ProGuardTester
+            .testThatGivenType("**/*")
+            .getsRewrittenTo("**/*")
+    }
+
+    @Test fun proGuard_typeMapper_wildcard_viaMap() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenProGuardMap(
+                "support/v7/*" to "test/v7/*"
+            )
+            .testThatGivenType("support.v7.*")
+            .getsRewrittenTo("test.v7.*")
+    }
+
+    @Test fun proGuard_typeMapper_wildcard_viaMap2() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenProGuardMap(
+                "support/v7/**" to "test/v7/**"
+            )
+            .testThatGivenType("support.v7.**")
+            .getsRewrittenTo("test.v7.**")
+    }
+
+    @Test fun proGuard_typeMapper_wildcard_viaTypesMap() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/v7/Activity" to "test/v7/Activity"
+            )
+            .testThatGivenType("support.v7.Activity")
+            .getsRewrittenTo("test.v7.Activity")
+    }
+
+    @Test fun proGuard_typeMapper_wildcard_notFoundInMap() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenProGuardMap(
+                "support/**" to "test/**"
+            )
+            .testThatGivenType("keep.me.**")
+            .getsRewrittenTo("keep.me.**")
+    }
+
+    @Test fun proGuard_typeMapper_differentPrefix_notRewritten() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "hello/Activity" to "test/Activity"
+            )
+            .testThatGivenType("hello.Activity")
+            .getsRewrittenTo("hello.Activity")
+    }
+
+    @Test fun proGuard_typeMapper_differentPrefix_wildcard_getsRewritten() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenProGuardMap(
+                "hello/**" to "test/**"
+            )
+            .testThatGivenType("hello.**")
+            .getsRewrittenTo("test.**")
+    }
+
+    @Test fun proGuard_typeMapper_innerClass() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity\$InnerClass" to "test/Activity\$InnerClass"
+            )
+            .testThatGivenType("support.Activity\$InnerClass")
+            .getsRewrittenTo("test.Activity\$InnerClass")
+    }
+
+    @Test fun proGuard_typeMapper_innerClass_wildcard() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenProGuardMap(
+                "**R\$Attrs" to "**R2\$Attrs"
+            )
+            .testThatGivenType("**R\$Attrs")
+            .getsRewrittenTo("**R2\$Attrs")
+    }
+
+    @Test fun proGuard_argsMapper_tripleDots() {
+        ProGuardTester
+            .testThatGivenArguments("...")
+            .getRewrittenTo("...")
+    }
+
+    @Test fun proGuard_argsMapper_wildcard() {
+        ProGuardTester
+            .testThatGivenArguments("*")
+            .getRewrittenTo("*")
+    }
+
+    @Test fun proGuard_argsMapper_wildcards() {
+        ProGuardTester
+            .testThatGivenArguments("**, **")
+            .getRewrittenTo("**, **")
+    }
+
+    @Test fun proGuard_argsMapper_viaMaps() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity"
+            )
+            .forGivenProGuardMap(
+                "support/v7/**" to "test/v7/**"
+            )
+            .testThatGivenArguments("support.Activity, support.v7.**, keep.Me")
+            .getRewrittenTo("test.Activity, test.v7.**, keep.Me")
+    }
+
+    @Test fun proGuard_argsMapper_viaMaps_spaces() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity"
+            )
+            .forGivenProGuardMap(
+                "support/v7/**" to "test/v7/**"
+            )
+            .testThatGivenArguments(" support.Activity , \t support.v7.**,  keep.Me ")
+            .getRewrittenTo("test.Activity, test.v7.**, keep.Me")
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ProguardSamplesTest.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ProguardSamplesTest.kt
new file mode 100644
index 0000000..0542e7d
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/proguard/ProguardSamplesTest.kt
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.proguard
+
+import org.junit.Test
+
+class ProguardSamplesTest {
+
+    @Test fun proGuard_sample() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "android/app/",
+                "android/view/",
+                "android/content/",
+                "android/os/",
+                "android/webkit/"
+            )
+            .forGivenTypesMap(
+                "android/app/Activity" to "test/app/Activity",
+                "android/app/Application" to "test/app/Application",
+                "android/view/View" to "test/view/View",
+                "android/view/MenuItem" to "test/view/MenuItem",
+                "android/content/Context" to "test/content/Context",
+                "android/os/Parcelable" to "test/os/Parcelable",
+                "android/webkit/JavascriptInterface" to "test/webkit/JavascriptInterface"
+            )
+            .testThatGivenProGuard(
+               "-injars      bin/classes \n" +
+               "-injars      libs \n" +
+               "-outjars     bin/classes-processed.jar \n" +
+               "-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar \n" +
+               "\n" +
+               "-dontpreverify \n" +
+               "-repackageclasses '' \n" +
+               "-allowaccessmodification \n" +
+               "-optimizations !code/simplification/arithmetic \n" +
+               "-keepattributes *Annotation* \n" +
+               "\n" +
+               "-keep public class * extends android.app.Activity \n" +
+               "-keep public class * extends android.app.Application \n" +
+               " \n" +
+               "-keep public class * extends android.view.View { \n" +
+               "      public <init>(android.content.Context); \n" +
+               "      public <init>(android.content.Context, android.util.AttributeSet); \n" +
+               "      public <init>(android.content.Context, android.util.AttributeSet, int); \n" +
+               "      public void set*(...); \n" +
+               "} \n" +
+               "\n" +
+               "-keepclasseswithmembers class * { \n" +
+               "    public <init>(android.content.Context, android.util.AttributeSet); \n" +
+               "} \n" +
+               "\n" +
+               "-keepclasseswithmembers class * { \n" +
+               "    public <init>(android.content.Context, android.util.AttributeSet, int); \n" +
+               "} \n" +
+               "\n" +
+               "-keepclassmembers class * extends android.content.Context { \n" +
+               "    public void *(android.view.View); \n" +
+               "    public void *(android.view.MenuItem); \n" +
+               "} \n" +
+               "\n" +
+               "-keepclassmembers class * implements android.os.Parcelable { \n" +
+               "    static ** CREATOR; \n" +
+               "} \n" +
+               "\n" +
+               "-keepclassmembers class **.R\$* { \n" +
+               "    public static <fields>; \n" +
+               "} \n" +
+               "\n" +
+               "-keepclassmembers class * { \n" +
+               "    @android.webkit.JavascriptInterface <methods>; \n" +
+               "} "
+            )
+            .rewritesTo(
+                "-injars      bin/classes \n" +
+                "-injars      libs \n" +
+                "-outjars     bin/classes-processed.jar \n" +
+                "-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar \n" +
+                "\n" +
+                "-dontpreverify \n" +
+                "-repackageclasses '' \n" +
+                "-allowaccessmodification \n" +
+                "-optimizations !code/simplification/arithmetic \n" +
+                "-keepattributes *Annotation* \n" +
+                "\n" +
+                "-keep public class * extends test.app.Activity \n" +
+                "-keep public class * extends test.app.Application \n" +
+                " \n" +
+                "-keep public class * extends test.view.View { \n" +
+                "      public <init>(test.content.Context); \n" +
+                "      public <init>(test.content.Context, android.util.AttributeSet); \n" +
+                "      public <init>(test.content.Context, android.util.AttributeSet, int); \n" +
+                "      public void set*(...); \n" +
+                "} \n" +
+                "\n" +
+                "-keepclasseswithmembers class * { \n" +
+                "    public <init>(test.content.Context, android.util.AttributeSet); \n" +
+                "} \n" +
+                "\n" +
+                "-keepclasseswithmembers class * { \n" +
+                "    public <init>(test.content.Context, android.util.AttributeSet, int); \n" +
+                "} \n" +
+                "\n" +
+                "-keepclassmembers class * extends test.content.Context { \n" +
+                "    public void *(test.view.View); \n" +
+                "    public void *(test.view.MenuItem); \n" +
+                "} \n" +
+                "\n" +
+                "-keepclassmembers class * implements test.os.Parcelable { \n" +
+                "    static ** CREATOR; \n" +
+                "} \n" +
+                "\n" +
+                "-keepclassmembers class **.R\$* { \n" +
+                "    public static <fields>; \n" +
+                "} \n" +
+                "\n" +
+                "-keepclassmembers class * { \n" +
+                "    @test.webkit.JavascriptInterface <methods>; \n" +
+                "} "
+            )
+    }
+
+    @Test fun proGuard_sample2() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "android/support/v7/"
+            )
+            .forGivenTypesMap(
+                "android/support/v7/preference/Preference" to "test/Preference"
+            )
+            .testThatGivenProGuard(
+                "-keep public class android.support.v7.preference.Preference {\n" +
+                "  public <init>(android.content.Context, android.util.AttributeSet);\n" +
+                "}\n" +
+                "-keep public class * extends android.support.v7.preference.Preference {\n" +
+                "  public <init>(android.content.Context, android.util.AttributeSet);\n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class test.Preference {\n" +
+                "  public <init>(android.content.Context, android.util.AttributeSet);\n" +
+                "}\n" +
+                "-keep public class * extends test.Preference {\n" +
+                "  public <init>(android.content.Context, android.util.AttributeSet);\n" +
+                "}"
+            )
+    }
+
+    @Test fun proGuard_sample3() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "android/support/design/",
+                "android/support/v7/"
+            )
+            .forGivenTypesMap(
+                "support/Fragment" to "test/Fragment",
+                "android/support/v7/widget/RoundRectDrawable" to "test/RoundRectDrawable"
+            )
+            .forGivenProGuardMap(
+                "android/support/design.**" to "test/design.**",
+                "android/support/design/R\$*" to "test/design/R\$*"
+            )
+            .testThatGivenProGuard(
+                "-dontwarn android.support.design.**\n" +
+                "-keep class android.support.design.** { *; }\n" +
+                "-keep interface android.support.design.** { *; }\n" +
+                "-keep public class android.support.design.R\$* { *; }\n" +
+                "-keep class android.support.v7.widget.RoundRectDrawable { *; }"
+            )
+            .rewritesTo(
+                "-dontwarn test.design.**\n" +
+                "-keep class test.design.** { *; }\n" +
+                "-keep interface test.design.** { *; }\n" +
+                "-keep public class test.design.R\$* { *; }\n" +
+                "-keep class test.RoundRectDrawable { *; }"
+            )
+    }
+
+    @Test fun proGuard_sample4() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "android/support/design/",
+                "android/support/v7/",
+                "android/support/v4/"
+            )
+            .forGivenTypesMap(
+                "android/support/v7/widget/LinearLayoutManager" to "test/LinearLayoutManager",
+                "android/support/v4/view/ActionProvider" to "test/ActionProvider"
+            )
+            .forGivenProGuardMap(
+                "android/support/v7/**" to "test/v7/**",
+                "android/support/v7/widget/**" to "test/v7/widget/**",
+                "android/support/v7/internal/widget/**" to "test/v7/internal/widget/**",
+                "android/support/v7/internal/**" to "test/v7/internal/**"
+            )
+            .testThatGivenProGuard(
+                "-dontwarn android.support.v7.**\n" +
+                "-keep public class android.support.v7.widget.** { *; }\n" +
+                "-keep public class android.support.v7.internal.widget.** { *; }\n" +
+                "-keep class android.support.v7.widget.LinearLayoutManager { *; }\n" +
+                "-keep class android.support.v7.internal.** { *; }\n" +
+                "-keep interface android.support.v7.internal.** { *; }\n" +
+                "\n" +
+                "-keep class android.support.v7.** { *; }\n" +
+                "-keep interface android.support.v7.** { *; }\n" +
+                "\n" +
+                "-keep public class * extends android.support.v4.view.ActionProvider {\n" +
+                "    public <init>(android.content.Context);"
+            )
+            .rewritesTo(
+                "-dontwarn test.v7.**\n" +
+                "-keep public class test.v7.widget.** { *; }\n" +
+                "-keep public class test.v7.internal.widget.** { *; }\n" +
+                "-keep class test.LinearLayoutManager { *; }\n" +
+                "-keep class test.v7.internal.** { *; }\n" +
+                "-keep interface test.v7.internal.** { *; }\n" +
+                "\n" +
+                "-keep class test.v7.** { *; }\n" +
+                "-keep interface test.v7.** { *; }\n" +
+                "\n" +
+                "-keep public class * extends test.ActionProvider {\n" +
+                "    public <init>(android.content.Context);"
+            )
+    }
+
+    @Test fun proGuard_sample5() {
+        ProGuardTester
+            .forGivenPrefixes(
+                "support/"
+            )
+            .forGivenTypesMap(
+                "support/Activity" to "test/Activity",
+                "support/Fragment" to "test/Fragment",
+                "support/Annotation" to "test/Annotation"
+            )
+            .testThatGivenProGuard(
+                "-keep public class * extends support.Activity { \n" +
+                "  public static <fields>; \n" +
+                "  public !static <methods>; \n" +
+                "  public support.Fragment height; \n" +
+                "  public static <fields>; \n" +
+                "  public not.related.Type width; public support.Fragment width; \n" +
+                "  ignoreMe; \n" +
+                "  @support.Annotation public support.Fragment get(); \n" +
+                "}"
+            )
+            .rewritesTo(
+                "-keep public class * extends test.Activity { \n" +
+                "  public static <fields>; \n" +
+                "  public !static <methods>; \n" +
+                "  public test.Fragment height; \n" +
+                "  public static <fields>; \n" +
+                "  public not.related.Type width; public test.Fragment width; \n" +
+                "  ignoreMe; \n" +
+                "  @test.Annotation public test.Fragment get(); \n" +
+                "}"
+            )
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/resource/XmlResourcesTransformerTest.kt b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/resource/XmlResourcesTransformerTest.kt
new file mode 100644
index 0000000..5788b40
--- /dev/null
+++ b/jetifier/jetifier/core/src/test/kotlin/android/support/tools/jetifier/core/transform/resource/XmlResourcesTransformerTest.kt
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.core.transform.resource
+
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.rules.JavaType
+import android.support.tools.jetifier.core.map.TypesMap
+import android.support.tools.jetifier.core.transform.TransformationContext
+import android.support.tools.jetifier.core.transform.proguard.ProGuardTypesMap
+import com.google.common.truth.Truth
+import org.junit.Test
+import java.nio.charset.Charset
+
+class XmlResourcesTransformerTest {
+
+    @Test fun layout_noPrefix_noChange() {
+        testRewriteToTheSame(
+            givenAndExpectedXml =
+                "<android.support.v7.preference.Preference>\n" +
+                "</android.support.v7.preference.Preference>",
+            prefixes = listOf(),
+            map = mapOf(
+                "android/support/v7/preference/Preference" to "android/test/pref/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_noRule_noChange() {
+        testRewriteToTheSame(
+            givenAndExpectedXml =
+                "<android.support.v7.preference.Preference>\n" +
+                "</android.support.v7.preference.Preference>",
+            prefixes = listOf("android/support/v7/"),
+            map = mapOf()
+        )
+    }
+
+    @Test fun layout_notApplicablePrefix_noChange() {
+        testRewriteToTheSame(
+            givenAndExpectedXml =
+                "<android.support.v7.preference.Preference>\n" +
+                "</android.support.v7.preference.Preference>",
+            prefixes = listOf("android/support/v14/"),
+            map = mapOf(
+                "android/support/v7/preference/Preference" to "android/test/pref/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_notApplicablePrefix2_noChange() {
+        testRewriteToTheSame(
+            givenAndExpectedXml =
+                "<my.android.support.v7.preference.Preference>\n" +
+                "</my.android.support.v7.preference.Preference>",
+            prefixes = listOf("android/support/v7/"),
+            map = mapOf(
+                "android/support/v7/preference/Preference" to "android/test/pref/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_notApplicableRule_noChange() {
+        testRewriteToTheSame(
+            givenAndExpectedXml =
+                "<android.support.v7.preference.Preference>\n" +
+                "</android.support.v7.preference.Preference>",
+            prefixes = listOf("android/support/"),
+            map = mapOf(
+                "android/support2/v7/preference/Preference" to "android/test/pref/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_onePrefix_oneRule_oneRewrite() {
+        testRewrite(
+            givenXml =
+                "<android.support.v7.preference.Preference/>",
+            expectedXml =
+                "<android.test.pref.Preference/>",
+            prefixes = listOf("android/support/"),
+            map = mapOf(
+                "android/support/v7/preference/Preference" to "android/test/pref/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_onePrefix_oneRule_attribute_oneRewrite() {
+        testRewrite(
+            givenXml =
+                "<android.support.v7.preference.Preference \n" +
+                "    someAttribute=\"android.support.v7.preference.Preference\"/>",
+            expectedXml =
+                "<android.test.pref.Preference \n" +
+                "    someAttribute=\"android.support.v7.preference.Preference\"/>",
+            prefixes = listOf("android/support/"),
+            map =  mapOf(
+                "android/support/v7/preference/Preference" to "android/test/pref/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_onePrefix_oneRule_twoRewrites() {
+        testRewrite(
+            givenXml =
+                "<android.support.v7.preference.Preference>\n" +
+                "</android.support.v7.preference.Preference>",
+            expectedXml =
+                "<android.test.pref.Preference>\n" +
+                "</android.test.pref.Preference>",
+            prefixes = listOf("android/support/"),
+            map = mapOf(
+                "android/support/v7/preference/Preference" to "android/test/pref/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_onePrefix_oneRule_viewTag_simple() {
+        testRewrite(
+            givenXml =
+                "<view class=\"android.support.v7.preference.Preference\">",
+            expectedXml =
+                "<view class=\"android.test.pref.Preference\">",
+            prefixes = listOf("android/support/"),
+            map = mapOf(
+                "android/support/v7/preference/Preference" to "android/test/pref/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_onePrefix_oneRule_viewTag_stuffAround() {
+        testRewrite(
+            givenXml =
+                "<view notRelated=\"true\" " +
+                "      class=\"android.support.v7.preference.Preference\"" +
+                "      ignoreMe=\"android.support.v7.preference.Preference\">",
+            expectedXml =
+                "<view notRelated=\"true\" " +
+                "      class=\"android.test.pref.Preference\"" +
+                "      ignoreMe=\"android.support.v7.preference.Preference\">",
+            prefixes = listOf("android/support/"),
+            map = mapOf(
+                "android/support/v7/preference/Preference" to "android/test/pref/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_onePrefix_oneRule_viewInText_notMatched() {
+        testRewriteToTheSame(
+            givenAndExpectedXml =
+                "<test attribute=\"view\" class=\"android.support.v7.preference.Preference\">",
+            prefixes = listOf("android/support/"),
+            map = mapOf(
+                "android/support/v7/preference/Preference" to "android/test/pref/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_onePrefix_oneRule_identity() {
+        testRewrite(
+            givenXml =
+                "<android.support.v7.preference.Preference>\n" +
+                "</android.support.v7.preference.Preference>",
+            expectedXml =
+                "<android.support.v7.preference.Preference>\n" +
+                "</android.support.v7.preference.Preference>",
+            prefixes = listOf("android/support/"),
+            map = mapOf(
+                "android/support/v7/preference/Preference" to "android/support/v7/preference/Preference"
+            )
+        )
+    }
+
+    @Test fun layout_twoPrefixes_threeRules_multipleRewrites() {
+        testRewrite(
+            givenXml =
+                "<android.support.v7.preference.Preference>\n" +
+                "  <android.support.v14.preference.DialogPreference" +
+                "      someAttribute=\"someValue\"/>\n" +
+                "  <android.support.v14.preference.DialogPreference" +
+                "      someAttribute=\"someValue2\"/>\n" +
+                "  <!-- This one should be ignored --> \n" +
+                "  <android.support.v21.preference.DialogPreference" +
+                "      someAttribute=\"someValue2\"/>\n" +
+                "</android.support.v7.preference.Preference>\n" +
+                "\n" +
+                "<android.support.v7.preference.ListPreference/>",
+            expectedXml =
+                "<android.test.pref.Preference>\n" +
+                "  <android.test14.pref.DialogPreference" +
+                "      someAttribute=\"someValue\"/>\n" +
+                "  <android.test14.pref.DialogPreference" +
+                "      someAttribute=\"someValue2\"/>\n" +
+                "  <!-- This one should be ignored --> \n" +
+                "  <android.support.v21.preference.DialogPreference" +
+                "      someAttribute=\"someValue2\"/>\n" +
+                "</android.test.pref.Preference>\n" +
+                "\n" +
+                "<android.test.pref.ListPref/>",
+            prefixes = listOf(
+                "android/support/v7/",
+                "android/support/v14/"
+            ),
+            map = mapOf(
+                "android/support/v7/preference/ListPreference" to "android/test/pref/ListPref",
+                "android/support/v7/preference/Preference" to "android/test/pref/Preference",
+                "android/support/v14/preference/DialogPreference" to "android/test14/pref/DialogPreference",
+                "android/support/v21/preference/DialogPreference" to "android/test21/pref/DialogPreference"
+            )
+        )
+    }
+
+    private fun testRewriteToTheSame(givenAndExpectedXml: String,
+                                     prefixes: List<String>,
+                                     map: Map<String, String>) {
+        testRewrite(givenAndExpectedXml, givenAndExpectedXml, prefixes, map)
+    }
+
+    private fun testRewrite(givenXml : String,
+                            expectedXml : String,
+                            prefixes: List<String>,
+                            map: Map<String, String>) {
+        val given =
+            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+            "$givenXml\n"
+
+        val expected =
+            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+            "$expectedXml\n"
+
+        val typesMap = TypesMap(map.map{ JavaType(it.key) to JavaType(it.value) }.toMap(),
+            emptyMap())
+        val config = Config(prefixes, emptyList(), emptyList(), typesMap, ProGuardTypesMap.EMPTY)
+        val context = TransformationContext(config)
+        val processor = XmlResourcesTransformer(context)
+        val result = processor.transform(given.toByteArray())
+        val strResult = result.toString(Charset.defaultCharset())
+
+        Truth.assertThat(strResult).isEqualTo(expected)
+    }
+}
+
diff --git a/jetifier/jetifier/gradle-plugin/build.gradle b/jetifier/jetifier/gradle-plugin/build.gradle
new file mode 100644
index 0000000..ca24b72
--- /dev/null
+++ b/jetifier/jetifier/gradle-plugin/build.gradle
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+version '0.1'
+
+apply plugin: 'maven-publish'
+
+dependencies {
+    compile project(':core')
+    compileOnly gradleApi()
+}
+
+// Task to create a jar with all the required dependencies bundled inside
+task fatJar(type: Jar) {
+    baseName = project.name + '-all'
+    destinationDir = rootProject.ext.distDir
+    from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } }
+    with jar
+}
+
+publishing {
+    publications {
+        mavenJava(MavenPublication) {
+            from components.java
+        }
+    }
+}
diff --git a/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierExtension.kt b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierExtension.kt
new file mode 100644
index 0000000..7b516ec
--- /dev/null
+++ b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierExtension.kt
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.plugin.gradle
+
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.artifacts.Dependency
+import org.gradle.api.file.FileCollection
+import java.nio.file.Paths
+
+/**
+ * Defines methods that can be used in gradle on the "jetifier" object and triggers [JetifyLibsTask]
+ * or [JetifyGlobalTask] based on its usage.
+ */
+open class JetifierExtension(val project: Project) {
+
+    /**
+     * Adds dependency defined via string notation to be processed by jetifyLibs task.
+     *
+     *
+     * Example usage in Gradle:
+     * dependencies {
+     *   compile jetifier.process('groupId:artifactId:1.0')
+     * }
+     */
+    fun process(dependencyNotation: String): FileCollection {
+        return process(project.dependencies.create(dependencyNotation))
+    }
+
+    /**
+     * Adds dependency defined via string notation to be processed by jetifyLibs task while also
+     * applying the given exclude rules.
+     *
+     *
+     * Example usage in Gradle:
+     * dependencies {
+     *   compile jetifier.processAndExclude('groupId:artifactId:1.0',
+     *     [group: 'some.package', module: 'moduleName'])
+     * }
+     */
+    fun processAndExclude(
+        dependencyNotation: String,
+        vararg excludes: Map<String, String>
+    ): FileCollection {
+        return processAndExclude(project.dependencies.create(dependencyNotation), *excludes)
+    }
+
+    /**
+     * Adds dependency to be processed by jetifyLibs task.
+     */
+    fun process(dependency: Dependency): FileCollection {
+        val configuration = project.configurations.detachedConfiguration()
+        configuration.dependencies.add(dependency)
+        return process(configuration)
+    }
+
+    /**
+     * Adds dependency to be processed by jetifyLibs task while also applying the given excludes
+     * rules.
+     */
+    fun processAndExclude(
+        dependency: Dependency,
+        vararg excludes: Map<String, String>
+    ): FileCollection {
+        val configuration = project.configurations.detachedConfiguration()
+        configuration.dependencies.add(dependency)
+        excludes.forEach { configuration.exclude(it) }
+        return process(configuration)
+    }
+
+    /**
+     * Adds dependencies defined via file collection to be processed by jetifyLibs task.
+     *
+     * Example usage in Gradle for a single file:
+     * dependencies {
+     *   compile jetifier.process(files('../myFile1.jar'))
+     *   compile jetifier.process(files('../myFile2.jar'))
+     * }
+     *
+     * Example usage in Gradle for a configuration:
+     * configurations.create('depToRefactor')
+     *
+     * dependencies {
+     *    depToRefactor 'test:myDependency:1.0'
+     *    depToRefactor 'test:myDependency2:1.0'
+     * }
+     *
+     * dependencies {
+     *   compile jetifier.process(configurations.depToRefactor)
+     * }
+     */
+    fun process(files: FileCollection): FileCollection {
+        return JetifyLibsTask.resolveTask(project).addFilesToProcess(files)
+    }
+
+    /**
+     * Adds a whole configuration to be processed by jetifyGlobal task. This is the recommended way
+     * if processing a set of dependencies where it is unknown which exactly need to be rewritten.
+     *
+     * This will create a new detached configuration and resolve all the dependencies = obtaining
+     * all the files. Jetifier is then run with all the files and only the files that were rewritten
+     * are added to the given configuration and the original dependencies that didn't have to be
+     * changed are kept.
+     *
+     * Advantage is that all the dependencies that didn't have to be changed are kept intact so
+     * their artifactsIds and groupIds are kept (instead of replacing them with files) which allows
+     * other steps in the build process to use the artifacts information to generate pom files
+     * and other stuff.
+     *
+     * This will NOT resolve the given configuration as the dependencies are resolved in a detached
+     * configuration. If you give it a configuration that was already resolved the process will
+     * end up with exception saying that resolved configuration cannot be changed. This is expected
+     * as Jetifier cannot add new files to an already resolved configuration.
+     *
+     *
+     * Example usage in Gradle:
+     * jetifier.addConfigurationToProcess(configurations.implementation)
+     * afterEvaluate {
+     *   tasks.preBuild.dependsOn tasks.jetifyGlobal
+     * }
+     *
+     *
+     */
+    fun addConfigurationToProcess(config: Configuration) {
+        JetifyGlobalTask.resolveTask(project).addConfigurationToProcess(config)
+    }
+
+    /**
+     * Sets a custom configuration file to be used by Jetifier.
+     */
+    fun setConfigFile(configFilePath: String) {
+        TasksCommon.configFilePath = Paths.get(configFilePath)
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierLoggerAdapter.kt b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierLoggerAdapter.kt
new file mode 100644
index 0000000..9d85851
--- /dev/null
+++ b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierLoggerAdapter.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.plugin.gradle
+
+import android.support.tools.jetifier.core.utils.LogConsumer
+import org.gradle.api.logging.Logger
+
+/**
+ * Logging adapter to hook jetfier logging into gradle.
+ */
+class JetifierLoggerAdapter(val gradleLogger: Logger) : LogConsumer {
+
+    override fun error(message: String) {
+        gradleLogger.error(message)
+    }
+
+    override fun info(message: String) {
+        gradleLogger.info(message)
+    }
+
+    override fun verbose(message: String) {
+        gradleLogger.info(message)
+    }
+
+    override fun debug(message: String) {
+        gradleLogger.debug(message)
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierPlugin.kt b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierPlugin.kt
new file mode 100644
index 0000000..109e4c4
--- /dev/null
+++ b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifierPlugin.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.plugin.gradle
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+/**
+ * This serves as the main entry point of this plugin and registers the extension object.
+ */
+open class JetifierPlugin : Plugin<Project>  {
+
+    companion object {
+        const val GROOVY_OBJECT_NAME : String = "jetifier"
+    }
+
+    override fun apply(project: Project) {
+        project.extensions.create(GROOVY_OBJECT_NAME, JetifierExtension::class.java, project)
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifyGlobalTask.kt b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifyGlobalTask.kt
new file mode 100644
index 0000000..4d35625
--- /dev/null
+++ b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifyGlobalTask.kt
@@ -0,0 +1,136 @@
+package android.support.tools.jetifier.plugin.gradle
+
+import android.support.tools.jetifier.core.config.ConfigParser
+import org.gradle.api.DefaultTask
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.artifacts.Dependency
+import org.gradle.api.artifacts.FileCollectionDependency
+import org.gradle.api.artifacts.ProjectDependency
+import org.gradle.api.logging.LogLevel
+import org.gradle.api.tasks.TaskAction
+import java.io.File
+
+/**
+ * Task that processes whole configurations. This is the recommended way if processing a set of
+ * dependencies where it is unknown which exactly need to be rewritten.
+ *
+ * This will create a new detached configuration and resolve all the dependencies = obtaining
+ * all the files. Jetifier is then run with all the files and only the files that were rewritten
+ * are added to the given configuration and the original dependencies that didn't have to be
+ * changed are kept.
+ *
+ * Advantage is that all the dependencies that didn't have to be changed are kept intact so
+ * their artifactsIds and groupIds are kept (instead of replacing them with files) which allows
+ * other steps in the build process to use the artifacts information to generate pom files
+ * and other stuff.
+ *
+ * This will NOT resolve the given configurations as the dependencies are resolved in a detached
+ * configuration. If you give it a configuration that was already resolved the process will
+ * end up with exception saying that resolved configuration cannot be changed. This is expected
+ * as Jetifier cannot add new files to an already resolved configuration.
+ *
+ * Example usage in Gradle:
+ * jetifier.addConfigurationToProcess(configurations.implementation)
+ * afterEvaluate {
+ *   tasks.preBuild.dependsOn tasks.jetifyGlobal
+ * }
+ *
+ * TODO: Add caching for this task
+ */
+open class JetifyGlobalTask : DefaultTask() {
+
+    companion object {
+        const val TASK_NAME = "jetifyGlobal"
+        const val GROUP_ID = "Pre-build"
+        // TODO: Get back to this once the name of the library is decided.
+        const val DESCRIPTION = "Rewrites input libraries to run with jetpack"
+
+        const val OUTPUT_DIR_APPENDIX = "jetifier"
+
+        fun resolveTask(project: Project) : JetifyGlobalTask {
+            val task = project.tasks.findByName(TASK_NAME) as? JetifyGlobalTask
+            if (task != null) {
+                return task
+            }
+            return project.tasks.create(TASK_NAME, JetifyGlobalTask::class.java)
+        }
+    }
+
+    private var configurationsToProcess = mutableListOf<Configuration>()
+
+    private val outputDir = File(project.buildDir, OUTPUT_DIR_APPENDIX)
+
+
+    override fun getGroup() = GROUP_ID
+
+    override fun getDescription() = DESCRIPTION
+
+    /**
+     * Add a whole configuration to be processed by Jetifier.
+     *
+     * See [JetifierExtension] for details on how to use this.
+     */
+    fun addConfigurationToProcess(config: Configuration) {
+        configurationsToProcess.add(config)
+    }
+
+    @TaskAction
+    @Throws(Exception::class)
+    fun run() {
+        val config = ConfigParser.loadConfigOrFail(TasksCommon.configFilePath)
+
+        val dependenciesMap = mutableMapOf<File, MutableSet<Dependency>>()
+        // Build a map where for each file we have a set of dependencies that pulled that file in.
+        configurationsToProcess.forEach { conf ->
+            for (dep in conf.dependencies) {
+                if (dep is ProjectDependency) {
+                    project.logger.log(LogLevel.DEBUG, "Ignoring project dependency {}", dep.name)
+                    continue
+                }
+
+                val fileDep = dep as? FileCollectionDependency
+                if (fileDep != null) {
+                    fileDep.files.forEach {
+                        dependenciesMap
+                            .getOrPut(it, { mutableSetOf<Dependency>() } )
+                            .add(fileDep)
+                    }
+                } else {
+                    if (TasksCommon.shouldSkipArtifact(dep.name, dep.group, config)) {
+                        project.logger.log(
+                            LogLevel.DEBUG, "Skipping rewriting of support library {}:{}:{}",
+                            dep.group, dep.name, dep.version)
+                        continue
+                    }
+
+                    val detached = project.configurations.detachedConfiguration()
+                    detached.dependencies.add(dep)
+                    detached.resolvedConfiguration.resolvedArtifacts.forEach {
+                        dependenciesMap
+                            .getOrPut(it.file, { mutableSetOf<Dependency>() } )
+                            .add(dep)
+                    }
+                }
+            }
+        }
+
+        // Process the files using Jetifier
+        val result = TasksCommon.processFiles(config, dependenciesMap.keys, project.logger, outputDir)
+
+        // Apply changes
+        configurationsToProcess.forEach { conf ->
+            // Apply that on our set
+            result.filesToRemove.forEach { file ->
+                dependenciesMap[file]!!.forEach {
+                    conf.dependencies.remove(it)
+                }
+            }
+
+            result.filesToAdd.forEach {
+                project.dependencies.add(conf.name, project.files(it))
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifyLibsTask.kt b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifyLibsTask.kt
new file mode 100644
index 0000000..873c8ec
--- /dev/null
+++ b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/JetifyLibsTask.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.plugin.gradle
+
+import android.support.tools.jetifier.core.config.ConfigParser
+import org.gradle.api.DefaultTask
+import org.gradle.api.Project
+import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.TaskAction
+import java.io.File
+
+/**
+ * Task that processes given file collections using Jetifier.
+ *
+ * This task also utilizes Gradle caching so it's run only when needed.
+ *
+ * Example usage in Gradle:
+ * dependencies {
+ *   compile jetifier.process('groupId:artifactId:1.0')
+ * }
+ */
+open class JetifyLibsTask : DefaultTask() {
+
+    companion object {
+        const val TASK_NAME = "jetifyLibs"
+        const val GROUP_ID = "Pre-build"
+        // TODO: Get back to this once the name of the library is decided.
+        const val DESCRIPTION = "Rewrites input libraries to run with jetpack"
+
+        const val OUTPUT_DIR_APPENDIX = "jetifier"
+
+
+        fun resolveTask(project: Project) : JetifyLibsTask {
+            val task = project.tasks.findByName(TASK_NAME) as? JetifyLibsTask
+            if (task != null) {
+                return task
+            }
+            return project.tasks.create(TASK_NAME, JetifyLibsTask::class.java)
+        }
+
+    }
+
+    private var filesToProcess : FileCollection = project.files()
+
+    private val outputDir = File(project.buildDir, OUTPUT_DIR_APPENDIX)
+
+
+    override fun getGroup() = GROUP_ID
+
+    override fun getDescription() = DESCRIPTION
+
+    /**
+     * Adds individual files collection to be processed by Jetifier.
+     *
+     * See [JetifierExtension] for details on how to use this.
+     */
+    fun addFilesToProcess(files: FileCollection) : FileCollection {
+        filesToProcess = filesToProcess.plus(files)
+        return project.files(files.map { File(outputDir, it.name) }.toList())
+    }
+
+    /**
+     * Used by Gradle to figure out whether this task should be re-run. If the result of this method
+     * is different then the task is re-run.
+     */
+    @InputFiles
+    fun getInputFiles() : FileCollection {
+        return filesToProcess
+    }
+
+    /**
+     * Used by Gradle to figure out whether this task should be re-run and if other tasks that are
+     * relying on files from this directory should be re-run. Actually not having this and only
+     * having [InputFiles] annotation would disable the whole incremental mechanism for this task
+     * and lead to constant re-runs.
+     */
+    @OutputDirectory
+    fun getOutputDir() : File {
+        return outputDir
+    }
+
+    @TaskAction
+    @Throws(Exception::class)
+    fun run() {
+        val config = ConfigParser.loadConfigOrFail(TasksCommon.configFilePath)
+
+        // Process the files using Jetifier
+        TasksCommon.processFiles(config, filesToProcess.toSet(), project.logger, outputDir)
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/TasksCommon.kt b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/TasksCommon.kt
new file mode 100644
index 0000000..dcc6375
--- /dev/null
+++ b/jetifier/jetifier/gradle-plugin/src/main/kotlin/android/support/tools/jetifier/plugin/gradle/TasksCommon.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.plugin.gradle
+
+import android.support.tools.jetifier.core.Processor
+import android.support.tools.jetifier.core.TransformationResult
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.utils.Log
+import org.gradle.api.logging.LogLevel
+import org.gradle.api.logging.Logger
+import java.io.File
+import java.nio.file.Path
+
+class TasksCommon {
+
+    companion object {
+
+        var configFilePath: Path? = null
+
+
+        fun processFiles(config: Config, filesToProcess: Set<File>, logger: Logger, outputDir: File) : TransformationResult {
+            outputDir.mkdirs()
+
+            logger.log(LogLevel.DEBUG, "Jetifier will now process the following files:")
+            filesToProcess.forEach {
+                logger.log(LogLevel.DEBUG, it.absolutePath)
+            }
+
+            // Hook to the gradle logger
+            Log.logConsumer = JetifierLoggerAdapter(logger)
+
+            val processor = Processor(config)
+            return processor.transform(filesToProcess, outputDir.toPath())
+        }
+
+        fun shouldSkipArtifact(artifactId: String, groupId: String?, config: Config) : Boolean {
+            return config.pomRewriteRules.any {
+                it.from.artifactId == artifactId && it.from.groupId == groupId
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/gradle-plugin/src/main/resources/META-INF/gradle-plugins/androidx.tools.jetifier.properties b/jetifier/jetifier/gradle-plugin/src/main/resources/META-INF/gradle-plugins/androidx.tools.jetifier.properties
new file mode 100644
index 0000000..7ee7e73
--- /dev/null
+++ b/jetifier/jetifier/gradle-plugin/src/main/resources/META-INF/gradle-plugins/androidx.tools.jetifier.properties
@@ -0,0 +1,17 @@
+#
+# 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
+#
+
+implementation-class=android.support.tools.jetifier.plugin.gradle.JetifierPlugin
\ No newline at end of file
diff --git a/jetifier/jetifier/gradle/wrapper/gradle-wrapper.jar b/jetifier/jetifier/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..2411732
--- /dev/null
+++ b/jetifier/jetifier/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/jetifier/jetifier/gradle/wrapper/gradle-wrapper.properties b/jetifier/jetifier/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..452b52a
--- /dev/null
+++ b/jetifier/jetifier/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=../../../../../../tools/external/gradle/gradle-4.3-bin.zip
diff --git a/jetifier/jetifier/gradlew b/jetifier/jetifier/gradlew
new file mode 100755
index 0000000..04fca86
--- /dev/null
+++ b/jetifier/jetifier/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save ( ) {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when runTransform from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/jetifier/jetifier/gradlew.bat b/jetifier/jetifier/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/jetifier/jetifier/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off

+@rem ##########################################################################

+@rem

+@rem  Gradle startup script for Windows

+@rem

+@rem ##########################################################################

+

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

+if "%OS%"=="Windows_NT" setlocal

+

+set DIRNAME=%~dp0

+if "%DIRNAME%" == "" set DIRNAME=.

+set APP_BASE_NAME=%~n0

+set APP_HOME=%DIRNAME%

+

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

+set DEFAULT_JVM_OPTS=

+

+@rem Find java.exe

+if defined JAVA_HOME goto findJavaFromJavaHome

+

+set JAVA_EXE=java.exe

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

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

+

+echo.

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

+echo.

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

+echo location of your Java installation.

+

+goto fail

+

+:findJavaFromJavaHome

+set JAVA_HOME=%JAVA_HOME:"=%

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

+

+if exist "%JAVA_EXE%" goto init

+

+echo.

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

+echo.

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

+echo location of your Java installation.

+

+goto fail

+

+:init

+@rem Get command-line arguments, handling Windows variants

+

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

+

+:win9xME_args

+@rem Slurp the command line arguments.

+set CMD_LINE_ARGS=

+set _SKIP=2

+

+:win9xME_args_slurp

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

+

+set CMD_LINE_ARGS=%*

+

+:execute

+@rem Setup the command line

+

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

+

+@rem Execute Gradle

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

+

+:end

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

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

+

+:fail

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

+rem the _cmd.exe /c_ return code!

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

+exit /b 1

+

+:mainEnd

+if "%OS%"=="Windows_NT" endlocal

+

+:omega

diff --git a/jetifier/jetifier/preprocessor/build.gradle b/jetifier/jetifier/preprocessor/build.gradle
new file mode 100644
index 0000000..b688a9d
--- /dev/null
+++ b/jetifier/jetifier/preprocessor/build.gradle
@@ -0,0 +1,26 @@
+/*
+ * 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
+ */
+
+version '1.0'
+
+apply plugin: "application"
+
+mainClassName = "android.support.tools.jetifier.preprocessor.MainKt"
+
+dependencies {
+    compile project(':core')
+    compile group: 'commons-cli', name: 'commons-cli', version: '1.3.1'
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/preprocessor/scripts/processDefaultConfig.sh b/jetifier/jetifier/preprocessor/scripts/processDefaultConfig.sh
new file mode 100644
index 0000000..d451c76
--- /dev/null
+++ b/jetifier/jetifier/preprocessor/scripts/processDefaultConfig.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+# 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
+
+# WHAT IT DOES
+# Grabs all the support libraries and runs them through a preprocessor
+# using the default Jetifier config to generate the final mappings.
+
+ROOT_DIR=$(dirname $(readlink -f $0))
+OUT_DIR="$ROOT_DIR/out"
+TEMP_LOG="$OUT_DIR/tempLog"
+
+JETIFIER_DIR="$ROOT_DIR/../.."
+DEFAULT_CONFIG="$JETIFIER_DIR/core/src/main/resources/default.config"
+GENERATED_CONFIG="$JETIFIER_DIR/core/src/main/resources/default.generated.config"
+PREPROCESSOR_DISTRO_PATH="$JETIFIER_DIR/preprocessor/build/distributions/preprocessor-1.0.zip"
+PREPROCESSOR_BIN_PATH="$OUT_DIR/preprocessor-1.0/bin/preprocessor"
+SUPPORT_LIBS_DOWNLOADED="$OUT_DIR/supportLibs"
+
+GREEN='\033[0;32m'
+RED='\033[0;31m'
+NC='\033[0m' # No Color
+
+function exitAndFail() {
+	cat $TEMP_LOG
+	echo -e "${RED}FAILED${NC}"
+	exit 1
+}
+
+function printSectionStart() {
+	echo ""
+	echo "======================================================"
+	echo "$1"
+	echo "======================================================"
+}
+
+function printSuccess() {
+	echo -e "${GREEN}SUCCESS${NC}"
+}
+
+function buildProjectUsingGradle() {
+	cd $1
+	sh gradlew clean build $2 > $TEMP_LOG --stacktrace || exitAndFail 2>&1
+}
+
+
+rm -r $OUT_DIR
+mkdir $OUT_DIR
+echo "OUT dir is at '$OUT_DIR'"
+
+printSectionStart "Downloading all affected support libraries"
+wget -nd -i $ROOT_DIR/repo-links -P $SUPPORT_LIBS_DOWNLOADED
+
+printSectionStart "Preparing Jetifier"
+buildProjectUsingGradle $JETIFIER_DIR
+echo "[OK] Clean build done"
+
+unzip $PREPROCESSOR_DISTRO_PATH -d $OUT_DIR > /dev/null
+echo "[OK] Copied & unziped jetifier preprocessor"
+
+printSectionStart "Preprocessing mappings on support libraries"
+sh $PREPROCESSOR_BIN_PATH -i "$SUPPORT_LIBS_DOWNLOADED" -o "$GENERATED_CONFIG" -c "$DEFAULT_CONFIG" -l verbose || exitAndFail
+echo "[OK] Done, config generated into $GENERATED_CONFIG"
+
+printSuccess
diff --git a/jetifier/jetifier/preprocessor/scripts/repo-links b/jetifier/jetifier/preprocessor/scripts/repo-links
new file mode 100644
index 0000000..961c149
--- /dev/null
+++ b/jetifier/jetifier/preprocessor/scripts/repo-links
@@ -0,0 +1,52 @@
+# 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
+
+https://maven.google.com/com/android/support/animated-vector-drawable/27.0.1/animated-vector-drawable-27.0.1.aar
+https://maven.google.com/com/android/support/appcompat-v7/27.0.1/appcompat-v7-27.0.1.aar
+https://maven.google.com/com/android/support/cardview-v7/27.0.1/cardview-v7-27.0.1.aar
+https://maven.google.com/com/android/support/customtabs/27.0.1/customtabs-27.0.1.aar
+https://maven.google.com/com/android/support/design/27.0.1/design-27.0.1.aar
+https://maven.google.com/com/android/support/exifinterface/27.0.1/exifinterface-27.0.1.aar
+https://maven.google.com/com/android/support/gridlayout-v7/27.0.1/gridlayout-v7-27.0.1.aar
+https://maven.google.com/com/android/support/instantvideo/26.0.0-alpha1/instantvideo-26.0.0-alpha1.aar
+https://maven.google.com/com/android/support/leanback-v17/27.0.1/leanback-v17-27.0.1.aar
+https://maven.google.com/com/android/support/mediarouter-v7/27.0.1/mediarouter-v7-27.0.1.aar
+https://maven.google.com/com/android/support/multidex/1.0.2/multidex-1.0.2.aar
+https://maven.google.com/com/android/support/multidex-instrumentation/1.0.2/multidex-instrumentation-1.0.2.aar
+https://maven.google.com/com/android/support/palette-v7/27.0.1/palette-v7-27.0.1.aar
+https://maven.google.com/com/android/support/percent/27.0.1/percent-27.0.1.aar
+https://maven.google.com/com/android/support/preference-leanback-v17/27.0.1/preference-leanback-v17-27.0.1.aar
+https://maven.google.com/com/android/support/preference-v14/27.0.1/preference-v14-27.0.1.aar
+https://maven.google.com/com/android/support/preference-v7/27.0.1/preference-v7-27.0.1.aar
+https://maven.google.com/com/android/support/recommendation/27.0.1/recommendation-27.0.1.aar
+https://maven.google.com/com/android/support/recyclerview-v7/27.0.1/recyclerview-v7-27.0.1.aar
+https://maven.google.com/com/android/support/support-annotations/27.0.1/support-annotations-27.0.1.jar
+https://maven.google.com/com/android/support/support-compat/27.0.1/support-compat-27.0.1.aar
+https://maven.google.com/com/android/support/support-content/27.0.1/support-content-27.0.1.aar
+https://maven.google.com/com/android/support/support-core-ui/27.0.1/support-core-ui-27.0.1.aar
+https://maven.google.com/com/android/support/support-core-utils/27.0.1/support-core-utils-27.0.1.aar
+https://maven.google.com/com/android/support/support-dynamic-animation/27.0.1/support-dynamic-animation-27.0.1.aar
+https://maven.google.com/com/android/support/support-emoji/27.0.1/support-emoji-27.0.1.aar
+https://maven.google.com/com/android/support/support-emoji-appcompat/27.0.1/support-emoji-appcompat-27.0.1.aar
+https://maven.google.com/com/android/support/support-emoji-bundled/27.0.1/support-emoji-bundled-27.0.1.aar
+https://maven.google.com/com/android/support/support-fragment/27.0.1/support-fragment-27.0.1.aar
+https://maven.google.com/com/android/support/support-media-compat/27.0.1/support-media-compat-27.0.1.aar
+https://maven.google.com/com/android/support/support-tv-provider/27.0.1/support-tv-provider-27.0.1.aar
+https://maven.google.com/com/android/support/support-v13/27.0.1/support-v13-27.0.1.aar
+https://maven.google.com/com/android/support/support-v4/27.0.1/support-v4-27.0.1.aar
+https://maven.google.com/com/android/support/support-vector-drawable/27.0.1/support-vector-drawable-27.0.1.aar
+https://maven.google.com/com/android/support/transition/27.0.1/transition-27.0.1.aar
+https://maven.google.com/com/android/support/wear/27.0.1/wear-27.0.1.aar
+https://maven.google.com/com/android/support/wearable/27.0.1/wearable-27.0.1.aar
+https://maven.google.com/com/android/support/constraint/constraint-layout/1.0.2/constraint-layout-1.0.2.aar
diff --git a/jetifier/jetifier/preprocessor/src/main/kotlin/android/support/tools/jetifier/preprocessor/ConfigGenerator.kt b/jetifier/jetifier/preprocessor/src/main/kotlin/android/support/tools/jetifier/preprocessor/ConfigGenerator.kt
new file mode 100644
index 0000000..ec12ac8
--- /dev/null
+++ b/jetifier/jetifier/preprocessor/src/main/kotlin/android/support/tools/jetifier/preprocessor/ConfigGenerator.kt
@@ -0,0 +1,72 @@
+package android.support.tools.jetifier.preprocessor
+
+import android.support.tools.jetifier.core.archive.Archive
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.config.ConfigParser
+import android.support.tools.jetifier.core.map.LibraryMapGenerator
+import java.io.File
+import java.nio.file.Path
+
+class ConfigGenerator {
+
+    companion object {
+        private const val LEGAL_NOTICE =
+            "# Copyright (C) 2017 The Android Open Source Project\n" +
+            "#\n" +
+            "# Licensed under the Apache License, Version 2.0 (the \"License\");\n" +
+            "# you may not use this file except in compliance with the License.\n" +
+            "# You may obtain a copy of the License at\n" +
+            "#\n" +
+            "#      http://www.apache.org/licenses/LICENSE-2.0\n" +
+            "#\n" +
+            "# Unless required by applicable law or agreed to in writing, software\n" +
+            "# distributed under the License is distributed on an \"AS IS\" BASIS,\n" +
+            "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +
+            "# See the License for the specific language governing permissions and\n" +
+            "# limitations under the License\n"
+
+        private const val GEN_NOTICE =
+            "# DO NOT EDIT MANUALLY! This file was auto-generated using Jetifier preprocessor.\n" +
+            "# To make some changes in the configuration edit \"default.config\" and run\n" +
+            "# preprocessor/scripts/processDefaultConfig.sh script to update this file.\n"
+    }
+
+    fun generateMapping(
+        config: Config,
+        inputLibraries: List<File>,
+        outputConfigPath: Path) {
+
+        val mapper = LibraryMapGenerator(config)
+        inputLibraries.forEach {
+            if (it.isDirectory) {
+                it.listFiles().forEach { fileInDir ->
+                    val library = Archive.Builder.extract(fileInDir)
+                    mapper.scanLibrary(library)
+                }
+            } else {
+                val library = Archive.Builder.extract(it)
+                mapper.scanLibrary(library)
+            }
+        }
+
+        val map = mapper.generateMap()
+        val newConfig = config.setNewMap(map)
+
+        saveConfigToFile(newConfig, outputConfigPath.toFile())
+    }
+
+    private fun saveConfigToFile(configToSave: Config, outputFile : File) {
+        val sb = StringBuilder()
+        sb.append(LEGAL_NOTICE)
+        sb.append("\n")
+        sb.append(GEN_NOTICE)
+        sb.append("\n")
+        sb.append(ConfigParser.writeToString(configToSave))
+
+        if (outputFile.exists()) {
+            outputFile.delete()
+        }
+        outputFile.createNewFile()
+        outputFile.writeText(sb.toString())
+    }
+}
\ No newline at end of file
diff --git a/jetifier/jetifier/preprocessor/src/main/kotlin/android/support/tools/jetifier/preprocessor/Main.kt b/jetifier/jetifier/preprocessor/src/main/kotlin/android/support/tools/jetifier/preprocessor/Main.kt
new file mode 100644
index 0000000..58cb20f
--- /dev/null
+++ b/jetifier/jetifier/preprocessor/src/main/kotlin/android/support/tools/jetifier/preprocessor/Main.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.preprocessor
+
+import android.support.tools.jetifier.core.config.ConfigParser
+import android.support.tools.jetifier.core.utils.Log
+import org.apache.commons.cli.CommandLine
+import org.apache.commons.cli.DefaultParser
+import org.apache.commons.cli.HelpFormatter
+import org.apache.commons.cli.Option
+import org.apache.commons.cli.Options
+import org.apache.commons.cli.ParseException
+import java.io.File
+import java.nio.file.Paths
+
+class Main {
+
+    companion object {
+        const val TAG = "Main"
+        const val TOOL_NAME = "preprocessor"
+
+        val OPTIONS = Options()
+        val OPTION_INPUT_LIBS = createOption("i", "Input libraries paths", multiple = true)
+        val OPTION_INPUT_CONFIG = createOption("c", "Input config path")
+        val OPTION_OUTPUT_CONFIG = createOption("o", "Output config path")
+        val OPTION_LOG_LEVEL = createOption("l", "Logging level. debug, verbose, default",
+            isRequired = false)
+
+        private fun createOption(argName: String,
+                                 desc: String,
+                                 isRequired: Boolean = true,
+                                 multiple: Boolean = false) : Option {
+            val op = Option(argName, true, desc)
+            op.isRequired = isRequired
+            if (multiple) {
+                op.args = Option.UNLIMITED_VALUES
+            }
+            OPTIONS.addOption(op)
+            return op
+        }
+    }
+
+    fun run(args : Array<String>) {
+        val cmd = parseCmdLine(args)
+        if (cmd == null) {
+            System.exit(1)
+            return
+        }
+
+        Log.setLevel(cmd.getOptionValue(OPTION_LOG_LEVEL.opt))
+
+        val inputLibraries = cmd.getOptionValues(OPTION_INPUT_LIBS.opt).map { File(it) }
+        val inputConfigPath = Paths.get(cmd.getOptionValue(OPTION_INPUT_CONFIG.opt))
+        val outputConfigPath = Paths.get(cmd.getOptionValue(OPTION_OUTPUT_CONFIG.opt))
+
+        val config = ConfigParser.loadFromFile(inputConfigPath)
+        if (config == null) {
+            System.exit(1)
+            return
+        }
+
+        val generator = ConfigGenerator()
+        generator.generateMapping(config, inputLibraries, outputConfigPath)
+    }
+
+    private fun parseCmdLine(args : Array<String>) : CommandLine? {
+        try {
+            return DefaultParser().parse(OPTIONS, args)
+        } catch (e: ParseException) {
+            Log.e(TAG, e.message.orEmpty())
+            HelpFormatter().printHelp(TOOL_NAME, OPTIONS)
+        }
+        return null
+    }
+
+}
+
+
+fun main(args : Array<String>) {
+    Main().run(args)
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/android/support/KotlinNoOp.kt b/jetifier/jetifier/settings.gradle
similarity index 65%
rename from buildSrc/src/main/kotlin/android/support/KotlinNoOp.kt
rename to jetifier/jetifier/settings.gradle
index 968f6ca..7d13b73 100644
--- a/buildSrc/src/main/kotlin/android/support/KotlinNoOp.kt
+++ b/jetifier/jetifier/settings.gradle
@@ -1,24 +1,22 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *       http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
 
-package android.support
+rootProject.name = 'jetifier'
+include 'core'
+include 'gradle-plugin'
+include 'standalone'
+include 'preprocessor'
 
-class KotlinNoOp {
-
-    fun noOp() {
-    }
-
-}
\ No newline at end of file
diff --git a/jetifier/jetifier/standalone/build.gradle b/jetifier/jetifier/standalone/build.gradle
new file mode 100644
index 0000000..8814d50
--- /dev/null
+++ b/jetifier/jetifier/standalone/build.gradle
@@ -0,0 +1,27 @@
+/*
+ * 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
+ */
+
+version '1.0'
+
+apply plugin: "application"
+
+mainClassName = "android.support.tools.jetifier.standalone.MainKt"
+
+dependencies {
+    compile project(':core')
+    compile group: 'commons-cli', name: 'commons-cli', version: '1.3.1'
+}
+
diff --git a/jetifier/jetifier/standalone/src/main/kotlin/android/support/tools/jetifier/standalone/Main.kt b/jetifier/jetifier/standalone/src/main/kotlin/android/support/tools/jetifier/standalone/Main.kt
new file mode 100644
index 0000000..de310e4
--- /dev/null
+++ b/jetifier/jetifier/standalone/src/main/kotlin/android/support/tools/jetifier/standalone/Main.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.tools.jetifier.standalone
+
+import android.support.tools.jetifier.core.Processor
+import android.support.tools.jetifier.core.config.Config
+import android.support.tools.jetifier.core.config.ConfigParser
+import android.support.tools.jetifier.core.utils.Log
+import org.apache.commons.cli.CommandLine
+import org.apache.commons.cli.DefaultParser
+import org.apache.commons.cli.HelpFormatter
+import org.apache.commons.cli.Option
+import org.apache.commons.cli.Options
+import org.apache.commons.cli.ParseException
+import java.io.File
+import java.nio.file.Paths
+
+class Main {
+
+    companion object {
+        const val TAG = "Main"
+        const val TOOL_NAME = "standalone"
+
+        val OPTIONS = Options()
+        val OPTION_INPUT = createOption("i", "Input libraries paths", multiple = true)
+        val OPTION_OUTPUT = createOption("o", "Output config path")
+        val OPTION_CONFIG = createOption("c", "Input config path", isRequired = false)
+        val OPTION_LOG_LEVEL = createOption("l", "Logging level. debug, verbose, default",
+            isRequired = false)
+
+        private fun createOption(argName: String,
+                                 desc: String,
+                                 isRequired: Boolean = true,
+                                 multiple: Boolean = false) : Option {
+            val op = Option(argName, true, desc)
+            op.isRequired = isRequired
+            if (multiple) {
+                op.args = Option.UNLIMITED_VALUES
+            }
+            OPTIONS.addOption(op)
+            return op
+        }
+    }
+
+    fun run(args : Array<String>) {
+        val cmd = parseCmdLine(args)
+        if (cmd == null) {
+            System.exit(1)
+            return
+        }
+
+        Log.setLevel(cmd.getOptionValue(OPTION_LOG_LEVEL.opt))
+
+        val inputLibraries = cmd.getOptionValues(OPTION_INPUT.opt).map { File(it) }.toSet()
+        val outputPath = Paths.get(cmd.getOptionValue(OPTION_OUTPUT.opt))
+
+        val config : Config?
+        if (cmd.hasOption(OPTION_CONFIG.opt)) {
+            val configPath = Paths.get(cmd.getOptionValue(OPTION_CONFIG.opt))
+            config = ConfigParser.loadFromFile(configPath)
+        } else {
+            config = ConfigParser.loadDefaultConfig()
+        }
+
+        if (config == null) {
+            Log.e(TAG, "Failed to load the config file")
+            System.exit(1)
+            return
+        }
+
+        val processor = Processor(config)
+        processor.transform(inputLibraries, outputPath)
+    }
+
+    private fun parseCmdLine(args : Array<String>) : CommandLine? {
+        try {
+            return DefaultParser().parse(OPTIONS, args)
+        } catch (e: ParseException) {
+            Log.e(TAG, e.message.orEmpty())
+            HelpFormatter().printHelp(TOOL_NAME, OPTIONS)
+        }
+        return null
+    }
+
+}
+
+
+fun main(args : Array<String>) {
+    Main().run(args)
+}
\ No newline at end of file
diff --git a/leanback/api/27.0.0.ignore b/leanback/api/27.0.0.ignore
new file mode 100644
index 0000000..35526be
--- /dev/null
+++ b/leanback/api/27.0.0.ignore
@@ -0,0 +1,9 @@
+5e0df8d
+9cc8101
+8be589f
+9acc564
+77de988
+3b4fb8e
+8ec3ebc
+f7a9631
+afc0ff4
diff --git a/leanback/api/current.txt b/leanback/api/current.txt
index 4a5067c..b045d8f 100644
--- a/leanback/api/current.txt
+++ b/leanback/api/current.txt
@@ -31,38 +31,6 @@
     method public void startEntranceTransition();
   }
 
-   abstract deprecated class BaseRowFragment extends android.app.Fragment {
-    method public final android.support.v17.leanback.widget.ObjectAdapter getAdapter();
-    method public final android.support.v17.leanback.widget.ItemBridgeAdapter getBridgeAdapter();
-    method public final android.support.v17.leanback.widget.PresenterSelector getPresenterSelector();
-    method public int getSelectedPosition();
-    method public final android.support.v17.leanback.widget.VerticalGridView getVerticalGridView();
-    method public void onTransitionEnd();
-    method public boolean onTransitionPrepare();
-    method public void onTransitionStart();
-    method public final void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
-    method public void setAlignment(int);
-    method public final void setPresenterSelector(android.support.v17.leanback.widget.PresenterSelector);
-    method public void setSelectedPosition(int);
-    method public void setSelectedPosition(int, boolean);
-  }
-
-   abstract class BaseRowSupportFragment extends android.support.v4.app.Fragment {
-    method public final android.support.v17.leanback.widget.ObjectAdapter getAdapter();
-    method public final android.support.v17.leanback.widget.ItemBridgeAdapter getBridgeAdapter();
-    method public final android.support.v17.leanback.widget.PresenterSelector getPresenterSelector();
-    method public int getSelectedPosition();
-    method public final android.support.v17.leanback.widget.VerticalGridView getVerticalGridView();
-    method public void onTransitionEnd();
-    method public boolean onTransitionPrepare();
-    method public void onTransitionStart();
-    method public final void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
-    method public void setAlignment(int);
-    method public final void setPresenterSelector(android.support.v17.leanback.widget.PresenterSelector);
-    method public void setSelectedPosition(int);
-    method public void setSelectedPosition(int, boolean);
-  }
-
   public class BaseSupportFragment extends android.support.v17.leanback.app.BrandedSupportFragment {
     method protected java.lang.Object createEntranceTransition();
     method public final android.support.v17.leanback.app.ProgressBarManager getProgressBarManager();
@@ -552,9 +520,11 @@
     field public static final int UI_STYLE_REPLACE = 0; // 0x0
   }
 
-  public deprecated class HeadersFragment extends android.support.v17.leanback.app.BaseRowFragment {
+  public deprecated class HeadersFragment extends android.app.Fragment {
     ctor public HeadersFragment();
     method public boolean isScrolling();
+    method public void onTransitionEnd();
+    method public void onTransitionStart();
     method public void setOnHeaderClickedListener(android.support.v17.leanback.app.HeadersFragment.OnHeaderClickedListener);
     method public void setOnHeaderViewSelectedListener(android.support.v17.leanback.app.HeadersFragment.OnHeaderViewSelectedListener);
   }
@@ -567,9 +537,11 @@
     method public abstract void onHeaderSelected(android.support.v17.leanback.widget.RowHeaderPresenter.ViewHolder, android.support.v17.leanback.widget.Row);
   }
 
-  public class HeadersSupportFragment extends android.support.v17.leanback.app.BaseRowSupportFragment {
+  public class HeadersSupportFragment extends android.support.v4.app.Fragment {
     ctor public HeadersSupportFragment();
     method public boolean isScrolling();
+    method public void onTransitionEnd();
+    method public void onTransitionStart();
     method public void setOnHeaderClickedListener(android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderClickedListener);
     method public void setOnHeaderViewSelectedListener(android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderViewSelectedListener);
   }
@@ -754,7 +726,7 @@
     method public void show();
   }
 
-  public deprecated class RowsFragment extends android.support.v17.leanback.app.BaseRowFragment implements android.support.v17.leanback.app.BrowseFragment.MainFragmentAdapterProvider android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapterProvider {
+  public deprecated class RowsFragment extends android.app.Fragment implements android.support.v17.leanback.app.BrowseFragment.MainFragmentAdapterProvider android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapterProvider {
     ctor public RowsFragment();
     method public deprecated void enableRowScaling(boolean);
     method protected android.support.v17.leanback.widget.VerticalGridView findGridViewFromRoot(android.view.View);
@@ -765,6 +737,9 @@
     method public android.support.v17.leanback.widget.BaseOnItemViewSelectedListener getOnItemViewSelectedListener();
     method public android.support.v17.leanback.widget.RowPresenter.ViewHolder getRowViewHolder(int);
     method public boolean isScrolling();
+    method public void onTransitionEnd();
+    method public boolean onTransitionPrepare();
+    method public void setAlignment(int);
     method public void setEntranceTransitionState(boolean);
     method public void setExpand(boolean);
     method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.BaseOnItemViewClickedListener);
@@ -780,7 +755,7 @@
     ctor public RowsFragment.MainFragmentRowsAdapter(android.support.v17.leanback.app.RowsFragment);
   }
 
-  public class RowsSupportFragment extends android.support.v17.leanback.app.BaseRowSupportFragment implements android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentAdapterProvider android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapterProvider {
+  public class RowsSupportFragment extends android.support.v4.app.Fragment implements android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentAdapterProvider android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapterProvider {
     ctor public RowsSupportFragment();
     method public deprecated void enableRowScaling(boolean);
     method protected android.support.v17.leanback.widget.VerticalGridView findGridViewFromRoot(android.view.View);
@@ -791,6 +766,9 @@
     method public android.support.v17.leanback.widget.BaseOnItemViewSelectedListener getOnItemViewSelectedListener();
     method public android.support.v17.leanback.widget.RowPresenter.ViewHolder getRowViewHolder(int);
     method public boolean isScrolling();
+    method public void onTransitionEnd();
+    method public boolean onTransitionPrepare();
+    method public void setAlignment(int);
     method public void setEntranceTransitionState(boolean);
     method public void setExpand(boolean);
     method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.BaseOnItemViewClickedListener);
@@ -1104,11 +1082,9 @@
     method public final boolean isPlaying();
     method public final boolean isPrepared();
     method protected static void notifyItemChanged(android.support.v17.leanback.widget.ArrayObjectAdapter, java.lang.Object);
-    method public abstract void onActionClicked(android.support.v17.leanback.widget.Action);
     method protected void onCreatePrimaryActions(android.support.v17.leanback.widget.ArrayObjectAdapter);
     method protected abstract android.support.v17.leanback.widget.PlaybackRowPresenter onCreateRowPresenter();
     method protected void onCreateSecondaryActions(android.support.v17.leanback.widget.ArrayObjectAdapter);
-    method public abstract boolean onKey(android.view.View, int, android.view.KeyEvent);
     method protected void onMetadataChanged();
     method protected void onPlayCompleted();
     method protected void onPlayStateChanged();
@@ -2826,7 +2802,7 @@
     method public abstract void requestAudioPermission();
   }
 
-  public class SearchEditText extends android.support.v17.leanback.widget.StreamingTextView {
+  public class SearchEditText extends android.widget.EditText {
     ctor public SearchEditText(android.content.Context);
     ctor public SearchEditText(android.content.Context, android.util.AttributeSet);
     ctor public SearchEditText(android.content.Context, android.util.AttributeSet, int);
@@ -2969,16 +2945,6 @@
     method public abstract void recognizeSpeech();
   }
 
-   class StreamingTextView extends android.widget.EditText {
-    ctor public StreamingTextView(android.content.Context, android.util.AttributeSet);
-    ctor public StreamingTextView(android.content.Context, android.util.AttributeSet, int);
-    method public static boolean isLayoutRtl(android.view.View);
-    method public void reset();
-    method public void setFinalRecognizedText(java.lang.CharSequence);
-    method public void updateRecognizedText(java.lang.String, java.lang.String);
-    method public void updateRecognizedText(java.lang.String, java.util.List<java.lang.Float>);
-  }
-
   public class TitleHelper {
     ctor public TitleHelper(android.view.ViewGroup, android.view.View);
     method public android.support.v17.leanback.widget.BrowseFrameLayout.OnFocusSearchListener getOnFocusSearchListener();
diff --git a/leanback/build.gradle b/leanback/build.gradle
index 4ebec71..036f08f 100644
--- a/leanback/build.gradle
+++ b/leanback/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,16 +7,16 @@
 }
 
 dependencies {
-    api project(':support-compat')
-    api project(':support-core-ui')
-    api project(':support-media-compat')
-    api project(':support-fragment')
-    api project(':recyclerview-v7')
+    api(project(":support-compat"))
+    api(project(":support-core-ui"))
+    api(project(":support-media-compat"))
+    api(project(":support-fragment"))
+    api(project(":recyclerview-v7"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
 }
 
 android {
diff --git a/leanback/lint-baseline.xml b/leanback/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/leanback/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java b/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
index d7020e9..9d159ec 100644
--- a/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
+++ b/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
@@ -2726,40 +2726,6 @@
         }
     }
 
-    // Observer is registered on Adapter to invalidate saved instance state
-    final RecyclerView.AdapterDataObserver mObServer = new RecyclerView.AdapterDataObserver() {
-        @Override
-        public void onChanged() {
-            mChildrenStates.clear();
-        }
-
-        @Override
-        public void onItemRangeChanged(int positionStart, int itemCount) {
-            if (DEBUG) {
-                Log.v(getTag(), "onItemRangeChanged positionStart "
-                        + positionStart + " itemCount " + itemCount);
-            }
-            for (int i = positionStart, end = positionStart + itemCount; i < end; i++) {
-                mChildrenStates.remove(i);
-            }
-        }
-
-        @Override
-        public void onItemRangeInserted(int positionStart, int itemCount) {
-            mChildrenStates.clear();
-        }
-
-        @Override
-        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
-            mChildrenStates.clear();
-        }
-
-        @Override
-        public void onItemRangeRemoved(int positionStart, int itemCount) {
-            mChildrenStates.clear();
-        }
-    };
-
     @Override
     public void onItemsAdded(RecyclerView recyclerView, int positionStart, int itemCount) {
         if (DEBUG) Log.v(getTag(), "onItemsAdded positionStart "
@@ -2771,12 +2737,14 @@
                 mFocusPositionOffset += itemCount;
             }
         }
+        mChildrenStates.clear();
     }
 
     @Override
     public void onItemsChanged(RecyclerView recyclerView) {
         if (DEBUG) Log.v(getTag(), "onItemsChanged");
         mFocusPositionOffset = 0;
+        mChildrenStates.clear();
     }
 
     @Override
@@ -2797,6 +2765,7 @@
                 }
             }
         }
+        mChildrenStates.clear();
     }
 
     @Override
@@ -2817,6 +2786,16 @@
                 mFocusPositionOffset += itemCount;
             }
         }
+        mChildrenStates.clear();
+    }
+
+    @Override
+    public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount) {
+        if (DEBUG) Log.v(getTag(), "onItemsUpdated positionStart "
+                + positionStart + " itemCount " + itemCount);
+        for (int i = positionStart, end = positionStart + itemCount; i < end; i++) {
+            mChildrenStates.remove(i);
+        }
     }
 
     @Override
@@ -3515,16 +3494,12 @@
             mFocusPosition = NO_POSITION;
             mFocusPositionOffset = 0;
             mChildrenStates.clear();
-            oldAdapter.unregisterAdapterDataObserver(mObServer);
         }
         if (newAdapter instanceof FacetProviderAdapter) {
             mFacetProviderAdapter = (FacetProviderAdapter) newAdapter;
         } else {
             mFacetProviderAdapter = null;
         }
-        if (newAdapter != null) {
-            newAdapter.registerAdapterDataObserver(mObServer);
-        }
         super.onAdapterChanged(oldAdapter, newAdapter);
     }
 
diff --git a/leanback/src/android/support/v17/leanback/widget/WindowAlignment.java b/leanback/src/android/support/v17/leanback/widget/WindowAlignment.java
index 55fa758..c6589d4 100644
--- a/leanback/src/android/support/v17/leanback/widget/WindowAlignment.java
+++ b/leanback/src/android/support/v17/leanback/widget/WindowAlignment.java
@@ -390,11 +390,7 @@
 
     @Override
     public String toString() {
-        return new StringBuffer().append("horizontal=")
-                .append(horizontal.toString())
-                .append("; vertical=")
-                .append(vertical.toString())
-                .toString();
+        return "horizontal=" + horizontal + "; vertical=" + vertical;
     }
 
 }
diff --git a/lifecycle/common-java8/build.gradle b/lifecycle/common-java8/build.gradle
index 7877b81..137ea32 100644
--- a/lifecycle/common-java8/build.gradle
+++ b/lifecycle/common-java8/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions;
 import android.support.SupportLibraryExtension;
@@ -23,14 +24,12 @@
 }
 
 dependencies {
-    testCompile libs.junit
-    testCompile libs.mockito_core
-    compile project(":lifecycle:common")
+    testCompile(JUNIT)
+    testCompile(MOCKITO_CORE)
+    compile(project(":lifecycle:common"))
     compile libs.support.annotations
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Lifecycle-Common for Java 8 Language"
     publish = true
diff --git a/lifecycle/common/build.gradle b/lifecycle/common/build.gradle
index a3b06dd..bc46d17 100644
--- a/lifecycle/common/build.gradle
+++ b/lifecycle/common/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions;
 import android.support.SupportLibraryExtension;
@@ -23,13 +24,11 @@
 }
 
 dependencies {
-    testCompile libs.junit
-    testCompile libs.mockito_core
+    testCompile(JUNIT)
+    testCompile(MOCKITO_CORE)
     compile libs.support.annotations
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Lifecycle-Common"
     publish = true
diff --git a/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java b/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java
index c0a2090..e04cdb4 100644
--- a/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java
+++ b/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java
@@ -108,6 +108,7 @@
      * @return The current state of the Lifecycle.
      */
     @MainThread
+    @NonNull
     public abstract State getCurrentState();
 
     @SuppressWarnings("WeakerAccess")
diff --git a/lifecycle/compiler/build.gradle b/lifecycle/compiler/build.gradle
index edc54b0..534d1ec 100644
--- a/lifecycle/compiler/build.gradle
+++ b/lifecycle/compiler/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -10,23 +11,20 @@
 // Temporary hack to stop AS to adding two guavas into test's classpath
 configurations.all {
     resolutionStrategy {
-        force libs.guava
+        force GUAVA
     }
 }
 
 dependencies {
-    compile project(":lifecycle:common")
-    compile libs.kotlin.stdlib
-    compile libs.auto_common
-    compile libs.javapoet
-    testCompile libs.google_compile_testing
-    testCompile libs.jsr250
+    compile(project(":lifecycle:common"))
+    compile(KOTLIN_STDLIB)
+    compile(AUTO_COMMON)
+    compile(JAVAPOET)
+    testCompile(GOOGLE_COMPILE_TESTING)
+    testCompile(JSR250)
     testCompile files(org.gradle.internal.jvm.Jvm.current().getToolsJar())
 }
 
-version = LibraryVersions.LIFECYCLES_EXT.toString()
-createKotlinCheckstyle(project)
-
 // we actually need to compile :lifecycle:common, but compileJava is easier
 task compileTestLibrarySource(type: JavaCompile, dependsOn: compileJava) {
     source "src/tests/test-data/lib/src"
@@ -43,7 +41,7 @@
 supportLibrary {
     name = "Android Lifecycles Compiler"
     publish = true
-    mavenVersion = LibraryVersions.LIFECYCLES_CORE
+    mavenVersion = LibraryVersions.LIFECYCLES_EXT
     mavenGroup = LibraryGroups.LIFECYCLE
     inceptionYear = "2017"
     description = "Android Lifecycles annotation processor"
diff --git a/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/LifecycleProcessor.kt b/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/LifecycleProcessor.kt
index 5355615..f57d2dd 100644
--- a/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/LifecycleProcessor.kt
+++ b/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/LifecycleProcessor.kt
@@ -19,7 +19,6 @@
 import javax.annotation.processing.AbstractProcessor
 import javax.annotation.processing.RoundEnvironment
 import javax.annotation.processing.SupportedAnnotationTypes
-import javax.annotation.processing.SupportedSourceVersion
 import javax.lang.model.SourceVersion
 import javax.lang.model.element.TypeElement
 
diff --git a/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/elements_ext.kt b/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/elements_ext.kt
index ed20c54..08b6ff2 100644
--- a/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/elements_ext.kt
+++ b/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/elements_ext.kt
@@ -38,7 +38,7 @@
 
 fun TypeElement.methods(): List<ExecutableElement> = ElementFilter.methodsIn(enclosedElements)
 
-private const val SYNTHETIC =  "__synthetic_"
+private const val SYNTHETIC = "__synthetic_"
 
 fun syntheticName(method: ExecutableElement) = "$SYNTHETIC${method.simpleName}"
 
diff --git a/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/writer.kt b/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/writer.kt
index 00549ee..5811c61 100644
--- a/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/writer.kt
+++ b/lifecycle/compiler/src/main/kotlin/android/arch/lifecycle/writer.kt
@@ -28,7 +28,6 @@
 import com.squareup.javapoet.TypeName
 import com.squareup.javapoet.TypeSpec
 import javax.annotation.processing.ProcessingEnvironment
-import javax.lang.model.element.ExecutableElement
 import javax.lang.model.element.Modifier
 import javax.lang.model.element.TypeElement
 import javax.tools.StandardLocation
@@ -149,10 +148,11 @@
     val adapterClass = type.getPackageQName() + "." + getAdapterName(type)
     val observerClass = type.toString()
     val keepRule = """# Generated keep rule for Lifecycle observer adapter.
+        |-if class $observerClass {
+        |    <init>(...);
+        |}
         |-keep class $adapterClass {
-        |   ifused class $observerClass {
-        |       <init>(...);
-        |   };
+        |    <init>(...);
         |}
         |""".trimMargin()
 
@@ -178,7 +178,6 @@
                 addStatement("$N.$L($paramString)", receiverField,
                         methodName,
                         *takeParams(count, OWNER_PARAM, EVENT_PARAM))
-
             } else {
                 val originalType = syntheticAccess
                 val paramString = generateParamString(count + 1)
@@ -195,4 +194,4 @@
 
 private fun takeParams(count: Int, vararg params: Any) = params.take(count).toTypedArray()
 
-private fun generateParamString(count: Int) = (0 until count).joinToString(",") { N }
\ No newline at end of file
+private fun generateParamString(count: Int) = (0 until count).joinToString(",") { N }
diff --git a/lifecycle/extensions/build.gradle b/lifecycle/extensions/build.gradle
index 6bd1bce..38640b6 100644
--- a/lifecycle/extensions/build.gradle
+++ b/lifecycle/extensions/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -33,23 +34,21 @@
 }
 
 dependencies {
-    api project(":lifecycle:runtime")
-    api project(":arch:common")
-    api project(":arch:runtime")
+    api(project(":lifecycle:runtime"))
+    api(project(":arch:common"))
+    api(project(":arch:runtime"))
     api libs.support.fragments, libs.support_exclude_config
-    api project(":lifecycle:common")
+    api(project(":lifecycle:common"))
 
-    testImplementation project(":arch:core-testing")
-    testImplementation libs.junit
-    testImplementation libs.mockito_core
+    testImplementation(project(":arch:core-testing"))
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
     androidTestImplementation libs.support.app_compat, libs.support_exclude_config
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Lifecycle Extensions"
     publish = true
diff --git a/lifecycle/extensions/lint-baseline.xml b/lifecycle/extensions/lint-baseline.xml
deleted file mode 100644
index 2cadde1..0000000
--- a/lifecycle/extensions/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0">
-
-</issues>
diff --git a/lifecycle/integration-tests/testapp/build.gradle b/lifecycle/integration-tests/testapp/build.gradle
index 64159bd..9f970a5 100644
--- a/lifecycle/integration-tests/testapp/build.gradle
+++ b/lifecycle/integration-tests/testapp/build.gradle
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-apply plugin: 'com.android.application'
+import static android.support.dependencies.DependenciesKt.*
 
-project.ext.noDocs = true
+apply plugin: 'com.android.application'
 
 android {
     compileSdkVersion tools.current_sdk
@@ -60,24 +60,19 @@
 
 dependencies {
     // IJ canont figure out transitive dependencies so need to declare them.
-    implementation project(":lifecycle:common")
-    implementation project(":lifecycle:runtime")
-    implementation project(":lifecycle:extensions")
-    annotationProcessor project(":lifecycle:compiler")
+    implementation(project(":lifecycle:common"))
+    implementation(project(":lifecycle:runtime"))
+    implementation(project(":lifecycle:extensions"))
+    annotationProcessor(project(":lifecycle:compiler"))
 
-    androidTestAnnotationProcessor project(":lifecycle:compiler")
-    androidTestImplementation(libs.test_runner) {
-        exclude module: 'support-annotations'
-    }
-    androidTestImplementation(libs.espresso_core, {
-        exclude group: 'com.android.support', module: 'support-annotations'
-    })
+    androidTestAnnotationProcessor(project(":lifecycle:compiler"))
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
 
-    testImplementation libs.junit
-    testImplementation libs.mockito_core
-    testAnnotationProcessor project(":lifecycle:compiler")
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
+    testAnnotationProcessor(project(":lifecycle:compiler"))
 }
-createAndroidCheckstyle(project)
 
 tasks['check'].dependsOn(tasks['connectedCheck'])
 
diff --git a/lifecycle/reactivestreams/build.gradle b/lifecycle/reactivestreams/build.gradle
index d2beeed..511ad7a 100644
--- a/lifecycle/reactivestreams/build.gradle
+++ b/lifecycle/reactivestreams/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -28,27 +29,21 @@
     }
 }
 
-allprojects {
-    dependencies {
-        api project(":arch:common")
-        api project(":lifecycle:common")
-        api project(":lifecycle:extensions")
-        api project(":lifecycle:runtime")
-        api libs.support.annotations
-        api libs.reactive_streams
+dependencies {
+    api(project(":arch:common"))
+    api(project(":lifecycle:common"))
+    api(project(":lifecycle:extensions"))
+    api(project(":lifecycle:runtime"))
+    api libs.support.annotations
+    api(REACTIVE_STREAMS)
 
-        testImplementation libs.junit
-        testImplementation libs.rx_java
+    testImplementation(JUNIT)
+    testImplementation(RX_JAVA)
+    testImplementation(TEST_RUNNER)
 
-        testImplementation(libs.test_runner) {
-            exclude module: 'support-annotations'
-        }
-        androidTestImplementation libs.support.app_compat, libs.support_exclude_config
-    }
+    androidTestImplementation libs.support.app_compat, libs.support_exclude_config
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Lifecycle Reactivestreams"
     publish = true
diff --git a/lifecycle/reactivestreams/lint-baseline.xml b/lifecycle/reactivestreams/lint-baseline.xml
deleted file mode 100644
index 2cadde1..0000000
--- a/lifecycle/reactivestreams/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0">
-
-</issues>
diff --git a/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java b/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java
index ba76f8e..ed3c57c 100644
--- a/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java
+++ b/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java
@@ -50,8 +50,9 @@
      * will buffer the latest item and emit it to the subscriber when data is again requested. Any
      * other items emitted during the time there was no backpressure requested will be dropped.
      */
+    @NonNull
     public static <T> Publisher<T> toPublisher(
-            final LifecycleOwner lifecycle, final LiveData<T> liveData) {
+            @NonNull LifecycleOwner lifecycle, @NonNull LiveData<T> liveData) {
 
         return new LiveDataPublisher<>(lifecycle, liveData);
     }
@@ -60,7 +61,7 @@
         final LifecycleOwner mLifecycle;
         final LiveData<T> mLiveData;
 
-        LiveDataPublisher(final LifecycleOwner lifecycle, final LiveData<T> liveData) {
+        LiveDataPublisher(LifecycleOwner lifecycle, LiveData<T> liveData) {
             this.mLifecycle = lifecycle;
             this.mLiveData = liveData;
         }
@@ -91,7 +92,7 @@
             }
 
             @Override
-            public void onChanged(T t) {
+            public void onChanged(@Nullable T t) {
                 if (mCanceled) {
                     return;
                 }
@@ -183,7 +184,8 @@
      *
      * @param <T> The type of data hold by this instance.
      */
-    public static <T> LiveData<T> fromPublisher(final Publisher<T> publisher) {
+    @NonNull
+    public static <T> LiveData<T> fromPublisher(@NonNull Publisher<T> publisher) {
         return new PublisherLiveData<>(publisher);
     }
 
@@ -209,10 +211,10 @@
      * @param <T> The type of data hold by this instance.
      */
     private static class PublisherLiveData<T> extends LiveData<T> {
-        private final Publisher mPublisher;
+        private final Publisher<T> mPublisher;
         final AtomicReference<LiveDataSubscriber> mSubscriber;
 
-        PublisherLiveData(@NonNull final Publisher publisher) {
+        PublisherLiveData(@NonNull Publisher<T> publisher) {
             mPublisher = publisher;
             mSubscriber = new AtomicReference<>();
         }
diff --git a/lifecycle/runtime/build.gradle b/lifecycle/runtime/build.gradle
index 01a8abb..44e992b 100644
--- a/lifecycle/runtime/build.gradle
+++ b/lifecycle/runtime/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -17,20 +18,18 @@
 }
 
 dependencies {
-    api project(":lifecycle:common")
-    api project(":arch:common")
+    api(project(":lifecycle:common"))
+    api(project(":arch:common"))
     // necessary for IJ to resolve dependencies.
     api libs.support.annotations
 
-    testImplementation libs.junit
-    testImplementation libs.mockito_core
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
 
-    androidTestImplementation libs.junit
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
+    androidTestImplementation(JUNIT)
+    androidTestImplementation(TEST_RUNNER)
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name 'Android Lifecycle Runtime'
     publish true
diff --git a/lifecycle/runtime/lint-baseline.xml b/lifecycle/runtime/lint-baseline.xml
deleted file mode 100644
index 2cadde1..0000000
--- a/lifecycle/runtime/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0">
-
-</issues>
diff --git a/lifecycle/runtime/src/main/java/android/arch/lifecycle/LifecycleRegistry.java b/lifecycle/runtime/src/main/java/android/arch/lifecycle/LifecycleRegistry.java
index bf8aff7..eff946b 100644
--- a/lifecycle/runtime/src/main/java/android/arch/lifecycle/LifecycleRegistry.java
+++ b/lifecycle/runtime/src/main/java/android/arch/lifecycle/LifecycleRegistry.java
@@ -225,6 +225,7 @@
         return mObserverMap.size();
     }
 
+    @NonNull
     @Override
     public State getCurrentState() {
         return mState;
diff --git a/media-compat/build.gradle b/media-compat/build.gradle
index ec4504e..18ff5a3 100644
--- a/media-compat/build.gradle
+++ b/media-compat/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,13 +7,13 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-compat')
+    api(project(":support-annotations"))
+    api(project(":support-compat"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
     androidTestImplementation project(':support-testutils')
 }
 
diff --git a/media-compat/java/android/support/v4/media/session/IMediaSession.aidl b/media-compat/java/android/support/v4/media/session/IMediaSession.aidl
index 56c04ac..f32f449 100644
--- a/media-compat/java/android/support/v4/media/session/IMediaSession.aidl
+++ b/media-compat/java/android/support/v4/media/session/IMediaSession.aidl
@@ -30,7 +30,7 @@
 import java.util.List;
 
 /**
- * Interface to a MediaSessionCompat. This is only used on pre-Lollipop systems.
+ * Interface to a MediaSessionCompat.
  * @hide
  */
 interface IMediaSession {
diff --git a/media-compat/java/android/support/v4/media/session/MediaControllerCompat.java b/media-compat/java/android/support/v4/media/session/MediaControllerCompat.java
index 2509cd4..f24da1e 100644
--- a/media-compat/java/android/support/v4/media/session/MediaControllerCompat.java
+++ b/media-compat/java/android/support/v4/media/session/MediaControllerCompat.java
@@ -1919,6 +1919,7 @@
                 }
             } else {
                 synchronized (mPendingCallbacks) {
+                    callback.mHasExtraCallback = false;
                     mPendingCallbacks.add(callback);
                 }
             }
@@ -1931,6 +1932,7 @@
                 try {
                     ExtraCallback extraCallback = mCallbackMap.remove(callback);
                     if (extraCallback != null) {
+                        callback.mHasExtraCallback = false;
                         mExtraBinder.unregisterCallbackListener(extraCallback);
                     }
                 } catch (RemoteException e) {
diff --git a/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java b/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java
index d7634b0..3b06125 100644
--- a/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java
+++ b/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java
@@ -24,6 +24,7 @@
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.support.annotation.IntDef;
+import android.support.annotation.LongDef;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.text.TextUtils;
@@ -45,7 +46,7 @@
      * @hide
      */
     @RestrictTo(LIBRARY_GROUP)
-    @IntDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
+    @LongDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
             ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING,
             ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH,
             ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE,
@@ -58,7 +59,7 @@
      * @hide
      */
     @RestrictTo(LIBRARY_GROUP)
-    @IntDef({ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND, ACTION_SKIP_TO_PREVIOUS,
+    @LongDef({ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND, ACTION_SKIP_TO_PREVIOUS,
             ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_PLAY_PAUSE})
     @Retention(RetentionPolicy.SOURCE)
     public @interface MediaKeyAction {}
diff --git a/media-compat/lint-baseline.xml b/media-compat/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/media-compat/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/media-compat/tests/AndroidManifest.xml b/media-compat/tests/AndroidManifest.xml
deleted file mode 100644
index 6d9a4f6..0000000
--- a/media-compat/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-   Copyright (C) 2016 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.support.mediacompat.test">
-    <uses-sdk android:targetSdkVersion="${target-sdk-version}"/>
-
-    <application android:supportsRtl="true">
-        <receiver android:name="android.support.v4.media.session.MediaButtonReceiver">
-            <intent-filter>
-                <action android:name="android.intent.action.MEDIA_BUTTON"/>
-            </intent-filter>
-        </receiver>
-        <service android:name="android.support.v4.media.StubMediaBrowserServiceCompat">
-            <intent-filter>
-                <action android:name="android.media.browse.MediaBrowserService"/>
-            </intent-filter>
-        </service>
-        <service android:name="android.support.v4.media.StubRemoteMediaBrowserServiceCompat"
-                 android:process=":remote">
-            <intent-filter>
-                <action android:name="android.media.browse.MediaBrowserService"/>
-            </intent-filter>
-        </service>
-        <service
-            android:name="android.support.v4.media.StubMediaBrowserServiceCompatWithDelayedMediaSession">
-            <intent-filter>
-                <action android:name="android.media.browse.MediaBrowserService"/>
-            </intent-filter>
-        </service>
-    </application>
-
-</manifest>
diff --git a/media-compat/tests/src/android/support/v4/media/MediaBrowserCompatTest.java b/media-compat/tests/src/android/support/v4/media/MediaBrowserCompatTest.java
deleted file mode 100644
index 6356e33..0000000
--- a/media-compat/tests/src/android/support/v4/media/MediaBrowserCompatTest.java
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v4.media;
-
-import static android.support.test.InstrumentationRegistry.getInstrumentation;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
-
-import android.content.ComponentName;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.test.filters.LargeTest;
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.testutils.PollingCheck;
-import android.support.v4.media.MediaBrowserCompat.MediaItem;
-import android.support.v4.media.session.MediaControllerCompat;
-import android.support.v4.media.session.MediaSessionCompat;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Test {@link android.support.v4.media.MediaBrowserCompat}.
- */
-@RunWith(AndroidJUnit4.class)
-public class MediaBrowserCompatTest {
-
-    // The maximum time to wait for an operation.
-    private static final long TIME_OUT_MS = 3000L;
-
-    /**
-     * To check {@link MediaBrowserCompat#unsubscribe} works properly,
-     * we notify to the browser after the unsubscription that the media items have changed.
-     * Then {@link MediaBrowserCompat.SubscriptionCallback#onChildrenLoaded} should not be called.
-     *
-     * The measured time from calling {@link StubMediaBrowserServiceCompat#notifyChildrenChanged}
-     * to {@link MediaBrowserCompat.SubscriptionCallback#onChildrenLoaded} being called is about
-     * 50ms.
-     * So we make the thread sleep for 100ms to properly check that the callback is not called.
-     */
-    private static final long SLEEP_MS = 100L;
-    private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
-            "android.support.mediacompat.test",
-            "android.support.v4.media.StubMediaBrowserServiceCompat");
-    private static final ComponentName TEST_REMOTE_BROWSER_SERVICE = new ComponentName(
-            "android.support.mediacompat.test",
-            "android.support.v4.media.StubRemoteMediaBrowserServiceCompat");
-    private static final ComponentName TEST_INVALID_BROWSER_SERVICE = new ComponentName(
-            "invalid.package", "invalid.ServiceClassName");
-
-    private MediaBrowserCompat mMediaBrowser;
-    private StubConnectionCallback mConnectionCallback;
-    private StubSubscriptionCallback mSubscriptionCallback;
-    private StubItemCallback mItemCallback;
-
-    @Before
-    public void setUp() {
-        mConnectionCallback = new StubConnectionCallback();
-        mSubscriptionCallback = new StubSubscriptionCallback();
-        mItemCallback = new StubItemCallback();
-    }
-
-    @Test
-    @SmallTest
-    public void testMediaBrowser() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        assertFalse(mMediaBrowser.isConnected());
-
-        connectMediaBrowserService();
-        assertTrue(mMediaBrowser.isConnected());
-
-        assertEquals(TEST_BROWSER_SERVICE, mMediaBrowser.getServiceComponent());
-        assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT, mMediaBrowser.getRoot());
-        assertEquals(StubMediaBrowserServiceCompat.EXTRAS_VALUE,
-                mMediaBrowser.getExtras().getString(StubMediaBrowserServiceCompat.EXTRAS_KEY));
-        assertEquals(StubMediaBrowserServiceCompat.sSession.getSessionToken(),
-                mMediaBrowser.getSessionToken());
-
-        mMediaBrowser.disconnect();
-        new PollingCheck(TIME_OUT_MS) {
-            @Override
-            protected boolean check() {
-                return !mMediaBrowser.isConnected();
-            }
-        }.run();
-    }
-
-    @Test
-    @SmallTest
-    public void testMediaBrowserWithRemoteService() throws Exception {
-        createMediaBrowser(TEST_REMOTE_BROWSER_SERVICE);
-        assertFalse(mMediaBrowser.isConnected());
-
-        connectMediaBrowserService();
-        assertTrue(mMediaBrowser.isConnected());
-
-        assertEquals(TEST_REMOTE_BROWSER_SERVICE, mMediaBrowser.getServiceComponent());
-        assertEquals(StubRemoteMediaBrowserServiceCompat.MEDIA_ID_ROOT, mMediaBrowser.getRoot());
-        assertEquals(StubRemoteMediaBrowserServiceCompat.EXTRAS_VALUE,
-                mMediaBrowser.getExtras().getString(
-                        StubRemoteMediaBrowserServiceCompat.EXTRAS_KEY));
-
-        mMediaBrowser.disconnect();
-        new PollingCheck(TIME_OUT_MS) {
-            @Override
-            protected boolean check() {
-                return !mMediaBrowser.isConnected();
-            }
-        }.run();
-    }
-
-    @Test
-    @SmallTest
-    public void testSessionReadyWithRemoteService() throws Exception {
-        if (android.os.Build.VERSION.SDK_INT < 21) {
-            // This test is for API 21+
-            return;
-        }
-
-        createMediaBrowser(TEST_REMOTE_BROWSER_SERVICE);
-        assertFalse(mMediaBrowser.isConnected());
-
-        connectMediaBrowserService();
-        assertTrue(mMediaBrowser.isConnected());
-
-        // Create a session token by removing the extra binder of the token from MediaBrowserCompat.
-        final MediaSessionCompat.Token tokenWithoutExtraBinder = MediaSessionCompat.Token.fromToken(
-                mMediaBrowser.getSessionToken().getToken());
-
-        final MediaControllerCallback callback = new MediaControllerCallback();
-        synchronized (callback.mWaitLock) {
-            getInstrumentation().runOnMainSync(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        MediaControllerCompat controller = new MediaControllerCompat(
-                                getInstrumentation().getTargetContext(), tokenWithoutExtraBinder);
-                        controller.registerCallback(callback, new Handler());
-                        assertFalse(controller.isSessionReady());
-                    } catch (Exception e) {
-                        fail();
-                    }
-                }
-            });
-            callback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(callback.mOnSessionReadyCalled);
-        }
-
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testSubscriptionWithCustomOptionsWithRemoteService() throws Exception {
-        final String mediaId = "1000";
-        createMediaBrowser(TEST_REMOTE_BROWSER_SERVICE);
-        assertFalse(mMediaBrowser.isConnected());
-
-        connectMediaBrowserService();
-        assertTrue(mMediaBrowser.isConnected());
-
-        MediaMetadataCompat mediaMetadataCompat = new MediaMetadataCompat.Builder()
-                .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, mediaId)
-                .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "title")
-                .putRating(MediaMetadataCompat.METADATA_KEY_RATING,
-                        RatingCompat.newPercentageRating(0.5f))
-                .putRating(MediaMetadataCompat.METADATA_KEY_USER_RATING,
-                        RatingCompat.newPercentageRating(0.8f))
-                .build();
-        Bundle options = new Bundle();
-        options.putParcelable(
-                StubRemoteMediaBrowserServiceCompat.MEDIA_METADATA, mediaMetadataCompat);
-
-        // Remote MediaBrowserService will create a media item with the given MediaMetadataCompat
-        mMediaBrowser.subscribe(mMediaBrowser.getRoot(), options, mSubscriptionCallback);
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(1, mSubscriptionCallback.mChildrenLoadedWithOptionCount);
-            assertEquals(1, mSubscriptionCallback.mLastChildMediaItems.size());
-            assertEquals(mediaId, mSubscriptionCallback.mLastChildMediaItems.get(0).getMediaId());
-        }
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testConnectTwice() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        connectMediaBrowserService();
-        try {
-            mMediaBrowser.connect();
-            fail();
-        } catch (IllegalStateException e) {
-            // expected
-        }
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testConnectionFailed() throws Exception {
-        createMediaBrowser(TEST_INVALID_BROWSER_SERVICE);
-
-        synchronized (mConnectionCallback.mWaitLock) {
-            mMediaBrowser.connect();
-            mConnectionCallback.mWaitLock.wait(TIME_OUT_MS);
-        }
-        assertTrue(mConnectionCallback.mConnectionFailedCount > 0);
-        assertEquals(0, mConnectionCallback.mConnectedCount);
-        assertEquals(0, mConnectionCallback.mConnectionSuspendedCount);
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testReconnection() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mMediaBrowser.connect();
-                // Reconnect before the first connection was established.
-                mMediaBrowser.disconnect();
-                mMediaBrowser.connect();
-            }
-        });
-
-        synchronized (mConnectionCallback.mWaitLock) {
-            mConnectionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(1, mConnectionCallback.mConnectedCount);
-        }
-
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            // Test subscribe.
-            resetCallbacks();
-            mMediaBrowser.subscribe(
-                    StubMediaBrowserServiceCompat.MEDIA_ID_ROOT, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedCount > 0);
-            assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT,
-                    mSubscriptionCallback.mLastParentId);
-        }
-
-        synchronized (mItemCallback.mWaitLock) {
-            // Test getItem.
-            resetCallbacks();
-            mMediaBrowser.getItem(
-                    StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN[0], mItemCallback);
-            mItemCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN[0],
-                    mItemCallback.mLastMediaItem.getMediaId());
-        }
-
-        // Reconnect after connection was established.
-        mMediaBrowser.disconnect();
-        resetCallbacks();
-        connectMediaBrowserService();
-
-        synchronized (mItemCallback.mWaitLock) {
-            // Test getItem.
-            resetCallbacks();
-            mMediaBrowser.getItem(
-                    StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN[0], mItemCallback);
-            mItemCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN[0],
-                    mItemCallback.mLastMediaItem.getMediaId());
-        }
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testConnectionCallbackNotCalledAfterDisconnect() {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mMediaBrowser.connect();
-                mMediaBrowser.disconnect();
-                resetCallbacks();
-            }
-        });
-
-        try {
-            Thread.sleep(SLEEP_MS);
-        } catch (InterruptedException e) {
-            fail("Unexpected InterruptedException occurred.");
-        }
-        assertEquals(0, mConnectionCallback.mConnectedCount);
-        assertEquals(0, mConnectionCallback.mConnectionFailedCount);
-        assertEquals(0, mConnectionCallback.mConnectionSuspendedCount);
-    }
-
-    @Test
-    @SmallTest
-    public void testGetServiceComponentBeforeConnection() {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        try {
-            ComponentName serviceComponent = mMediaBrowser.getServiceComponent();
-            fail();
-        } catch (IllegalStateException e) {
-            // expected
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testSubscribe() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        connectMediaBrowserService();
-
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mMediaBrowser.subscribe(
-                    StubMediaBrowserServiceCompat.MEDIA_ID_ROOT, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedCount > 0);
-            assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT,
-                    mSubscriptionCallback.mLastParentId);
-            assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN.length,
-                    mSubscriptionCallback.mLastChildMediaItems.size());
-            for (int i = 0; i < StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN.length; ++i) {
-                assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN[i],
-                        mSubscriptionCallback.mLastChildMediaItems.get(i).getMediaId());
-            }
-        }
-
-        // Test unsubscribe.
-        resetCallbacks();
-        mMediaBrowser.unsubscribe(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT);
-
-        // After unsubscribing, make StubMediaBrowserServiceCompat notify that the children are
-        // changed.
-        StubMediaBrowserServiceCompat.sInstance.notifyChildrenChanged(
-                StubMediaBrowserServiceCompat.MEDIA_ID_ROOT);
-        try {
-            Thread.sleep(SLEEP_MS);
-        } catch (InterruptedException e) {
-            fail("Unexpected InterruptedException occurred.");
-        }
-        // onChildrenLoaded should not be called.
-        assertEquals(0, mSubscriptionCallback.mChildrenLoadedCount);
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testSubscribeWithOptions() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        connectMediaBrowserService();
-        final int pageSize = 3;
-        final int lastPage =
-                (StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN.length - 1) / pageSize;
-        Bundle options = new Bundle();
-        options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
-
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            for (int page = 0; page <= lastPage; ++page) {
-                resetCallbacks();
-                options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
-                mMediaBrowser.subscribe(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT, options,
-                        mSubscriptionCallback);
-                mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-                assertTrue(mSubscriptionCallback.mChildrenLoadedWithOptionCount > 0);
-                assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT,
-                        mSubscriptionCallback.mLastParentId);
-                if (page != lastPage) {
-                    assertEquals(pageSize, mSubscriptionCallback.mLastChildMediaItems.size());
-                } else {
-                    assertEquals(
-                            (StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN.length - 1) % pageSize
-                                    + 1,
-                            mSubscriptionCallback.mLastChildMediaItems.size());
-                }
-                // Check whether all the items in the current page are loaded.
-                for (int i = 0; i < mSubscriptionCallback.mLastChildMediaItems.size(); ++i) {
-                    assertEquals(
-                            StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN[page * pageSize + i],
-                            mSubscriptionCallback.mLastChildMediaItems.get(i).getMediaId());
-                }
-            }
-        }
-
-        // Test unsubscribe with callback argument.
-        resetCallbacks();
-        mMediaBrowser.unsubscribe(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT,
-                mSubscriptionCallback);
-
-        // After unsubscribing, make StubMediaBrowserServiceCompat notify that the children are
-        // changed.
-        StubMediaBrowserServiceCompat.sInstance.notifyChildrenChanged(
-                StubMediaBrowserServiceCompat.MEDIA_ID_ROOT);
-        try {
-            Thread.sleep(SLEEP_MS);
-        } catch (InterruptedException e) {
-            fail("Unexpected InterruptedException occurred.");
-        }
-        // onChildrenLoaded should not be called.
-        assertEquals(0, mSubscriptionCallback.mChildrenLoadedCount);
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testSubscribeInvalidItem() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        connectMediaBrowserService();
-
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mMediaBrowser.subscribe(StubMediaBrowserServiceCompat.MEDIA_ID_INVALID,
-                    mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_INVALID,
-                    mSubscriptionCallback.mLastErrorId);
-        }
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testSubscribeInvalidItemWithOptions() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        connectMediaBrowserService();
-
-        final int pageSize = 5;
-        final int page = 2;
-        Bundle options = new Bundle();
-        options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
-        options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
-
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mMediaBrowser.subscribe(StubMediaBrowserServiceCompat.MEDIA_ID_INVALID, options,
-                    mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_INVALID,
-                    mSubscriptionCallback.mLastErrorId);
-            assertNotNull(mSubscriptionCallback.mLastOptions);
-            assertEquals(page,
-                    mSubscriptionCallback.mLastOptions.getInt(MediaBrowserCompat.EXTRA_PAGE));
-            assertEquals(pageSize,
-                    mSubscriptionCallback.mLastOptions.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE));
-        }
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testUnsubscribeForMultipleSubscriptions() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        connectMediaBrowserService();
-        final List<StubSubscriptionCallback> subscriptionCallbacks = new ArrayList<>();
-        final int pageSize = 1;
-
-        // Subscribe four pages, one item per page.
-        for (int page = 0; page < 4; page++) {
-            final StubSubscriptionCallback callback = new StubSubscriptionCallback();
-            subscriptionCallbacks.add(callback);
-
-            Bundle options = new Bundle();
-            options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
-            options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
-            mMediaBrowser.subscribe(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT, options,
-                    callback);
-            synchronized (callback.mWaitLock) {
-                callback.mWaitLock.wait(TIME_OUT_MS);
-            }
-            // Each onChildrenLoaded() must be called.
-            assertEquals(1, callback.mChildrenLoadedWithOptionCount);
-        }
-
-        // Reset callbacks and unsubscribe.
-        for (StubSubscriptionCallback callback : subscriptionCallbacks) {
-            callback.reset();
-        }
-        mMediaBrowser.unsubscribe(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT);
-
-        // After unsubscribing, make StubMediaBrowserServiceCompat notify that the children are
-        // changed.
-        StubMediaBrowserServiceCompat.sInstance.notifyChildrenChanged(
-                StubMediaBrowserServiceCompat.MEDIA_ID_ROOT);
-        try {
-            Thread.sleep(SLEEP_MS);
-        } catch (InterruptedException e) {
-            fail("Unexpected InterruptedException occurred.");
-        }
-
-        // onChildrenLoaded should not be called.
-        for (StubSubscriptionCallback callback : subscriptionCallbacks) {
-            assertEquals(0, callback.mChildrenLoadedWithOptionCount);
-        }
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @MediumTest
-    public void testUnsubscribeWithSubscriptionCallbackForMultipleSubscriptions() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        connectMediaBrowserService();
-        final List<StubSubscriptionCallback> subscriptionCallbacks = new ArrayList<>();
-        final int pageSize = 1;
-
-        // Subscribe four pages, one item per page.
-        for (int page = 0; page < 4; page++) {
-            final StubSubscriptionCallback callback = new StubSubscriptionCallback();
-            subscriptionCallbacks.add(callback);
-
-            Bundle options = new Bundle();
-            options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
-            options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
-            mMediaBrowser.subscribe(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT, options,
-                    callback);
-            synchronized (callback.mWaitLock) {
-                callback.mWaitLock.wait(TIME_OUT_MS);
-            }
-            // Each onChildrenLoaded() must be called.
-            assertEquals(1, callback.mChildrenLoadedWithOptionCount);
-        }
-
-        // Unsubscribe existing subscriptions one-by-one.
-        final int[] orderOfRemovingCallbacks = {2, 0, 3, 1};
-        for (int i = 0; i < orderOfRemovingCallbacks.length; i++) {
-            // Reset callbacks
-            for (StubSubscriptionCallback callback : subscriptionCallbacks) {
-                callback.reset();
-            }
-
-            // Remove one subscription
-            mMediaBrowser.unsubscribe(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT,
-                    subscriptionCallbacks.get(orderOfRemovingCallbacks[i]));
-
-            // Make StubMediaBrowserServiceCompat notify that the children are changed.
-            StubMediaBrowserServiceCompat.sInstance.notifyChildrenChanged(
-                    StubMediaBrowserServiceCompat.MEDIA_ID_ROOT);
-            try {
-                Thread.sleep(SLEEP_MS);
-            } catch (InterruptedException e) {
-                fail("Unexpected InterruptedException occurred.");
-            }
-
-            // Only the remaining subscriptionCallbacks should be called.
-            for (int j = 0; j < 4; j++) {
-                int childrenLoadedWithOptionsCount = subscriptionCallbacks
-                        .get(orderOfRemovingCallbacks[j]).mChildrenLoadedWithOptionCount;
-                if (j <= i) {
-                    assertEquals(0, childrenLoadedWithOptionsCount);
-                } else {
-                    assertEquals(1, childrenLoadedWithOptionsCount);
-                }
-            }
-        }
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testGetItem() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        connectMediaBrowserService();
-
-        synchronized (mItemCallback.mWaitLock) {
-            mMediaBrowser.getItem(StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN[0],
-                    mItemCallback);
-            mItemCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertNotNull(mItemCallback.mLastMediaItem);
-            assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN[0],
-                    mItemCallback.mLastMediaItem.getMediaId());
-        }
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @LargeTest
-    public void testGetItemWhenOnLoadItemIsNotImplemented() throws Exception {
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        connectMediaBrowserService();
-        synchronized (mItemCallback.mWaitLock) {
-            mMediaBrowser.getItem(
-                    StubMediaBrowserServiceCompat.MEDIA_ID_ON_LOAD_ITEM_NOT_IMPLEMENTED,
-                    mItemCallback);
-            mItemCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(StubMediaBrowserServiceCompat.MEDIA_ID_ON_LOAD_ITEM_NOT_IMPLEMENTED,
-                    mItemCallback.mLastErrorId);
-        }
-        mMediaBrowser.disconnect();
-    }
-
-    @Test
-    @SmallTest
-    public void testGetItemWhenMediaIdIsInvalid() throws Exception {
-        mItemCallback.mLastMediaItem = new MediaItem(new MediaDescriptionCompat.Builder()
-                .setMediaId("dummy_id").build(), MediaItem.FLAG_BROWSABLE);
-
-        createMediaBrowser(TEST_BROWSER_SERVICE);
-        connectMediaBrowserService();
-        synchronized (mItemCallback.mWaitLock) {
-            mMediaBrowser.getItem(StubMediaBrowserServiceCompat.MEDIA_ID_INVALID, mItemCallback);
-            mItemCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertNull(mItemCallback.mLastMediaItem);
-            assertNull(mItemCallback.mLastErrorId);
-        }
-        mMediaBrowser.disconnect();
-    }
-
-    private void createMediaBrowser(final ComponentName component) {
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mMediaBrowser = new MediaBrowserCompat(getInstrumentation().getTargetContext(),
-                        component, mConnectionCallback, null);
-            }
-        });
-    }
-
-    private void connectMediaBrowserService() throws Exception {
-        synchronized (mConnectionCallback.mWaitLock) {
-            mMediaBrowser.connect();
-            mConnectionCallback.mWaitLock.wait(TIME_OUT_MS);
-        }
-    }
-
-    private void resetCallbacks() {
-        mConnectionCallback.reset();
-        mSubscriptionCallback.reset();
-        mItemCallback.reset();
-    }
-
-    private class StubConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
-        Object mWaitLock = new Object();
-        volatile int mConnectedCount;
-        volatile int mConnectionFailedCount;
-        volatile int mConnectionSuspendedCount;
-
-        public void reset() {
-            mConnectedCount = 0;
-            mConnectionFailedCount = 0;
-            mConnectionSuspendedCount = 0;
-        }
-
-        @Override
-        public void onConnected() {
-            synchronized (mWaitLock) {
-                mConnectedCount++;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onConnectionFailed() {
-            synchronized (mWaitLock) {
-                mConnectionFailedCount++;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onConnectionSuspended() {
-            synchronized (mWaitLock) {
-                mConnectionSuspendedCount++;
-                mWaitLock.notify();
-            }
-        }
-    }
-
-    private class StubSubscriptionCallback extends MediaBrowserCompat.SubscriptionCallback {
-        Object mWaitLock = new Object();
-        private volatile int mChildrenLoadedCount;
-        private volatile int mChildrenLoadedWithOptionCount;
-        private volatile String mLastErrorId;
-        private volatile String mLastParentId;
-        private volatile Bundle mLastOptions;
-        private volatile List<MediaItem> mLastChildMediaItems;
-
-        public void reset() {
-            mChildrenLoadedCount = 0;
-            mChildrenLoadedWithOptionCount = 0;
-            mLastErrorId = null;
-            mLastParentId = null;
-            mLastOptions = null;
-            mLastChildMediaItems = null;
-        }
-
-        @Override
-        public void onChildrenLoaded(String parentId, List<MediaItem> children) {
-            synchronized (mWaitLock) {
-                mChildrenLoadedCount++;
-                mLastParentId = parentId;
-                mLastChildMediaItems = children;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onChildrenLoaded(String parentId, List<MediaItem> children, Bundle options) {
-            synchronized (mWaitLock) {
-                mChildrenLoadedWithOptionCount++;
-                mLastParentId = parentId;
-                mLastOptions = options;
-                mLastChildMediaItems = children;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onError(String id) {
-            synchronized (mWaitLock) {
-                mLastErrorId = id;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onError(String id, Bundle options) {
-            synchronized (mWaitLock) {
-                mLastErrorId = id;
-                mLastOptions = options;
-                mWaitLock.notify();
-            }
-        }
-    }
-
-    private class StubItemCallback extends MediaBrowserCompat.ItemCallback {
-        Object mWaitLock = new Object();
-        private volatile MediaItem mLastMediaItem;
-        private volatile String mLastErrorId;
-
-        public void reset() {
-            mLastMediaItem = null;
-            mLastErrorId = null;
-        }
-
-        @Override
-        public void onItemLoaded(MediaItem item) {
-            synchronized (mWaitLock) {
-                mLastMediaItem = item;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onError(String id) {
-            synchronized (mWaitLock) {
-                mLastErrorId = id;
-                mWaitLock.notify();
-            }
-        }
-    }
-
-    private class MediaControllerCallback extends MediaControllerCompat.Callback {
-        Object mWaitLock = new Object();
-        private volatile boolean mOnSessionReadyCalled;
-
-        @Override
-        public void onSessionReady() {
-            synchronized (mWaitLock) {
-                mOnSessionReadyCalled = true;
-                mWaitLock.notify();
-            }
-        }
-    }
-}
diff --git a/media-compat/tests/src/android/support/v4/media/MediaBrowserServiceCompatTest.java b/media-compat/tests/src/android/support/v4/media/MediaBrowserServiceCompatTest.java
deleted file mode 100644
index 4ceac10..0000000
--- a/media-compat/tests/src/android/support/v4/media/MediaBrowserServiceCompatTest.java
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.support.v4.media;
-
-import static android.support.test.InstrumentationRegistry.getInstrumentation;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
-
-import android.content.ComponentName;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.testutils.PollingCheck;
-import android.support.v4.media.MediaBrowserCompat.MediaItem;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-/**
- * Test {@link android.support.v4.media.MediaBrowserServiceCompat}.
- */
-@RunWith(AndroidJUnit4.class)
-public class MediaBrowserServiceCompatTest {
-    // The maximum time to wait for an operation.
-    private static final long TIME_OUT_MS = 3000L;
-    private static final long WAIT_TIME_FOR_NO_RESPONSE_MS = 500L;
-    private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
-            "android.support.mediacompat.test",
-            "android.support.v4.media.StubMediaBrowserServiceCompat");
-    private static final ComponentName TEST_BROWSER_SERVICE_DELAYED_MEDIA_SESSION =
-            new ComponentName(
-                    "android.support.mediacompat.test",
-                    "android.support.v4.media"
-                            + ".StubMediaBrowserServiceCompatWithDelayedMediaSession");
-    private static final String TEST_KEY_1 = "key_1";
-    private static final String TEST_VALUE_1 = "value_1";
-    private static final String TEST_KEY_2 = "key_2";
-    private static final String TEST_VALUE_2 = "value_2";
-    private static final String TEST_KEY_3 = "key_3";
-    private static final String TEST_VALUE_3 = "value_3";
-    private static final String TEST_KEY_4 = "key_4";
-    private static final String TEST_VALUE_4 = "value_4";
-    private final Object mWaitLock = new Object();
-
-    private final ConnectionCallback mConnectionCallback = new ConnectionCallback();
-    private final SubscriptionCallback mSubscriptionCallback = new SubscriptionCallback();
-    private final ItemCallback mItemCallback = new ItemCallback();
-    private final SearchCallback mSearchCallback = new SearchCallback();
-
-    private MediaBrowserCompat mMediaBrowser;
-    private MediaBrowserCompat mMediaBrowserForDelayedMediaSession;
-    private StubMediaBrowserServiceCompat mMediaBrowserService;
-    private Bundle mRootHints;
-
-    @Before
-    public void setUp() throws Exception {
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mRootHints = new Bundle();
-                mRootHints.putBoolean(MediaBrowserServiceCompat.BrowserRoot.EXTRA_RECENT, true);
-                mRootHints.putBoolean(MediaBrowserServiceCompat.BrowserRoot.EXTRA_OFFLINE, true);
-                mRootHints.putBoolean(MediaBrowserServiceCompat.BrowserRoot.EXTRA_SUGGESTED, true);
-                mMediaBrowser = new MediaBrowserCompat(getInstrumentation().getTargetContext(),
-                        TEST_BROWSER_SERVICE, mConnectionCallback, mRootHints);
-            }
-        });
-        synchronized (mWaitLock) {
-            mMediaBrowser.connect();
-            mWaitLock.wait(TIME_OUT_MS);
-        }
-        assertNotNull(mMediaBrowserService);
-        mMediaBrowserService.mCustomActionExtras = null;
-        mMediaBrowserService.mCustomActionResult = null;
-    }
-
-    @Test
-    @SmallTest
-    public void testGetSessionToken() {
-        assertEquals(StubMediaBrowserServiceCompat.sSession.getSessionToken(),
-                mMediaBrowserService.getSessionToken());
-    }
-
-    @Test
-    @SmallTest
-    public void testNotifyChildrenChanged() throws Exception {
-        synchronized (mWaitLock) {
-            mSubscriptionCallback.reset();
-            mMediaBrowser.subscribe(
-                    StubMediaBrowserServiceCompat.MEDIA_ID_ROOT, mSubscriptionCallback);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
-
-            mSubscriptionCallback.reset();
-            mMediaBrowserService.notifyChildrenChanged(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testNotifyChildrenChangedWithPagination() throws Exception {
-        synchronized (mWaitLock) {
-            final int pageSize = 5;
-            final int page = 2;
-            Bundle options = new Bundle();
-            options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
-            options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
-
-            mSubscriptionCallback.reset();
-            mMediaBrowser.subscribe(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT, options,
-                    mSubscriptionCallback);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoadedWithOptions);
-
-            mSubscriptionCallback.reset();
-            mMediaBrowserService.notifyChildrenChanged(StubMediaBrowserServiceCompat.MEDIA_ID_ROOT);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoadedWithOptions);
-        }
-    }
-
-    @Test
-    @MediumTest
-    public void testDelayedNotifyChildrenChanged() throws Exception {
-        synchronized (mWaitLock) {
-            mSubscriptionCallback.reset();
-            mMediaBrowser.subscribe(StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN_DELAYED,
-                    mSubscriptionCallback);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertFalse(mSubscriptionCallback.mOnChildrenLoaded);
-
-            mMediaBrowserService.sendDelayedNotifyChildrenChanged();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
-
-            mSubscriptionCallback.reset();
-            mMediaBrowserService.notifyChildrenChanged(
-                    StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN_DELAYED);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertFalse(mSubscriptionCallback.mOnChildrenLoaded);
-
-            mMediaBrowserService.sendDelayedNotifyChildrenChanged();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
-        }
-    }
-
-    @Test
-    @MediumTest
-    public void testDelayedItem() throws Exception {
-        synchronized (mWaitLock) {
-            mItemCallback.reset();
-            mMediaBrowser.getItem(
-                    StubMediaBrowserServiceCompat.MEDIA_ID_CHILDREN_DELAYED, mItemCallback);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertFalse(mItemCallback.mOnItemLoaded);
-
-            mItemCallback.reset();
-            mMediaBrowserService.sendDelayedItemLoaded();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mItemCallback.mOnItemLoaded);
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testSearch() throws Exception {
-        final String key = "test-key";
-        final String val = "test-val";
-
-        synchronized (mWaitLock) {
-            mSearchCallback.reset();
-            mMediaBrowser.search(StubMediaBrowserServiceCompat.SEARCH_QUERY_FOR_NO_RESULT, null,
-                    mSearchCallback);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(mSearchCallback.mOnSearchResult);
-            assertTrue(mSearchCallback.mSearchResults != null
-                    && mSearchCallback.mSearchResults.size() == 0);
-            assertEquals(null, mSearchCallback.mSearchExtras);
-
-            mSearchCallback.reset();
-            mMediaBrowser.search(StubMediaBrowserServiceCompat.SEARCH_QUERY_FOR_ERROR, null,
-                    mSearchCallback);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(mSearchCallback.mOnSearchResult);
-            assertNull(mSearchCallback.mSearchResults);
-            assertEquals(null, mSearchCallback.mSearchExtras);
-
-            mSearchCallback.reset();
-            Bundle extras = new Bundle();
-            extras.putString(key, val);
-            mMediaBrowser.search(StubMediaBrowserServiceCompat.SEARCH_QUERY, extras,
-                    mSearchCallback);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(mSearchCallback.mOnSearchResult);
-            assertNotNull(mSearchCallback.mSearchResults);
-            for (MediaItem item : mSearchCallback.mSearchResults) {
-                assertNotNull(item.getMediaId());
-                assertTrue(item.getMediaId().contains(StubMediaBrowserServiceCompat.SEARCH_QUERY));
-            }
-            assertNotNull(mSearchCallback.mSearchExtras);
-            assertEquals(val, mSearchCallback.mSearchExtras.getString(key));
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testSendCustomAction() throws Exception {
-        synchronized (mWaitLock) {
-            CustomActionCallback callback = new CustomActionCallback();
-            Bundle extras = new Bundle();
-            extras.putString(TEST_KEY_1, TEST_VALUE_1);
-            mMediaBrowser.sendCustomAction(StubMediaBrowserServiceCompat.CUSTOM_ACTION, extras,
-                    callback);
-            new PollingCheck(TIME_OUT_MS) {
-                @Override
-                protected boolean check() {
-                    return mMediaBrowserService.mCustomActionResult != null;
-                }
-            }.run();
-            assertNotNull(mMediaBrowserService.mCustomActionResult);
-            assertNotNull(mMediaBrowserService.mCustomActionExtras);
-            assertEquals(TEST_VALUE_1,
-                    mMediaBrowserService.mCustomActionExtras.getString(TEST_KEY_1));
-
-            callback.reset();
-            Bundle bundle1 = new Bundle();
-            bundle1.putString(TEST_KEY_2, TEST_VALUE_2);
-            mMediaBrowserService.mCustomActionResult.sendProgressUpdate(bundle1);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(callback.mOnProgressUpdateCalled);
-            assertNotNull(callback.mExtras);
-            assertEquals(TEST_VALUE_1, callback.mExtras.getString(TEST_KEY_1));
-            assertNotNull(callback.mData);
-            assertEquals(TEST_VALUE_2, callback.mData.getString(TEST_KEY_2));
-
-            callback.reset();
-            Bundle bundle2 = new Bundle();
-            bundle2.putString(TEST_KEY_3, TEST_VALUE_3);
-            mMediaBrowserService.mCustomActionResult.sendProgressUpdate(bundle2);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(callback.mOnProgressUpdateCalled);
-            assertNotNull(callback.mExtras);
-            assertEquals(TEST_VALUE_1, callback.mExtras.getString(TEST_KEY_1));
-            assertNotNull(callback.mData);
-            assertEquals(TEST_VALUE_3, callback.mData.getString(TEST_KEY_3));
-
-            Bundle bundle3 = new Bundle();
-            bundle3.putString(TEST_KEY_4, TEST_VALUE_4);
-            callback.reset();
-            mMediaBrowserService.mCustomActionResult.sendResult(bundle3);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(callback.mOnResultCalled);
-            assertNotNull(callback.mExtras);
-            assertEquals(TEST_VALUE_1, callback.mExtras.getString(TEST_KEY_1));
-            assertNotNull(callback.mData);
-            assertEquals(TEST_VALUE_4, callback.mData.getString(TEST_KEY_4));
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testSendCustomActionWithDetachedError() throws Exception {
-        synchronized (mWaitLock) {
-            CustomActionCallback callback = new CustomActionCallback();
-            Bundle extras = new Bundle();
-            extras.putString(TEST_KEY_1, TEST_VALUE_1);
-            mMediaBrowser.sendCustomAction(StubMediaBrowserServiceCompat.CUSTOM_ACTION, extras,
-                    callback);
-            new PollingCheck(TIME_OUT_MS) {
-                @Override
-                protected boolean check() {
-                    return mMediaBrowserService.mCustomActionResult != null;
-                }
-            }.run();
-            assertNotNull(mMediaBrowserService.mCustomActionResult);
-            assertNotNull(mMediaBrowserService.mCustomActionExtras);
-            assertEquals(TEST_VALUE_1,
-                    mMediaBrowserService.mCustomActionExtras.getString(TEST_KEY_1));
-
-            callback.reset();
-            Bundle bundle1 = new Bundle();
-            bundle1.putString(TEST_KEY_2, TEST_VALUE_2);
-            mMediaBrowserService.mCustomActionResult.sendProgressUpdate(bundle1);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(callback.mOnProgressUpdateCalled);
-            assertNotNull(callback.mExtras);
-            assertEquals(TEST_VALUE_1, callback.mExtras.getString(TEST_KEY_1));
-            assertNotNull(callback.mData);
-            assertEquals(TEST_VALUE_2, callback.mData.getString(TEST_KEY_2));
-
-            callback.reset();
-            Bundle bundle2 = new Bundle();
-            bundle2.putString(TEST_KEY_3, TEST_VALUE_3);
-            mMediaBrowserService.mCustomActionResult.sendError(bundle2);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(callback.mOnErrorCalled);
-            assertNotNull(callback.mExtras);
-            assertEquals(TEST_VALUE_1, callback.mExtras.getString(TEST_KEY_1));
-            assertNotNull(callback.mData);
-            assertEquals(TEST_VALUE_3, callback.mData.getString(TEST_KEY_3));
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testSendCustomActionWithNullCallback() throws Exception {
-        Bundle extras = new Bundle();
-        extras.putString(TEST_KEY_1, TEST_VALUE_1);
-        mMediaBrowser.sendCustomAction(StubMediaBrowserServiceCompat.CUSTOM_ACTION, extras, null);
-        new PollingCheck(TIME_OUT_MS) {
-            @Override
-            protected boolean check() {
-                return mMediaBrowserService.mCustomActionResult != null;
-            }
-        }.run();
-        assertNotNull(mMediaBrowserService.mCustomActionResult);
-        assertNotNull(mMediaBrowserService.mCustomActionExtras);
-        assertEquals(TEST_VALUE_1, mMediaBrowserService.mCustomActionExtras.getString(TEST_KEY_1));
-    }
-
-    @Test
-    @SmallTest
-    public void testSendCustomActionWithError() throws Exception {
-        synchronized (mWaitLock) {
-            CustomActionCallback callback = new CustomActionCallback();
-            mMediaBrowser.sendCustomAction(StubMediaBrowserServiceCompat.CUSTOM_ACTION_FOR_ERROR,
-                    null, callback);
-            new PollingCheck(TIME_OUT_MS) {
-                @Override
-                protected boolean check() {
-                    return mMediaBrowserService.mCustomActionResult != null;
-                }
-            }.run();
-            assertNotNull(mMediaBrowserService.mCustomActionResult);
-            assertNull(mMediaBrowserService.mCustomActionExtras);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(callback.mOnErrorCalled);
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testBrowserRoot() {
-        final String id = "test-id";
-        final String key = "test-key";
-        final String val = "test-val";
-        final Bundle extras = new Bundle();
-        extras.putString(key, val);
-
-        MediaBrowserServiceCompat.BrowserRoot browserRoot =
-                new MediaBrowserServiceCompat.BrowserRoot(id, extras);
-        assertEquals(id, browserRoot.getRootId());
-        assertEquals(val, browserRoot.getExtras().getString(key));
-    }
-
-    @Test
-    @SmallTest
-    public void testDelayedSetSessionToken() throws Exception {
-        // This test has no meaning in API 21. The framework MediaBrowserService just connects to
-        // the media browser without waiting setMediaSession() to be called.
-        if (Build.VERSION.SDK_INT == 21) {
-            return;
-        }
-        final ConnectionCallbackForDelayedMediaSession callback =
-                new ConnectionCallbackForDelayedMediaSession();
-
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mMediaBrowserForDelayedMediaSession =
-                        new MediaBrowserCompat(getInstrumentation().getTargetContext(),
-                                TEST_BROWSER_SERVICE_DELAYED_MEDIA_SESSION, callback, null);
-            }
-        });
-
-        synchronized (mWaitLock) {
-            mMediaBrowserForDelayedMediaSession.connect();
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertEquals(0, callback.mConnectedCount);
-
-            StubMediaBrowserServiceCompatWithDelayedMediaSession.sInstance.callSetSessionToken();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(1, callback.mConnectedCount);
-
-            if (Build.VERSION.SDK_INT >= 21) {
-                assertNotNull(
-                        mMediaBrowserForDelayedMediaSession.getSessionToken().getExtraBinder());
-            }
-        }
-    }
-
-    private void assertRootHints(MediaItem item) {
-        Bundle rootHints = item.getDescription().getExtras();
-        assertNotNull(rootHints);
-        assertEquals(mRootHints.getBoolean(MediaBrowserServiceCompat.BrowserRoot.EXTRA_RECENT),
-                rootHints.getBoolean(MediaBrowserServiceCompat.BrowserRoot.EXTRA_RECENT));
-        assertEquals(mRootHints.getBoolean(MediaBrowserServiceCompat.BrowserRoot.EXTRA_OFFLINE),
-                rootHints.getBoolean(MediaBrowserServiceCompat.BrowserRoot.EXTRA_OFFLINE));
-        assertEquals(mRootHints.getBoolean(MediaBrowserServiceCompat.BrowserRoot.EXTRA_SUGGESTED),
-                rootHints.getBoolean(MediaBrowserServiceCompat.BrowserRoot.EXTRA_SUGGESTED));
-    }
-
-    private class ConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
-        @Override
-        public void onConnected() {
-            synchronized (mWaitLock) {
-                mMediaBrowserService = StubMediaBrowserServiceCompat.sInstance;
-                mWaitLock.notify();
-            }
-        }
-    }
-
-    private class SubscriptionCallback extends MediaBrowserCompat.SubscriptionCallback {
-        boolean mOnChildrenLoaded;
-        boolean mOnChildrenLoadedWithOptions;
-
-        @Override
-        public void onChildrenLoaded(String parentId, List<MediaItem> children) {
-            synchronized (mWaitLock) {
-                mOnChildrenLoaded = true;
-                if (children != null) {
-                    for (MediaItem item : children) {
-                        assertRootHints(item);
-                    }
-                }
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onChildrenLoaded(String parentId, List<MediaItem> children, Bundle options) {
-            synchronized (mWaitLock) {
-                mOnChildrenLoadedWithOptions = true;
-                if (children != null) {
-                    for (MediaItem item : children) {
-                        assertRootHints(item);
-                    }
-                }
-                mWaitLock.notify();
-            }
-        }
-
-        public void reset() {
-            mOnChildrenLoaded = false;
-            mOnChildrenLoadedWithOptions = false;
-        }
-    }
-
-    private class ItemCallback extends MediaBrowserCompat.ItemCallback {
-        boolean mOnItemLoaded;
-
-        @Override
-        public void onItemLoaded(MediaItem item) {
-            synchronized (mWaitLock) {
-                mOnItemLoaded = true;
-                assertRootHints(item);
-                mWaitLock.notify();
-            }
-        }
-
-        public void reset() {
-            mOnItemLoaded = false;
-        }
-    }
-
-    private class SearchCallback extends MediaBrowserCompat.SearchCallback {
-        boolean mOnSearchResult;
-        Bundle mSearchExtras;
-        List<MediaItem> mSearchResults;
-
-        @Override
-        public void onSearchResult(String query, Bundle extras, List<MediaItem> items) {
-            synchronized (mWaitLock) {
-                mOnSearchResult = true;
-                mSearchResults = items;
-                mSearchExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onError(String query, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnSearchResult = true;
-                mSearchResults = null;
-                mSearchExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        public void reset() {
-            mOnSearchResult = false;
-            mSearchExtras = null;
-            mSearchResults = null;
-        }
-    }
-
-    private class CustomActionCallback extends MediaBrowserCompat.CustomActionCallback {
-        String mAction;
-        Bundle mExtras;
-        Bundle mData;
-        boolean mOnProgressUpdateCalled;
-        boolean mOnResultCalled;
-        boolean mOnErrorCalled;
-
-        @Override
-        public void onProgressUpdate(String action, Bundle extras, Bundle data) {
-            synchronized (mWaitLock) {
-                mOnProgressUpdateCalled = true;
-                mAction = action;
-                mExtras = extras;
-                mData = data;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onResult(String action, Bundle extras, Bundle resultData) {
-            synchronized (mWaitLock) {
-                mOnResultCalled = true;
-                mAction = action;
-                mExtras = extras;
-                mData = resultData;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onError(String action, Bundle extras, Bundle data) {
-            synchronized (mWaitLock) {
-                mOnErrorCalled = true;
-                mAction = action;
-                mExtras = extras;
-                mData = data;
-                mWaitLock.notify();
-            }
-        }
-
-        public void reset() {
-            mOnResultCalled = false;
-            mOnProgressUpdateCalled = false;
-            mOnErrorCalled = false;
-            mAction = null;
-            mExtras = null;
-            mData = null;
-        }
-    }
-
-    private class ConnectionCallbackForDelayedMediaSession extends
-            MediaBrowserCompat.ConnectionCallback {
-        private int mConnectedCount = 0;
-
-        @Override
-        public void onConnected() {
-            synchronized (mWaitLock) {
-                mConnectedCount++;
-                mWaitLock.notify();
-            }
-        }
-    }
-}
diff --git a/media-compat/tests/src/android/support/v4/media/StubMediaBrowserServiceCompat.java b/media-compat/tests/src/android/support/v4/media/StubMediaBrowserServiceCompat.java
deleted file mode 100644
index c817dce..0000000
--- a/media-compat/tests/src/android/support/v4/media/StubMediaBrowserServiceCompat.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v4.media;
-
-import android.os.Bundle;
-import android.support.v4.media.MediaBrowserCompat.MediaItem;
-import android.support.v4.media.session.MediaSessionCompat;
-
-import junit.framework.Assert;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Stub implementation of {@link android.support.v4.media.MediaBrowserServiceCompat}.
- */
-public class StubMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
-    static final String EXTRAS_KEY = "test_extras_key";
-    static final String EXTRAS_VALUE = "test_extras_value";
-
-    static final String MEDIA_ID = "test_media_id";
-    static final String MEDIA_ID_INVALID = "test_media_id_invalid";
-    static final String MEDIA_ID_ROOT = "test_media_id_root";
-    static final String MEDIA_ID_CHILDREN_DELAYED = "test_media_id_children_delayed";
-    static final String MEDIA_ID_ON_LOAD_ITEM_NOT_IMPLEMENTED =
-            "test_media_id_on_load_item_not_implemented";
-
-    static final String[] MEDIA_ID_CHILDREN = new String[]{
-            "test_media_id_children_0", "test_media_id_children_1",
-            "test_media_id_children_2", "test_media_id_children_3",
-            MEDIA_ID_CHILDREN_DELAYED
-    };
-
-    static final String SEARCH_QUERY = "children_2";
-    static final String SEARCH_QUERY_FOR_NO_RESULT = "query no result";
-    static final String SEARCH_QUERY_FOR_ERROR = "query for error";
-
-    static final String CUSTOM_ACTION = "CUSTOM_ACTION";
-    static final String CUSTOM_ACTION_FOR_ERROR = "CUSTOM_ACTION_FOR_ERROR";
-
-    static StubMediaBrowserServiceCompat sInstance;
-
-    /* package private */ static MediaSessionCompat sSession;
-    private Bundle mExtras;
-    private Result<List<MediaItem>> mPendingLoadChildrenResult;
-    private Result<MediaItem> mPendingLoadItemResult;
-    private Bundle mPendingRootHints;
-
-    /* package private */ Bundle mCustomActionExtras;
-    /* package private */ Result<Bundle> mCustomActionResult;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        sInstance = this;
-        sSession = new MediaSessionCompat(this, "StubMediaBrowserServiceCompat");
-        setSessionToken(sSession.getSessionToken());
-    }
-
-    @Override
-    public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
-        mExtras = new Bundle();
-        mExtras.putString(EXTRAS_KEY, EXTRAS_VALUE);
-        return new BrowserRoot(MEDIA_ID_ROOT, mExtras);
-    }
-
-    @Override
-    public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
-        List<MediaItem> mediaItems = new ArrayList<>();
-        if (MEDIA_ID_ROOT.equals(parentMediaId)) {
-            Bundle rootHints = getBrowserRootHints();
-            for (String id : MEDIA_ID_CHILDREN) {
-                mediaItems.add(createMediaItem(id));
-            }
-            result.sendResult(mediaItems);
-        } else if (MEDIA_ID_CHILDREN_DELAYED.equals(parentMediaId)) {
-            Assert.assertNull(mPendingLoadChildrenResult);
-            mPendingLoadChildrenResult = result;
-            mPendingRootHints = getBrowserRootHints();
-            result.detach();
-        } else if (MEDIA_ID_INVALID.equals(parentMediaId)) {
-            result.sendResult(null);
-        }
-    }
-
-    @Override
-    public void onLoadItem(String itemId, Result<MediaItem> result) {
-        if (MEDIA_ID_CHILDREN_DELAYED.equals(itemId)) {
-            mPendingLoadItemResult = result;
-            mPendingRootHints = getBrowserRootHints();
-            result.detach();
-            return;
-        }
-
-        if (MEDIA_ID_INVALID.equals(itemId)) {
-            result.sendResult(null);
-            return;
-        }
-
-        for (String id : MEDIA_ID_CHILDREN) {
-            if (id.equals(itemId)) {
-                result.sendResult(createMediaItem(id));
-                return;
-            }
-        }
-
-        // Test the case where onLoadItem is not implemented.
-        super.onLoadItem(itemId, result);
-    }
-
-    @Override
-    public void onSearch(String query, Bundle extras, Result<List<MediaItem>> result) {
-        if (SEARCH_QUERY_FOR_NO_RESULT.equals(query)) {
-            result.sendResult(Collections.<MediaItem>emptyList());
-        } else if (SEARCH_QUERY_FOR_ERROR.equals(query)) {
-            result.sendResult(null);
-        } else if (SEARCH_QUERY.equals(query)) {
-            List<MediaItem> items = new ArrayList<>();
-            for (String id : MEDIA_ID_CHILDREN) {
-                if (id.contains(query)) {
-                    items.add(createMediaItem(id));
-                }
-            }
-            result.sendResult(items);
-        }
-    }
-
-    @Override
-    public void onCustomAction(String action, Bundle extras,
-            Result<Bundle> result) {
-        mCustomActionResult = result;
-        mCustomActionExtras = extras;
-        if (CUSTOM_ACTION_FOR_ERROR.equals(action)) {
-            result.sendError(null);
-        } else if (CUSTOM_ACTION.equals(action)) {
-            result.detach();
-        }
-    }
-
-    public void sendDelayedNotifyChildrenChanged() {
-        if (mPendingLoadChildrenResult != null) {
-            mPendingLoadChildrenResult.sendResult(Collections.<MediaItem>emptyList());
-            mPendingRootHints = null;
-            mPendingLoadChildrenResult = null;
-        }
-    }
-
-    public void sendDelayedItemLoaded() {
-        if (mPendingLoadItemResult != null) {
-            mPendingLoadItemResult.sendResult(new MediaItem(new MediaDescriptionCompat.Builder()
-                    .setMediaId(MEDIA_ID_CHILDREN_DELAYED).setExtras(mPendingRootHints).build(),
-                    MediaItem.FLAG_BROWSABLE));
-            mPendingRootHints = null;
-            mPendingLoadItemResult = null;
-        }
-    }
-
-    private MediaItem createMediaItem(String id) {
-        return new MediaItem(new MediaDescriptionCompat.Builder()
-                .setMediaId(id).setExtras(getBrowserRootHints()).build(),
-                MediaItem.FLAG_BROWSABLE);
-    }
-}
diff --git a/media-compat/tests/src/android/support/v4/media/StubMediaBrowserServiceCompatWithDelayedMediaSession.java b/media-compat/tests/src/android/support/v4/media/StubMediaBrowserServiceCompatWithDelayedMediaSession.java
deleted file mode 100644
index e93c940..0000000
--- a/media-compat/tests/src/android/support/v4/media/StubMediaBrowserServiceCompatWithDelayedMediaSession.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v4.media;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.media.session.MediaSessionCompat;
-
-import java.util.List;
-
-/**
- * Stub implementation of {@link MediaBrowserServiceCompat}.
- * This implementation does not call
- * {@link MediaBrowserServiceCompat#setSessionToken(MediaSessionCompat.Token)} in its
- * {@link android.app.Service#onCreate}.
- */
-public class StubMediaBrowserServiceCompatWithDelayedMediaSession extends
-        MediaBrowserServiceCompat {
-
-    static StubMediaBrowserServiceCompatWithDelayedMediaSession sInstance;
-    private MediaSessionCompat mSession;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        sInstance = this;
-        mSession = new MediaSessionCompat(
-                this, "StubMediaBrowserServiceCompatWithDelayedMediaSession");
-    }
-
-    @Nullable
-    @Override
-    public BrowserRoot onGetRoot(@NonNull String clientPackageName,
-            int clientUid, @Nullable Bundle rootHints) {
-        return new BrowserRoot("StubRootId", null);
-    }
-
-    @Override
-    public void onLoadChildren(@NonNull String parentId,
-            @NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
-        result.detach();
-    }
-
-    void callSetSessionToken() {
-        setSessionToken(mSession.getSessionToken());
-    }
-}
diff --git a/media-compat/tests/src/android/support/v4/media/StubRemoteMediaBrowserServiceCompat.java b/media-compat/tests/src/android/support/v4/media/StubRemoteMediaBrowserServiceCompat.java
deleted file mode 100644
index 8e03ab2..0000000
--- a/media-compat/tests/src/android/support/v4/media/StubRemoteMediaBrowserServiceCompat.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v4.media;
-
-import android.os.Bundle;
-import android.support.v4.media.MediaBrowserCompat.MediaItem;
-import android.support.v4.media.session.MediaSessionCompat;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Stub implementation of {@link android.support.v4.media.MediaBrowserServiceCompat}.
- */
-public class StubRemoteMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
-    static final String EXTRAS_KEY = "test_extras_key";
-    static final String EXTRAS_VALUE = "test_extras_value";
-
-    static final String MEDIA_ID_ROOT = "test_media_id_root";
-    static final String MEDIA_METADATA = "test_media_metadata";
-
-    static final String[] MEDIA_ID_CHILDREN = new String[]{
-            "test_media_id_children_0", "test_media_id_children_1",
-            "test_media_id_children_2", "test_media_id_children_3"
-    };
-
-    private static MediaSessionCompat mSession;
-    private Bundle mExtras;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mSession = new MediaSessionCompat(this, "StubRemoteMediaBrowserServiceCompat");
-        setSessionToken(mSession.getSessionToken());
-    }
-
-    @Override
-    public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
-        mExtras = new Bundle();
-        mExtras.putString(EXTRAS_KEY, EXTRAS_VALUE);
-        return new BrowserRoot(MEDIA_ID_ROOT, mExtras);
-    }
-
-    @Override
-    public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
-        List<MediaItem> mediaItems = new ArrayList<>();
-        if (MEDIA_ID_ROOT.equals(parentMediaId)) {
-            Bundle rootHints = getBrowserRootHints();
-            for (String id : MEDIA_ID_CHILDREN) {
-                mediaItems.add(createMediaItem(id));
-            }
-            result.sendResult(mediaItems);
-        }
-    }
-
-    @Override
-    public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result,
-            final Bundle options) {
-        MediaMetadataCompat metadata = options.getParcelable(MEDIA_METADATA);
-        if (metadata == null) {
-            super.onLoadChildren(parentMediaId, result, options);
-        } else {
-            List<MediaItem> mediaItems = new ArrayList<>();
-            mediaItems.add(new MediaItem(metadata.getDescription(), MediaItem.FLAG_PLAYABLE));
-            result.sendResult(mediaItems);
-        }
-    }
-
-    private MediaItem createMediaItem(String id) {
-        return new MediaItem(new MediaDescriptionCompat.Builder()
-                .setMediaId(id).setExtras(getBrowserRootHints()).build(),
-                MediaItem.FLAG_BROWSABLE);
-    }
-}
diff --git a/media-compat/tests/src/android/support/v4/media/session/MediaControllerCompatTest.java b/media-compat/tests/src/android/support/v4/media/session/MediaControllerCompatTest.java
deleted file mode 100644
index b197a42..0000000
--- a/media-compat/tests/src/android/support/v4/media/session/MediaControllerCompatTest.java
+++ /dev/null
@@ -1,795 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.support.v4.media.session;
-
-import static android.support.test.InstrumentationRegistry.getContext;
-import static android.support.test.InstrumentationRegistry.getInstrumentation;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.media.AudioManager;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.media.session.PlaybackState;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.ResultReceiver;
-import android.os.SystemClock;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.v4.media.MediaDescriptionCompat;
-import android.support.v4.media.RatingCompat;
-import android.support.v4.media.VolumeProviderCompat;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Test {@link MediaControllerCompat}.
- */
-@RunWith(AndroidJUnit4.class)
-public class MediaControllerCompatTest {
-    // The maximum time to wait for an operation.
-    private static final long TIME_OUT_MS = 3000L;
-    private static final String SESSION_TAG = "test-session";
-    private static final String EXTRAS_KEY = "test-key";
-    private static final String EXTRAS_VALUE = "test-val";
-    private static final float DELTA = 1e-4f;
-    private static final boolean ENABLED = true;
-    private static final boolean DISABLED = false;
-    private static final long TEST_POSITION = 1000000L;
-    private static final float TEST_PLAYBACK_SPEED = 3.0f;
-
-
-    private final Object mWaitLock = new Object();
-    private Handler mHandler = new Handler(Looper.getMainLooper());
-    private MediaSessionCompat mSession;
-    private MediaSessionCallback mCallback = new MediaSessionCallback();
-    private MediaControllerCompat mController;
-
-    @Before
-    public void setUp() throws Exception {
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mSession = new MediaSessionCompat(getContext(), SESSION_TAG);
-                mSession.setCallback(mCallback, mHandler);
-                mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS);
-                mController = mSession.getController();
-            }
-        });
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mSession.release();
-    }
-
-    @Test
-    @SmallTest
-    public void testGetPackageName() {
-        assertEquals(getContext().getPackageName(), mController.getPackageName());
-    }
-
-    @Test
-    @SmallTest
-    public void testGetRatingType() {
-        assertEquals("Default rating type of a session must be RatingCompat.RATING_NONE",
-                RatingCompat.RATING_NONE, mController.getRatingType());
-
-        mSession.setRatingType(RatingCompat.RATING_5_STARS);
-        assertEquals(RatingCompat.RATING_5_STARS, mController.getRatingType());
-    }
-
-    @Test
-    @SmallTest
-    public void testGetSessionToken() throws Exception {
-        assertEquals(mSession.getSessionToken(), mController.getSessionToken());
-    }
-
-    @Test
-    @SmallTest
-    public void testIsSessionReady() throws Exception {
-        // mController already has the extra binder since it was created with the session token
-        // which holds the extra binder.
-        assertTrue(mController.isSessionReady());
-    }
-
-    @Test
-    @SmallTest
-    public void testSendCommand() throws Exception {
-        synchronized (mWaitLock) {
-            mCallback.reset();
-            final String command = "test-command";
-            final Bundle extras = new Bundle();
-            extras.putString(EXTRAS_KEY, EXTRAS_VALUE);
-            mController.sendCommand(command, extras, new ResultReceiver(null));
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCommandCalled);
-            assertNotNull(mCallback.mCommandCallback);
-            assertEquals(command, mCallback.mCommand);
-            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testAddRemoveQueueItems() throws Exception {
-        final String mediaId1 = "media_id_1";
-        final String mediaTitle1 = "media_title_1";
-        MediaDescriptionCompat itemDescription1 = new MediaDescriptionCompat.Builder()
-                .setMediaId(mediaId1).setTitle(mediaTitle1).build();
-
-        final String mediaId2 = "media_id_2";
-        final String mediaTitle2 = "media_title_2";
-        MediaDescriptionCompat itemDescription2 = new MediaDescriptionCompat.Builder()
-                .setMediaId(mediaId2).setTitle(mediaTitle2).build();
-
-        synchronized (mWaitLock) {
-            mCallback.reset();
-            mController.addQueueItem(itemDescription1);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnAddQueueItemCalled);
-            assertEquals(-1, mCallback.mQueueIndex);
-            assertEquals(mediaId1, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle1, mCallback.mQueueDescription.getTitle());
-
-            mCallback.reset();
-            mController.addQueueItem(itemDescription2, 0);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnAddQueueItemAtCalled);
-            assertEquals(0, mCallback.mQueueIndex);
-            assertEquals(mediaId2, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle2, mCallback.mQueueDescription.getTitle());
-
-            mCallback.reset();
-            mController.removeQueueItemAt(0);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRemoveQueueItemCalled);
-            assertEquals(mediaId2, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle2, mCallback.mQueueDescription.getTitle());
-
-            mCallback.reset();
-            mController.removeQueueItem(itemDescription1);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRemoveQueueItemCalled);
-            assertEquals(mediaId1, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle1, mCallback.mQueueDescription.getTitle());
-
-            // Try to modify the queue when the session does not support queue management.
-            mSession.setFlags(0);
-            try {
-                mController.addQueueItem(itemDescription1);
-                fail();
-            } catch (UnsupportedOperationException e) {
-                // Expected.
-            }
-        }
-    }
-
-    // TODO: Uncomment after fixing this test. This test causes an Exception on System UI.
-    // @Test
-    // @SmallTest
-    public void testVolumeControl() throws Exception {
-        VolumeProviderCompat vp =
-                new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 11, 5) {
-            @Override
-            public void onSetVolumeTo(int volume) {
-                synchronized (mWaitLock) {
-                    setCurrentVolume(volume);
-                    mWaitLock.notify();
-                }
-            }
-
-            @Override
-            public void onAdjustVolume(int direction) {
-                synchronized (mWaitLock) {
-                    switch (direction) {
-                        case AudioManager.ADJUST_LOWER:
-                            setCurrentVolume(getCurrentVolume() - 1);
-                            break;
-                        case AudioManager.ADJUST_RAISE:
-                            setCurrentVolume(getCurrentVolume() + 1);
-                            break;
-                    }
-                    mWaitLock.notify();
-                }
-            }
-        };
-        mSession.setPlaybackToRemote(vp);
-
-        synchronized (mWaitLock) {
-            // test setVolumeTo
-            mController.setVolumeTo(7, 0);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(7, vp.getCurrentVolume());
-
-            // test adjustVolume
-            mController.adjustVolume(AudioManager.ADJUST_LOWER, 0);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(6, vp.getCurrentVolume());
-
-            mController.adjustVolume(AudioManager.ADJUST_RAISE, 0);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(7, vp.getCurrentVolume());
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testTransportControlsAndMediaSessionCallback() throws Exception {
-        MediaControllerCompat.TransportControls controls = mController.getTransportControls();
-        synchronized (mWaitLock) {
-            mCallback.reset();
-            controls.play();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayCalled);
-
-            mCallback.reset();
-            controls.pause();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPauseCalled);
-
-            mCallback.reset();
-            controls.stop();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnStopCalled);
-
-            mCallback.reset();
-            controls.fastForward();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnFastForwardCalled);
-
-            mCallback.reset();
-            controls.rewind();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRewindCalled);
-
-            mCallback.reset();
-            controls.skipToPrevious();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSkipToPreviousCalled);
-
-            mCallback.reset();
-            controls.skipToNext();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSkipToNextCalled);
-
-            mCallback.reset();
-            final long seekPosition = 1000;
-            controls.seekTo(seekPosition);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSeekToCalled);
-            assertEquals(seekPosition, mCallback.mSeekPosition);
-
-            mCallback.reset();
-            final RatingCompat rating =
-                    RatingCompat.newStarRating(RatingCompat.RATING_5_STARS, 3f);
-            controls.setRating(rating);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetRatingCalled);
-            assertEquals(rating.getRatingStyle(), mCallback.mRating.getRatingStyle());
-            assertEquals(rating.getStarRating(), mCallback.mRating.getStarRating(), DELTA);
-
-            mCallback.reset();
-            final Bundle extras = new Bundle();
-            extras.putString(EXTRAS_KEY, EXTRAS_VALUE);
-            controls.setRating(rating, extras);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetRatingCalled);
-            assertEquals(rating.getRatingStyle(), mCallback.mRating.getRatingStyle());
-            assertEquals(rating.getStarRating(), mCallback.mRating.getStarRating(), DELTA);
-            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-
-            mCallback.reset();
-            final String mediaId = "test-media-id";
-            controls.playFromMediaId(mediaId, extras);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayFromMediaIdCalled);
-            assertEquals(mediaId, mCallback.mMediaId);
-            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-
-            mCallback.reset();
-            final String query = "test-query";
-            controls.playFromSearch(query, extras);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayFromSearchCalled);
-            assertEquals(query, mCallback.mQuery);
-            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-
-            mCallback.reset();
-            final Uri uri = Uri.parse("content://test/popcorn.mod");
-            controls.playFromUri(uri, extras);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayFromUriCalled);
-            assertEquals(uri, mCallback.mUri);
-            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-
-            mCallback.reset();
-            final String action = "test-action";
-            controls.sendCustomAction(action, extras);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCustomActionCalled);
-            assertEquals(action, mCallback.mAction);
-            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-
-            mCallback.reset();
-            mCallback.mOnCustomActionCalled = false;
-            final PlaybackStateCompat.CustomAction customAction =
-                    new PlaybackStateCompat.CustomAction.Builder(action, action, -1)
-                            .setExtras(extras)
-                            .build();
-            controls.sendCustomAction(customAction, extras);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCustomActionCalled);
-            assertEquals(action, mCallback.mAction);
-            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-
-            mCallback.reset();
-            final long queueItemId = 1000;
-            controls.skipToQueueItem(queueItemId);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSkipToQueueItemCalled);
-            assertEquals(queueItemId, mCallback.mQueueItemId);
-
-            mCallback.reset();
-            controls.prepare();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareCalled);
-
-            mCallback.reset();
-            controls.prepareFromMediaId(mediaId, extras);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareFromMediaIdCalled);
-            assertEquals(mediaId, mCallback.mMediaId);
-            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-
-            mCallback.reset();
-            controls.prepareFromSearch(query, extras);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareFromSearchCalled);
-            assertEquals(query, mCallback.mQuery);
-            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-
-            mCallback.reset();
-            controls.prepareFromUri(uri, extras);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareFromUriCalled);
-            assertEquals(uri, mCallback.mUri);
-            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-
-            mCallback.reset();
-            controls.setCaptioningEnabled(ENABLED);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetCaptioningEnabledCalled);
-            assertEquals(ENABLED, mCallback.mCaptioningEnabled);
-
-            mCallback.reset();
-            final int repeatMode = PlaybackStateCompat.REPEAT_MODE_ALL;
-            controls.setRepeatMode(repeatMode);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetRepeatModeCalled);
-            assertEquals(repeatMode, mCallback.mRepeatMode);
-
-            mCallback.reset();
-            controls.setShuffleMode(PlaybackStateCompat.SHUFFLE_MODE_ALL);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetShuffleModeCalled);
-            assertEquals(PlaybackStateCompat.SHUFFLE_MODE_ALL, mCallback.mShuffleMode);
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testPlaybackInfo() {
-        final int playbackType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL;
-        final int volumeControl = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
-        final int maxVolume = 10;
-        final int currentVolume = 3;
-
-        int audioStream = 77;
-        MediaControllerCompat.PlaybackInfo info = new MediaControllerCompat.PlaybackInfo(
-                playbackType, audioStream, volumeControl, maxVolume, currentVolume);
-
-        assertEquals(playbackType, info.getPlaybackType());
-        assertEquals(audioStream, info.getAudioStream());
-        assertEquals(volumeControl, info.getVolumeControl());
-        assertEquals(maxVolume, info.getMaxVolume());
-        assertEquals(currentVolume, info.getCurrentVolume());
-    }
-
-    @Test
-    @SmallTest
-    public void testGetPlaybackStateWithPositionUpdate() throws InterruptedException {
-        final long stateSetTime = SystemClock.elapsedRealtime();
-        PlaybackStateCompat stateIn = new PlaybackStateCompat.Builder()
-                .setState(PlaybackStateCompat.STATE_PLAYING, TEST_POSITION, TEST_PLAYBACK_SPEED,
-                        stateSetTime)
-                .build();
-        mSession.setPlaybackState(stateIn);
-
-        final long waitDuration = 100L;
-        Thread.sleep(waitDuration);
-
-        final long expectedUpdateTime = waitDuration + stateSetTime;
-        final long expectedPosition = (long) (TEST_PLAYBACK_SPEED * waitDuration) + TEST_POSITION;
-
-        final double updateTimeTolerance = 50L;
-        final double positionTolerance = updateTimeTolerance * TEST_PLAYBACK_SPEED;
-
-        PlaybackStateCompat stateOut = mSession.getController().getPlaybackState();
-        assertEquals(expectedUpdateTime, stateOut.getLastPositionUpdateTime(), updateTimeTolerance);
-        assertEquals(expectedPosition, stateOut.getPosition(), positionTolerance);
-
-        // Compare the result with MediaController.getPlaybackState().
-        if (Build.VERSION.SDK_INT >= 21) {
-            MediaController controller = new MediaController(
-                    getContext(), (MediaSession.Token) mSession.getSessionToken().getToken());
-            PlaybackState state = controller.getPlaybackState();
-            assertEquals(state.getLastPositionUpdateTime(), stateOut.getLastPositionUpdateTime(),
-                    updateTimeTolerance);
-            assertEquals(state.getPosition(), stateOut.getPosition(), positionTolerance);
-        }
-    }
-
-    private class MediaSessionCallback extends MediaSessionCompat.Callback {
-        private long mSeekPosition;
-        private long mQueueItemId;
-        private RatingCompat mRating;
-        private String mMediaId;
-        private String mQuery;
-        private Uri mUri;
-        private String mAction;
-        private String mCommand;
-        private Bundle mExtras;
-        private ResultReceiver mCommandCallback;
-        private boolean mCaptioningEnabled;
-        private int mRepeatMode;
-        private int mShuffleMode;
-        private int mQueueIndex;
-        private MediaDescriptionCompat mQueueDescription;
-        private List<MediaSessionCompat.QueueItem> mQueue = new ArrayList<>();
-
-        private boolean mOnPlayCalled;
-        private boolean mOnPauseCalled;
-        private boolean mOnStopCalled;
-        private boolean mOnFastForwardCalled;
-        private boolean mOnRewindCalled;
-        private boolean mOnSkipToPreviousCalled;
-        private boolean mOnSkipToNextCalled;
-        private boolean mOnSeekToCalled;
-        private boolean mOnSkipToQueueItemCalled;
-        private boolean mOnSetRatingCalled;
-        private boolean mOnPlayFromMediaIdCalled;
-        private boolean mOnPlayFromSearchCalled;
-        private boolean mOnPlayFromUriCalled;
-        private boolean mOnCustomActionCalled;
-        private boolean mOnCommandCalled;
-        private boolean mOnPrepareCalled;
-        private boolean mOnPrepareFromMediaIdCalled;
-        private boolean mOnPrepareFromSearchCalled;
-        private boolean mOnPrepareFromUriCalled;
-        private boolean mOnSetCaptioningEnabledCalled;
-        private boolean mOnSetRepeatModeCalled;
-        private boolean mOnSetShuffleModeCalled;
-        private boolean mOnAddQueueItemCalled;
-        private boolean mOnAddQueueItemAtCalled;
-        private boolean mOnRemoveQueueItemCalled;
-
-        public void reset() {
-            mSeekPosition = -1;
-            mQueueItemId = -1;
-            mRating = null;
-            mMediaId = null;
-            mQuery = null;
-            mUri = null;
-            mAction = null;
-            mExtras = null;
-            mCommand = null;
-            mCommandCallback = null;
-            mCaptioningEnabled = false;
-            mRepeatMode = PlaybackStateCompat.REPEAT_MODE_NONE;
-            mShuffleMode = PlaybackStateCompat.SHUFFLE_MODE_NONE;
-            mQueueIndex = -1;
-            mQueueDescription = null;
-
-            mOnPlayCalled = false;
-            mOnPauseCalled = false;
-            mOnStopCalled = false;
-            mOnFastForwardCalled = false;
-            mOnRewindCalled = false;
-            mOnSkipToPreviousCalled = false;
-            mOnSkipToNextCalled = false;
-            mOnSkipToQueueItemCalled = false;
-            mOnSeekToCalled = false;
-            mOnSetRatingCalled = false;
-            mOnPlayFromMediaIdCalled = false;
-            mOnPlayFromSearchCalled = false;
-            mOnPlayFromUriCalled = false;
-            mOnCustomActionCalled = false;
-            mOnCommandCalled = false;
-            mOnPrepareCalled = false;
-            mOnPrepareFromMediaIdCalled = false;
-            mOnPrepareFromSearchCalled = false;
-            mOnPrepareFromUriCalled = false;
-            mOnSetCaptioningEnabledCalled = false;
-            mOnSetRepeatModeCalled = false;
-            mOnSetShuffleModeCalled = false;
-            mOnAddQueueItemCalled = false;
-            mOnAddQueueItemAtCalled = false;
-            mOnRemoveQueueItemCalled = false;
-        }
-
-        @Override
-        public void onPlay() {
-            synchronized (mWaitLock) {
-                mOnPlayCalled = true;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onPause() {
-            synchronized (mWaitLock) {
-                mOnPauseCalled = true;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onStop() {
-            synchronized (mWaitLock) {
-                mOnStopCalled = true;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onFastForward() {
-            synchronized (mWaitLock) {
-                mOnFastForwardCalled = true;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onRewind() {
-            synchronized (mWaitLock) {
-                mOnRewindCalled = true;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSkipToPrevious() {
-            synchronized (mWaitLock) {
-                mOnSkipToPreviousCalled = true;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSkipToNext() {
-            synchronized (mWaitLock) {
-                mOnSkipToNextCalled = true;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSeekTo(long pos) {
-            synchronized (mWaitLock) {
-                mOnSeekToCalled = true;
-                mSeekPosition = pos;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSetRating(RatingCompat rating) {
-            synchronized (mWaitLock) {
-                mOnSetRatingCalled = true;
-                mRating = rating;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSetRating(RatingCompat rating, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnSetRatingCalled = true;
-                mRating = rating;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onPlayFromMediaId(String mediaId, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPlayFromMediaIdCalled = true;
-                mMediaId = mediaId;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onPlayFromSearch(String query, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPlayFromSearchCalled = true;
-                mQuery = query;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onPlayFromUri(Uri uri, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPlayFromUriCalled = true;
-                mUri = uri;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onCustomAction(String action, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnCustomActionCalled = true;
-                mAction = action;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSkipToQueueItem(long id) {
-            synchronized (mWaitLock) {
-                mOnSkipToQueueItemCalled = true;
-                mQueueItemId = id;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onCommand(String command, Bundle extras, ResultReceiver cb) {
-            synchronized (mWaitLock) {
-                mOnCommandCalled = true;
-                mCommand = command;
-                mExtras = extras;
-                mCommandCallback = cb;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onPrepare() {
-            synchronized (mWaitLock) {
-                mOnPrepareCalled = true;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onPrepareFromMediaId(String mediaId, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPrepareFromMediaIdCalled = true;
-                mMediaId = mediaId;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onPrepareFromSearch(String query, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPrepareFromSearchCalled = true;
-                mQuery = query;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onPrepareFromUri(Uri uri, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPrepareFromUriCalled = true;
-                mUri = uri;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSetRepeatMode(int repeatMode) {
-            synchronized (mWaitLock) {
-                mOnSetRepeatModeCalled = true;
-                mRepeatMode = repeatMode;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onAddQueueItem(MediaDescriptionCompat description) {
-            synchronized (mWaitLock) {
-                mOnAddQueueItemCalled = true;
-                mQueueDescription = description;
-                mQueue.add(new MediaSessionCompat.QueueItem(description, mQueue.size()));
-                mSession.setQueue(mQueue);
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onAddQueueItem(MediaDescriptionCompat description, int index) {
-            synchronized (mWaitLock) {
-                mOnAddQueueItemAtCalled = true;
-                mQueueIndex = index;
-                mQueueDescription = description;
-                mQueue.add(index, new MediaSessionCompat.QueueItem(description, mQueue.size()));
-                mSession.setQueue(mQueue);
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onRemoveQueueItem(MediaDescriptionCompat description) {
-            synchronized (mWaitLock) {
-                mOnRemoveQueueItemCalled = true;
-                String mediaId = description.getMediaId();
-                for (int i = mQueue.size() - 1; i >= 0; --i) {
-                    if (mediaId.equals(mQueue.get(i).getDescription().getMediaId())) {
-                        mQueueDescription = mQueue.remove(i).getDescription();
-                        mSession.setQueue(mQueue);
-                        break;
-                    }
-                }
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSetCaptioningEnabled(boolean enabled) {
-            synchronized (mWaitLock) {
-                mOnSetCaptioningEnabledCalled = true;
-                mCaptioningEnabled = enabled;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSetShuffleMode(int shuffleMode) {
-            synchronized (mWaitLock) {
-                mOnSetShuffleModeCalled = true;
-                mShuffleMode = shuffleMode;
-                mWaitLock.notify();
-            }
-        }
-    }
-}
diff --git a/media-compat/tests/src/android/support/v4/media/session/MediaSessionCompatTest.java b/media-compat/tests/src/android/support/v4/media/session/MediaSessionCompatTest.java
deleted file mode 100644
index 9911c11..0000000
--- a/media-compat/tests/src/android/support/v4/media/session/MediaSessionCompatTest.java
+++ /dev/null
@@ -1,1038 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v4.media.session;
-
-import static android.support.test.InstrumentationRegistry.getContext;
-import static android.support.test.InstrumentationRegistry.getInstrumentation;
-import static android.support.v4.media.MediaMetadataCompat.METADATA_KEY_RATING;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-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.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.v4.media.MediaDescriptionCompat;
-import android.support.v4.media.MediaMetadataCompat;
-import android.support.v4.media.RatingCompat;
-import android.support.v4.media.VolumeProviderCompat;
-import android.view.KeyEvent;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Test {@link MediaSessionCompat}.
- */
-@RunWith(AndroidJUnit4.class)
-public class MediaSessionCompatTest {
-    // The maximum time to wait for an operation, that is expected to happen.
-    private static final long TIME_OUT_MS = 3000L;
-    // The maximum time to wait for an operation, that is expected not to happen.
-    private static final long WAIT_TIME_MS = 30L;
-    private static final int MAX_AUDIO_INFO_CHANGED_CALLBACK_COUNT = 10;
-    private static final String TEST_SESSION_TAG = "test-session-tag";
-    private static final String TEST_KEY = "test-key";
-    private static final String TEST_VALUE = "test-val";
-    private static final Bundle TEST_BUNDLE = createTestBundle();
-    private static final String TEST_SESSION_EVENT = "test-session-event";
-    private static final int TEST_CURRENT_VOLUME = 10;
-    private static final int TEST_MAX_VOLUME = 11;
-    private static final long TEST_QUEUE_ID = 12L;
-    private static final long TEST_ACTION = 55L;
-    private static final int TEST_ERROR_CODE =
-            PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED;
-    private static final String TEST_ERROR_MSG = "test-error-msg";
-
-    private static Bundle createTestBundle() {
-        Bundle bundle = new Bundle();
-        bundle.putString(TEST_KEY, TEST_VALUE);
-        return bundle;
-    }
-
-    private AudioManager mAudioManager;
-    private Handler mHandler = new Handler(Looper.getMainLooper());
-    private Object mWaitLock = new Object();
-    private MediaControllerCallback mCallback = new MediaControllerCallback();
-    private MediaSessionCompat mSession;
-
-    @Before
-    public void setUp() throws Exception {
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
-                mSession = new MediaSessionCompat(getContext(), TEST_SESSION_TAG);
-            }
-        });
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        // It is OK to call release() twice.
-        mSession.release();
-        mSession = null;
-    }
-
-    /**
-     * Tests that a session can be created and that all the fields are
-     * initialized correctly.
-     */
-    @Test
-    @SmallTest
-    public void testCreateSession() throws Exception {
-        assertNotNull(mSession.getSessionToken());
-        assertFalse("New session should not be active", mSession.isActive());
-
-        // Verify by getting the controller and checking all its fields
-        MediaControllerCompat controller = mSession.getController();
-        assertNotNull(controller);
-        verifyNewSession(controller, TEST_SESSION_TAG);
-    }
-
-    /**
-     * Tests that a session can be created from the framework session object and the callback
-     * set on the framework session object before fromSession() is called works properly.
-     */
-    @Test
-    @SmallTest
-    public void testFromSession() throws Exception {
-        if (android.os.Build.VERSION.SDK_INT < 21) {
-            // MediaSession was introduced from API level 21.
-            return;
-        }
-        MediaSessionCallback callback = new MediaSessionCallback();
-        callback.reset(1);
-        mSession.setCallback(callback, new Handler(Looper.getMainLooper()));
-        MediaSessionCompat session = MediaSessionCompat.fromMediaSession(
-                getContext(), mSession.getMediaSession());
-        assertEquals(session.getSessionToken(), mSession.getSessionToken());
-        synchronized (mWaitLock) {
-            session.getController().getTransportControls().play();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(1, callback.mOnPlayCalledCount);
-        }
-    }
-
-    /**
-     * Tests MediaSessionCompat.Token created in the constructor of MediaSessionCompat.
-     */
-    @Test
-    @SmallTest
-    public void testSessionToken() throws Exception {
-        MediaSessionCompat.Token sessionToken = mSession.getSessionToken();
-
-        assertNotNull(sessionToken);
-        assertEquals(0, sessionToken.describeContents());
-
-        // Test writeToParcel
-        Parcel p = Parcel.obtain();
-        sessionToken.writeToParcel(p, 0);
-        p.setDataPosition(0);
-        MediaSessionCompat.Token token = MediaSessionCompat.Token.CREATOR.createFromParcel(p);
-        assertEquals(token, sessionToken);
-        p.recycle();
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setExtras}.
-     */
-    @Test
-    @SmallTest
-    public void testSetExtras() throws Exception {
-        final Bundle extras = new Bundle();
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            mCallback.resetLocked();
-            mSession.setExtras(TEST_BUNDLE);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnExtraChangedCalled);
-
-            Bundle extrasOut = mCallback.mExtras;
-            assertNotNull(extrasOut);
-            assertEquals(TEST_VALUE, extrasOut.get(TEST_KEY));
-
-            extrasOut = controller.getExtras();
-            assertNotNull(extrasOut);
-            assertEquals(TEST_VALUE, extrasOut.get(TEST_KEY));
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setFlags}.
-     */
-    @Test
-    @SmallTest
-    public void testSetFlags() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            mCallback.resetLocked();
-            mSession.setFlags(5);
-            assertEquals(5, controller.getFlags());
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setMetadata}.
-     */
-    @Test
-    @SmallTest
-    public void testSetMetadata() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            mCallback.resetLocked();
-            RatingCompat rating = RatingCompat.newHeartRating(true);
-            MediaMetadataCompat metadata = new MediaMetadataCompat.Builder()
-                    .putString(TEST_KEY, TEST_VALUE)
-                    .putRating(METADATA_KEY_RATING, rating)
-                    .build();
-            mSession.setActive(true);
-            mSession.setMetadata(metadata);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnMetadataChangedCalled);
-
-            MediaMetadataCompat metadataOut = mCallback.mMediaMetadata;
-            assertNotNull(metadataOut);
-            assertEquals(TEST_VALUE, metadataOut.getString(TEST_KEY));
-
-            metadataOut = controller.getMetadata();
-            assertNotNull(metadataOut);
-            assertEquals(TEST_VALUE, metadataOut.getString(TEST_KEY));
-
-            assertNotNull(metadataOut.getRating(METADATA_KEY_RATING));
-            RatingCompat ratingOut = metadataOut.getRating(METADATA_KEY_RATING);
-            assertEquals(rating.getRatingStyle(), ratingOut.getRatingStyle());
-            assertEquals(rating.getPercentRating(), ratingOut.getPercentRating(), 0.0f);
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setMetadata} with artwork bitmaps.
-     */
-    @Test
-    @SmallTest
-    public void testSetMetadataWithArtworks() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        final Bitmap bitmapSmall = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
-        final Bitmap bitmapLarge = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ALPHA_8);
-
-        controller.registerCallback(mCallback, mHandler);
-        mSession.setActive(true);
-        synchronized (mWaitLock) {
-            mCallback.resetLocked();
-            MediaMetadataCompat metadata = new MediaMetadataCompat.Builder()
-                    .putString(TEST_KEY, TEST_VALUE)
-                    .putBitmap(MediaMetadataCompat.METADATA_KEY_ART, bitmapSmall)
-                    .build();
-            mSession.setMetadata(metadata);
-            mWaitLock.wait(TIME_OUT_MS);
-
-            assertTrue(mCallback.mOnMetadataChangedCalled);
-            MediaMetadataCompat metadataOut = mCallback.mMediaMetadata;
-            assertNotNull(metadataOut);
-            assertEquals(TEST_VALUE, metadataOut.getString(TEST_KEY));
-            Bitmap bitmapSmallOut = metadataOut.getBitmap(MediaMetadataCompat.METADATA_KEY_ART);
-            assertNotNull(bitmapSmallOut);
-            assertEquals(bitmapSmall.getHeight(), bitmapSmallOut.getHeight());
-            assertEquals(bitmapSmall.getWidth(), bitmapSmallOut.getWidth());
-            assertEquals(bitmapSmall.getConfig(), bitmapSmallOut.getConfig());
-
-            metadata = new MediaMetadataCompat.Builder()
-                    .putString(TEST_KEY, TEST_VALUE)
-                    .putBitmap(MediaMetadataCompat.METADATA_KEY_ART, bitmapLarge)
-                    .build();
-            mSession.setMetadata(metadata);
-            mWaitLock.wait(TIME_OUT_MS);
-
-            assertTrue(mCallback.mOnMetadataChangedCalled);
-            metadataOut = mCallback.mMediaMetadata;
-            assertNotNull(metadataOut);
-            assertEquals(TEST_VALUE, metadataOut.getString(TEST_KEY));
-            Bitmap bitmapLargeOut = metadataOut.getBitmap(MediaMetadataCompat.METADATA_KEY_ART);
-            assertNotNull(bitmapLargeOut);
-            // Don't check size here because large bitmaps can be scaled down.
-            assertEquals(bitmapLarge.getConfig(), bitmapLargeOut.getConfig());
-
-            assertFalse(bitmapSmall.isRecycled());
-            assertFalse(bitmapLarge.isRecycled());
-            assertFalse(bitmapSmallOut.isRecycled());
-            assertFalse(bitmapLargeOut.isRecycled());
-            bitmapSmallOut.recycle();
-            bitmapLargeOut.recycle();
-        }
-        bitmapSmall.recycle();
-        bitmapLarge.recycle();
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setPlaybackState}.
-     */
-    @Test
-    @SmallTest
-    public void testSetPlaybackState() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            mCallback.resetLocked();
-            PlaybackStateCompat state =
-                    new PlaybackStateCompat.Builder()
-                            .setActions(TEST_ACTION)
-                            .setErrorMessage(TEST_ERROR_CODE, TEST_ERROR_MSG)
-                            .build();
-            mSession.setPlaybackState(state);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlaybackStateChangedCalled);
-
-            PlaybackStateCompat stateOut = mCallback.mPlaybackState;
-            assertNotNull(stateOut);
-            assertEquals(TEST_ACTION, stateOut.getActions());
-            assertEquals(TEST_ERROR_CODE, stateOut.getErrorCode());
-            assertEquals(TEST_ERROR_MSG, stateOut.getErrorMessage().toString());
-
-            stateOut = controller.getPlaybackState();
-            assertNotNull(stateOut);
-            assertEquals(TEST_ACTION, stateOut.getActions());
-            assertEquals(TEST_ERROR_CODE, stateOut.getErrorCode());
-            assertEquals(TEST_ERROR_MSG, stateOut.getErrorMessage().toString());
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setQueue} and {@link MediaSessionCompat#setQueueTitle}.
-     */
-    @Test
-    @SmallTest
-    public void testSetQueueAndSetQueueTitle() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            mCallback.resetLocked();
-            List<MediaSessionCompat.QueueItem> queue = new ArrayList<>();
-            MediaSessionCompat.QueueItem item = new MediaSessionCompat.QueueItem(
-                    new MediaDescriptionCompat.Builder()
-                            .setMediaId(TEST_VALUE)
-                            .setTitle("title")
-                            .build(),
-                    TEST_QUEUE_ID);
-            queue.add(item);
-            mSession.setQueue(queue);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnQueueChangedCalled);
-
-            mSession.setQueueTitle(TEST_VALUE);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnQueueTitleChangedCalled);
-
-            assertEquals(TEST_VALUE, mCallback.mTitle);
-            assertEquals(queue.size(), mCallback.mQueue.size());
-            assertEquals(TEST_QUEUE_ID, mCallback.mQueue.get(0).getQueueId());
-            assertEquals(TEST_VALUE, mCallback.mQueue.get(0).getDescription().getMediaId());
-
-            assertEquals(TEST_VALUE, controller.getQueueTitle());
-            assertEquals(queue.size(), controller.getQueue().size());
-            assertEquals(TEST_QUEUE_ID, controller.getQueue().get(0).getQueueId());
-            assertEquals(TEST_VALUE, controller.getQueue().get(0).getDescription().getMediaId());
-
-            mCallback.resetLocked();
-            mSession.setQueue(null);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnQueueChangedCalled);
-
-            mSession.setQueueTitle(null);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnQueueTitleChangedCalled);
-
-            assertNull(mCallback.mTitle);
-            assertNull(mCallback.mQueue);
-            assertNull(controller.getQueueTitle());
-            assertNull(controller.getQueue());
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setSessionActivity}.
-     */
-    @Test
-    @SmallTest
-    public void testSessionActivity() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        synchronized (mWaitLock) {
-            Intent intent = new Intent("cts.MEDIA_SESSION_ACTION");
-            PendingIntent pi = PendingIntent.getActivity(getContext(), 555, intent, 0);
-            mSession.setSessionActivity(pi);
-            assertEquals(pi, controller.getSessionActivity());
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setCaptioningEnabled}.
-     */
-    @Test
-    @SmallTest
-    public void testSetCaptioningEnabled() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            mCallback.resetLocked();
-            mSession.setCaptioningEnabled(true);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCaptioningEnabledChangedCalled);
-            assertEquals(true, mCallback.mCaptioningEnabled);
-            assertEquals(true, controller.isCaptioningEnabled());
-
-            mCallback.resetLocked();
-            mSession.setCaptioningEnabled(false);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCaptioningEnabledChangedCalled);
-            assertEquals(false, mCallback.mCaptioningEnabled);
-            assertEquals(false, controller.isCaptioningEnabled());
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setRepeatMode}.
-     */
-    @Test
-    @SmallTest
-    public void testSetRepeatMode() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            mCallback.resetLocked();
-            final int repeatMode = PlaybackStateCompat.REPEAT_MODE_ALL;
-            mSession.setRepeatMode(repeatMode);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRepeatModeChangedCalled);
-            assertEquals(repeatMode, mCallback.mRepeatMode);
-            assertEquals(repeatMode, controller.getRepeatMode());
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setShuffleMode}.
-     */
-    @Test
-    @SmallTest
-    public void testSetShuffleMode() throws Exception {
-        final int shuffleMode = PlaybackStateCompat.SHUFFLE_MODE_ALL;
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            mCallback.resetLocked();
-            mSession.setShuffleMode(shuffleMode);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnShuffleModeChangedCalled);
-            assertEquals(shuffleMode, mCallback.mShuffleMode);
-            assertEquals(shuffleMode, controller.getShuffleMode());
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#sendSessionEvent}.
-     */
-    @Test
-    @SmallTest
-    public void testSendSessionEvent() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            mCallback.resetLocked();
-            mSession.sendSessionEvent(TEST_SESSION_EVENT, TEST_BUNDLE);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSessionEventCalled);
-            assertEquals(TEST_SESSION_EVENT, mCallback.mEvent);
-            assertEquals(TEST_VALUE, mCallback.mExtras.getString(TEST_KEY));
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setActive} and {@link MediaSessionCompat#release}.
-     */
-    @Test
-    @SmallTest
-    public void testSetActiveAndRelease() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            mSession.setActive(true);
-            assertTrue(mSession.isActive());
-
-            mCallback.resetLocked();
-            mSession.release();
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSessionDestroyedCalled);
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setCallback} with {@code null}. No callback will be called
-     * once {@code setCallback(null)} is done.
-     */
-    @Test
-    @SmallTest
-    public void testSetCallbackWithNull() throws Exception {
-        MediaSessionCallback sessionCallback = new MediaSessionCallback();
-        mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
-        mSession.setActive(true);
-        mSession.setCallback(sessionCallback, mHandler);
-
-        MediaControllerCompat controller = mSession.getController();
-        setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
-
-        sessionCallback.reset(1);
-        mSession.setCallback(null, mHandler);
-
-        controller.getTransportControls().pause();
-        assertFalse(sessionCallback.await(WAIT_TIME_MS));
-        assertFalse("Callback shouldn't be called.", sessionCallback.mOnPauseCalled);
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat#setPlaybackToLocal} and
-     * {@link MediaSessionCompat#setPlaybackToRemote}.
-     */
-    @Test
-    @SmallTest
-    public void testPlaybackToLocalAndRemote() throws Exception {
-        MediaControllerCompat controller = mSession.getController();
-        controller.registerCallback(mCallback, mHandler);
-        synchronized (mWaitLock) {
-            // test setPlaybackToRemote, do this before testing setPlaybackToLocal
-            // to ensure it switches correctly.
-            mCallback.resetLocked();
-            try {
-                mSession.setPlaybackToRemote(null);
-                fail("Expected IAE for setPlaybackToRemote(null)");
-            } catch (IllegalArgumentException e) {
-                // expected
-            }
-            VolumeProviderCompat vp = new VolumeProviderCompat(
-                    VolumeProviderCompat.VOLUME_CONTROL_FIXED,
-                    TEST_MAX_VOLUME,
-                    TEST_CURRENT_VOLUME) {};
-            mSession.setPlaybackToRemote(vp);
-
-            MediaControllerCompat.PlaybackInfo info = null;
-            for (int i = 0; i < MAX_AUDIO_INFO_CHANGED_CALLBACK_COUNT; ++i) {
-                mCallback.mOnAudioInfoChangedCalled = false;
-                mWaitLock.wait(TIME_OUT_MS);
-                assertTrue(mCallback.mOnAudioInfoChangedCalled);
-                info = mCallback.mPlaybackInfo;
-                if (info != null && info.getCurrentVolume() == TEST_CURRENT_VOLUME
-                        && info.getMaxVolume() == TEST_MAX_VOLUME
-                        && info.getVolumeControl() == VolumeProviderCompat.VOLUME_CONTROL_FIXED
-                        && info.getPlaybackType()
-                        == MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
-                    break;
-                }
-            }
-            assertNotNull(info);
-            assertEquals(MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
-                    info.getPlaybackType());
-            assertEquals(TEST_MAX_VOLUME, info.getMaxVolume());
-            assertEquals(TEST_CURRENT_VOLUME, info.getCurrentVolume());
-            assertEquals(VolumeProviderCompat.VOLUME_CONTROL_FIXED,
-                    info.getVolumeControl());
-
-            info = controller.getPlaybackInfo();
-            assertNotNull(info);
-            assertEquals(MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
-                    info.getPlaybackType());
-            assertEquals(TEST_MAX_VOLUME, info.getMaxVolume());
-            assertEquals(TEST_CURRENT_VOLUME, info.getCurrentVolume());
-            assertEquals(VolumeProviderCompat.VOLUME_CONTROL_FIXED, info.getVolumeControl());
-
-            // test setPlaybackToLocal
-            mSession.setPlaybackToLocal(AudioManager.STREAM_RING);
-            info = controller.getPlaybackInfo();
-            assertNotNull(info);
-            assertEquals(MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
-                    info.getPlaybackType());
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat.Callback#onMediaButtonEvent}.
-     */
-    @Test
-    @SmallTest
-    public void testCallbackOnMediaButtonEvent() throws Exception {
-        MediaSessionCallback sessionCallback = new MediaSessionCallback();
-        mSession.setCallback(sessionCallback, new Handler(Looper.getMainLooper()));
-        mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
-        mSession.setActive(true);
-
-        Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON).setComponent(
-                new ComponentName(getContext(), getContext().getClass()));
-        PendingIntent pi = PendingIntent.getBroadcast(getContext(), 0, mediaButtonIntent, 0);
-        mSession.setMediaButtonReceiver(pi);
-
-        // Set state to STATE_PLAYING to get higher priority.
-        setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
-
-        sessionCallback.reset(1);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertEquals(1, sessionCallback.mOnPlayCalledCount);
-
-        sessionCallback.reset(1);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PAUSE);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertTrue(sessionCallback.mOnPauseCalled);
-
-        sessionCallback.reset(1);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_NEXT);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertTrue(sessionCallback.mOnSkipToNextCalled);
-
-        sessionCallback.reset(1);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertTrue(sessionCallback.mOnSkipToPreviousCalled);
-
-        sessionCallback.reset(1);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertTrue(sessionCallback.mOnStopCalled);
-
-        sessionCallback.reset(1);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertTrue(sessionCallback.mOnFastForwardCalled);
-
-        sessionCallback.reset(1);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_REWIND);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertTrue(sessionCallback.mOnRewindCalled);
-
-        // Test PLAY_PAUSE button twice.
-        // First, send PLAY_PAUSE button event while in STATE_PAUSED.
-        sessionCallback.reset(1);
-        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertEquals(1, sessionCallback.mOnPlayCalledCount);
-
-        // Next, send PLAY_PAUSE button event while in STATE_PLAYING.
-        sessionCallback.reset(1);
-        setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertTrue(sessionCallback.mOnPauseCalled);
-
-        // Double tap of PLAY_PAUSE is the next track.
-        sessionCallback.reset(2);
-        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
-        assertFalse(sessionCallback.await(WAIT_TIME_MS));
-        assertTrue(sessionCallback.mOnSkipToNextCalled);
-        assertEquals(0, sessionCallback.mOnPlayCalledCount);
-        assertFalse(sessionCallback.mOnPauseCalled);
-
-        // Test PLAY_PAUSE button long-press.
-        // It should be the same as the single short-press.
-        sessionCallback.reset(1);
-        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertEquals(1, sessionCallback.mOnPlayCalledCount);
-
-        // Double tap of PLAY_PAUSE should be handled once.
-        // Initial down event from the second press within double tap time-out will make
-        // onSkipToNext() to be called, so further down events shouldn't be handled again.
-        sessionCallback.reset(2);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
-        assertFalse(sessionCallback.await(WAIT_TIME_MS));
-        assertTrue(sessionCallback.mOnSkipToNextCalled);
-        assertEquals(0, sessionCallback.mOnPlayCalledCount);
-        assertFalse(sessionCallback.mOnPauseCalled);
-
-        // Test PLAY_PAUSE button short-press followed by the long-press.
-        // Initial long-press of the PLAY_PAUSE is considered as the single short-press already,
-        // so it shouldn't be used as the first tap of the double tap.
-        sessionCallback.reset(2);
-        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        // onMediaButtonEvent() calls either onPlay() or onPause() depending on the playback state,
-        // so onPlay() should be called twice while onPause() isn't called.
-        assertEquals(1, sessionCallback.mOnPlayCalledCount);
-        assertTrue(sessionCallback.mOnPauseCalled);
-        assertFalse(sessionCallback.mOnSkipToNextCalled);
-
-        // If another media key is pressed while the double tap of PLAY_PAUSE,
-        // PLAY_PAUSE should be handles as normal.
-        sessionCallback.reset(3);
-        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertFalse(sessionCallback.mOnSkipToNextCalled);
-        assertTrue(sessionCallback.mOnStopCalled);
-        assertEquals(2, sessionCallback.mOnPlayCalledCount);
-
-        // Test if media keys are handled in order.
-        sessionCallback.reset(2);
-        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
-        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
-        assertTrue(sessionCallback.await(TIME_OUT_MS));
-        assertEquals(1, sessionCallback.mOnPlayCalledCount);
-        assertTrue(sessionCallback.mOnStopCalled);
-        synchronized (mWaitLock) {
-            assertEquals(PlaybackStateCompat.STATE_STOPPED,
-                    mSession.getController().getPlaybackState().getState());
-        }
-    }
-
-    private void setPlaybackState(int state) {
-        final long allActions = PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE
-                | PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_STOP
-                | PlaybackStateCompat.ACTION_SKIP_TO_NEXT
-                | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
-                | PlaybackStateCompat.ACTION_FAST_FORWARD | PlaybackStateCompat.ACTION_REWIND;
-        PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder().setActions(allActions)
-                .setState(state, 0L, 0.0f).build();
-        synchronized (mWaitLock) {
-            mSession.setPlaybackState(playbackState);
-        }
-    }
-
-    /**
-     * Tests {@link MediaSessionCompat.QueueItem}.
-     */
-    @Test
-    @SmallTest
-    public void testQueueItem() {
-        MediaSessionCompat.QueueItem item = new MediaSessionCompat.QueueItem(
-                new MediaDescriptionCompat.Builder()
-                        .setMediaId("media-id")
-                        .setTitle("title")
-                        .build(),
-                TEST_QUEUE_ID);
-        assertEquals(TEST_QUEUE_ID, item.getQueueId());
-        assertEquals("media-id", item.getDescription().getMediaId());
-        assertEquals("title", item.getDescription().getTitle());
-        assertEquals(0, item.describeContents());
-
-        Parcel p = Parcel.obtain();
-        item.writeToParcel(p, 0);
-        p.setDataPosition(0);
-        MediaSessionCompat.QueueItem other =
-                MediaSessionCompat.QueueItem.CREATOR.createFromParcel(p);
-        assertEquals(item.toString(), other.toString());
-        p.recycle();
-    }
-
-    /**
-     * Verifies that a new session hasn't had any configuration bits set yet.
-     *
-     * @param controller The controller for the session
-     */
-    private void verifyNewSession(MediaControllerCompat controller, String tag) {
-        assertEquals("New session has unexpected configuration", 0L, controller.getFlags());
-        assertNull("New session has unexpected configuration", controller.getExtras());
-        assertNull("New session has unexpected configuration", controller.getMetadata());
-        assertEquals("New session has unexpected configuration",
-                getContext().getPackageName(), controller.getPackageName());
-        assertNull("New session has unexpected configuration", controller.getPlaybackState());
-        assertNull("New session has unexpected configuration", controller.getQueue());
-        assertNull("New session has unexpected configuration", controller.getQueueTitle());
-        assertEquals("New session has unexpected configuration", RatingCompat.RATING_NONE,
-                controller.getRatingType());
-        assertNull("New session has unexpected configuration", controller.getSessionActivity());
-
-        assertNotNull(controller.getSessionToken());
-        assertNotNull(controller.getTransportControls());
-
-        MediaControllerCompat.PlaybackInfo info = controller.getPlaybackInfo();
-        assertNotNull(info);
-        assertEquals(MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
-                info.getPlaybackType());
-        assertEquals(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC),
-                info.getCurrentVolume());
-    }
-
-    private void sendMediaKeyInputToController(int keyCode) {
-        sendMediaKeyInputToController(keyCode, false);
-    }
-
-    private void sendMediaKeyInputToController(int keyCode, boolean isLongPress) {
-        MediaControllerCompat controller = mSession.getController();
-        long currentTimeMs = System.currentTimeMillis();
-        KeyEvent down = new KeyEvent(
-                currentTimeMs, currentTimeMs, KeyEvent.ACTION_DOWN, keyCode, 0);
-        controller.dispatchMediaButtonEvent(down);
-        if (isLongPress) {
-            KeyEvent longPress = new KeyEvent(
-                    currentTimeMs, System.currentTimeMillis(), KeyEvent.ACTION_DOWN, keyCode, 1);
-            controller.dispatchMediaButtonEvent(longPress);
-        }
-        KeyEvent up = new KeyEvent(
-                currentTimeMs, System.currentTimeMillis(), KeyEvent.ACTION_UP, keyCode, 0);
-        controller.dispatchMediaButtonEvent(up);
-    }
-
-    private class MediaControllerCallback extends MediaControllerCompat.Callback {
-        private volatile boolean mOnPlaybackStateChangedCalled;
-        private volatile boolean mOnMetadataChangedCalled;
-        private volatile boolean mOnQueueChangedCalled;
-        private volatile boolean mOnQueueTitleChangedCalled;
-        private volatile boolean mOnExtraChangedCalled;
-        private volatile boolean mOnAudioInfoChangedCalled;
-        private volatile boolean mOnSessionDestroyedCalled;
-        private volatile boolean mOnSessionEventCalled;
-        private volatile boolean mOnCaptioningEnabledChangedCalled;
-        private volatile boolean mOnRepeatModeChangedCalled;
-        private volatile boolean mOnShuffleModeChangedCalled;
-
-        private volatile PlaybackStateCompat mPlaybackState;
-        private volatile MediaMetadataCompat mMediaMetadata;
-        private volatile List<MediaSessionCompat.QueueItem> mQueue;
-        private volatile CharSequence mTitle;
-        private volatile String mEvent;
-        private volatile Bundle mExtras;
-        private volatile MediaControllerCompat.PlaybackInfo mPlaybackInfo;
-        private volatile boolean mCaptioningEnabled;
-        private volatile int mRepeatMode;
-        private volatile int mShuffleMode;
-
-        public void resetLocked() {
-            mOnPlaybackStateChangedCalled = false;
-            mOnMetadataChangedCalled = false;
-            mOnQueueChangedCalled = false;
-            mOnQueueTitleChangedCalled = false;
-            mOnExtraChangedCalled = false;
-            mOnAudioInfoChangedCalled = false;
-            mOnSessionDestroyedCalled = false;
-            mOnSessionEventCalled = false;
-            mOnRepeatModeChangedCalled = false;
-            mOnShuffleModeChangedCalled = false;
-
-            mPlaybackState = null;
-            mMediaMetadata = null;
-            mQueue = null;
-            mTitle = null;
-            mExtras = null;
-            mPlaybackInfo = null;
-            mCaptioningEnabled = false;
-            mRepeatMode = PlaybackStateCompat.REPEAT_MODE_NONE;
-            mShuffleMode = PlaybackStateCompat.SHUFFLE_MODE_NONE;
-        }
-
-        @Override
-        public void onPlaybackStateChanged(PlaybackStateCompat state) {
-            synchronized (mWaitLock) {
-                mOnPlaybackStateChangedCalled = true;
-                mPlaybackState = state;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onMetadataChanged(MediaMetadataCompat metadata) {
-            synchronized (mWaitLock) {
-                mOnMetadataChangedCalled = true;
-                mMediaMetadata = metadata;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onQueueChanged(List<MediaSessionCompat.QueueItem> queue) {
-            synchronized (mWaitLock) {
-                mOnQueueChangedCalled = true;
-                mQueue = queue;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onQueueTitleChanged(CharSequence title) {
-            synchronized (mWaitLock) {
-                mOnQueueTitleChangedCalled = true;
-                mTitle = title;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onExtrasChanged(Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnExtraChangedCalled = true;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onAudioInfoChanged(MediaControllerCompat.PlaybackInfo info) {
-            synchronized (mWaitLock) {
-                mOnAudioInfoChangedCalled = true;
-                mPlaybackInfo = info;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSessionDestroyed() {
-            synchronized (mWaitLock) {
-                mOnSessionDestroyedCalled = true;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSessionEvent(String event, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnSessionEventCalled = true;
-                mEvent = event;
-                mExtras = (Bundle) extras.clone();
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onCaptioningEnabledChanged(boolean enabled) {
-            synchronized (mWaitLock) {
-                mOnCaptioningEnabledChangedCalled = true;
-                mCaptioningEnabled = enabled;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onRepeatModeChanged(int repeatMode) {
-            synchronized (mWaitLock) {
-                mOnRepeatModeChangedCalled = true;
-                mRepeatMode = repeatMode;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onShuffleModeChanged(int shuffleMode) {
-            synchronized (mWaitLock) {
-                mOnShuffleModeChangedCalled = true;
-                mShuffleMode = shuffleMode;
-                mWaitLock.notify();
-            }
-        }
-    }
-
-    private class MediaSessionCallback extends MediaSessionCompat.Callback {
-        private CountDownLatch mLatch;
-        private int mOnPlayCalledCount;
-        private boolean mOnPauseCalled;
-        private boolean mOnStopCalled;
-        private boolean mOnFastForwardCalled;
-        private boolean mOnRewindCalled;
-        private boolean mOnSkipToPreviousCalled;
-        private boolean mOnSkipToNextCalled;
-
-        public void reset(int count) {
-            mLatch = new CountDownLatch(count);
-            mOnPlayCalledCount = 0;
-            mOnPauseCalled = false;
-            mOnStopCalled = false;
-            mOnFastForwardCalled = false;
-            mOnRewindCalled = false;
-            mOnSkipToPreviousCalled = false;
-            mOnSkipToNextCalled = false;
-        }
-
-        public boolean await(long timeoutMs) {
-            try {
-                return mLatch.await(timeoutMs, TimeUnit.MILLISECONDS);
-            } catch (InterruptedException e) {
-                return false;
-            }
-        }
-
-        @Override
-        public void onPlay() {
-            mOnPlayCalledCount++;
-            setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
-            mLatch.countDown();
-        }
-
-        @Override
-        public void onPause() {
-            mOnPauseCalled = true;
-            setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
-            mLatch.countDown();
-        }
-
-        @Override
-        public void onStop() {
-            mOnStopCalled = true;
-            setPlaybackState(PlaybackStateCompat.STATE_STOPPED);
-            mLatch.countDown();
-        }
-
-        @Override
-        public void onFastForward() {
-            mOnFastForwardCalled = true;
-            mLatch.countDown();
-        }
-
-        @Override
-        public void onRewind() {
-            mOnRewindCalled = true;
-            mLatch.countDown();
-        }
-
-        @Override
-        public void onSkipToPrevious() {
-            mOnSkipToPreviousCalled = true;
-            mLatch.countDown();
-        }
-
-        @Override
-        public void onSkipToNext() {
-            mOnSkipToNextCalled = true;
-            mLatch.countDown();
-        }
-    }
-}
diff --git a/media-compat/version-compat-tests/current/client/build.gradle b/media-compat/version-compat-tests/current/client/build.gradle
index d6f0e7d..aeb82c1 100644
--- a/media-compat/version-compat-tests/current/client/build.gradle
+++ b/media-compat/version-compat-tests/current/client/build.gradle
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
+
 plugins {
     id("SupportAndroidLibraryPlugin")
 }
 
 dependencies {
-    androidTestImplementation project(':support-media-compat')
-    androidTestImplementation project(':support-media-compat-test-lib')
+    androidTestImplementation(project(":support-media-compat"))
+    androidTestImplementation(project(":support-media-compat-test-lib"))
 
-    androidTestImplementation(libs.test_runner)
+    androidTestImplementation(TEST_RUNNER)
 }
 
 android {
diff --git a/media-compat/tests/src/android/support/v4/media/AudioAttributesCompatTest.java b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/AudioAttributesCompatTest.java
similarity index 97%
rename from media-compat/tests/src/android/support/v4/media/AudioAttributesCompatTest.java
rename to media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/AudioAttributesCompatTest.java
index d66c7fc..675c0fc 100644
--- a/media-compat/tests/src/android/support/v4/media/AudioAttributesCompatTest.java
+++ b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/AudioAttributesCompatTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.support.v4.media;
+package android.support.mediacompat.client;
 
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.hamcrest.core.IsNot.not;
@@ -25,6 +25,7 @@
 import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.media.AudioAttributesCompat;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/ClientBroadcastReceiver.java b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/ClientBroadcastReceiver.java
index 3166e55..3227482 100644
--- a/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/ClientBroadcastReceiver.java
+++ b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/ClientBroadcastReceiver.java
@@ -19,6 +19,7 @@
 import static android.support.mediacompat.testlib.MediaControllerConstants.ADD_QUEUE_ITEM;
 import static android.support.mediacompat.testlib.MediaControllerConstants
         .ADD_QUEUE_ITEM_WITH_INDEX;
+import static android.support.mediacompat.testlib.MediaControllerConstants.ADJUST_VOLUME;
 import static android.support.mediacompat.testlib.MediaControllerConstants.FAST_FORWARD;
 import static android.support.mediacompat.testlib.MediaControllerConstants.PAUSE;
 import static android.support.mediacompat.testlib.MediaControllerConstants.PLAY;
@@ -40,6 +41,7 @@
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_RATING;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_REPEAT_MODE;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_SHUFFLE_MODE;
+import static android.support.mediacompat.testlib.MediaControllerConstants.SET_VOLUME_TO;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_NEXT;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_PREVIOUS;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_QUEUE_ITEM;
@@ -105,6 +107,12 @@
                     controller.removeQueueItem(
                             (MediaDescriptionCompat) extras.getParcelable(KEY_ARGUMENT));
                     break;
+                case SET_VOLUME_TO:
+                    controller.setVolumeTo(extras.getInt(KEY_ARGUMENT), 0);
+                    break;
+                case ADJUST_VOLUME:
+                    controller.adjustVolume(extras.getInt(KEY_ARGUMENT), 0);
+                    break;
             }
         } else if (ACTION_CALL_TRANSPORT_CONTROLS_METHOD.equals(intent.getAction())
                 && extras != null) {
diff --git a/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaBrowserCompatTest.java b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaBrowserCompatTest.java
index 31bdb7a..6144ede 100644
--- a/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaBrowserCompatTest.java
+++ b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaBrowserCompatTest.java
@@ -26,10 +26,12 @@
 import static android.support.mediacompat.testlib.MediaBrowserConstants.EXTRAS_VALUE;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_CHILDREN;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_CHILDREN_DELAYED;
+import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_INCLUDE_METADATA;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_INVALID;
 import static android.support.mediacompat.testlib.MediaBrowserConstants
         .MEDIA_ID_ON_LOAD_ITEM_NOT_IMPLEMENTED;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_ROOT;
+import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_METADATA;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.NOTIFY_CHILDREN_CHANGED;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY_FOR_ERROR;
@@ -47,6 +49,8 @@
 import static android.support.mediacompat.testlib.MediaBrowserConstants.TEST_VALUE_3;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.TEST_VALUE_4;
 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.mediacompat.testlib.util.IntentUtil.callMediaBrowserServiceMethod;
 import static android.support.test.InstrumentationRegistry.getArguments;
 import static android.support.test.InstrumentationRegistry.getContext;
@@ -56,6 +60,7 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
 
@@ -71,6 +76,8 @@
 import android.support.v4.media.MediaBrowserCompat.MediaItem;
 import android.support.v4.media.MediaBrowserServiceCompat;
 import android.support.v4.media.MediaDescriptionCompat;
+import android.support.v4.media.MediaMetadataCompat;
+import android.support.v4.media.RatingCompat;
 import android.util.Log;
 
 import org.junit.After;
@@ -80,6 +87,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Test {@link android.support.v4.media.MediaBrowserCompat}.
@@ -105,13 +114,15 @@
      */
     private static final long SLEEP_MS = 100L;
     private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
-            "android.support.mediacompat.service.test",
+            SERVICE_PACKAGE_NAME,
             "android.support.mediacompat.service.StubMediaBrowserServiceCompat");
     private static final ComponentName TEST_BROWSER_SERVICE_DELAYED_MEDIA_SESSION =
             new ComponentName(
-                    "android.support.mediacompat.service.test",
+                    SERVICE_PACKAGE_NAME,
                     "android.support.mediacompat.service"
                             + ".StubMediaBrowserServiceCompatWithDelayedMediaSession");
+    private static final ComponentName TEST_INVALID_BROWSER_SERVICE = new ComponentName(
+            "invalid.package", "invalid.ServiceClassName");
 
     private String mServiceVersion;
     private MediaBrowserCompat mMediaBrowser;
@@ -157,6 +168,21 @@
 
     @Test
     @SmallTest
+    public void testBrowserRoot() {
+        final String id = "test-id";
+        final String key = "test-key";
+        final String val = "test-val";
+        final Bundle extras = new Bundle();
+        extras.putString(key, val);
+
+        MediaBrowserServiceCompat.BrowserRoot browserRoot =
+                new MediaBrowserServiceCompat.BrowserRoot(id, extras);
+        assertEquals(id, browserRoot.getRootId());
+        assertEquals(val, browserRoot.getExtras().getString(key));
+    }
+
+    @Test
+    @SmallTest
     public void testMediaBrowser() throws Exception {
         assertFalse(mMediaBrowser.isConnected());
 
@@ -178,6 +204,37 @@
 
     @Test
     @SmallTest
+    public void testGetServiceComponentBeforeConnection() {
+        try {
+            ComponentName serviceComponent = mMediaBrowser.getServiceComponent();
+            fail();
+        } catch (IllegalStateException e) {
+            // expected
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testConnectionFailed() throws Exception {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mMediaBrowser = new MediaBrowserCompat(getInstrumentation().getTargetContext(),
+                        TEST_INVALID_BROWSER_SERVICE, mConnectionCallback, mRootHints);
+            }
+        });
+
+        synchronized (mConnectionCallback.mWaitLock) {
+            mMediaBrowser.connect();
+            mConnectionCallback.mWaitLock.wait(TIME_OUT_MS);
+        }
+        assertEquals(1, mConnectionCallback.mConnectionFailedCount);
+        assertEquals(0, mConnectionCallback.mConnectedCount);
+        assertEquals(0, mConnectionCallback.mConnectionSuspendedCount);
+    }
+
+    @Test
+    @SmallTest
     public void testConnectTwice() throws Exception {
         connectMediaBrowserService();
         try {
@@ -206,18 +263,16 @@
             assertEquals(1, mConnectionCallback.mConnectedCount);
         }
 
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            // Test subscribe.
-            resetCallbacks();
-            mMediaBrowser.subscribe(MEDIA_ID_ROOT, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedCount > 0);
-            assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
-        }
+        // Test subscribe.
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_ROOT, mSubscriptionCallback);
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(1, mSubscriptionCallback.mChildrenLoadedCount);
+        assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
 
         synchronized (mItemCallback.mWaitLock) {
             // Test getItem.
-            resetCallbacks();
+            mItemCallback.reset();
             mMediaBrowser.getItem(MEDIA_ID_CHILDREN[0], mItemCallback);
             mItemCallback.mWaitLock.wait(TIME_OUT_MS);
             assertEquals(MEDIA_ID_CHILDREN[0], mItemCallback.mLastMediaItem.getMediaId());
@@ -225,12 +280,11 @@
 
         // Reconnect after connection was established.
         mMediaBrowser.disconnect();
-        resetCallbacks();
         connectMediaBrowserService();
 
         synchronized (mItemCallback.mWaitLock) {
             // Test getItem.
-            resetCallbacks();
+            mItemCallback.reset();
             mMediaBrowser.getItem(MEDIA_ID_CHILDREN[0], mItemCallback);
             mItemCallback.mWaitLock.wait(TIME_OUT_MS);
             assertEquals(MEDIA_ID_CHILDREN[0], mItemCallback.mLastMediaItem.getMediaId());
@@ -245,7 +299,7 @@
             public void run() {
                 mMediaBrowser.connect();
                 mMediaBrowser.disconnect();
-                resetCallbacks();
+                mConnectionCallback.reset();
             }
         });
 
@@ -259,48 +313,43 @@
         assertEquals(0, mConnectionCallback.mConnectionSuspendedCount);
     }
 
-//    @Test
-//    @MediumTest
+    @Test
+    @MediumTest
     public void testSubscribe() throws Exception {
         connectMediaBrowserService();
 
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mMediaBrowser.subscribe(MEDIA_ID_ROOT, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedCount > 0);
-            assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
-            assertEquals(MEDIA_ID_CHILDREN.length,
-                    mSubscriptionCallback.mLastChildMediaItems.size());
-            for (int i = 0; i < MEDIA_ID_CHILDREN.length; ++i) {
-                assertEquals(MEDIA_ID_CHILDREN[i],
-                        mSubscriptionCallback.mLastChildMediaItems.get(i).getMediaId());
-            }
-
-            // Test MediaBrowserServiceCompat.notifyChildrenChanged()
-            mSubscriptionCallback.reset();
-            callMediaBrowserServiceMethod(NOTIFY_CHILDREN_CHANGED, MEDIA_ID_ROOT, getContext());
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedCount > 0);
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_ROOT, mSubscriptionCallback);
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(1, mSubscriptionCallback.mChildrenLoadedCount);
+        assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
+        assertEquals(MEDIA_ID_CHILDREN.length, mSubscriptionCallback.mLastChildMediaItems.size());
+        for (int i = 0; i < MEDIA_ID_CHILDREN.length; ++i) {
+            assertEquals(MEDIA_ID_CHILDREN[i],
+                    mSubscriptionCallback.mLastChildMediaItems.get(i).getMediaId());
         }
 
+        // Test MediaBrowserServiceCompat.notifyChildrenChanged()
+        mSubscriptionCallback.reset(1);
+        callMediaBrowserServiceMethod(NOTIFY_CHILDREN_CHANGED, MEDIA_ID_ROOT, getContext());
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(1, mSubscriptionCallback.mChildrenLoadedCount);
+
         // Test unsubscribe.
-        resetCallbacks();
+        mSubscriptionCallback.reset(1);
         mMediaBrowser.unsubscribe(MEDIA_ID_ROOT);
 
         // After unsubscribing, make StubMediaBrowserServiceCompat notify that the children are
         // changed.
         callMediaBrowserServiceMethod(NOTIFY_CHILDREN_CHANGED, MEDIA_ID_ROOT, getContext());
-        try {
-            Thread.sleep(SLEEP_MS);
-        } catch (InterruptedException e) {
-            fail("Unexpected InterruptedException occurred.");
-        }
+        mSubscriptionCallback.await(WAIT_TIME_FOR_NO_RESPONSE_MS);
+
         // onChildrenLoaded should not be called.
         assertEquals(0, mSubscriptionCallback.mChildrenLoadedCount);
     }
 
-//    @Test
-//    @MediumTest
+    @Test
+    @MediumTest
     public void testSubscribeWithOptions() throws Exception {
         connectMediaBrowserService();
         final int pageSize = 3;
@@ -308,36 +357,34 @@
         Bundle options = new Bundle();
         options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
 
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            for (int page = 0; page <= lastPage; ++page) {
-                resetCallbacks();
-                options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
-                mMediaBrowser.subscribe(MEDIA_ID_ROOT, options, mSubscriptionCallback);
-                mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-                assertTrue(mSubscriptionCallback.mChildrenLoadedWithOptionCount > 0);
-                assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
-                if (page != lastPage) {
-                    assertEquals(pageSize, mSubscriptionCallback.mLastChildMediaItems.size());
-                } else {
-                    assertEquals((MEDIA_ID_CHILDREN.length - 1) % pageSize + 1,
-                            mSubscriptionCallback.mLastChildMediaItems.size());
-                }
-                // Check whether all the items in the current page are loaded.
-                for (int i = 0; i < mSubscriptionCallback.mLastChildMediaItems.size(); ++i) {
-                    assertEquals(MEDIA_ID_CHILDREN[page * pageSize + i],
-                            mSubscriptionCallback.mLastChildMediaItems.get(i).getMediaId());
-                }
+        for (int page = 0; page <= lastPage; ++page) {
+            mSubscriptionCallback.reset(1);
+            options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
+            mMediaBrowser.subscribe(MEDIA_ID_ROOT, options, mSubscriptionCallback);
+            mSubscriptionCallback.await(TIME_OUT_MS);
+            assertEquals(1, mSubscriptionCallback.mChildrenLoadedWithOptionCount);
+            assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
+            if (page != lastPage) {
+                assertEquals(pageSize, mSubscriptionCallback.mLastChildMediaItems.size());
+            } else {
+                assertEquals((MEDIA_ID_CHILDREN.length - 1) % pageSize + 1,
+                        mSubscriptionCallback.mLastChildMediaItems.size());
+            }
+            // Check whether all the items in the current page are loaded.
+            for (int i = 0; i < mSubscriptionCallback.mLastChildMediaItems.size(); ++i) {
+                assertEquals(MEDIA_ID_CHILDREN[page * pageSize + i],
+                        mSubscriptionCallback.mLastChildMediaItems.get(i).getMediaId());
             }
 
             // Test MediaBrowserServiceCompat.notifyChildrenChanged()
-            mSubscriptionCallback.reset();
+            mSubscriptionCallback.reset(page + 1);
             callMediaBrowserServiceMethod(NOTIFY_CHILDREN_CHANGED, MEDIA_ID_ROOT, getContext());
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedWithOptionCount > 0);
+            mSubscriptionCallback.await(TIME_OUT_MS);
+            assertEquals(page + 1, mSubscriptionCallback.mChildrenLoadedWithOptionCount);
         }
 
         // Test unsubscribe with callback argument.
-        resetCallbacks();
+        mSubscriptionCallback.reset(1);
         mMediaBrowser.unsubscribe(MEDIA_ID_ROOT, mSubscriptionCallback);
 
         // After unsubscribing, make StubMediaBrowserServiceCompat notify that the children are
@@ -353,20 +400,61 @@
     }
 
     @Test
+    @SmallTest
+    public void testSubscribeWithOptionsIncludingCompatParcelables() throws Exception {
+        if (Build.VERSION.SDK_INT >= 26 && !VERSION_TOT.equals(mServiceVersion)) {
+            // This test will fail on API 26 or newer APIs if the service application uses
+            // support library v27.0.1 or lower versions.
+            return;
+        }
+        connectMediaBrowserService();
+
+        final String mediaId = "1000";
+        final RatingCompat percentageRating = RatingCompat.newPercentageRating(0.5f);
+        final RatingCompat starRating =
+                RatingCompat.newStarRating(RatingCompat.RATING_5_STARS, 4.0f);
+        MediaMetadataCompat mediaMetadataCompat = new MediaMetadataCompat.Builder()
+                .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, mediaId)
+                .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "title")
+                .putRating(MediaMetadataCompat.METADATA_KEY_RATING, percentageRating)
+                .putRating(MediaMetadataCompat.METADATA_KEY_USER_RATING, starRating)
+                .build();
+        Bundle options = new Bundle();
+        options.putParcelable(MEDIA_METADATA, mediaMetadataCompat);
+
+        // Remote MediaBrowserService will create a media item with the given MediaMetadataCompat.
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_INCLUDE_METADATA, options, mSubscriptionCallback);
+        mSubscriptionCallback.await(TIME_OUT_MS);
+
+        assertEquals(1, mSubscriptionCallback.mChildrenLoadedWithOptionCount);
+        assertEquals(1, mSubscriptionCallback.mLastChildMediaItems.size());
+        assertEquals(mediaId, mSubscriptionCallback.mLastChildMediaItems.get(0).getMediaId());
+
+        MediaMetadataCompat metadataOut = mSubscriptionCallback.mLastOptions
+                .getParcelable(MEDIA_METADATA);
+        assertEquals(mediaId, metadataOut.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID));
+        assertEquals("title", metadataOut.getString(MediaMetadataCompat.METADATA_KEY_TITLE));
+        assertRatingEquals(percentageRating,
+                metadataOut.getRating(MediaMetadataCompat.METADATA_KEY_RATING));
+        assertRatingEquals(starRating,
+                metadataOut.getRating(MediaMetadataCompat.METADATA_KEY_USER_RATING));
+    }
+
+    @Test
     @MediumTest
     public void testSubscribeDelayedItems() throws Exception {
         connectMediaBrowserService();
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mSubscriptionCallback.reset();
-            mMediaBrowser.subscribe(MEDIA_ID_CHILDREN_DELAYED, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertEquals(0, mSubscriptionCallback.mChildrenLoadedCount);
 
-            callMediaBrowserServiceMethod(
-                    SEND_DELAYED_NOTIFY_CHILDREN_CHANGED, MEDIA_ID_CHILDREN_DELAYED, getContext());
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedCount > 0);
-        }
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_CHILDREN_DELAYED, mSubscriptionCallback);
+        mSubscriptionCallback.await(WAIT_TIME_FOR_NO_RESPONSE_MS);
+        assertEquals(0, mSubscriptionCallback.mChildrenLoadedCount);
+
+        callMediaBrowserServiceMethod(
+                SEND_DELAYED_NOTIFY_CHILDREN_CHANGED, MEDIA_ID_CHILDREN_DELAYED, getContext());
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(1, mSubscriptionCallback.mChildrenLoadedCount);
     }
 
     @Test
@@ -374,11 +462,10 @@
     public void testSubscribeInvalidItem() throws Exception {
         connectMediaBrowserService();
 
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mMediaBrowser.subscribe(MEDIA_ID_INVALID, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(MEDIA_ID_INVALID, mSubscriptionCallback.mLastErrorId);
-        }
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_INVALID, mSubscriptionCallback);
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(MEDIA_ID_INVALID, mSubscriptionCallback.mLastErrorId);
     }
 
     @Test
@@ -392,16 +479,15 @@
         options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
         options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
 
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mMediaBrowser.subscribe(MEDIA_ID_INVALID, options, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(MEDIA_ID_INVALID, mSubscriptionCallback.mLastErrorId);
-            assertNotNull(mSubscriptionCallback.mLastOptions);
-            assertEquals(page,
-                    mSubscriptionCallback.mLastOptions.getInt(MediaBrowserCompat.EXTRA_PAGE));
-            assertEquals(pageSize,
-                    mSubscriptionCallback.mLastOptions.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE));
-        }
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_INVALID, options, mSubscriptionCallback);
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(MEDIA_ID_INVALID, mSubscriptionCallback.mLastErrorId);
+        assertNotNull(mSubscriptionCallback.mLastOptions);
+        assertEquals(page,
+                mSubscriptionCallback.mLastOptions.getInt(MediaBrowserCompat.EXTRA_PAGE));
+        assertEquals(pageSize,
+                mSubscriptionCallback.mLastOptions.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE));
     }
 
     @Test
@@ -419,17 +505,17 @@
             Bundle options = new Bundle();
             options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
             options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
+            callback.reset(1);
             mMediaBrowser.subscribe(MEDIA_ID_ROOT, options, callback);
-            synchronized (callback.mWaitLock) {
-                callback.mWaitLock.wait(TIME_OUT_MS);
-            }
+            callback.await(TIME_OUT_MS);
+
             // Each onChildrenLoaded() must be called.
             assertEquals(1, callback.mChildrenLoadedWithOptionCount);
         }
 
         // Reset callbacks and unsubscribe.
         for (StubSubscriptionCallback callback : subscriptionCallbacks) {
-            callback.reset();
+            callback.reset(1);
         }
         mMediaBrowser.unsubscribe(MEDIA_ID_ROOT);
 
@@ -448,8 +534,8 @@
         }
     }
 
-//    @Test
-//    @MediumTest
+    @Test
+    @MediumTest
     public void testUnsubscribeWithSubscriptionCallbackForMultipleSubscriptions() throws Exception {
         connectMediaBrowserService();
         final List<StubSubscriptionCallback> subscriptionCallbacks = new ArrayList<>();
@@ -463,10 +549,10 @@
             Bundle options = new Bundle();
             options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
             options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
+            callback.reset(1);
             mMediaBrowser.subscribe(MEDIA_ID_ROOT, options, callback);
-            synchronized (callback.mWaitLock) {
-                callback.mWaitLock.wait(TIME_OUT_MS);
-            }
+            callback.await(TIME_OUT_MS);
+
             // Each onChildrenLoaded() must be called.
             assertEquals(1, callback.mChildrenLoadedWithOptionCount);
         }
@@ -476,7 +562,7 @@
         for (int i = 0; i < orderOfRemovingCallbacks.length; i++) {
             // Reset callbacks
             for (StubSubscriptionCallback callback : subscriptionCallbacks) {
-                callback.reset();
+                callback.reset(1);
             }
 
             // Remove one subscription
@@ -611,6 +697,7 @@
             customActionExtras.putString(TEST_KEY_1, TEST_VALUE_1);
             mMediaBrowser.sendCustomAction(
                     CUSTOM_ACTION, customActionExtras, mCustomActionCallback);
+            mCustomActionCallback.mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
 
             mCustomActionCallback.reset();
             Bundle data1 = new Bundle();
@@ -701,6 +788,8 @@
         Bundle customActionExtras = new Bundle();
         customActionExtras.putString(TEST_KEY_1, TEST_VALUE_1);
         mMediaBrowser.sendCustomAction(CUSTOM_ACTION, customActionExtras, null);
+        // Wait some time so that the service can get a result receiver for the custom action.
+        Thread.sleep(WAIT_TIME_FOR_NO_RESPONSE_MS);
 
         // These calls should not make any exceptions.
         callMediaBrowserServiceMethod(CUSTOM_ACTION_SEND_PROGRESS_UPDATE, new Bundle(),
@@ -768,10 +857,20 @@
         }
     }
 
-    private void resetCallbacks() {
-        mConnectionCallback.reset();
-        mSubscriptionCallback.reset();
-        mItemCallback.reset();
+    private void assertRatingEquals(RatingCompat expected, RatingCompat observed) {
+        if (expected == null || observed == null) {
+            assertSame(expected, observed);
+        }
+        assertEquals(expected.getRatingStyle(), observed.getRatingStyle());
+
+        if (expected.getRatingStyle() == RatingCompat.RATING_PERCENTAGE) {
+            assertEquals(expected.getPercentRating(), observed.getPercentRating());
+        } else if (expected.getRatingStyle() == RatingCompat.RATING_5_STARS) {
+            assertEquals(expected.getStarRating(), observed.getStarRating());
+        } else {
+            // Currently, we use only star and percentage rating.
+            fail("Rating style should be either percentage rating or star rating.");
+        }
     }
 
     private class StubConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
@@ -812,7 +911,7 @@
     }
 
     private class StubSubscriptionCallback extends MediaBrowserCompat.SubscriptionCallback {
-        final Object mWaitLock = new Object();
+        private CountDownLatch mLatch;
         private volatile int mChildrenLoadedCount;
         private volatile int mChildrenLoadedWithOptionCount;
         private volatile String mLastErrorId;
@@ -820,7 +919,8 @@
         private volatile Bundle mLastOptions;
         private volatile List<MediaItem> mLastChildMediaItems;
 
-        public void reset() {
+        public void reset(int count) {
+            mLatch = new CountDownLatch(count);
             mChildrenLoadedCount = 0;
             mChildrenLoadedWithOptionCount = 0;
             mLastErrorId = null;
@@ -829,43 +929,43 @@
             mLastChildMediaItems = null;
         }
 
+        public boolean await(long timeoutMs) {
+            try {
+                return mLatch.await(timeoutMs, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                return false;
+            }
+        }
+
         @Override
         public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children) {
-            synchronized (mWaitLock) {
-                mChildrenLoadedCount++;
-                mLastParentId = parentId;
-                mLastChildMediaItems = children;
-                mWaitLock.notify();
-            }
+            mChildrenLoadedCount++;
+            mLastParentId = parentId;
+            mLastChildMediaItems = children;
+            mLatch.countDown();
         }
 
         @Override
         public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children,
                 @NonNull Bundle options) {
-            synchronized (mWaitLock) {
-                mChildrenLoadedWithOptionCount++;
-                mLastParentId = parentId;
-                mLastOptions = options;
-                mLastChildMediaItems = children;
-                mWaitLock.notify();
-            }
+            mChildrenLoadedWithOptionCount++;
+            mLastParentId = parentId;
+            mLastOptions = options;
+            mLastChildMediaItems = children;
+            mLatch.countDown();
         }
 
         @Override
         public void onError(@NonNull String id) {
-            synchronized (mWaitLock) {
-                mLastErrorId = id;
-                mWaitLock.notify();
-            }
+            mLastErrorId = id;
+            mLatch.countDown();
         }
 
         @Override
         public void onError(@NonNull String id, @NonNull Bundle options) {
-            synchronized (mWaitLock) {
-                mLastErrorId = id;
-                mLastOptions = options;
-                mWaitLock.notify();
-            }
+            mLastErrorId = id;
+            mLastOptions = options;
+            mLatch.countDown();
         }
     }
 
diff --git a/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaControllerCompatCallbackTest.java b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaControllerCompatCallbackTest.java
index 79993ef..4b845c1 100644
--- a/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaControllerCompatCallbackTest.java
+++ b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaControllerCompatCallbackTest.java
@@ -46,6 +46,7 @@
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_SESSION_EVENT;
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_VALUE;
 import static android.support.mediacompat.testlib.VersionConstants.KEY_SERVICE_VERSION;
+import static android.support.mediacompat.testlib.util.IntentUtil.SERVICE_PACKAGE_NAME;
 import static android.support.mediacompat.testlib.util.IntentUtil.callMediaSessionMethod;
 import static android.support.mediacompat.testlib.util.TestUtil.assertBundleEquals;
 import static android.support.test.InstrumentationRegistry.getArguments;
@@ -55,9 +56,11 @@
 import static android.support.v4.media.MediaMetadataCompat.METADATA_KEY_RATING;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 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.ComponentName;
@@ -84,8 +87,6 @@
 import android.support.v4.media.session.PlaybackStateCompat;
 import android.util.Log;
 
-import junit.framework.Assert;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -107,7 +108,7 @@
     private static final int MAX_AUDIO_INFO_CHANGED_CALLBACK_COUNT = 10;
 
     private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
-            "android.support.mediacompat.service.test",
+            SERVICE_PACKAGE_NAME,
             "android.support.mediacompat.service.StubMediaBrowserServiceCompat");
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -119,6 +120,7 @@
     private MediaBrowserCompat mMediaBrowser;
     private ConnectionCallback mConnectionCallback = new ConnectionCallback();
 
+    private MediaSessionCompat.Token mSessionToken;
     private MediaControllerCompat mController;
     private MediaControllerCallback mMediaControllerCallback = new MediaControllerCallback();
 
@@ -140,11 +142,11 @@
             mMediaBrowser.connect();
             mConnectionCallback.mWaitLock.wait(TIME_OUT_MS);
             if (!mMediaBrowser.isConnected()) {
-                Assert.fail("Browser failed to connect!");
+                fail("Browser failed to connect!");
             }
         }
-        mController =
-                new MediaControllerCompat(getTargetContext(), mMediaBrowser.getSessionToken());
+        mSessionToken = mMediaBrowser.getSessionToken();
+        mController = new MediaControllerCompat(getTargetContext(), mSessionToken);
         mController.registerCallback(mMediaControllerCallback, mHandler);
     }
 
@@ -155,6 +157,20 @@
         }
     }
 
+    @Test
+    @SmallTest
+    public void testGetPackageName() {
+        assertEquals(SERVICE_PACKAGE_NAME, mController.getPackageName());
+    }
+
+    @Test
+    @SmallTest
+    public void testIsSessionReady() throws Exception {
+        // mController already has the extra binder since it was created with the session token
+        // which holds the extra binder.
+        assertTrue(mController.isSessionReady());
+    }
+
     /**
      * Tests {@link MediaSessionCompat#setExtras}.
      */
@@ -541,6 +557,36 @@
         }.run();
     }
 
+    @Test
+    @SmallTest
+    public void testSessionReady() throws Exception {
+        if (android.os.Build.VERSION.SDK_INT < 21) {
+            return;
+        }
+
+        final MediaSessionCompat.Token tokenWithoutExtraBinder =
+                MediaSessionCompat.Token.fromToken(mSessionToken.getToken());
+
+        final MediaControllerCallback callback = new MediaControllerCallback();
+        synchronized (mWaitLock) {
+            getInstrumentation().runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        MediaControllerCompat controller = new MediaControllerCompat(
+                                getInstrumentation().getTargetContext(), tokenWithoutExtraBinder);
+                        controller.registerCallback(callback, new Handler());
+                        assertFalse(controller.isSessionReady());
+                    } catch (Exception e) {
+                        fail();
+                    }
+                }
+            });
+            mWaitLock.wait(TIME_OUT_MS);
+            assertTrue(callback.mOnSessionReadyCalled);
+        }
+    }
+
     private void assertQueueEquals(List<QueueItem> expected, List<QueueItem> observed) {
         if (expected == null || observed == null) {
             assertTrue(expected == observed);
@@ -570,6 +616,7 @@
         private volatile boolean mOnCaptioningEnabledChangedCalled;
         private volatile boolean mOnRepeatModeChangedCalled;
         private volatile boolean mOnShuffleModeChangedCalled;
+        private volatile boolean mOnSessionReadyCalled;
 
         private volatile PlaybackStateCompat mPlaybackState;
         private volatile MediaMetadataCompat mMediaMetadata;
@@ -703,6 +750,14 @@
                 mWaitLock.notify();
             }
         }
+
+        @Override
+        public void onSessionReady() {
+            synchronized (mWaitLock) {
+                mOnSessionReadyCalled = true;
+                mWaitLock.notify();
+            }
+        }
     }
 
     private class ConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
diff --git a/media-compat/tests/src/android/support/v4/media/MediaItemTest.java b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaItemTest.java
similarity index 94%
rename from media-compat/tests/src/android/support/v4/media/MediaItemTest.java
rename to media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaItemTest.java
index bd2565f..179a178 100644
--- a/media-compat/tests/src/android/support/v4/media/MediaItemTest.java
+++ b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/MediaItemTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.support.v4.media;
+package android.support.mediacompat.client;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -22,11 +22,12 @@
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
 import android.support.v4.media.MediaBrowserCompat.MediaItem;
+import android.support.v4.media.MediaDescriptionCompat;
 
 import org.junit.Test;
 
 /**
- * Test {@link MediaBrowserCompat.MediaItem}.
+ * Test {@link MediaItem}.
  */
 public class MediaItemTest {
     private static final String DESCRIPTION = "test_description";
diff --git a/media-compat/tests/src/android/support/v4/media/session/PlaybackStateCompatTest.java b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/PlaybackStateCompatTest.java
similarity index 97%
rename from media-compat/tests/src/android/support/v4/media/session/PlaybackStateCompatTest.java
rename to media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/PlaybackStateCompatTest.java
index 9e320cd..7962731 100644
--- a/media-compat/tests/src/android/support/v4/media/session/PlaybackStateCompatTest.java
+++ b/media-compat/version-compat-tests/current/client/tests/src/android/support/mediacompat/client/PlaybackStateCompatTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.v4.media.session;
+package android.support.mediacompat.client;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -24,6 +24,8 @@
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.media.session.MediaSessionCompat;
+import android.support.v4.media.session.PlaybackStateCompat;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/media-compat/version-compat-tests/current/service/build.gradle b/media-compat/version-compat-tests/current/service/build.gradle
index 2cfa5ce..cf82918 100644
--- a/media-compat/version-compat-tests/current/service/build.gradle
+++ b/media-compat/version-compat-tests/current/service/build.gradle
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
+
 plugins {
     id("SupportAndroidLibraryPlugin")
 }
 
 dependencies {
-    androidTestImplementation project(':support-media-compat')
-    androidTestImplementation project(':support-media-compat-test-lib')
+    androidTestImplementation(project(":support-media-compat"))
+    androidTestImplementation(project(":support-media-compat-test-lib"))
 
-    androidTestImplementation(libs.test_runner)
+    androidTestImplementation(TEST_RUNNER)
 }
 
 android {
diff --git a/media-compat/version-compat-tests/current/service/tests/src/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java b/media-compat/version-compat-tests/current/service/tests/src/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
index d36eba3..5c5a432 100644
--- a/media-compat/version-compat-tests/current/service/tests/src/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
+++ b/media-compat/version-compat-tests/current/service/tests/src/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
@@ -18,6 +18,7 @@
 import static android.support.mediacompat.testlib.MediaControllerConstants.ADD_QUEUE_ITEM;
 import static android.support.mediacompat.testlib.MediaControllerConstants
         .ADD_QUEUE_ITEM_WITH_INDEX;
+import static android.support.mediacompat.testlib.MediaControllerConstants.ADJUST_VOLUME;
 import static android.support.mediacompat.testlib.MediaControllerConstants.FAST_FORWARD;
 import static android.support.mediacompat.testlib.MediaControllerConstants.PAUSE;
 import static android.support.mediacompat.testlib.MediaControllerConstants.PLAY;
@@ -39,12 +40,18 @@
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_RATING;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_REPEAT_MODE;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_SHUFFLE_MODE;
+import static android.support.mediacompat.testlib.MediaControllerConstants.SET_VOLUME_TO;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_NEXT;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_PREVIOUS;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_QUEUE_ITEM;
 import static android.support.mediacompat.testlib.MediaControllerConstants.STOP;
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_COMMAND;
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_KEY;
+import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_MEDIA_ID_1;
+import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_MEDIA_ID_2;
+import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_MEDIA_TITLE_1;
+import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_MEDIA_TITLE_2;
+import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_QUEUE_ID_1;
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_SESSION_TAG;
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_VALUE;
 import static android.support.mediacompat.testlib.VersionConstants.KEY_CLIENT_VERSION;
@@ -57,21 +64,38 @@
 import static android.support.test.InstrumentationRegistry.getTargetContext;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.PlaybackState;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.Parcel;
 import android.os.ResultReceiver;
+import android.os.SystemClock;
+import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.v4.media.MediaDescriptionCompat;
 import android.support.v4.media.RatingCompat;
+import android.support.v4.media.VolumeProviderCompat;
+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 android.view.KeyEvent;
 
 import org.junit.After;
 import org.junit.Before;
@@ -80,6 +104,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Test {@link MediaSessionCompat.Callback}.
@@ -91,6 +117,10 @@
 
     // The maximum time to wait for an operation.
     private static final long TIME_OUT_MS = 3000L;
+    private static final long WAIT_TIME_FOR_NO_RESPONSE_MS = 300L;
+
+    private static final long TEST_POSITION = 1000000L;
+    private static final float TEST_PLAYBACK_SPEED = 3.0f;
     private static final float DELTA = 1e-4f;
     private static final boolean ENABLED = true;
 
@@ -99,6 +129,7 @@
     private String mClientVersion;
     private MediaSessionCompat mSession;
     private MediaSessionCallback mCallback = new MediaSessionCallback();
+    private AudioManager mAudioManager;
 
     @Before
     public void setUp() throws Exception {
@@ -109,9 +140,9 @@
         getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {
+                mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
                 mSession = new MediaSessionCompat(getTargetContext(), TEST_SESSION_TAG);
                 mSession.setCallback(mCallback, mHandler);
-                mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS);
             }
         });
     }
@@ -121,277 +152,662 @@
         mSession.release();
     }
 
+    /**
+     * Tests that a session can be created and that all the fields are initialized correctly.
+     */
+    @Test
+    @SmallTest
+    public void testCreateSession() throws Exception {
+        assertNotNull(mSession.getSessionToken());
+        assertFalse("New session should not be active", mSession.isActive());
+
+        // Verify by getting the controller and checking all its fields
+        MediaControllerCompat controller = mSession.getController();
+        assertNotNull(controller);
+
+        final String errorMsg = "New session has unexpected configuration.";
+        assertEquals(errorMsg, 0L, controller.getFlags());
+        assertNull(errorMsg, controller.getExtras());
+        assertNull(errorMsg, controller.getMetadata());
+        assertEquals(errorMsg, getContext().getPackageName(), controller.getPackageName());
+        assertNull(errorMsg, controller.getPlaybackState());
+        assertNull(errorMsg, controller.getQueue());
+        assertNull(errorMsg, controller.getQueueTitle());
+        assertEquals(errorMsg, RatingCompat.RATING_NONE, controller.getRatingType());
+        assertNull(errorMsg, controller.getSessionActivity());
+
+        assertNotNull(controller.getSessionToken());
+        assertNotNull(controller.getTransportControls());
+
+        MediaControllerCompat.PlaybackInfo info = controller.getPlaybackInfo();
+        assertNotNull(info);
+        assertEquals(errorMsg, MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
+                info.getPlaybackType());
+        assertEquals(errorMsg, mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC),
+                info.getCurrentVolume());
+    }
+
+    @Test
+    @SmallTest
+    public void testGetSessionToken() throws Exception {
+        assertEquals(mSession.getSessionToken(), mSession.getController().getSessionToken());
+    }
+
+    /**
+     * Tests that a session can be created from the framework session object and the callback
+     * set on the framework session object before fromSession() is called works properly.
+     */
+    @Test
+    @SmallTest
+    public void testFromSession() throws Exception {
+        if (android.os.Build.VERSION.SDK_INT < 21) {
+            // MediaSession was introduced from API level 21.
+            return;
+        }
+        mCallback.reset(1);
+        mSession.setCallback(mCallback, new Handler(Looper.getMainLooper()));
+        MediaSessionCompat session = MediaSessionCompat.fromMediaSession(
+                getContext(), mSession.getMediaSession());
+        assertEquals(session.getSessionToken(), mSession.getSessionToken());
+
+        session.getController().getTransportControls().play();
+        mCallback.await(TIME_OUT_MS);
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+    }
+
+    /**
+     * Tests {@link MediaSessionCompat.Token} created in the constructor of MediaSessionCompat.
+     */
+    @Test
+    @SmallTest
+    public void testSessionToken() throws Exception {
+        MediaSessionCompat.Token sessionToken = mSession.getSessionToken();
+
+        assertNotNull(sessionToken);
+        assertEquals(0, sessionToken.describeContents());
+
+        // Test writeToParcel
+        Parcel p = Parcel.obtain();
+        sessionToken.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        MediaSessionCompat.Token token = MediaSessionCompat.Token.CREATOR.createFromParcel(p);
+        assertEquals(token, sessionToken);
+        p.recycle();
+    }
+
+    /**
+     * Tests {@link MediaSessionCompat.QueueItem}.
+     */
+    @Test
+    @SmallTest
+    public void testQueueItem() {
+        MediaSessionCompat.QueueItem item = new MediaSessionCompat.QueueItem(
+                new MediaDescriptionCompat.Builder()
+                        .setMediaId(TEST_MEDIA_ID_1)
+                        .setTitle(TEST_MEDIA_TITLE_1)
+                        .build(),
+                TEST_QUEUE_ID_1);
+        assertEquals(TEST_QUEUE_ID_1, item.getQueueId());
+        assertEquals(TEST_MEDIA_ID_1, item.getDescription().getMediaId());
+        assertEquals(TEST_MEDIA_TITLE_1, item.getDescription().getTitle());
+        assertEquals(0, item.describeContents());
+
+        Parcel p = Parcel.obtain();
+        item.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        MediaSessionCompat.QueueItem other =
+                MediaSessionCompat.QueueItem.CREATOR.createFromParcel(p);
+        assertEquals(item.toString(), other.toString());
+        p.recycle();
+    }
+
+    /**
+     * Tests {@link MediaSessionCompat#setActive}.
+     */
+    @Test
+    @SmallTest
+    public void testSetActive() throws Exception {
+        mSession.setActive(true);
+        assertTrue(mSession.isActive());
+    }
+
+    @Test
+    @SmallTest
+    public void testGetPlaybackStateWithPositionUpdate() throws InterruptedException {
+        final long stateSetTime = SystemClock.elapsedRealtime();
+        PlaybackStateCompat stateIn = new PlaybackStateCompat.Builder()
+                .setState(PlaybackStateCompat.STATE_PLAYING, TEST_POSITION, TEST_PLAYBACK_SPEED,
+                        stateSetTime)
+                .build();
+        mSession.setPlaybackState(stateIn);
+
+        final long waitDuration = 100L;
+        Thread.sleep(waitDuration);
+
+        final long expectedUpdateTime = waitDuration + stateSetTime;
+        final long expectedPosition = (long) (TEST_PLAYBACK_SPEED * waitDuration) + TEST_POSITION;
+
+        final double updateTimeTolerance = 50L;
+        final double positionTolerance = updateTimeTolerance * TEST_PLAYBACK_SPEED;
+
+        PlaybackStateCompat stateOut = mSession.getController().getPlaybackState();
+        assertEquals(expectedUpdateTime, stateOut.getLastPositionUpdateTime(), updateTimeTolerance);
+        assertEquals(expectedPosition, stateOut.getPosition(), positionTolerance);
+
+        // Compare the result with MediaController.getPlaybackState().
+        if (Build.VERSION.SDK_INT >= 21) {
+            MediaController controller = new MediaController(
+                    getContext(), (MediaSession.Token) mSession.getSessionToken().getToken());
+            PlaybackState state = controller.getPlaybackState();
+            assertEquals(state.getLastPositionUpdateTime(), stateOut.getLastPositionUpdateTime(),
+                    updateTimeTolerance);
+            assertEquals(state.getPosition(), stateOut.getPosition(), positionTolerance);
+        }
+    }
+
+    /**
+     * Tests {@link MediaSessionCompat#setCallback} with {@code null}.
+     * No callback should be called once {@code setCallback(null)} is done.
+     */
+    @Test
+    @SmallTest
+    public void testSetCallbackWithNull() throws Exception {
+        mSession.setActive(true);
+        mCallback.reset(1);
+        callTransportControlsMethod(PLAY, null, getContext(), mSession.getSessionToken());
+        mSession.setCallback(null, mHandler);
+        mCallback.await(WAIT_TIME_FOR_NO_RESPONSE_MS);
+        assertEquals("Callback shouldn't be called.", 0, mCallback.mOnPlayCalledCount);
+    }
+
     @Test
     @SmallTest
     public void testSendCommand() throws Exception {
-        synchronized (mWaitLock) {
-            mCallback.reset();
+        mCallback.reset(1);
 
-            Bundle arguments = new Bundle();
-            arguments.putString("command", TEST_COMMAND);
-            Bundle extras = new Bundle();
-            extras.putString(TEST_KEY, TEST_VALUE);
-            arguments.putBundle("extras", extras);
-            callMediaControllerMethod(
-                    SEND_COMMAND, arguments, getContext(), mSession.getSessionToken());
+        Bundle arguments = new Bundle();
+        arguments.putString("command", TEST_COMMAND);
+        Bundle extras = new Bundle();
+        extras.putString(TEST_KEY, TEST_VALUE);
+        arguments.putBundle("extras", extras);
+        callMediaControllerMethod(
+                SEND_COMMAND, arguments, getContext(), mSession.getSessionToken());
 
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCommandCalled);
-            assertNotNull(mCallback.mCommandCallback);
-            assertEquals(TEST_COMMAND, mCallback.mCommand);
-            assertBundleEquals(extras, mCallback.mExtras);
-        }
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnCommandCalled);
+        assertNotNull(mCallback.mCommandCallback);
+        assertEquals(TEST_COMMAND, mCallback.mCommand);
+        assertBundleEquals(extras, mCallback.mExtras);
     }
 
     @Test
     @SmallTest
     public void testAddRemoveQueueItems() throws Exception {
-        final String mediaId1 = "media_id_1";
-        final String mediaTitle1 = "media_title_1";
+        mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS);
+
         MediaDescriptionCompat itemDescription1 = new MediaDescriptionCompat.Builder()
-                .setMediaId(mediaId1).setTitle(mediaTitle1).build();
+                .setMediaId(TEST_MEDIA_ID_1).setTitle(TEST_MEDIA_TITLE_1).build();
 
-        final String mediaId2 = "media_id_2";
-        final String mediaTitle2 = "media_title_2";
         MediaDescriptionCompat itemDescription2 = new MediaDescriptionCompat.Builder()
-                .setMediaId(mediaId2).setTitle(mediaTitle2).build();
+                .setMediaId(TEST_MEDIA_ID_2).setTitle(TEST_MEDIA_TITLE_2).build();
 
-        synchronized (mWaitLock) {
-            mCallback.reset();
-            callMediaControllerMethod(
-                    ADD_QUEUE_ITEM, itemDescription1, getContext(), mSession.getSessionToken());
+        mCallback.reset(1);
+        callMediaControllerMethod(
+                ADD_QUEUE_ITEM, itemDescription1, getContext(), mSession.getSessionToken());
 
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnAddQueueItemCalled);
-            assertEquals(-1, mCallback.mQueueIndex);
-            assertEquals(mediaId1, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle1, mCallback.mQueueDescription.getTitle());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnAddQueueItemCalled);
+        assertEquals(-1, mCallback.mQueueIndex);
+        assertEquals(TEST_MEDIA_ID_1, mCallback.mQueueDescription.getMediaId());
+        assertEquals(TEST_MEDIA_TITLE_1, mCallback.mQueueDescription.getTitle());
 
-            mCallback.reset();
-            Bundle arguments = new Bundle();
-            arguments.putParcelable("description", itemDescription2);
-            arguments.putInt("index", 0);
-            callMediaControllerMethod(
-                    ADD_QUEUE_ITEM_WITH_INDEX, arguments, getContext(), mSession.getSessionToken());
+        mCallback.reset(1);
+        Bundle arguments = new Bundle();
+        arguments.putParcelable("description", itemDescription2);
+        arguments.putInt("index", 0);
+        callMediaControllerMethod(
+                ADD_QUEUE_ITEM_WITH_INDEX, arguments, getContext(), mSession.getSessionToken());
 
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnAddQueueItemAtCalled);
-            assertEquals(0, mCallback.mQueueIndex);
-            assertEquals(mediaId2, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle2, mCallback.mQueueDescription.getTitle());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnAddQueueItemAtCalled);
+        assertEquals(0, mCallback.mQueueIndex);
+        assertEquals(TEST_MEDIA_ID_2, mCallback.mQueueDescription.getMediaId());
+        assertEquals(TEST_MEDIA_TITLE_2, mCallback.mQueueDescription.getTitle());
 
-            mCallback.reset();
-            callMediaControllerMethod(
-                    REMOVE_QUEUE_ITEM, itemDescription1, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRemoveQueueItemCalled);
-            assertEquals(mediaId1, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle1, mCallback.mQueueDescription.getTitle());
-        }
+        mCallback.reset(1);
+        callMediaControllerMethod(
+                REMOVE_QUEUE_ITEM, itemDescription1, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnRemoveQueueItemCalled);
+        assertEquals(TEST_MEDIA_ID_1, mCallback.mQueueDescription.getMediaId());
+        assertEquals(TEST_MEDIA_TITLE_1, mCallback.mQueueDescription.getTitle());
     }
 
     @Test
     @SmallTest
     public void testTransportControlsAndMediaSessionCallback() throws Exception {
+        mCallback.reset(1);
+        callTransportControlsMethod(PLAY, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(PAUSE, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPauseCalled);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(STOP, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnStopCalled);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(
+                FAST_FORWARD, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnFastForwardCalled);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(REWIND, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnRewindCalled);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(
+                SKIP_TO_PREVIOUS, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSkipToPreviousCalled);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(
+                SKIP_TO_NEXT, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSkipToNextCalled);
+
+        mCallback.reset(1);
+        final long seekPosition = 1000;
+        callTransportControlsMethod(
+                SEEK_TO, seekPosition, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSeekToCalled);
+        assertEquals(seekPosition, mCallback.mSeekPosition);
+
+        mCallback.reset(1);
+        final RatingCompat rating =
+                RatingCompat.newStarRating(RatingCompat.RATING_5_STARS, 3f);
+        callTransportControlsMethod(
+                SET_RATING, rating, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSetRatingCalled);
+        assertEquals(rating.getRatingStyle(), mCallback.mRating.getRatingStyle());
+        assertEquals(rating.getStarRating(), mCallback.mRating.getStarRating(), DELTA);
+
+        mCallback.reset(1);
+        final Bundle extras = new Bundle();
+        extras.putString(TEST_KEY, TEST_VALUE);
+        Bundle arguments = new Bundle();
+        arguments.putString("mediaId", TEST_MEDIA_ID_1);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PLAY_FROM_MEDIA_ID, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPlayFromMediaIdCalled);
+        assertEquals(TEST_MEDIA_ID_1, mCallback.mMediaId);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        final String query = "test-query";
+        arguments = new Bundle();
+        arguments.putString("query", query);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PLAY_FROM_SEARCH, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPlayFromSearchCalled);
+        assertEquals(query, mCallback.mQuery);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        final Uri uri = Uri.parse("content://test/popcorn.mod");
+        arguments = new Bundle();
+        arguments.putParcelable("uri", uri);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PLAY_FROM_URI, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPlayFromUriCalled);
+        assertEquals(uri, mCallback.mUri);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        final String action = "test-action";
+        arguments = new Bundle();
+        arguments.putString("action", action);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                SEND_CUSTOM_ACTION, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnCustomActionCalled);
+        assertEquals(action, mCallback.mAction);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        mCallback.mOnCustomActionCalled = false;
+        final PlaybackStateCompat.CustomAction customAction =
+                new PlaybackStateCompat.CustomAction.Builder(action, action, -1)
+                        .setExtras(extras)
+                        .build();
+        arguments = new Bundle();
+        arguments.putParcelable("action", customAction);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                SEND_CUSTOM_ACTION_PARCELABLE,
+                arguments,
+                getContext(),
+                mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnCustomActionCalled);
+        assertEquals(action, mCallback.mAction);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        final long queueItemId = 1000;
+        callTransportControlsMethod(
+                SKIP_TO_QUEUE_ITEM, queueItemId, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSkipToQueueItemCalled);
+        assertEquals(queueItemId, mCallback.mQueueItemId);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(
+                PREPARE, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPrepareCalled);
+
+        mCallback.reset(1);
+        arguments = new Bundle();
+        arguments.putString("mediaId", TEST_MEDIA_ID_2);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PREPARE_FROM_MEDIA_ID, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPrepareFromMediaIdCalled);
+        assertEquals(TEST_MEDIA_ID_2, mCallback.mMediaId);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        arguments = new Bundle();
+        arguments.putString("query", query);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PREPARE_FROM_SEARCH, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPrepareFromSearchCalled);
+        assertEquals(query, mCallback.mQuery);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        arguments = new Bundle();
+        arguments.putParcelable("uri", uri);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PREPARE_FROM_URI, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPrepareFromUriCalled);
+        assertEquals(uri, mCallback.mUri);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(
+                SET_CAPTIONING_ENABLED, ENABLED, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSetCaptioningEnabledCalled);
+        assertEquals(ENABLED, mCallback.mCaptioningEnabled);
+
+        mCallback.reset(1);
+        final int repeatMode = PlaybackStateCompat.REPEAT_MODE_ALL;
+        callTransportControlsMethod(
+                SET_REPEAT_MODE, repeatMode, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSetRepeatModeCalled);
+        assertEquals(repeatMode, mCallback.mRepeatMode);
+
+        mCallback.reset(1);
+        final int shuffleMode = PlaybackStateCompat.SHUFFLE_MODE_ALL;
+        callTransportControlsMethod(
+                SET_SHUFFLE_MODE, shuffleMode, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSetShuffleModeCalled);
+        assertEquals(shuffleMode, mCallback.mShuffleMode);
+    }
+
+    /**
+     * Tests {@link MediaSessionCompat.Callback#onMediaButtonEvent}.
+     */
+    @Test
+    @MediumTest
+    public void testCallbackOnMediaButtonEvent() throws Exception {
+        mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
+        mSession.setActive(true);
+
+        final long waitTimeForNoResponse = 30L;
+
+        Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON)
+                .setComponent(new ComponentName(getContext(), getContext().getClass()));
+        PendingIntent pi = PendingIntent.getBroadcast(getContext(), 0, mediaButtonIntent, 0);
+        mSession.setMediaButtonReceiver(pi);
+
+        // Set state to STATE_PLAYING to get higher priority.
+        setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PAUSE);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnPauseCalled);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_NEXT);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnSkipToNextCalled);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnSkipToPreviousCalled);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnStopCalled);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnFastForwardCalled);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_REWIND);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnRewindCalled);
+
+        // Test PLAY_PAUSE button twice.
+        // First, send PLAY_PAUSE button event while in STATE_PAUSED.
+        mCallback.reset(1);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+
+        // Next, send PLAY_PAUSE button event while in STATE_PLAYING.
+        mCallback.reset(1);
+        setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnPauseCalled);
+
+        // Double tap of PLAY_PAUSE is the next track.
+        mCallback.reset(2);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        assertFalse(mCallback.await(waitTimeForNoResponse));
+        assertTrue(mCallback.mOnSkipToNextCalled);
+        assertEquals(0, mCallback.mOnPlayCalledCount);
+        assertFalse(mCallback.mOnPauseCalled);
+
+        // Test PLAY_PAUSE button long-press.
+        // It should be the same as the single short-press.
+        mCallback.reset(1);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+
+        // Double tap of PLAY_PAUSE should be handled once.
+        // Initial down event from the second press within double tap time-out will make
+        // onSkipToNext() to be called, so further down events shouldn't be handled again.
+        mCallback.reset(2);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
+        assertFalse(mCallback.await(waitTimeForNoResponse));
+        assertTrue(mCallback.mOnSkipToNextCalled);
+        assertEquals(0, mCallback.mOnPlayCalledCount);
+        assertFalse(mCallback.mOnPauseCalled);
+
+        // Test PLAY_PAUSE button long-press followed by the short-press.
+        // Initial long-press of the PLAY_PAUSE is considered as the single short-press already,
+        // so it shouldn't be used as the first tap of the double tap.
+        mCallback.reset(2);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        // onMediaButtonEvent() calls either onPlay() or onPause() depending on the playback state,
+        // so onPlay() should be called once and onPause() also should be called once.
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+        assertTrue(mCallback.mOnPauseCalled);
+        assertFalse(mCallback.mOnSkipToNextCalled);
+
+        // If another media key is pressed while the double tap of PLAY_PAUSE,
+        // PLAY_PAUSE should be handled as normal.
+        mCallback.reset(3);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertFalse(mCallback.mOnSkipToNextCalled);
+        assertTrue(mCallback.mOnStopCalled);
+        assertEquals(2, mCallback.mOnPlayCalledCount);
+
+        // Test if media keys are handled in order.
+        mCallback.reset(2);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+        assertTrue(mCallback.mOnStopCalled);
         synchronized (mWaitLock) {
-            mCallback.reset();
-            callTransportControlsMethod(PLAY, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(PAUSE, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPauseCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(STOP, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnStopCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(
-                    FAST_FORWARD, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnFastForwardCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(REWIND, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRewindCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(
-                    SKIP_TO_PREVIOUS, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSkipToPreviousCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(
-                    SKIP_TO_NEXT, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSkipToNextCalled);
-
-            mCallback.reset();
-            final long seekPosition = 1000;
-            callTransportControlsMethod(
-                    SEEK_TO, seekPosition, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSeekToCalled);
-            assertEquals(seekPosition, mCallback.mSeekPosition);
-
-            mCallback.reset();
-            final RatingCompat rating =
-                    RatingCompat.newStarRating(RatingCompat.RATING_5_STARS, 3f);
-            callTransportControlsMethod(
-                    SET_RATING, rating, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetRatingCalled);
-            assertEquals(rating.getRatingStyle(), mCallback.mRating.getRatingStyle());
-            assertEquals(rating.getStarRating(), mCallback.mRating.getStarRating(), DELTA);
-
-            mCallback.reset();
-            final String mediaId = "test-media-id";
-            final Bundle extras = new Bundle();
-            extras.putString(TEST_KEY, TEST_VALUE);
-            Bundle arguments = new Bundle();
-            arguments.putString("mediaId", mediaId);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PLAY_FROM_MEDIA_ID, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayFromMediaIdCalled);
-            assertEquals(mediaId, mCallback.mMediaId);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            final String query = "test-query";
-            arguments = new Bundle();
-            arguments.putString("query", query);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PLAY_FROM_SEARCH, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayFromSearchCalled);
-            assertEquals(query, mCallback.mQuery);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            final Uri uri = Uri.parse("content://test/popcorn.mod");
-            arguments = new Bundle();
-            arguments.putParcelable("uri", uri);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PLAY_FROM_URI, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayFromUriCalled);
-            assertEquals(uri, mCallback.mUri);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            final String action = "test-action";
-            arguments = new Bundle();
-            arguments.putString("action", action);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    SEND_CUSTOM_ACTION, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCustomActionCalled);
-            assertEquals(action, mCallback.mAction);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            mCallback.mOnCustomActionCalled = false;
-            final PlaybackStateCompat.CustomAction customAction =
-                    new PlaybackStateCompat.CustomAction.Builder(action, action, -1)
-                            .setExtras(extras)
-                            .build();
-            arguments = new Bundle();
-            arguments.putParcelable("action", customAction);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    SEND_CUSTOM_ACTION_PARCELABLE,
-                    arguments,
-                    getContext(),
-                    mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCustomActionCalled);
-            assertEquals(action, mCallback.mAction);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            final long queueItemId = 1000;
-            callTransportControlsMethod(
-                    SKIP_TO_QUEUE_ITEM, queueItemId, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSkipToQueueItemCalled);
-            assertEquals(queueItemId, mCallback.mQueueItemId);
-
-            mCallback.reset();
-            callTransportControlsMethod(
-                    PREPARE, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareCalled);
-
-            mCallback.reset();
-            arguments = new Bundle();
-            arguments.putString("mediaId", mediaId);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PREPARE_FROM_MEDIA_ID, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareFromMediaIdCalled);
-            assertEquals(mediaId, mCallback.mMediaId);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            arguments = new Bundle();
-            arguments.putString("query", query);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PREPARE_FROM_SEARCH, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareFromSearchCalled);
-            assertEquals(query, mCallback.mQuery);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            arguments = new Bundle();
-            arguments.putParcelable("uri", uri);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PREPARE_FROM_URI, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareFromUriCalled);
-            assertEquals(uri, mCallback.mUri);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            callTransportControlsMethod(
-                    SET_CAPTIONING_ENABLED, ENABLED, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetCaptioningEnabledCalled);
-            assertEquals(ENABLED, mCallback.mCaptioningEnabled);
-
-            mCallback.reset();
-            final int repeatMode = PlaybackStateCompat.REPEAT_MODE_ALL;
-            callTransportControlsMethod(
-                    SET_REPEAT_MODE, repeatMode, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetRepeatModeCalled);
-            assertEquals(repeatMode, mCallback.mRepeatMode);
-
-            mCallback.reset();
-            final int shuffleMode = PlaybackStateCompat.SHUFFLE_MODE_ALL;
-            callTransportControlsMethod(
-                    SET_SHUFFLE_MODE, shuffleMode, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetShuffleModeCalled);
-            assertEquals(shuffleMode, mCallback.mShuffleMode);
+            assertEquals(PlaybackStateCompat.STATE_STOPPED,
+                    mSession.getController().getPlaybackState().getState());
         }
     }
 
+    @Test
+    @SmallTest
+    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;
+        }
+        VolumeProviderCompat vp =
+                new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 11, 5) {
+                    @Override
+                    public void onSetVolumeTo(int volume) {
+                        synchronized (mWaitLock) {
+                            setCurrentVolume(volume);
+                            mWaitLock.notify();
+                        }
+                    }
+
+                    @Override
+                    public void onAdjustVolume(int direction) {
+                        synchronized (mWaitLock) {
+                            switch (direction) {
+                                case AudioManager.ADJUST_LOWER:
+                                    setCurrentVolume(getCurrentVolume() - 1);
+                                    break;
+                                case AudioManager.ADJUST_RAISE:
+                                    setCurrentVolume(getCurrentVolume() + 1);
+                                    break;
+                            }
+                            mWaitLock.notify();
+                        }
+                    }
+                };
+        mSession.setPlaybackToRemote(vp);
+
+        synchronized (mWaitLock) {
+            // test setVolumeTo
+            callMediaControllerMethod(SET_VOLUME_TO,
+                    7 /* Target volume */, getContext(), mSession.getSessionToken());
+            mWaitLock.wait(TIME_OUT_MS);
+            assertEquals(7, vp.getCurrentVolume());
+
+            // test adjustVolume
+            callMediaControllerMethod(ADJUST_VOLUME,
+                    AudioManager.ADJUST_LOWER, getContext(), mSession.getSessionToken());
+            mWaitLock.wait(TIME_OUT_MS);
+            assertEquals(6, vp.getCurrentVolume());
+
+            callMediaControllerMethod(ADJUST_VOLUME,
+                    AudioManager.ADJUST_RAISE, getContext(), mSession.getSessionToken());
+            mWaitLock.wait(TIME_OUT_MS);
+            assertEquals(7, vp.getCurrentVolume());
+        }
+    }
+
+    private void setPlaybackState(int state) {
+        final long allActions = PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE
+                | PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_STOP
+                | PlaybackStateCompat.ACTION_SKIP_TO_NEXT
+                | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
+                | PlaybackStateCompat.ACTION_FAST_FORWARD | PlaybackStateCompat.ACTION_REWIND;
+        PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder().setActions(allActions)
+                .setState(state, 0L, 0.0f).build();
+        synchronized (mWaitLock) {
+            mSession.setPlaybackState(playbackState);
+        }
+    }
+
+    private void sendMediaKeyInputToController(int keyCode) {
+        sendMediaKeyInputToController(keyCode, false);
+    }
+
+    private void sendMediaKeyInputToController(int keyCode, boolean isLongPress) {
+        MediaControllerCompat controller = mSession.getController();
+        long currentTimeMs = System.currentTimeMillis();
+        KeyEvent down = new KeyEvent(
+                currentTimeMs, currentTimeMs, KeyEvent.ACTION_DOWN, keyCode, 0);
+        controller.dispatchMediaButtonEvent(down);
+        if (isLongPress) {
+            KeyEvent longPress = new KeyEvent(
+                    currentTimeMs, System.currentTimeMillis(), KeyEvent.ACTION_DOWN, keyCode, 1);
+            controller.dispatchMediaButtonEvent(longPress);
+        }
+        KeyEvent up = new KeyEvent(
+                currentTimeMs, System.currentTimeMillis(), KeyEvent.ACTION_UP, keyCode, 0);
+        controller.dispatchMediaButtonEvent(up);
+    }
+
     private class MediaSessionCallback extends MediaSessionCompat.Callback {
+        private CountDownLatch mLatch;
         private long mSeekPosition;
         private long mQueueItemId;
         private RatingCompat mRating;
@@ -409,7 +825,7 @@
         private MediaDescriptionCompat mQueueDescription;
         private List<MediaSessionCompat.QueueItem> mQueue = new ArrayList<>();
 
-        private boolean mOnPlayCalled;
+        private int mOnPlayCalledCount;
         private boolean mOnPauseCalled;
         private boolean mOnStopCalled;
         private boolean mOnFastForwardCalled;
@@ -435,7 +851,8 @@
         private boolean mOnAddQueueItemAtCalled;
         private boolean mOnRemoveQueueItemCalled;
 
-        public void reset() {
+        public void reset(int count) {
+            mLatch = new CountDownLatch(count);
             mSeekPosition = -1;
             mQueueItemId = -1;
             mRating = null;
@@ -452,7 +869,7 @@
             mQueueIndex = -1;
             mQueueDescription = null;
 
-            mOnPlayCalled = false;
+            mOnPlayCalledCount = 0;
             mOnPauseCalled = false;
             mOnStopCalled = false;
             mOnFastForwardCalled = false;
@@ -479,242 +896,203 @@
             mOnRemoveQueueItemCalled = false;
         }
 
+        public boolean await(long timeoutMs) {
+            try {
+                return mLatch.await(timeoutMs, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                return false;
+            }
+        }
+
         @Override
         public void onPlay() {
-            synchronized (mWaitLock) {
-                mOnPlayCalled = true;
-                mWaitLock.notify();
-            }
+            mOnPlayCalledCount++;
+            setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
+            mLatch.countDown();
         }
 
         @Override
         public void onPause() {
-            synchronized (mWaitLock) {
-                mOnPauseCalled = true;
-                mWaitLock.notify();
-            }
+            mOnPauseCalled = true;
+            setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+            mLatch.countDown();
         }
 
         @Override
         public void onStop() {
-            synchronized (mWaitLock) {
-                mOnStopCalled = true;
-                mWaitLock.notify();
-            }
+            mOnStopCalled = true;
+            setPlaybackState(PlaybackStateCompat.STATE_STOPPED);
+            mLatch.countDown();
         }
 
         @Override
         public void onFastForward() {
-            synchronized (mWaitLock) {
-                mOnFastForwardCalled = true;
-                mWaitLock.notify();
-            }
+            mOnFastForwardCalled = true;
+            mLatch.countDown();
         }
 
         @Override
         public void onRewind() {
-            synchronized (mWaitLock) {
-                mOnRewindCalled = true;
-                mWaitLock.notify();
-            }
+            mOnRewindCalled = true;
+            mLatch.countDown();
         }
 
         @Override
         public void onSkipToPrevious() {
-            synchronized (mWaitLock) {
-                mOnSkipToPreviousCalled = true;
-                mWaitLock.notify();
-            }
+            mOnSkipToPreviousCalled = true;
+            mLatch.countDown();
         }
 
         @Override
         public void onSkipToNext() {
-            synchronized (mWaitLock) {
-                mOnSkipToNextCalled = true;
-                mWaitLock.notify();
-            }
+            mOnSkipToNextCalled = true;
+            mLatch.countDown();
         }
 
         @Override
         public void onSeekTo(long pos) {
-            synchronized (mWaitLock) {
-                mOnSeekToCalled = true;
-                mSeekPosition = pos;
-                mWaitLock.notify();
-            }
+            mOnSeekToCalled = true;
+            mSeekPosition = pos;
+            mLatch.countDown();
         }
 
         @Override
         public void onSetRating(RatingCompat rating) {
-            synchronized (mWaitLock) {
-                mOnSetRatingCalled = true;
-                mRating = rating;
-                mWaitLock.notify();
-            }
+            mOnSetRatingCalled = true;
+            mRating = rating;
+            mLatch.countDown();
         }
 
         @Override
         public void onPlayFromMediaId(String mediaId, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPlayFromMediaIdCalled = true;
-                mMediaId = mediaId;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPlayFromMediaIdCalled = true;
+            mMediaId = mediaId;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onPlayFromSearch(String query, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPlayFromSearchCalled = true;
-                mQuery = query;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPlayFromSearchCalled = true;
+            mQuery = query;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onPlayFromUri(Uri uri, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPlayFromUriCalled = true;
-                mUri = uri;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPlayFromUriCalled = true;
+            mUri = uri;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onCustomAction(String action, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnCustomActionCalled = true;
-                mAction = action;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnCustomActionCalled = true;
+            mAction = action;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onSkipToQueueItem(long id) {
-            synchronized (mWaitLock) {
-                mOnSkipToQueueItemCalled = true;
-                mQueueItemId = id;
-                mWaitLock.notify();
-            }
+            mOnSkipToQueueItemCalled = true;
+            mQueueItemId = id;
+            mLatch.countDown();
         }
 
         @Override
         public void onCommand(String command, Bundle extras, ResultReceiver cb) {
-            synchronized (mWaitLock) {
-                mOnCommandCalled = true;
-                mCommand = command;
-                mExtras = extras;
-                mCommandCallback = cb;
-                mWaitLock.notify();
-            }
+            mOnCommandCalled = true;
+            mCommand = command;
+            mExtras = extras;
+            mCommandCallback = cb;
+            mLatch.countDown();
         }
 
         @Override
         public void onPrepare() {
-            synchronized (mWaitLock) {
-                mOnPrepareCalled = true;
-                mWaitLock.notify();
-            }
+            mOnPrepareCalled = true;
+            mLatch.countDown();
         }
 
         @Override
         public void onPrepareFromMediaId(String mediaId, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPrepareFromMediaIdCalled = true;
-                mMediaId = mediaId;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPrepareFromMediaIdCalled = true;
+            mMediaId = mediaId;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onPrepareFromSearch(String query, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPrepareFromSearchCalled = true;
-                mQuery = query;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPrepareFromSearchCalled = true;
+            mQuery = query;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onPrepareFromUri(Uri uri, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPrepareFromUriCalled = true;
-                mUri = uri;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPrepareFromUriCalled = true;
+            mUri = uri;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onSetRepeatMode(int repeatMode) {
-            synchronized (mWaitLock) {
-                mOnSetRepeatModeCalled = true;
-                mRepeatMode = repeatMode;
-                mWaitLock.notify();
-            }
+            mOnSetRepeatModeCalled = true;
+            mRepeatMode = repeatMode;
+            mLatch.countDown();
         }
 
         @Override
         public void onAddQueueItem(MediaDescriptionCompat description) {
-            synchronized (mWaitLock) {
-                mOnAddQueueItemCalled = true;
-                mQueueDescription = description;
-                mQueue.add(new MediaSessionCompat.QueueItem(description, mQueue.size()));
-                mSession.setQueue(mQueue);
-                mWaitLock.notify();
-            }
+            mOnAddQueueItemCalled = true;
+            mQueueDescription = description;
+            mQueue.add(new MediaSessionCompat.QueueItem(description, mQueue.size()));
+            mSession.setQueue(mQueue);
+            mLatch.countDown();
         }
 
         @Override
         public void onAddQueueItem(MediaDescriptionCompat description, int index) {
-            synchronized (mWaitLock) {
-                mOnAddQueueItemAtCalled = true;
-                mQueueIndex = index;
-                mQueueDescription = description;
-                mQueue.add(index, new MediaSessionCompat.QueueItem(description, mQueue.size()));
-                mSession.setQueue(mQueue);
-                mWaitLock.notify();
-            }
+            mOnAddQueueItemAtCalled = true;
+            mQueueIndex = index;
+            mQueueDescription = description;
+            mQueue.add(index, new MediaSessionCompat.QueueItem(description, mQueue.size()));
+            mSession.setQueue(mQueue);
+            mLatch.countDown();
         }
 
         @Override
         public void onRemoveQueueItem(MediaDescriptionCompat description) {
-            synchronized (mWaitLock) {
-                mOnRemoveQueueItemCalled = true;
-                String mediaId = description.getMediaId();
-                for (int i = mQueue.size() - 1; i >= 0; --i) {
-                    if (mediaId.equals(mQueue.get(i).getDescription().getMediaId())) {
-                        mQueueDescription = mQueue.remove(i).getDescription();
-                        mSession.setQueue(mQueue);
-                        break;
-                    }
+            mOnRemoveQueueItemCalled = true;
+            String mediaId = description.getMediaId();
+            for (int i = mQueue.size() - 1; i >= 0; --i) {
+                if (mediaId.equals(mQueue.get(i).getDescription().getMediaId())) {
+                    mQueueDescription = mQueue.remove(i).getDescription();
+                    mSession.setQueue(mQueue);
+                    break;
                 }
-                mWaitLock.notify();
             }
+            mLatch.countDown();
         }
 
         @Override
         public void onSetCaptioningEnabled(boolean enabled) {
-            synchronized (mWaitLock) {
-                mOnSetCaptioningEnabledCalled = true;
-                mCaptioningEnabled = enabled;
-                mWaitLock.notify();
-            }
+            mOnSetCaptioningEnabledCalled = true;
+            mCaptioningEnabled = enabled;
+            mLatch.countDown();
         }
 
         @Override
         public void onSetShuffleMode(int shuffleMode) {
-            synchronized (mWaitLock) {
-                mOnSetShuffleModeCalled = true;
-                mShuffleMode = shuffleMode;
-                mWaitLock.notify();
-            }
+            mOnSetShuffleModeCalled = true;
+            mShuffleMode = shuffleMode;
+            mLatch.countDown();
         }
     }
 }
diff --git a/media-compat/version-compat-tests/current/service/tests/src/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java b/media-compat/version-compat-tests/current/service/tests/src/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java
index 61c33f8..7032a0b 100644
--- a/media-compat/version-compat-tests/current/service/tests/src/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java
+++ b/media-compat/version-compat-tests/current/service/tests/src/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java
@@ -22,16 +22,20 @@
 import static android.support.mediacompat.testlib.MediaBrowserConstants.EXTRAS_VALUE;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_CHILDREN;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_CHILDREN_DELAYED;
+import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_INCLUDE_METADATA;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_INVALID;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_ROOT;
+import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_METADATA;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY_FOR_ERROR;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY_FOR_NO_RESULT;
 
 import android.os.Bundle;
+import android.support.annotation.NonNull;
 import android.support.v4.media.MediaBrowserCompat.MediaItem;
 import android.support.v4.media.MediaBrowserServiceCompat;
 import android.support.v4.media.MediaDescriptionCompat;
+import android.support.v4.media.MediaMetadataCompat;
 import android.support.v4.media.session.MediaSessionCompat;
 
 import junit.framework.Assert;
@@ -79,25 +83,43 @@
     }
 
     @Override
-    public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
+    public void onLoadChildren(final String parentId, final Result<List<MediaItem>> result) {
         List<MediaItem> mediaItems = new ArrayList<>();
-        if (MEDIA_ID_ROOT.equals(parentMediaId)) {
+        if (MEDIA_ID_ROOT.equals(parentId)) {
             Bundle rootHints = getBrowserRootHints();
             for (String id : MEDIA_ID_CHILDREN) {
                 mediaItems.add(createMediaItem(id));
             }
             result.sendResult(mediaItems);
-        } else if (MEDIA_ID_CHILDREN_DELAYED.equals(parentMediaId)) {
+        } else if (MEDIA_ID_CHILDREN_DELAYED.equals(parentId)) {
             Assert.assertNull(mPendingLoadChildrenResult);
             mPendingLoadChildrenResult = result;
             mPendingRootHints = getBrowserRootHints();
             result.detach();
-        } else if (MEDIA_ID_INVALID.equals(parentMediaId)) {
+        } else if (MEDIA_ID_INVALID.equals(parentId)) {
             result.sendResult(null);
         }
     }
 
     @Override
+    public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaItem>> result,
+            @NonNull Bundle options) {
+        if (MEDIA_ID_INCLUDE_METADATA.equals(parentId)) {
+            // Test unparcelling the Bundle.
+            MediaMetadataCompat metadata = options.getParcelable(MEDIA_METADATA);
+            if (metadata == null) {
+                super.onLoadChildren(parentId, result, options);
+            } else {
+                List<MediaItem> mediaItems = new ArrayList<>();
+                mediaItems.add(new MediaItem(metadata.getDescription(), MediaItem.FLAG_PLAYABLE));
+                result.sendResult(mediaItems);
+            }
+        } else {
+            super.onLoadChildren(parentId, result, options);
+        }
+    }
+
+    @Override
     public void onLoadItem(String itemId, Result<MediaItem> result) {
         if (MEDIA_ID_CHILDREN_DELAYED.equals(itemId)) {
             mPendingLoadItemResult = result;
diff --git a/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaBrowserConstants.java b/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaBrowserConstants.java
index 86024d9..f961308 100644
--- a/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaBrowserConstants.java
+++ b/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaBrowserConstants.java
@@ -31,14 +31,16 @@
     public static final int SET_SESSION_TOKEN = 7;
 
     public static final String MEDIA_ID_ROOT = "test_media_id_root";
-
-    public static final String EXTRAS_KEY = "test_extras_key";
-    public static final String EXTRAS_VALUE = "test_extras_value";
-
     public static final String MEDIA_ID_INVALID = "test_media_id_invalid";
     public static final String MEDIA_ID_CHILDREN_DELAYED = "test_media_id_children_delayed";
     public static final String MEDIA_ID_ON_LOAD_ITEM_NOT_IMPLEMENTED =
             "test_media_id_on_load_item_not_implemented";
+    public static final String MEDIA_ID_INCLUDE_METADATA = "test_media_id_include_metadata";
+
+    public static final String EXTRAS_KEY = "test_extras_key";
+    public static final String EXTRAS_VALUE = "test_extras_value";
+
+    public static final String MEDIA_METADATA = "test_media_metadata";
 
     public static final String SEARCH_QUERY = "children_2";
     public static final String SEARCH_QUERY_FOR_NO_RESULT = "query no result";
diff --git a/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaControllerConstants.java b/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaControllerConstants.java
index 5fa086b..4978888 100644
--- a/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaControllerConstants.java
+++ b/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaControllerConstants.java
@@ -26,6 +26,8 @@
     public static final int ADD_QUEUE_ITEM = 202;
     public static final int ADD_QUEUE_ITEM_WITH_INDEX = 203;
     public static final int REMOVE_QUEUE_ITEM = 204;
+    public static final int SET_VOLUME_TO = 205;
+    public static final int ADJUST_VOLUME = 206;
 
     // TransportControls methods.
     public static final int PLAY = 301;
diff --git a/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaSessionConstants.java b/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaSessionConstants.java
index cbdccc1..c0a64d4 100644
--- a/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaSessionConstants.java
+++ b/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaSessionConstants.java
@@ -51,6 +51,8 @@
     public static final long TEST_QUEUE_ID_2 = 20L;
     public static final String TEST_MEDIA_ID_1 = "media_id_1";
     public static final String TEST_MEDIA_ID_2 = "media_id_2";
+    public static final String TEST_MEDIA_TITLE_1 = "media_title_1";
+    public static final String TEST_MEDIA_TITLE_2 = "media_title_2";
     public static final long TEST_ACTION = 55L;
 
     public static final int TEST_ERROR_CODE = 0x3;
diff --git a/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/VersionConstants.java b/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/VersionConstants.java
index 6533ee1..4b217b1 100644
--- a/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/VersionConstants.java
+++ b/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/VersionConstants.java
@@ -22,4 +22,7 @@
 public class VersionConstants {
     public static final String KEY_CLIENT_VERSION = "client_version";
     public static final String KEY_SERVICE_VERSION = "service_version";
+
+    public static final String VERSION_TOT = "tot";
+    public static final String VERSION_PREVIOUS = "previous";
 }
diff --git a/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/util/IntentUtil.java b/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/util/IntentUtil.java
index bbf9752..8d58a6f 100644
--- a/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/util/IntentUtil.java
+++ b/media-compat/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/util/IntentUtil.java
@@ -30,12 +30,13 @@
  */
 public class IntentUtil {
 
+    public static final String SERVICE_PACKAGE_NAME = "android.support.mediacompat.service.test";
+    public static final String CLIENT_PACKAGE_NAME = "android.support.mediacompat.client.test";
+
     public static final ComponentName SERVICE_RECEIVER_COMPONENT_NAME = new ComponentName(
-            "android.support.mediacompat.service.test",
-            "android.support.mediacompat.service.ServiceBroadcastReceiver");
+            SERVICE_PACKAGE_NAME, "android.support.mediacompat.service.ServiceBroadcastReceiver");
     public static final ComponentName CLIENT_RECEIVER_COMPONENT_NAME = new ComponentName(
-            "android.support.mediacompat.client.test",
-            "android.support.mediacompat.client.ClientBroadcastReceiver");
+            CLIENT_PACKAGE_NAME, "android.support.mediacompat.client.ClientBroadcastReceiver");
 
     public static final String ACTION_CALL_MEDIA_BROWSER_SERVICE_METHOD =
             "android.support.mediacompat.service.action.CALL_MEDIA_BROWSER_SERVICE_METHOD";
diff --git a/media-compat/version-compat-tests/previous/client/build.gradle b/media-compat/version-compat-tests/previous/client/build.gradle
index 01b3847..2788a1a 100644
--- a/media-compat/version-compat-tests/previous/client/build.gradle
+++ b/media-compat/version-compat-tests/previous/client/build.gradle
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
+
 plugins {
     id("SupportAndroidLibraryPlugin")
 }
@@ -22,7 +24,7 @@
     androidTestImplementation project(':support-media-compat-test-lib')
     androidTestImplementation "com.android.support:support-media-compat:27.0.1"
 
-    androidTestImplementation(libs.test_runner)
+    androidTestImplementation(TEST_RUNNER)
 }
 
 android {
diff --git a/media-compat/tests/src/android/support/v4/media/AudioAttributesCompatTest.java b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/AudioAttributesCompatTest.java
similarity index 97%
copy from media-compat/tests/src/android/support/v4/media/AudioAttributesCompatTest.java
copy to media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/AudioAttributesCompatTest.java
index d66c7fc..675c0fc 100644
--- a/media-compat/tests/src/android/support/v4/media/AudioAttributesCompatTest.java
+++ b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/AudioAttributesCompatTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.support.v4.media;
+package android.support.mediacompat.client;
 
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.hamcrest.core.IsNot.not;
@@ -25,6 +25,7 @@
 import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.media.AudioAttributesCompat;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/ClientBroadcastReceiver.java b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/ClientBroadcastReceiver.java
index 3166e55..3227482 100644
--- a/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/ClientBroadcastReceiver.java
+++ b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/ClientBroadcastReceiver.java
@@ -19,6 +19,7 @@
 import static android.support.mediacompat.testlib.MediaControllerConstants.ADD_QUEUE_ITEM;
 import static android.support.mediacompat.testlib.MediaControllerConstants
         .ADD_QUEUE_ITEM_WITH_INDEX;
+import static android.support.mediacompat.testlib.MediaControllerConstants.ADJUST_VOLUME;
 import static android.support.mediacompat.testlib.MediaControllerConstants.FAST_FORWARD;
 import static android.support.mediacompat.testlib.MediaControllerConstants.PAUSE;
 import static android.support.mediacompat.testlib.MediaControllerConstants.PLAY;
@@ -40,6 +41,7 @@
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_RATING;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_REPEAT_MODE;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_SHUFFLE_MODE;
+import static android.support.mediacompat.testlib.MediaControllerConstants.SET_VOLUME_TO;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_NEXT;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_PREVIOUS;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_QUEUE_ITEM;
@@ -105,6 +107,12 @@
                     controller.removeQueueItem(
                             (MediaDescriptionCompat) extras.getParcelable(KEY_ARGUMENT));
                     break;
+                case SET_VOLUME_TO:
+                    controller.setVolumeTo(extras.getInt(KEY_ARGUMENT), 0);
+                    break;
+                case ADJUST_VOLUME:
+                    controller.adjustVolume(extras.getInt(KEY_ARGUMENT), 0);
+                    break;
             }
         } else if (ACTION_CALL_TRANSPORT_CONTROLS_METHOD.equals(intent.getAction())
                 && extras != null) {
diff --git a/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaBrowserCompatTest.java b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaBrowserCompatTest.java
index 31bdb7a..a2e77ff 100644
--- a/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaBrowserCompatTest.java
+++ b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaBrowserCompatTest.java
@@ -47,6 +47,7 @@
 import static android.support.mediacompat.testlib.MediaBrowserConstants.TEST_VALUE_3;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.TEST_VALUE_4;
 import static android.support.mediacompat.testlib.VersionConstants.KEY_SERVICE_VERSION;
+import static android.support.mediacompat.testlib.util.IntentUtil.SERVICE_PACKAGE_NAME;
 import static android.support.mediacompat.testlib.util.IntentUtil.callMediaBrowserServiceMethod;
 import static android.support.test.InstrumentationRegistry.getArguments;
 import static android.support.test.InstrumentationRegistry.getContext;
@@ -80,6 +81,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Test {@link android.support.v4.media.MediaBrowserCompat}.
@@ -105,13 +108,15 @@
      */
     private static final long SLEEP_MS = 100L;
     private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
-            "android.support.mediacompat.service.test",
+            SERVICE_PACKAGE_NAME,
             "android.support.mediacompat.service.StubMediaBrowserServiceCompat");
     private static final ComponentName TEST_BROWSER_SERVICE_DELAYED_MEDIA_SESSION =
             new ComponentName(
-                    "android.support.mediacompat.service.test",
+                    SERVICE_PACKAGE_NAME,
                     "android.support.mediacompat.service"
                             + ".StubMediaBrowserServiceCompatWithDelayedMediaSession");
+    private static final ComponentName TEST_INVALID_BROWSER_SERVICE = new ComponentName(
+            "invalid.package", "invalid.ServiceClassName");
 
     private String mServiceVersion;
     private MediaBrowserCompat mMediaBrowser;
@@ -157,6 +162,21 @@
 
     @Test
     @SmallTest
+    public void testBrowserRoot() {
+        final String id = "test-id";
+        final String key = "test-key";
+        final String val = "test-val";
+        final Bundle extras = new Bundle();
+        extras.putString(key, val);
+
+        MediaBrowserServiceCompat.BrowserRoot browserRoot =
+                new MediaBrowserServiceCompat.BrowserRoot(id, extras);
+        assertEquals(id, browserRoot.getRootId());
+        assertEquals(val, browserRoot.getExtras().getString(key));
+    }
+
+    @Test
+    @SmallTest
     public void testMediaBrowser() throws Exception {
         assertFalse(mMediaBrowser.isConnected());
 
@@ -178,6 +198,37 @@
 
     @Test
     @SmallTest
+    public void testGetServiceComponentBeforeConnection() {
+        try {
+            ComponentName serviceComponent = mMediaBrowser.getServiceComponent();
+            fail();
+        } catch (IllegalStateException e) {
+            // expected
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testConnectionFailed() throws Exception {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mMediaBrowser = new MediaBrowserCompat(getInstrumentation().getTargetContext(),
+                        TEST_INVALID_BROWSER_SERVICE, mConnectionCallback, mRootHints);
+            }
+        });
+
+        synchronized (mConnectionCallback.mWaitLock) {
+            mMediaBrowser.connect();
+            mConnectionCallback.mWaitLock.wait(TIME_OUT_MS);
+        }
+        assertEquals(1, mConnectionCallback.mConnectionFailedCount);
+        assertEquals(0, mConnectionCallback.mConnectedCount);
+        assertEquals(0, mConnectionCallback.mConnectionSuspendedCount);
+    }
+
+    @Test
+    @SmallTest
     public void testConnectTwice() throws Exception {
         connectMediaBrowserService();
         try {
@@ -206,18 +257,16 @@
             assertEquals(1, mConnectionCallback.mConnectedCount);
         }
 
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            // Test subscribe.
-            resetCallbacks();
-            mMediaBrowser.subscribe(MEDIA_ID_ROOT, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedCount > 0);
-            assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
-        }
+        // Test subscribe.
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_ROOT, mSubscriptionCallback);
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(1, mSubscriptionCallback.mChildrenLoadedCount);
+        assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
 
         synchronized (mItemCallback.mWaitLock) {
             // Test getItem.
-            resetCallbacks();
+            mItemCallback.reset();
             mMediaBrowser.getItem(MEDIA_ID_CHILDREN[0], mItemCallback);
             mItemCallback.mWaitLock.wait(TIME_OUT_MS);
             assertEquals(MEDIA_ID_CHILDREN[0], mItemCallback.mLastMediaItem.getMediaId());
@@ -225,12 +274,11 @@
 
         // Reconnect after connection was established.
         mMediaBrowser.disconnect();
-        resetCallbacks();
         connectMediaBrowserService();
 
         synchronized (mItemCallback.mWaitLock) {
             // Test getItem.
-            resetCallbacks();
+            mItemCallback.reset();
             mMediaBrowser.getItem(MEDIA_ID_CHILDREN[0], mItemCallback);
             mItemCallback.mWaitLock.wait(TIME_OUT_MS);
             assertEquals(MEDIA_ID_CHILDREN[0], mItemCallback.mLastMediaItem.getMediaId());
@@ -245,7 +293,7 @@
             public void run() {
                 mMediaBrowser.connect();
                 mMediaBrowser.disconnect();
-                resetCallbacks();
+                mConnectionCallback.reset();
             }
         });
 
@@ -259,48 +307,43 @@
         assertEquals(0, mConnectionCallback.mConnectionSuspendedCount);
     }
 
-//    @Test
-//    @MediumTest
+    @Test
+    @MediumTest
     public void testSubscribe() throws Exception {
         connectMediaBrowserService();
 
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mMediaBrowser.subscribe(MEDIA_ID_ROOT, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedCount > 0);
-            assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
-            assertEquals(MEDIA_ID_CHILDREN.length,
-                    mSubscriptionCallback.mLastChildMediaItems.size());
-            for (int i = 0; i < MEDIA_ID_CHILDREN.length; ++i) {
-                assertEquals(MEDIA_ID_CHILDREN[i],
-                        mSubscriptionCallback.mLastChildMediaItems.get(i).getMediaId());
-            }
-
-            // Test MediaBrowserServiceCompat.notifyChildrenChanged()
-            mSubscriptionCallback.reset();
-            callMediaBrowserServiceMethod(NOTIFY_CHILDREN_CHANGED, MEDIA_ID_ROOT, getContext());
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedCount > 0);
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_ROOT, mSubscriptionCallback);
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(1, mSubscriptionCallback.mChildrenLoadedCount);
+        assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
+        assertEquals(MEDIA_ID_CHILDREN.length, mSubscriptionCallback.mLastChildMediaItems.size());
+        for (int i = 0; i < MEDIA_ID_CHILDREN.length; ++i) {
+            assertEquals(MEDIA_ID_CHILDREN[i],
+                    mSubscriptionCallback.mLastChildMediaItems.get(i).getMediaId());
         }
 
+        // Test MediaBrowserServiceCompat.notifyChildrenChanged()
+        mSubscriptionCallback.reset(1);
+        callMediaBrowserServiceMethod(NOTIFY_CHILDREN_CHANGED, MEDIA_ID_ROOT, getContext());
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(1, mSubscriptionCallback.mChildrenLoadedCount);
+
         // Test unsubscribe.
-        resetCallbacks();
+        mSubscriptionCallback.reset(1);
         mMediaBrowser.unsubscribe(MEDIA_ID_ROOT);
 
         // After unsubscribing, make StubMediaBrowserServiceCompat notify that the children are
         // changed.
         callMediaBrowserServiceMethod(NOTIFY_CHILDREN_CHANGED, MEDIA_ID_ROOT, getContext());
-        try {
-            Thread.sleep(SLEEP_MS);
-        } catch (InterruptedException e) {
-            fail("Unexpected InterruptedException occurred.");
-        }
+        mSubscriptionCallback.await(WAIT_TIME_FOR_NO_RESPONSE_MS);
+
         // onChildrenLoaded should not be called.
         assertEquals(0, mSubscriptionCallback.mChildrenLoadedCount);
     }
 
-//    @Test
-//    @MediumTest
+    @Test
+    @MediumTest
     public void testSubscribeWithOptions() throws Exception {
         connectMediaBrowserService();
         final int pageSize = 3;
@@ -308,36 +351,34 @@
         Bundle options = new Bundle();
         options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
 
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            for (int page = 0; page <= lastPage; ++page) {
-                resetCallbacks();
-                options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
-                mMediaBrowser.subscribe(MEDIA_ID_ROOT, options, mSubscriptionCallback);
-                mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-                assertTrue(mSubscriptionCallback.mChildrenLoadedWithOptionCount > 0);
-                assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
-                if (page != lastPage) {
-                    assertEquals(pageSize, mSubscriptionCallback.mLastChildMediaItems.size());
-                } else {
-                    assertEquals((MEDIA_ID_CHILDREN.length - 1) % pageSize + 1,
-                            mSubscriptionCallback.mLastChildMediaItems.size());
-                }
-                // Check whether all the items in the current page are loaded.
-                for (int i = 0; i < mSubscriptionCallback.mLastChildMediaItems.size(); ++i) {
-                    assertEquals(MEDIA_ID_CHILDREN[page * pageSize + i],
-                            mSubscriptionCallback.mLastChildMediaItems.get(i).getMediaId());
-                }
+        for (int page = 0; page <= lastPage; ++page) {
+            mSubscriptionCallback.reset(1);
+            options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
+            mMediaBrowser.subscribe(MEDIA_ID_ROOT, options, mSubscriptionCallback);
+            mSubscriptionCallback.await(TIME_OUT_MS);
+            assertEquals(1, mSubscriptionCallback.mChildrenLoadedWithOptionCount);
+            assertEquals(MEDIA_ID_ROOT, mSubscriptionCallback.mLastParentId);
+            if (page != lastPage) {
+                assertEquals(pageSize, mSubscriptionCallback.mLastChildMediaItems.size());
+            } else {
+                assertEquals((MEDIA_ID_CHILDREN.length - 1) % pageSize + 1,
+                        mSubscriptionCallback.mLastChildMediaItems.size());
+            }
+            // Check whether all the items in the current page are loaded.
+            for (int i = 0; i < mSubscriptionCallback.mLastChildMediaItems.size(); ++i) {
+                assertEquals(MEDIA_ID_CHILDREN[page * pageSize + i],
+                        mSubscriptionCallback.mLastChildMediaItems.get(i).getMediaId());
             }
 
             // Test MediaBrowserServiceCompat.notifyChildrenChanged()
-            mSubscriptionCallback.reset();
+            mSubscriptionCallback.reset(page + 1);
             callMediaBrowserServiceMethod(NOTIFY_CHILDREN_CHANGED, MEDIA_ID_ROOT, getContext());
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedWithOptionCount > 0);
+            mSubscriptionCallback.await(TIME_OUT_MS);
+            assertEquals(page + 1, mSubscriptionCallback.mChildrenLoadedWithOptionCount);
         }
 
         // Test unsubscribe with callback argument.
-        resetCallbacks();
+        mSubscriptionCallback.reset(1);
         mMediaBrowser.unsubscribe(MEDIA_ID_ROOT, mSubscriptionCallback);
 
         // After unsubscribing, make StubMediaBrowserServiceCompat notify that the children are
@@ -356,17 +397,16 @@
     @MediumTest
     public void testSubscribeDelayedItems() throws Exception {
         connectMediaBrowserService();
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mSubscriptionCallback.reset();
-            mMediaBrowser.subscribe(MEDIA_ID_CHILDREN_DELAYED, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertEquals(0, mSubscriptionCallback.mChildrenLoadedCount);
 
-            callMediaBrowserServiceMethod(
-                    SEND_DELAYED_NOTIFY_CHILDREN_CHANGED, MEDIA_ID_CHILDREN_DELAYED, getContext());
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mChildrenLoadedCount > 0);
-        }
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_CHILDREN_DELAYED, mSubscriptionCallback);
+        mSubscriptionCallback.await(WAIT_TIME_FOR_NO_RESPONSE_MS);
+        assertEquals(0, mSubscriptionCallback.mChildrenLoadedCount);
+
+        callMediaBrowserServiceMethod(
+                SEND_DELAYED_NOTIFY_CHILDREN_CHANGED, MEDIA_ID_CHILDREN_DELAYED, getContext());
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(1, mSubscriptionCallback.mChildrenLoadedCount);
     }
 
     @Test
@@ -374,11 +414,10 @@
     public void testSubscribeInvalidItem() throws Exception {
         connectMediaBrowserService();
 
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mMediaBrowser.subscribe(MEDIA_ID_INVALID, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(MEDIA_ID_INVALID, mSubscriptionCallback.mLastErrorId);
-        }
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_INVALID, mSubscriptionCallback);
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(MEDIA_ID_INVALID, mSubscriptionCallback.mLastErrorId);
     }
 
     @Test
@@ -392,16 +431,15 @@
         options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
         options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
 
-        synchronized (mSubscriptionCallback.mWaitLock) {
-            mMediaBrowser.subscribe(MEDIA_ID_INVALID, options, mSubscriptionCallback);
-            mSubscriptionCallback.mWaitLock.wait(TIME_OUT_MS);
-            assertEquals(MEDIA_ID_INVALID, mSubscriptionCallback.mLastErrorId);
-            assertNotNull(mSubscriptionCallback.mLastOptions);
-            assertEquals(page,
-                    mSubscriptionCallback.mLastOptions.getInt(MediaBrowserCompat.EXTRA_PAGE));
-            assertEquals(pageSize,
-                    mSubscriptionCallback.mLastOptions.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE));
-        }
+        mSubscriptionCallback.reset(1);
+        mMediaBrowser.subscribe(MEDIA_ID_INVALID, options, mSubscriptionCallback);
+        mSubscriptionCallback.await(TIME_OUT_MS);
+        assertEquals(MEDIA_ID_INVALID, mSubscriptionCallback.mLastErrorId);
+        assertNotNull(mSubscriptionCallback.mLastOptions);
+        assertEquals(page,
+                mSubscriptionCallback.mLastOptions.getInt(MediaBrowserCompat.EXTRA_PAGE));
+        assertEquals(pageSize,
+                mSubscriptionCallback.mLastOptions.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE));
     }
 
     @Test
@@ -419,17 +457,17 @@
             Bundle options = new Bundle();
             options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
             options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
+            callback.reset(1);
             mMediaBrowser.subscribe(MEDIA_ID_ROOT, options, callback);
-            synchronized (callback.mWaitLock) {
-                callback.mWaitLock.wait(TIME_OUT_MS);
-            }
+            callback.await(TIME_OUT_MS);
+
             // Each onChildrenLoaded() must be called.
             assertEquals(1, callback.mChildrenLoadedWithOptionCount);
         }
 
         // Reset callbacks and unsubscribe.
         for (StubSubscriptionCallback callback : subscriptionCallbacks) {
-            callback.reset();
+            callback.reset(1);
         }
         mMediaBrowser.unsubscribe(MEDIA_ID_ROOT);
 
@@ -448,8 +486,8 @@
         }
     }
 
-//    @Test
-//    @MediumTest
+    @Test
+    @MediumTest
     public void testUnsubscribeWithSubscriptionCallbackForMultipleSubscriptions() throws Exception {
         connectMediaBrowserService();
         final List<StubSubscriptionCallback> subscriptionCallbacks = new ArrayList<>();
@@ -463,10 +501,10 @@
             Bundle options = new Bundle();
             options.putInt(MediaBrowserCompat.EXTRA_PAGE, page);
             options.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, pageSize);
+            callback.reset(1);
             mMediaBrowser.subscribe(MEDIA_ID_ROOT, options, callback);
-            synchronized (callback.mWaitLock) {
-                callback.mWaitLock.wait(TIME_OUT_MS);
-            }
+            callback.await(TIME_OUT_MS);
+
             // Each onChildrenLoaded() must be called.
             assertEquals(1, callback.mChildrenLoadedWithOptionCount);
         }
@@ -476,7 +514,7 @@
         for (int i = 0; i < orderOfRemovingCallbacks.length; i++) {
             // Reset callbacks
             for (StubSubscriptionCallback callback : subscriptionCallbacks) {
-                callback.reset();
+                callback.reset(1);
             }
 
             // Remove one subscription
@@ -611,6 +649,7 @@
             customActionExtras.putString(TEST_KEY_1, TEST_VALUE_1);
             mMediaBrowser.sendCustomAction(
                     CUSTOM_ACTION, customActionExtras, mCustomActionCallback);
+            mCustomActionCallback.mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
 
             mCustomActionCallback.reset();
             Bundle data1 = new Bundle();
@@ -701,6 +740,8 @@
         Bundle customActionExtras = new Bundle();
         customActionExtras.putString(TEST_KEY_1, TEST_VALUE_1);
         mMediaBrowser.sendCustomAction(CUSTOM_ACTION, customActionExtras, null);
+        // Wait some time so that the service can get a result receiver for the custom action.
+        Thread.sleep(WAIT_TIME_FOR_NO_RESPONSE_MS);
 
         // These calls should not make any exceptions.
         callMediaBrowserServiceMethod(CUSTOM_ACTION_SEND_PROGRESS_UPDATE, new Bundle(),
@@ -768,12 +809,6 @@
         }
     }
 
-    private void resetCallbacks() {
-        mConnectionCallback.reset();
-        mSubscriptionCallback.reset();
-        mItemCallback.reset();
-    }
-
     private class StubConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
         final Object mWaitLock = new Object();
         volatile int mConnectedCount;
@@ -812,7 +847,7 @@
     }
 
     private class StubSubscriptionCallback extends MediaBrowserCompat.SubscriptionCallback {
-        final Object mWaitLock = new Object();
+        private CountDownLatch mLatch;
         private volatile int mChildrenLoadedCount;
         private volatile int mChildrenLoadedWithOptionCount;
         private volatile String mLastErrorId;
@@ -820,7 +855,8 @@
         private volatile Bundle mLastOptions;
         private volatile List<MediaItem> mLastChildMediaItems;
 
-        public void reset() {
+        public void reset(int count) {
+            mLatch = new CountDownLatch(count);
             mChildrenLoadedCount = 0;
             mChildrenLoadedWithOptionCount = 0;
             mLastErrorId = null;
@@ -829,43 +865,43 @@
             mLastChildMediaItems = null;
         }
 
+        public boolean await(long timeoutMs) {
+            try {
+                return mLatch.await(timeoutMs, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                return false;
+            }
+        }
+
         @Override
         public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children) {
-            synchronized (mWaitLock) {
-                mChildrenLoadedCount++;
-                mLastParentId = parentId;
-                mLastChildMediaItems = children;
-                mWaitLock.notify();
-            }
+            mChildrenLoadedCount++;
+            mLastParentId = parentId;
+            mLastChildMediaItems = children;
+            mLatch.countDown();
         }
 
         @Override
         public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children,
                 @NonNull Bundle options) {
-            synchronized (mWaitLock) {
-                mChildrenLoadedWithOptionCount++;
-                mLastParentId = parentId;
-                mLastOptions = options;
-                mLastChildMediaItems = children;
-                mWaitLock.notify();
-            }
+            mChildrenLoadedWithOptionCount++;
+            mLastParentId = parentId;
+            mLastOptions = options;
+            mLastChildMediaItems = children;
+            mLatch.countDown();
         }
 
         @Override
         public void onError(@NonNull String id) {
-            synchronized (mWaitLock) {
-                mLastErrorId = id;
-                mWaitLock.notify();
-            }
+            mLastErrorId = id;
+            mLatch.countDown();
         }
 
         @Override
         public void onError(@NonNull String id, @NonNull Bundle options) {
-            synchronized (mWaitLock) {
-                mLastErrorId = id;
-                mLastOptions = options;
-                mWaitLock.notify();
-            }
+            mLastErrorId = id;
+            mLastOptions = options;
+            mLatch.countDown();
         }
     }
 
diff --git a/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaControllerCompatCallbackTest.java b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaControllerCompatCallbackTest.java
index 79993ef..b173a4d 100644
--- a/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaControllerCompatCallbackTest.java
+++ b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaControllerCompatCallbackTest.java
@@ -46,6 +46,7 @@
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_SESSION_EVENT;
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_VALUE;
 import static android.support.mediacompat.testlib.VersionConstants.KEY_SERVICE_VERSION;
+import static android.support.mediacompat.testlib.util.IntentUtil.SERVICE_PACKAGE_NAME;
 import static android.support.mediacompat.testlib.util.IntentUtil.callMediaSessionMethod;
 import static android.support.mediacompat.testlib.util.TestUtil.assertBundleEquals;
 import static android.support.test.InstrumentationRegistry.getArguments;
@@ -55,9 +56,11 @@
 import static android.support.v4.media.MediaMetadataCompat.METADATA_KEY_RATING;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 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.ComponentName;
@@ -84,8 +87,6 @@
 import android.support.v4.media.session.PlaybackStateCompat;
 import android.util.Log;
 
-import junit.framework.Assert;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -107,7 +108,7 @@
     private static final int MAX_AUDIO_INFO_CHANGED_CALLBACK_COUNT = 10;
 
     private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
-            "android.support.mediacompat.service.test",
+            SERVICE_PACKAGE_NAME,
             "android.support.mediacompat.service.StubMediaBrowserServiceCompat");
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -119,6 +120,7 @@
     private MediaBrowserCompat mMediaBrowser;
     private ConnectionCallback mConnectionCallback = new ConnectionCallback();
 
+    private MediaSessionCompat.Token mSessionToken;
     private MediaControllerCompat mController;
     private MediaControllerCallback mMediaControllerCallback = new MediaControllerCallback();
 
@@ -140,11 +142,11 @@
             mMediaBrowser.connect();
             mConnectionCallback.mWaitLock.wait(TIME_OUT_MS);
             if (!mMediaBrowser.isConnected()) {
-                Assert.fail("Browser failed to connect!");
+                fail("Browser failed to connect!");
             }
         }
-        mController =
-                new MediaControllerCompat(getTargetContext(), mMediaBrowser.getSessionToken());
+        mSessionToken = mMediaBrowser.getSessionToken();
+        mController = new MediaControllerCompat(getTargetContext(), mSessionToken);
         mController.registerCallback(mMediaControllerCallback, mHandler);
     }
 
@@ -155,6 +157,20 @@
         }
     }
 
+    @Test
+    @SmallTest
+    public void testGetPackageName() {
+        assertEquals(SERVICE_PACKAGE_NAME, mController.getPackageName());
+    }
+
+    @Test
+    @SmallTest
+    public void testIsSessionReady() throws Exception {
+        // mController already has the extra binder since it was created with the session token
+        // which holds the extra binder.
+        assertTrue(mController.isSessionReady());
+    }
+
     /**
      * Tests {@link MediaSessionCompat#setExtras}.
      */
@@ -487,7 +503,7 @@
                         && info.getMaxVolume() == TEST_MAX_VOLUME
                         && info.getVolumeControl() == VolumeProviderCompat.VOLUME_CONTROL_FIXED
                         && info.getPlaybackType()
-                                == MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
+                        == MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
                     break;
                 }
             }
@@ -541,6 +557,36 @@
         }.run();
     }
 
+    @Test
+    @SmallTest
+    public void testSessionReady() throws Exception {
+        if (android.os.Build.VERSION.SDK_INT < 21) {
+            return;
+        }
+
+        final MediaSessionCompat.Token tokenWithoutExtraBinder =
+                MediaSessionCompat.Token.fromToken(mSessionToken.getToken());
+
+        final MediaControllerCallback callback = new MediaControllerCallback();
+        synchronized (mWaitLock) {
+            getInstrumentation().runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        MediaControllerCompat controller = new MediaControllerCompat(
+                                getInstrumentation().getTargetContext(), tokenWithoutExtraBinder);
+                        controller.registerCallback(callback, new Handler());
+                        assertFalse(controller.isSessionReady());
+                    } catch (Exception e) {
+                        fail();
+                    }
+                }
+            });
+            mWaitLock.wait(TIME_OUT_MS);
+            assertTrue(callback.mOnSessionReadyCalled);
+        }
+    }
+
     private void assertQueueEquals(List<QueueItem> expected, List<QueueItem> observed) {
         if (expected == null || observed == null) {
             assertTrue(expected == observed);
@@ -570,6 +616,7 @@
         private volatile boolean mOnCaptioningEnabledChangedCalled;
         private volatile boolean mOnRepeatModeChangedCalled;
         private volatile boolean mOnShuffleModeChangedCalled;
+        private volatile boolean mOnSessionReadyCalled;
 
         private volatile PlaybackStateCompat mPlaybackState;
         private volatile MediaMetadataCompat mMediaMetadata;
@@ -703,6 +750,14 @@
                 mWaitLock.notify();
             }
         }
+
+        @Override
+        public void onSessionReady() {
+            synchronized (mWaitLock) {
+                mOnSessionReadyCalled = true;
+                mWaitLock.notify();
+            }
+        }
     }
 
     private class ConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
diff --git a/media-compat/tests/src/android/support/v4/media/MediaItemTest.java b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaItemTest.java
similarity index 94%
copy from media-compat/tests/src/android/support/v4/media/MediaItemTest.java
copy to media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaItemTest.java
index bd2565f..179a178 100644
--- a/media-compat/tests/src/android/support/v4/media/MediaItemTest.java
+++ b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/MediaItemTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.support.v4.media;
+package android.support.mediacompat.client;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -22,11 +22,12 @@
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
 import android.support.v4.media.MediaBrowserCompat.MediaItem;
+import android.support.v4.media.MediaDescriptionCompat;
 
 import org.junit.Test;
 
 /**
- * Test {@link MediaBrowserCompat.MediaItem}.
+ * Test {@link MediaItem}.
  */
 public class MediaItemTest {
     private static final String DESCRIPTION = "test_description";
diff --git a/media-compat/tests/src/android/support/v4/media/session/PlaybackStateCompatTest.java b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/PlaybackStateCompatTest.java
similarity index 97%
copy from media-compat/tests/src/android/support/v4/media/session/PlaybackStateCompatTest.java
copy to media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/PlaybackStateCompatTest.java
index 9e320cd..7962731 100644
--- a/media-compat/tests/src/android/support/v4/media/session/PlaybackStateCompatTest.java
+++ b/media-compat/version-compat-tests/previous/client/tests/src/android/support/mediacompat/client/PlaybackStateCompatTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.v4.media.session;
+package android.support.mediacompat.client;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -24,6 +24,8 @@
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.media.session.MediaSessionCompat;
+import android.support.v4.media.session.PlaybackStateCompat;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/media-compat/version-compat-tests/previous/service/build.gradle b/media-compat/version-compat-tests/previous/service/build.gradle
index 03f95ce..469f6e4 100644
--- a/media-compat/version-compat-tests/previous/service/build.gradle
+++ b/media-compat/version-compat-tests/previous/service/build.gradle
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
+
 plugins {
     id("SupportAndroidLibraryPlugin")
 }
@@ -22,7 +24,7 @@
     androidTestImplementation project(':support-media-compat-test-lib')
     androidTestImplementation "com.android.support:support-media-compat:27.0.1"
 
-    androidTestImplementation(libs.test_runner)
+    androidTestImplementation(TEST_RUNNER)
 }
 
 android {
diff --git a/media-compat/version-compat-tests/previous/service/tests/src/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java b/media-compat/version-compat-tests/previous/service/tests/src/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
index d36eba3..5c5a432 100644
--- a/media-compat/version-compat-tests/previous/service/tests/src/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
+++ b/media-compat/version-compat-tests/previous/service/tests/src/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
@@ -18,6 +18,7 @@
 import static android.support.mediacompat.testlib.MediaControllerConstants.ADD_QUEUE_ITEM;
 import static android.support.mediacompat.testlib.MediaControllerConstants
         .ADD_QUEUE_ITEM_WITH_INDEX;
+import static android.support.mediacompat.testlib.MediaControllerConstants.ADJUST_VOLUME;
 import static android.support.mediacompat.testlib.MediaControllerConstants.FAST_FORWARD;
 import static android.support.mediacompat.testlib.MediaControllerConstants.PAUSE;
 import static android.support.mediacompat.testlib.MediaControllerConstants.PLAY;
@@ -39,12 +40,18 @@
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_RATING;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_REPEAT_MODE;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SET_SHUFFLE_MODE;
+import static android.support.mediacompat.testlib.MediaControllerConstants.SET_VOLUME_TO;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_NEXT;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_PREVIOUS;
 import static android.support.mediacompat.testlib.MediaControllerConstants.SKIP_TO_QUEUE_ITEM;
 import static android.support.mediacompat.testlib.MediaControllerConstants.STOP;
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_COMMAND;
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_KEY;
+import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_MEDIA_ID_1;
+import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_MEDIA_ID_2;
+import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_MEDIA_TITLE_1;
+import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_MEDIA_TITLE_2;
+import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_QUEUE_ID_1;
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_SESSION_TAG;
 import static android.support.mediacompat.testlib.MediaSessionConstants.TEST_VALUE;
 import static android.support.mediacompat.testlib.VersionConstants.KEY_CLIENT_VERSION;
@@ -57,21 +64,38 @@
 import static android.support.test.InstrumentationRegistry.getTargetContext;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.PlaybackState;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.Parcel;
 import android.os.ResultReceiver;
+import android.os.SystemClock;
+import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.v4.media.MediaDescriptionCompat;
 import android.support.v4.media.RatingCompat;
+import android.support.v4.media.VolumeProviderCompat;
+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 android.view.KeyEvent;
 
 import org.junit.After;
 import org.junit.Before;
@@ -80,6 +104,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Test {@link MediaSessionCompat.Callback}.
@@ -91,6 +117,10 @@
 
     // The maximum time to wait for an operation.
     private static final long TIME_OUT_MS = 3000L;
+    private static final long WAIT_TIME_FOR_NO_RESPONSE_MS = 300L;
+
+    private static final long TEST_POSITION = 1000000L;
+    private static final float TEST_PLAYBACK_SPEED = 3.0f;
     private static final float DELTA = 1e-4f;
     private static final boolean ENABLED = true;
 
@@ -99,6 +129,7 @@
     private String mClientVersion;
     private MediaSessionCompat mSession;
     private MediaSessionCallback mCallback = new MediaSessionCallback();
+    private AudioManager mAudioManager;
 
     @Before
     public void setUp() throws Exception {
@@ -109,9 +140,9 @@
         getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {
+                mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
                 mSession = new MediaSessionCompat(getTargetContext(), TEST_SESSION_TAG);
                 mSession.setCallback(mCallback, mHandler);
-                mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS);
             }
         });
     }
@@ -121,277 +152,662 @@
         mSession.release();
     }
 
+    /**
+     * Tests that a session can be created and that all the fields are initialized correctly.
+     */
+    @Test
+    @SmallTest
+    public void testCreateSession() throws Exception {
+        assertNotNull(mSession.getSessionToken());
+        assertFalse("New session should not be active", mSession.isActive());
+
+        // Verify by getting the controller and checking all its fields
+        MediaControllerCompat controller = mSession.getController();
+        assertNotNull(controller);
+
+        final String errorMsg = "New session has unexpected configuration.";
+        assertEquals(errorMsg, 0L, controller.getFlags());
+        assertNull(errorMsg, controller.getExtras());
+        assertNull(errorMsg, controller.getMetadata());
+        assertEquals(errorMsg, getContext().getPackageName(), controller.getPackageName());
+        assertNull(errorMsg, controller.getPlaybackState());
+        assertNull(errorMsg, controller.getQueue());
+        assertNull(errorMsg, controller.getQueueTitle());
+        assertEquals(errorMsg, RatingCompat.RATING_NONE, controller.getRatingType());
+        assertNull(errorMsg, controller.getSessionActivity());
+
+        assertNotNull(controller.getSessionToken());
+        assertNotNull(controller.getTransportControls());
+
+        MediaControllerCompat.PlaybackInfo info = controller.getPlaybackInfo();
+        assertNotNull(info);
+        assertEquals(errorMsg, MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
+                info.getPlaybackType());
+        assertEquals(errorMsg, mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC),
+                info.getCurrentVolume());
+    }
+
+    @Test
+    @SmallTest
+    public void testGetSessionToken() throws Exception {
+        assertEquals(mSession.getSessionToken(), mSession.getController().getSessionToken());
+    }
+
+    /**
+     * Tests that a session can be created from the framework session object and the callback
+     * set on the framework session object before fromSession() is called works properly.
+     */
+    @Test
+    @SmallTest
+    public void testFromSession() throws Exception {
+        if (android.os.Build.VERSION.SDK_INT < 21) {
+            // MediaSession was introduced from API level 21.
+            return;
+        }
+        mCallback.reset(1);
+        mSession.setCallback(mCallback, new Handler(Looper.getMainLooper()));
+        MediaSessionCompat session = MediaSessionCompat.fromMediaSession(
+                getContext(), mSession.getMediaSession());
+        assertEquals(session.getSessionToken(), mSession.getSessionToken());
+
+        session.getController().getTransportControls().play();
+        mCallback.await(TIME_OUT_MS);
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+    }
+
+    /**
+     * Tests {@link MediaSessionCompat.Token} created in the constructor of MediaSessionCompat.
+     */
+    @Test
+    @SmallTest
+    public void testSessionToken() throws Exception {
+        MediaSessionCompat.Token sessionToken = mSession.getSessionToken();
+
+        assertNotNull(sessionToken);
+        assertEquals(0, sessionToken.describeContents());
+
+        // Test writeToParcel
+        Parcel p = Parcel.obtain();
+        sessionToken.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        MediaSessionCompat.Token token = MediaSessionCompat.Token.CREATOR.createFromParcel(p);
+        assertEquals(token, sessionToken);
+        p.recycle();
+    }
+
+    /**
+     * Tests {@link MediaSessionCompat.QueueItem}.
+     */
+    @Test
+    @SmallTest
+    public void testQueueItem() {
+        MediaSessionCompat.QueueItem item = new MediaSessionCompat.QueueItem(
+                new MediaDescriptionCompat.Builder()
+                        .setMediaId(TEST_MEDIA_ID_1)
+                        .setTitle(TEST_MEDIA_TITLE_1)
+                        .build(),
+                TEST_QUEUE_ID_1);
+        assertEquals(TEST_QUEUE_ID_1, item.getQueueId());
+        assertEquals(TEST_MEDIA_ID_1, item.getDescription().getMediaId());
+        assertEquals(TEST_MEDIA_TITLE_1, item.getDescription().getTitle());
+        assertEquals(0, item.describeContents());
+
+        Parcel p = Parcel.obtain();
+        item.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        MediaSessionCompat.QueueItem other =
+                MediaSessionCompat.QueueItem.CREATOR.createFromParcel(p);
+        assertEquals(item.toString(), other.toString());
+        p.recycle();
+    }
+
+    /**
+     * Tests {@link MediaSessionCompat#setActive}.
+     */
+    @Test
+    @SmallTest
+    public void testSetActive() throws Exception {
+        mSession.setActive(true);
+        assertTrue(mSession.isActive());
+    }
+
+    @Test
+    @SmallTest
+    public void testGetPlaybackStateWithPositionUpdate() throws InterruptedException {
+        final long stateSetTime = SystemClock.elapsedRealtime();
+        PlaybackStateCompat stateIn = new PlaybackStateCompat.Builder()
+                .setState(PlaybackStateCompat.STATE_PLAYING, TEST_POSITION, TEST_PLAYBACK_SPEED,
+                        stateSetTime)
+                .build();
+        mSession.setPlaybackState(stateIn);
+
+        final long waitDuration = 100L;
+        Thread.sleep(waitDuration);
+
+        final long expectedUpdateTime = waitDuration + stateSetTime;
+        final long expectedPosition = (long) (TEST_PLAYBACK_SPEED * waitDuration) + TEST_POSITION;
+
+        final double updateTimeTolerance = 50L;
+        final double positionTolerance = updateTimeTolerance * TEST_PLAYBACK_SPEED;
+
+        PlaybackStateCompat stateOut = mSession.getController().getPlaybackState();
+        assertEquals(expectedUpdateTime, stateOut.getLastPositionUpdateTime(), updateTimeTolerance);
+        assertEquals(expectedPosition, stateOut.getPosition(), positionTolerance);
+
+        // Compare the result with MediaController.getPlaybackState().
+        if (Build.VERSION.SDK_INT >= 21) {
+            MediaController controller = new MediaController(
+                    getContext(), (MediaSession.Token) mSession.getSessionToken().getToken());
+            PlaybackState state = controller.getPlaybackState();
+            assertEquals(state.getLastPositionUpdateTime(), stateOut.getLastPositionUpdateTime(),
+                    updateTimeTolerance);
+            assertEquals(state.getPosition(), stateOut.getPosition(), positionTolerance);
+        }
+    }
+
+    /**
+     * Tests {@link MediaSessionCompat#setCallback} with {@code null}.
+     * No callback should be called once {@code setCallback(null)} is done.
+     */
+    @Test
+    @SmallTest
+    public void testSetCallbackWithNull() throws Exception {
+        mSession.setActive(true);
+        mCallback.reset(1);
+        callTransportControlsMethod(PLAY, null, getContext(), mSession.getSessionToken());
+        mSession.setCallback(null, mHandler);
+        mCallback.await(WAIT_TIME_FOR_NO_RESPONSE_MS);
+        assertEquals("Callback shouldn't be called.", 0, mCallback.mOnPlayCalledCount);
+    }
+
     @Test
     @SmallTest
     public void testSendCommand() throws Exception {
-        synchronized (mWaitLock) {
-            mCallback.reset();
+        mCallback.reset(1);
 
-            Bundle arguments = new Bundle();
-            arguments.putString("command", TEST_COMMAND);
-            Bundle extras = new Bundle();
-            extras.putString(TEST_KEY, TEST_VALUE);
-            arguments.putBundle("extras", extras);
-            callMediaControllerMethod(
-                    SEND_COMMAND, arguments, getContext(), mSession.getSessionToken());
+        Bundle arguments = new Bundle();
+        arguments.putString("command", TEST_COMMAND);
+        Bundle extras = new Bundle();
+        extras.putString(TEST_KEY, TEST_VALUE);
+        arguments.putBundle("extras", extras);
+        callMediaControllerMethod(
+                SEND_COMMAND, arguments, getContext(), mSession.getSessionToken());
 
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCommandCalled);
-            assertNotNull(mCallback.mCommandCallback);
-            assertEquals(TEST_COMMAND, mCallback.mCommand);
-            assertBundleEquals(extras, mCallback.mExtras);
-        }
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnCommandCalled);
+        assertNotNull(mCallback.mCommandCallback);
+        assertEquals(TEST_COMMAND, mCallback.mCommand);
+        assertBundleEquals(extras, mCallback.mExtras);
     }
 
     @Test
     @SmallTest
     public void testAddRemoveQueueItems() throws Exception {
-        final String mediaId1 = "media_id_1";
-        final String mediaTitle1 = "media_title_1";
+        mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS);
+
         MediaDescriptionCompat itemDescription1 = new MediaDescriptionCompat.Builder()
-                .setMediaId(mediaId1).setTitle(mediaTitle1).build();
+                .setMediaId(TEST_MEDIA_ID_1).setTitle(TEST_MEDIA_TITLE_1).build();
 
-        final String mediaId2 = "media_id_2";
-        final String mediaTitle2 = "media_title_2";
         MediaDescriptionCompat itemDescription2 = new MediaDescriptionCompat.Builder()
-                .setMediaId(mediaId2).setTitle(mediaTitle2).build();
+                .setMediaId(TEST_MEDIA_ID_2).setTitle(TEST_MEDIA_TITLE_2).build();
 
-        synchronized (mWaitLock) {
-            mCallback.reset();
-            callMediaControllerMethod(
-                    ADD_QUEUE_ITEM, itemDescription1, getContext(), mSession.getSessionToken());
+        mCallback.reset(1);
+        callMediaControllerMethod(
+                ADD_QUEUE_ITEM, itemDescription1, getContext(), mSession.getSessionToken());
 
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnAddQueueItemCalled);
-            assertEquals(-1, mCallback.mQueueIndex);
-            assertEquals(mediaId1, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle1, mCallback.mQueueDescription.getTitle());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnAddQueueItemCalled);
+        assertEquals(-1, mCallback.mQueueIndex);
+        assertEquals(TEST_MEDIA_ID_1, mCallback.mQueueDescription.getMediaId());
+        assertEquals(TEST_MEDIA_TITLE_1, mCallback.mQueueDescription.getTitle());
 
-            mCallback.reset();
-            Bundle arguments = new Bundle();
-            arguments.putParcelable("description", itemDescription2);
-            arguments.putInt("index", 0);
-            callMediaControllerMethod(
-                    ADD_QUEUE_ITEM_WITH_INDEX, arguments, getContext(), mSession.getSessionToken());
+        mCallback.reset(1);
+        Bundle arguments = new Bundle();
+        arguments.putParcelable("description", itemDescription2);
+        arguments.putInt("index", 0);
+        callMediaControllerMethod(
+                ADD_QUEUE_ITEM_WITH_INDEX, arguments, getContext(), mSession.getSessionToken());
 
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnAddQueueItemAtCalled);
-            assertEquals(0, mCallback.mQueueIndex);
-            assertEquals(mediaId2, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle2, mCallback.mQueueDescription.getTitle());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnAddQueueItemAtCalled);
+        assertEquals(0, mCallback.mQueueIndex);
+        assertEquals(TEST_MEDIA_ID_2, mCallback.mQueueDescription.getMediaId());
+        assertEquals(TEST_MEDIA_TITLE_2, mCallback.mQueueDescription.getTitle());
 
-            mCallback.reset();
-            callMediaControllerMethod(
-                    REMOVE_QUEUE_ITEM, itemDescription1, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRemoveQueueItemCalled);
-            assertEquals(mediaId1, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle1, mCallback.mQueueDescription.getTitle());
-        }
+        mCallback.reset(1);
+        callMediaControllerMethod(
+                REMOVE_QUEUE_ITEM, itemDescription1, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnRemoveQueueItemCalled);
+        assertEquals(TEST_MEDIA_ID_1, mCallback.mQueueDescription.getMediaId());
+        assertEquals(TEST_MEDIA_TITLE_1, mCallback.mQueueDescription.getTitle());
     }
 
     @Test
     @SmallTest
     public void testTransportControlsAndMediaSessionCallback() throws Exception {
+        mCallback.reset(1);
+        callTransportControlsMethod(PLAY, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(PAUSE, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPauseCalled);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(STOP, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnStopCalled);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(
+                FAST_FORWARD, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnFastForwardCalled);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(REWIND, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnRewindCalled);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(
+                SKIP_TO_PREVIOUS, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSkipToPreviousCalled);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(
+                SKIP_TO_NEXT, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSkipToNextCalled);
+
+        mCallback.reset(1);
+        final long seekPosition = 1000;
+        callTransportControlsMethod(
+                SEEK_TO, seekPosition, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSeekToCalled);
+        assertEquals(seekPosition, mCallback.mSeekPosition);
+
+        mCallback.reset(1);
+        final RatingCompat rating =
+                RatingCompat.newStarRating(RatingCompat.RATING_5_STARS, 3f);
+        callTransportControlsMethod(
+                SET_RATING, rating, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSetRatingCalled);
+        assertEquals(rating.getRatingStyle(), mCallback.mRating.getRatingStyle());
+        assertEquals(rating.getStarRating(), mCallback.mRating.getStarRating(), DELTA);
+
+        mCallback.reset(1);
+        final Bundle extras = new Bundle();
+        extras.putString(TEST_KEY, TEST_VALUE);
+        Bundle arguments = new Bundle();
+        arguments.putString("mediaId", TEST_MEDIA_ID_1);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PLAY_FROM_MEDIA_ID, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPlayFromMediaIdCalled);
+        assertEquals(TEST_MEDIA_ID_1, mCallback.mMediaId);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        final String query = "test-query";
+        arguments = new Bundle();
+        arguments.putString("query", query);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PLAY_FROM_SEARCH, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPlayFromSearchCalled);
+        assertEquals(query, mCallback.mQuery);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        final Uri uri = Uri.parse("content://test/popcorn.mod");
+        arguments = new Bundle();
+        arguments.putParcelable("uri", uri);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PLAY_FROM_URI, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPlayFromUriCalled);
+        assertEquals(uri, mCallback.mUri);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        final String action = "test-action";
+        arguments = new Bundle();
+        arguments.putString("action", action);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                SEND_CUSTOM_ACTION, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnCustomActionCalled);
+        assertEquals(action, mCallback.mAction);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        mCallback.mOnCustomActionCalled = false;
+        final PlaybackStateCompat.CustomAction customAction =
+                new PlaybackStateCompat.CustomAction.Builder(action, action, -1)
+                        .setExtras(extras)
+                        .build();
+        arguments = new Bundle();
+        arguments.putParcelable("action", customAction);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                SEND_CUSTOM_ACTION_PARCELABLE,
+                arguments,
+                getContext(),
+                mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnCustomActionCalled);
+        assertEquals(action, mCallback.mAction);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        final long queueItemId = 1000;
+        callTransportControlsMethod(
+                SKIP_TO_QUEUE_ITEM, queueItemId, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSkipToQueueItemCalled);
+        assertEquals(queueItemId, mCallback.mQueueItemId);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(
+                PREPARE, null, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPrepareCalled);
+
+        mCallback.reset(1);
+        arguments = new Bundle();
+        arguments.putString("mediaId", TEST_MEDIA_ID_2);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PREPARE_FROM_MEDIA_ID, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPrepareFromMediaIdCalled);
+        assertEquals(TEST_MEDIA_ID_2, mCallback.mMediaId);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        arguments = new Bundle();
+        arguments.putString("query", query);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PREPARE_FROM_SEARCH, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPrepareFromSearchCalled);
+        assertEquals(query, mCallback.mQuery);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        arguments = new Bundle();
+        arguments.putParcelable("uri", uri);
+        arguments.putBundle("extras", extras);
+        callTransportControlsMethod(
+                PREPARE_FROM_URI, arguments, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnPrepareFromUriCalled);
+        assertEquals(uri, mCallback.mUri);
+        assertBundleEquals(extras, mCallback.mExtras);
+
+        mCallback.reset(1);
+        callTransportControlsMethod(
+                SET_CAPTIONING_ENABLED, ENABLED, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSetCaptioningEnabledCalled);
+        assertEquals(ENABLED, mCallback.mCaptioningEnabled);
+
+        mCallback.reset(1);
+        final int repeatMode = PlaybackStateCompat.REPEAT_MODE_ALL;
+        callTransportControlsMethod(
+                SET_REPEAT_MODE, repeatMode, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSetRepeatModeCalled);
+        assertEquals(repeatMode, mCallback.mRepeatMode);
+
+        mCallback.reset(1);
+        final int shuffleMode = PlaybackStateCompat.SHUFFLE_MODE_ALL;
+        callTransportControlsMethod(
+                SET_SHUFFLE_MODE, shuffleMode, getContext(), mSession.getSessionToken());
+        mCallback.await(TIME_OUT_MS);
+        assertTrue(mCallback.mOnSetShuffleModeCalled);
+        assertEquals(shuffleMode, mCallback.mShuffleMode);
+    }
+
+    /**
+     * Tests {@link MediaSessionCompat.Callback#onMediaButtonEvent}.
+     */
+    @Test
+    @MediumTest
+    public void testCallbackOnMediaButtonEvent() throws Exception {
+        mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
+        mSession.setActive(true);
+
+        final long waitTimeForNoResponse = 30L;
+
+        Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON)
+                .setComponent(new ComponentName(getContext(), getContext().getClass()));
+        PendingIntent pi = PendingIntent.getBroadcast(getContext(), 0, mediaButtonIntent, 0);
+        mSession.setMediaButtonReceiver(pi);
+
+        // Set state to STATE_PLAYING to get higher priority.
+        setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PAUSE);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnPauseCalled);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_NEXT);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnSkipToNextCalled);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnSkipToPreviousCalled);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnStopCalled);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnFastForwardCalled);
+
+        mCallback.reset(1);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_REWIND);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnRewindCalled);
+
+        // Test PLAY_PAUSE button twice.
+        // First, send PLAY_PAUSE button event while in STATE_PAUSED.
+        mCallback.reset(1);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+
+        // Next, send PLAY_PAUSE button event while in STATE_PLAYING.
+        mCallback.reset(1);
+        setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertTrue(mCallback.mOnPauseCalled);
+
+        // Double tap of PLAY_PAUSE is the next track.
+        mCallback.reset(2);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        assertFalse(mCallback.await(waitTimeForNoResponse));
+        assertTrue(mCallback.mOnSkipToNextCalled);
+        assertEquals(0, mCallback.mOnPlayCalledCount);
+        assertFalse(mCallback.mOnPauseCalled);
+
+        // Test PLAY_PAUSE button long-press.
+        // It should be the same as the single short-press.
+        mCallback.reset(1);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+
+        // Double tap of PLAY_PAUSE should be handled once.
+        // Initial down event from the second press within double tap time-out will make
+        // onSkipToNext() to be called, so further down events shouldn't be handled again.
+        mCallback.reset(2);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
+        assertFalse(mCallback.await(waitTimeForNoResponse));
+        assertTrue(mCallback.mOnSkipToNextCalled);
+        assertEquals(0, mCallback.mOnPlayCalledCount);
+        assertFalse(mCallback.mOnPauseCalled);
+
+        // Test PLAY_PAUSE button long-press followed by the short-press.
+        // Initial long-press of the PLAY_PAUSE is considered as the single short-press already,
+        // so it shouldn't be used as the first tap of the double tap.
+        mCallback.reset(2);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        // onMediaButtonEvent() calls either onPlay() or onPause() depending on the playback state,
+        // so onPlay() should be called once and onPause() also should be called once.
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+        assertTrue(mCallback.mOnPauseCalled);
+        assertFalse(mCallback.mOnSkipToNextCalled);
+
+        // If another media key is pressed while the double tap of PLAY_PAUSE,
+        // PLAY_PAUSE should be handled as normal.
+        mCallback.reset(3);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertFalse(mCallback.mOnSkipToNextCalled);
+        assertTrue(mCallback.mOnStopCalled);
+        assertEquals(2, mCallback.mOnPlayCalledCount);
+
+        // Test if media keys are handled in order.
+        mCallback.reset(2);
+        setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
+        assertTrue(mCallback.await(TIME_OUT_MS));
+        assertEquals(1, mCallback.mOnPlayCalledCount);
+        assertTrue(mCallback.mOnStopCalled);
         synchronized (mWaitLock) {
-            mCallback.reset();
-            callTransportControlsMethod(PLAY, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(PAUSE, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPauseCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(STOP, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnStopCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(
-                    FAST_FORWARD, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnFastForwardCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(REWIND, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRewindCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(
-                    SKIP_TO_PREVIOUS, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSkipToPreviousCalled);
-
-            mCallback.reset();
-            callTransportControlsMethod(
-                    SKIP_TO_NEXT, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSkipToNextCalled);
-
-            mCallback.reset();
-            final long seekPosition = 1000;
-            callTransportControlsMethod(
-                    SEEK_TO, seekPosition, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSeekToCalled);
-            assertEquals(seekPosition, mCallback.mSeekPosition);
-
-            mCallback.reset();
-            final RatingCompat rating =
-                    RatingCompat.newStarRating(RatingCompat.RATING_5_STARS, 3f);
-            callTransportControlsMethod(
-                    SET_RATING, rating, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetRatingCalled);
-            assertEquals(rating.getRatingStyle(), mCallback.mRating.getRatingStyle());
-            assertEquals(rating.getStarRating(), mCallback.mRating.getStarRating(), DELTA);
-
-            mCallback.reset();
-            final String mediaId = "test-media-id";
-            final Bundle extras = new Bundle();
-            extras.putString(TEST_KEY, TEST_VALUE);
-            Bundle arguments = new Bundle();
-            arguments.putString("mediaId", mediaId);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PLAY_FROM_MEDIA_ID, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayFromMediaIdCalled);
-            assertEquals(mediaId, mCallback.mMediaId);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            final String query = "test-query";
-            arguments = new Bundle();
-            arguments.putString("query", query);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PLAY_FROM_SEARCH, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayFromSearchCalled);
-            assertEquals(query, mCallback.mQuery);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            final Uri uri = Uri.parse("content://test/popcorn.mod");
-            arguments = new Bundle();
-            arguments.putParcelable("uri", uri);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PLAY_FROM_URI, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPlayFromUriCalled);
-            assertEquals(uri, mCallback.mUri);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            final String action = "test-action";
-            arguments = new Bundle();
-            arguments.putString("action", action);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    SEND_CUSTOM_ACTION, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCustomActionCalled);
-            assertEquals(action, mCallback.mAction);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            mCallback.mOnCustomActionCalled = false;
-            final PlaybackStateCompat.CustomAction customAction =
-                    new PlaybackStateCompat.CustomAction.Builder(action, action, -1)
-                            .setExtras(extras)
-                            .build();
-            arguments = new Bundle();
-            arguments.putParcelable("action", customAction);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    SEND_CUSTOM_ACTION_PARCELABLE,
-                    arguments,
-                    getContext(),
-                    mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnCustomActionCalled);
-            assertEquals(action, mCallback.mAction);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            final long queueItemId = 1000;
-            callTransportControlsMethod(
-                    SKIP_TO_QUEUE_ITEM, queueItemId, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSkipToQueueItemCalled);
-            assertEquals(queueItemId, mCallback.mQueueItemId);
-
-            mCallback.reset();
-            callTransportControlsMethod(
-                    PREPARE, null, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareCalled);
-
-            mCallback.reset();
-            arguments = new Bundle();
-            arguments.putString("mediaId", mediaId);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PREPARE_FROM_MEDIA_ID, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareFromMediaIdCalled);
-            assertEquals(mediaId, mCallback.mMediaId);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            arguments = new Bundle();
-            arguments.putString("query", query);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PREPARE_FROM_SEARCH, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareFromSearchCalled);
-            assertEquals(query, mCallback.mQuery);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            arguments = new Bundle();
-            arguments.putParcelable("uri", uri);
-            arguments.putBundle("extras", extras);
-            callTransportControlsMethod(
-                    PREPARE_FROM_URI, arguments, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnPrepareFromUriCalled);
-            assertEquals(uri, mCallback.mUri);
-            assertBundleEquals(extras, mCallback.mExtras);
-
-            mCallback.reset();
-            callTransportControlsMethod(
-                    SET_CAPTIONING_ENABLED, ENABLED, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetCaptioningEnabledCalled);
-            assertEquals(ENABLED, mCallback.mCaptioningEnabled);
-
-            mCallback.reset();
-            final int repeatMode = PlaybackStateCompat.REPEAT_MODE_ALL;
-            callTransportControlsMethod(
-                    SET_REPEAT_MODE, repeatMode, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetRepeatModeCalled);
-            assertEquals(repeatMode, mCallback.mRepeatMode);
-
-            mCallback.reset();
-            final int shuffleMode = PlaybackStateCompat.SHUFFLE_MODE_ALL;
-            callTransportControlsMethod(
-                    SET_SHUFFLE_MODE, shuffleMode, getContext(), mSession.getSessionToken());
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetShuffleModeCalled);
-            assertEquals(shuffleMode, mCallback.mShuffleMode);
+            assertEquals(PlaybackStateCompat.STATE_STOPPED,
+                    mSession.getController().getPlaybackState().getState());
         }
     }
 
+    @Test
+    @SmallTest
+    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;
+        }
+        VolumeProviderCompat vp =
+                new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 11, 5) {
+                    @Override
+                    public void onSetVolumeTo(int volume) {
+                        synchronized (mWaitLock) {
+                            setCurrentVolume(volume);
+                            mWaitLock.notify();
+                        }
+                    }
+
+                    @Override
+                    public void onAdjustVolume(int direction) {
+                        synchronized (mWaitLock) {
+                            switch (direction) {
+                                case AudioManager.ADJUST_LOWER:
+                                    setCurrentVolume(getCurrentVolume() - 1);
+                                    break;
+                                case AudioManager.ADJUST_RAISE:
+                                    setCurrentVolume(getCurrentVolume() + 1);
+                                    break;
+                            }
+                            mWaitLock.notify();
+                        }
+                    }
+                };
+        mSession.setPlaybackToRemote(vp);
+
+        synchronized (mWaitLock) {
+            // test setVolumeTo
+            callMediaControllerMethod(SET_VOLUME_TO,
+                    7 /* Target volume */, getContext(), mSession.getSessionToken());
+            mWaitLock.wait(TIME_OUT_MS);
+            assertEquals(7, vp.getCurrentVolume());
+
+            // test adjustVolume
+            callMediaControllerMethod(ADJUST_VOLUME,
+                    AudioManager.ADJUST_LOWER, getContext(), mSession.getSessionToken());
+            mWaitLock.wait(TIME_OUT_MS);
+            assertEquals(6, vp.getCurrentVolume());
+
+            callMediaControllerMethod(ADJUST_VOLUME,
+                    AudioManager.ADJUST_RAISE, getContext(), mSession.getSessionToken());
+            mWaitLock.wait(TIME_OUT_MS);
+            assertEquals(7, vp.getCurrentVolume());
+        }
+    }
+
+    private void setPlaybackState(int state) {
+        final long allActions = PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE
+                | PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_STOP
+                | PlaybackStateCompat.ACTION_SKIP_TO_NEXT
+                | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
+                | PlaybackStateCompat.ACTION_FAST_FORWARD | PlaybackStateCompat.ACTION_REWIND;
+        PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder().setActions(allActions)
+                .setState(state, 0L, 0.0f).build();
+        synchronized (mWaitLock) {
+            mSession.setPlaybackState(playbackState);
+        }
+    }
+
+    private void sendMediaKeyInputToController(int keyCode) {
+        sendMediaKeyInputToController(keyCode, false);
+    }
+
+    private void sendMediaKeyInputToController(int keyCode, boolean isLongPress) {
+        MediaControllerCompat controller = mSession.getController();
+        long currentTimeMs = System.currentTimeMillis();
+        KeyEvent down = new KeyEvent(
+                currentTimeMs, currentTimeMs, KeyEvent.ACTION_DOWN, keyCode, 0);
+        controller.dispatchMediaButtonEvent(down);
+        if (isLongPress) {
+            KeyEvent longPress = new KeyEvent(
+                    currentTimeMs, System.currentTimeMillis(), KeyEvent.ACTION_DOWN, keyCode, 1);
+            controller.dispatchMediaButtonEvent(longPress);
+        }
+        KeyEvent up = new KeyEvent(
+                currentTimeMs, System.currentTimeMillis(), KeyEvent.ACTION_UP, keyCode, 0);
+        controller.dispatchMediaButtonEvent(up);
+    }
+
     private class MediaSessionCallback extends MediaSessionCompat.Callback {
+        private CountDownLatch mLatch;
         private long mSeekPosition;
         private long mQueueItemId;
         private RatingCompat mRating;
@@ -409,7 +825,7 @@
         private MediaDescriptionCompat mQueueDescription;
         private List<MediaSessionCompat.QueueItem> mQueue = new ArrayList<>();
 
-        private boolean mOnPlayCalled;
+        private int mOnPlayCalledCount;
         private boolean mOnPauseCalled;
         private boolean mOnStopCalled;
         private boolean mOnFastForwardCalled;
@@ -435,7 +851,8 @@
         private boolean mOnAddQueueItemAtCalled;
         private boolean mOnRemoveQueueItemCalled;
 
-        public void reset() {
+        public void reset(int count) {
+            mLatch = new CountDownLatch(count);
             mSeekPosition = -1;
             mQueueItemId = -1;
             mRating = null;
@@ -452,7 +869,7 @@
             mQueueIndex = -1;
             mQueueDescription = null;
 
-            mOnPlayCalled = false;
+            mOnPlayCalledCount = 0;
             mOnPauseCalled = false;
             mOnStopCalled = false;
             mOnFastForwardCalled = false;
@@ -479,242 +896,203 @@
             mOnRemoveQueueItemCalled = false;
         }
 
+        public boolean await(long timeoutMs) {
+            try {
+                return mLatch.await(timeoutMs, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                return false;
+            }
+        }
+
         @Override
         public void onPlay() {
-            synchronized (mWaitLock) {
-                mOnPlayCalled = true;
-                mWaitLock.notify();
-            }
+            mOnPlayCalledCount++;
+            setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
+            mLatch.countDown();
         }
 
         @Override
         public void onPause() {
-            synchronized (mWaitLock) {
-                mOnPauseCalled = true;
-                mWaitLock.notify();
-            }
+            mOnPauseCalled = true;
+            setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
+            mLatch.countDown();
         }
 
         @Override
         public void onStop() {
-            synchronized (mWaitLock) {
-                mOnStopCalled = true;
-                mWaitLock.notify();
-            }
+            mOnStopCalled = true;
+            setPlaybackState(PlaybackStateCompat.STATE_STOPPED);
+            mLatch.countDown();
         }
 
         @Override
         public void onFastForward() {
-            synchronized (mWaitLock) {
-                mOnFastForwardCalled = true;
-                mWaitLock.notify();
-            }
+            mOnFastForwardCalled = true;
+            mLatch.countDown();
         }
 
         @Override
         public void onRewind() {
-            synchronized (mWaitLock) {
-                mOnRewindCalled = true;
-                mWaitLock.notify();
-            }
+            mOnRewindCalled = true;
+            mLatch.countDown();
         }
 
         @Override
         public void onSkipToPrevious() {
-            synchronized (mWaitLock) {
-                mOnSkipToPreviousCalled = true;
-                mWaitLock.notify();
-            }
+            mOnSkipToPreviousCalled = true;
+            mLatch.countDown();
         }
 
         @Override
         public void onSkipToNext() {
-            synchronized (mWaitLock) {
-                mOnSkipToNextCalled = true;
-                mWaitLock.notify();
-            }
+            mOnSkipToNextCalled = true;
+            mLatch.countDown();
         }
 
         @Override
         public void onSeekTo(long pos) {
-            synchronized (mWaitLock) {
-                mOnSeekToCalled = true;
-                mSeekPosition = pos;
-                mWaitLock.notify();
-            }
+            mOnSeekToCalled = true;
+            mSeekPosition = pos;
+            mLatch.countDown();
         }
 
         @Override
         public void onSetRating(RatingCompat rating) {
-            synchronized (mWaitLock) {
-                mOnSetRatingCalled = true;
-                mRating = rating;
-                mWaitLock.notify();
-            }
+            mOnSetRatingCalled = true;
+            mRating = rating;
+            mLatch.countDown();
         }
 
         @Override
         public void onPlayFromMediaId(String mediaId, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPlayFromMediaIdCalled = true;
-                mMediaId = mediaId;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPlayFromMediaIdCalled = true;
+            mMediaId = mediaId;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onPlayFromSearch(String query, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPlayFromSearchCalled = true;
-                mQuery = query;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPlayFromSearchCalled = true;
+            mQuery = query;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onPlayFromUri(Uri uri, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPlayFromUriCalled = true;
-                mUri = uri;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPlayFromUriCalled = true;
+            mUri = uri;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onCustomAction(String action, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnCustomActionCalled = true;
-                mAction = action;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnCustomActionCalled = true;
+            mAction = action;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onSkipToQueueItem(long id) {
-            synchronized (mWaitLock) {
-                mOnSkipToQueueItemCalled = true;
-                mQueueItemId = id;
-                mWaitLock.notify();
-            }
+            mOnSkipToQueueItemCalled = true;
+            mQueueItemId = id;
+            mLatch.countDown();
         }
 
         @Override
         public void onCommand(String command, Bundle extras, ResultReceiver cb) {
-            synchronized (mWaitLock) {
-                mOnCommandCalled = true;
-                mCommand = command;
-                mExtras = extras;
-                mCommandCallback = cb;
-                mWaitLock.notify();
-            }
+            mOnCommandCalled = true;
+            mCommand = command;
+            mExtras = extras;
+            mCommandCallback = cb;
+            mLatch.countDown();
         }
 
         @Override
         public void onPrepare() {
-            synchronized (mWaitLock) {
-                mOnPrepareCalled = true;
-                mWaitLock.notify();
-            }
+            mOnPrepareCalled = true;
+            mLatch.countDown();
         }
 
         @Override
         public void onPrepareFromMediaId(String mediaId, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPrepareFromMediaIdCalled = true;
-                mMediaId = mediaId;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPrepareFromMediaIdCalled = true;
+            mMediaId = mediaId;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onPrepareFromSearch(String query, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPrepareFromSearchCalled = true;
-                mQuery = query;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPrepareFromSearchCalled = true;
+            mQuery = query;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onPrepareFromUri(Uri uri, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnPrepareFromUriCalled = true;
-                mUri = uri;
-                mExtras = extras;
-                mWaitLock.notify();
-            }
+            mOnPrepareFromUriCalled = true;
+            mUri = uri;
+            mExtras = extras;
+            mLatch.countDown();
         }
 
         @Override
         public void onSetRepeatMode(int repeatMode) {
-            synchronized (mWaitLock) {
-                mOnSetRepeatModeCalled = true;
-                mRepeatMode = repeatMode;
-                mWaitLock.notify();
-            }
+            mOnSetRepeatModeCalled = true;
+            mRepeatMode = repeatMode;
+            mLatch.countDown();
         }
 
         @Override
         public void onAddQueueItem(MediaDescriptionCompat description) {
-            synchronized (mWaitLock) {
-                mOnAddQueueItemCalled = true;
-                mQueueDescription = description;
-                mQueue.add(new MediaSessionCompat.QueueItem(description, mQueue.size()));
-                mSession.setQueue(mQueue);
-                mWaitLock.notify();
-            }
+            mOnAddQueueItemCalled = true;
+            mQueueDescription = description;
+            mQueue.add(new MediaSessionCompat.QueueItem(description, mQueue.size()));
+            mSession.setQueue(mQueue);
+            mLatch.countDown();
         }
 
         @Override
         public void onAddQueueItem(MediaDescriptionCompat description, int index) {
-            synchronized (mWaitLock) {
-                mOnAddQueueItemAtCalled = true;
-                mQueueIndex = index;
-                mQueueDescription = description;
-                mQueue.add(index, new MediaSessionCompat.QueueItem(description, mQueue.size()));
-                mSession.setQueue(mQueue);
-                mWaitLock.notify();
-            }
+            mOnAddQueueItemAtCalled = true;
+            mQueueIndex = index;
+            mQueueDescription = description;
+            mQueue.add(index, new MediaSessionCompat.QueueItem(description, mQueue.size()));
+            mSession.setQueue(mQueue);
+            mLatch.countDown();
         }
 
         @Override
         public void onRemoveQueueItem(MediaDescriptionCompat description) {
-            synchronized (mWaitLock) {
-                mOnRemoveQueueItemCalled = true;
-                String mediaId = description.getMediaId();
-                for (int i = mQueue.size() - 1; i >= 0; --i) {
-                    if (mediaId.equals(mQueue.get(i).getDescription().getMediaId())) {
-                        mQueueDescription = mQueue.remove(i).getDescription();
-                        mSession.setQueue(mQueue);
-                        break;
-                    }
+            mOnRemoveQueueItemCalled = true;
+            String mediaId = description.getMediaId();
+            for (int i = mQueue.size() - 1; i >= 0; --i) {
+                if (mediaId.equals(mQueue.get(i).getDescription().getMediaId())) {
+                    mQueueDescription = mQueue.remove(i).getDescription();
+                    mSession.setQueue(mQueue);
+                    break;
                 }
-                mWaitLock.notify();
             }
+            mLatch.countDown();
         }
 
         @Override
         public void onSetCaptioningEnabled(boolean enabled) {
-            synchronized (mWaitLock) {
-                mOnSetCaptioningEnabledCalled = true;
-                mCaptioningEnabled = enabled;
-                mWaitLock.notify();
-            }
+            mOnSetCaptioningEnabledCalled = true;
+            mCaptioningEnabled = enabled;
+            mLatch.countDown();
         }
 
         @Override
         public void onSetShuffleMode(int shuffleMode) {
-            synchronized (mWaitLock) {
-                mOnSetShuffleModeCalled = true;
-                mShuffleMode = shuffleMode;
-                mWaitLock.notify();
-            }
+            mOnSetShuffleModeCalled = true;
+            mShuffleMode = shuffleMode;
+            mLatch.countDown();
         }
     }
 }
diff --git a/media-compat/version-compat-tests/previous/service/tests/src/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java b/media-compat/version-compat-tests/previous/service/tests/src/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java
index 61c33f8..7032a0b 100644
--- a/media-compat/version-compat-tests/previous/service/tests/src/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java
+++ b/media-compat/version-compat-tests/previous/service/tests/src/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java
@@ -22,16 +22,20 @@
 import static android.support.mediacompat.testlib.MediaBrowserConstants.EXTRAS_VALUE;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_CHILDREN;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_CHILDREN_DELAYED;
+import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_INCLUDE_METADATA;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_INVALID;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_ROOT;
+import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_METADATA;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY_FOR_ERROR;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY_FOR_NO_RESULT;
 
 import android.os.Bundle;
+import android.support.annotation.NonNull;
 import android.support.v4.media.MediaBrowserCompat.MediaItem;
 import android.support.v4.media.MediaBrowserServiceCompat;
 import android.support.v4.media.MediaDescriptionCompat;
+import android.support.v4.media.MediaMetadataCompat;
 import android.support.v4.media.session.MediaSessionCompat;
 
 import junit.framework.Assert;
@@ -79,25 +83,43 @@
     }
 
     @Override
-    public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
+    public void onLoadChildren(final String parentId, final Result<List<MediaItem>> result) {
         List<MediaItem> mediaItems = new ArrayList<>();
-        if (MEDIA_ID_ROOT.equals(parentMediaId)) {
+        if (MEDIA_ID_ROOT.equals(parentId)) {
             Bundle rootHints = getBrowserRootHints();
             for (String id : MEDIA_ID_CHILDREN) {
                 mediaItems.add(createMediaItem(id));
             }
             result.sendResult(mediaItems);
-        } else if (MEDIA_ID_CHILDREN_DELAYED.equals(parentMediaId)) {
+        } else if (MEDIA_ID_CHILDREN_DELAYED.equals(parentId)) {
             Assert.assertNull(mPendingLoadChildrenResult);
             mPendingLoadChildrenResult = result;
             mPendingRootHints = getBrowserRootHints();
             result.detach();
-        } else if (MEDIA_ID_INVALID.equals(parentMediaId)) {
+        } else if (MEDIA_ID_INVALID.equals(parentId)) {
             result.sendResult(null);
         }
     }
 
     @Override
+    public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaItem>> result,
+            @NonNull Bundle options) {
+        if (MEDIA_ID_INCLUDE_METADATA.equals(parentId)) {
+            // Test unparcelling the Bundle.
+            MediaMetadataCompat metadata = options.getParcelable(MEDIA_METADATA);
+            if (metadata == null) {
+                super.onLoadChildren(parentId, result, options);
+            } else {
+                List<MediaItem> mediaItems = new ArrayList<>();
+                mediaItems.add(new MediaItem(metadata.getDescription(), MediaItem.FLAG_PLAYABLE));
+                result.sendResult(mediaItems);
+            }
+        } else {
+            super.onLoadChildren(parentId, result, options);
+        }
+    }
+
+    @Override
     public void onLoadItem(String itemId, Result<MediaItem> result) {
         if (MEDIA_ID_CHILDREN_DELAYED.equals(itemId)) {
             mPendingLoadItemResult = result;
diff --git a/media-compat/version-compat-tests/runtest.sh b/media-compat/version-compat-tests/runtest.sh
index d1a3c3a..817cd33 100755
--- a/media-compat/version-compat-tests/runtest.sh
+++ b/media-compat/version-compat-tests/runtest.sh
@@ -19,17 +19,28 @@
 #  - Exactly one test device should be connected.
 #
 # TODO:
-#  - The test result should be easily seen. (Can we report the results to the Sponge?)
-#  - Run specific combination of the test (e.g. Only want to test ToT-ToT)
-#  - Run specific test class / method by using argument.
 #  - Support simultaneous multiple device connection
 
-# Usage './runtest.sh'
+# Usage './runtest.sh <version_combination_number> [option]'
 
 CLIENT_MODULE_NAME_BASE="support-media-compat-test-client"
 SERVICE_MODULE_NAME_BASE="support-media-compat-test-service"
 CLIENT_VERSION=""
 SERVICE_VERSION=""
+OPTION_TEST_TARGET=""
+
+function printRunTestUsage() {
+  echo "Usage: ./runtest.sh <version_combination_number> [option]"
+  echo ""
+  echo "Version combination number:"
+  echo "    1. Client-ToT             / Service-ToT"
+  echo "    2. Client-ToT             / Service-Latest release"
+  echo "    3. Client-Latest release  / Service-ToT"
+  echo "    4. Run all of the above"
+  echo ""
+  echo "Option:"
+  echo "    -t <class/method>: Only run the specific test class/method."
+}
 
 function runTest() {
   echo "Running test: Client-$CLIENT_VERSION / Service-$SERVICE_VERSION"
@@ -38,42 +49,59 @@
   local SERVICE_MODULE_NAME="$SERVICE_MODULE_NAME_BASE$([ "$SERVICE_VERSION" = "tot" ] || echo "-previous")"
 
   # Build test apks
-  ./gradlew $CLIENT_MODULE_NAME:assembleDebugAndroidTest || (echo "Build failed. Aborting."; return 1)
-  ./gradlew $SERVICE_MODULE_NAME:assembleDebugAndroidTest || (echo "Build failed. Aborting."; return 1)
+  ./gradlew $CLIENT_MODULE_NAME:assembleDebugAndroidTest || { echo "Build failed. Aborting."; exit 1; }
+  ./gradlew $SERVICE_MODULE_NAME:assembleDebugAndroidTest || { echo "Build failed. Aborting."; exit 1; }
 
   # Install the apks
-  adb install -r -d "../../out/dist/$CLIENT_MODULE_NAME.apk" || (echo "Apk installation failed. Aborting."; return 1)
-  adb install -r -d "../../out/dist/$SERVICE_MODULE_NAME.apk" || (echo "Apk installation failed. Aborting."; return 1)
+  adb install -r -d "../../out/dist/$CLIENT_MODULE_NAME.apk" || { echo "Apk installation failed. Aborting."; exit 1; }
+  adb install -r -d "../../out/dist/$SERVICE_MODULE_NAME.apk" || { echo "Apk installation failed. Aborting."; exit 1; }
 
   # Run the tests
+  local test_command="adb shell am instrument -w -e debug false -e client_version $CLIENT_VERSION -e service_version $SERVICE_VERSION"
+  local client_test_runner="android.support.mediacompat.client.test/android.support.test.runner.AndroidJUnitRunner"
+  local service_test_runner="android.support.mediacompat.service.test/android.support.test.runner.AndroidJUnitRunner"
+
   echo ">>>>>>>>>>>>>>>>>>>>>>>> Test Started: Client-$CLIENT_VERSION & Service-$SERVICE_VERSION <<<<<<<<<<<<<<<<<<<<<<<<"
-  adb shell am instrument -w -r -e package android.support.mediacompat.client -e debug false -e client_version $CLIENT_VERSION \
-     -e service_version $SERVICE_VERSION android.support.mediacompat.client.test/android.support.test.runner.AndroidJUnitRunner
-  adb shell am instrument -w -r -e package android.support.mediacompat.service -e debug false -e client_version $CLIENT_VERSION \
-     -e service_version $SERVICE_VERSION android.support.mediacompat.service.test/android.support.test.runner.AndroidJUnitRunner
+
+  if [[ $OPTION_TEST_TARGET == *"client"* ]]; then
+    ${test_command} $OPTION_TEST_TARGET ${client_test_runner}
+  elif [[ $OPTION_TEST_TARGET == *"service"* ]]; then
+    ${test_command} $OPTION_TEST_TARGET ${service_test_runner}
+  else
+    ${test_command} ${client_test_runner}
+    ${test_command} ${service_test_runner}
+  fi
+
   echo ">>>>>>>>>>>>>>>>>>>>>>>> Test Ended: Client-$CLIENT_VERSION & Service-$SERVICE_VERSION <<<<<<<<<<<<<<<<<<<<<<<<<<"
 }
 
 
 OLD_PWD=$(pwd)
-if [[ $OLD_PWD != *"frameworks/support"* ]]; then
-  echo "Current working directory is" $OLD_PWD.
+
+if ! cd "$(echo $OLD_PWD | awk -F'frameworks/support' '{print $1}')"/frameworks/support &> /dev/null
+then
+  echo "Current working directory is $OLD_PWD"
   echo "Please re-run this script in any folder under frameworks/support."
   exit 1;
-else
-  # Change working directory to frameworks/support
-  cd "$(echo $OLD_PWD | awk -F'frameworks/support' '{print $1}')"/frameworks/support
 fi
 
-echo "Choose the support library versions of the test you want to run:"
-echo "    1. Client-ToT             / Service-ToT"
-echo "    2. Client-ToT             / Service-Latest release"
-echo "    3. Client-Latest release  / Service-ToT"
-echo "    4. Run all of the above"
-printf "Pick one of them: "
+if [[ $# -eq 0 || $1 -le 0 || $1 -gt 4 ]]
+then
+  printRunTestUsage
+  exit 1;
+fi
 
-read ANSWER
-case $ANSWER in
+if [[ ${2} == "-t" ]]; then
+  if [[ ${3} == *"client"* || ${3} == *"service"* ]]; then
+    OPTION_TEST_TARGET="-e class ${3}"
+  else
+    echo "Wrong test class/method name. Aborting."
+    echo "It should be in the form of \"<FULL_CLASS_NAME>[#METHOD_NAME]\"."
+    exit 1;
+  fi
+fi
+
+case ${1} in
   1)
      CLIENT_VERSION="tot"
      SERVICE_VERSION="tot"
diff --git a/paging/common/build.gradle b/paging/common/build.gradle
index d07103f..fc9964e 100644
--- a/paging/common/build.gradle
+++ b/paging/common/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension;
@@ -25,18 +26,13 @@
 
 dependencies {
     compile libs.support.annotations
-    compile project(":arch:common")
+    compile(project(":arch:common"))
 
-    testCompile libs.junit
-    testCompile libs.mockito_core
-    compile libs.support.annotations
-    compile project(path: ':arch:common')
-    testCompile libs.kotlin.stdlib
+    testCompile(JUNIT)
+    testCompile(MOCKITO_CORE)
+    testCompile(KOTLIN_STDLIB)
 }
 
-createAndroidCheckstyle(project)
-createKotlinCheckstyle(project)
-
 supportLibrary {
     name = "Android Paging-Common"
     publish = true
diff --git a/paging/common/src/main/java/android/arch/paging/ContiguousDataSource.java b/paging/common/src/main/java/android/arch/paging/ContiguousDataSource.java
index 03f2e86..b2e389f 100644
--- a/paging/common/src/main/java/android/arch/paging/ContiguousDataSource.java
+++ b/paging/common/src/main/java/android/arch/paging/ContiguousDataSource.java
@@ -19,21 +19,35 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
+import java.util.concurrent.Executor;
+
 abstract class ContiguousDataSource<Key, Value> extends DataSource<Key, Value> {
     @Override
     boolean isContiguous() {
         return true;
     }
 
-    public abstract void loadInitial(@Nullable Key key, int initialLoadSize,
+    abstract void dispatchLoadInitial(
+            @Nullable Key key,
+            int initialLoadSize,
+            int pageSize,
             boolean enablePlaceholders,
-            @NonNull InitialLoadCallback<Value> callback);
+            @NonNull Executor mainThreadExecutor,
+            @NonNull PageResult.Receiver<Value> receiver);
 
-    abstract void loadAfter(int currentEndIndex, @NonNull Value currentEndItem, int pageSize,
-            @NonNull LoadCallback<Value> callback);
+    abstract void dispatchLoadAfter(
+            int currentEndIndex,
+            @NonNull Value currentEndItem,
+            int pageSize,
+            @NonNull Executor mainThreadExecutor,
+            @NonNull PageResult.Receiver<Value> receiver);
 
-    abstract void loadBefore(int currentBeginIndex, @NonNull Value currentBeginItem, int pageSize,
-            @NonNull LoadCallback<Value> callback);
+    abstract void dispatchLoadBefore(
+            int currentBeginIndex,
+            @NonNull Value currentBeginItem,
+            int pageSize,
+            @NonNull Executor mainThreadExecutor,
+            @NonNull PageResult.Receiver<Value> receiver);
 
     /**
      * Get the key from either the position, or item, or null if position/item invalid.
diff --git a/paging/common/src/main/java/android/arch/paging/ContiguousPagedList.java b/paging/common/src/main/java/android/arch/paging/ContiguousPagedList.java
index 302263d..42eb320 100644
--- a/paging/common/src/main/java/android/arch/paging/ContiguousPagedList.java
+++ b/paging/common/src/main/java/android/arch/paging/ContiguousPagedList.java
@@ -53,11 +53,6 @@
             if (resultType == PageResult.INIT) {
                 mStorage.init(pageResult.leadingNulls, page, pageResult.trailingNulls,
                         pageResult.positionOffset, ContiguousPagedList.this);
-
-                // notifyInserted is safe here, since if we're not on main thread, we won't have any
-                // Callbacks registered to listen to the notify.
-                notifyInserted(0, mStorage.size());
-
                 mLastLoad = pageResult.leadingNulls + pageResult.positionOffset + page.size() / 2;
             } else if (resultType == PageResult.APPEND) {
                 mStorage.appendPage(page, ContiguousPagedList.this);
@@ -92,21 +87,12 @@
         if (mDataSource.isInvalid()) {
             detach();
         } else {
-            @DataSource.LoadCountType int type = mConfig.enablePlaceholders
-                    ? DataSource.LOAD_COUNT_ACCEPTED
-                    : DataSource.LOAD_COUNT_PREVENTED;
-
-            DataSource.InitialLoadCallback<V> callback = new DataSource.InitialLoadCallback<>(
-                    type, mConfig.pageSize, mDataSource, mReceiver);
-            mDataSource.loadInitial(key,
+            mDataSource.dispatchLoadInitial(key,
                     mConfig.initialLoadSizeHint,
+                    mConfig.pageSize,
                     mConfig.enablePlaceholders,
-                    callback);
-
-            // If initialLoad's callback is not called within the body, we force any following calls
-            // to post to the UI thread. This constructor may be run on a background thread, but
-            // after constructor, mutation must happen on UI thread.
-            callback.setPostExecutor(mMainThreadExecutor);
+                    mMainThreadExecutor,
+                    mReceiver);
         }
     }
 
@@ -198,9 +184,8 @@
                 if (mDataSource.isInvalid()) {
                     detach();
                 } else {
-                    DataSource.LoadCallback<V> callback = new DataSource.LoadCallback<>(
-                            PageResult.PREPEND, mMainThreadExecutor, mDataSource, mReceiver);
-                    mDataSource.loadBefore(position, item, mConfig.pageSize, callback);
+                    mDataSource.dispatchLoadBefore(position, item, mConfig.pageSize,
+                            mMainThreadExecutor, mReceiver);
                 }
 
             }
@@ -228,9 +213,8 @@
                 if (mDataSource.isInvalid()) {
                     detach();
                 } else {
-                    DataSource.LoadCallback<V> callback = new DataSource.LoadCallback<>(
-                            PageResult.APPEND, mMainThreadExecutor, mDataSource, mReceiver);
-                    mDataSource.loadAfter(position, item, mConfig.pageSize, callback);
+                    mDataSource.dispatchLoadAfter(position, item, mConfig.pageSize,
+                            mMainThreadExecutor, mReceiver);
                 }
             }
         });
diff --git a/paging/common/src/main/java/android/arch/paging/DataSource.java b/paging/common/src/main/java/android/arch/paging/DataSource.java
index 2e41cf6..bbf7ccb 100644
--- a/paging/common/src/main/java/android/arch/paging/DataSource.java
+++ b/paging/common/src/main/java/android/arch/paging/DataSource.java
@@ -16,14 +16,11 @@
 
 package android.arch.paging;
 
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
 import android.support.annotation.AnyThread;
-import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.WorkerThread;
 
-import java.lang.annotation.Retention;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Executor;
@@ -33,11 +30,8 @@
  * Base class for loading pages of snapshot data into a {@link PagedList}.
  * <p>
  * DataSource is queried to load pages of content into a {@link PagedList}. A PagedList can grow as
- * it loads more data, but the data loaded cannot be updated.
- * <p>
- * A PagedList / DataSource pair serve as a snapshot of the data set being loaded. If the
- * underlying data set is modified, a new PagedList / DataSource pair must be created to represent
- * the new data.
+ * it loads more data, but the data loaded cannot be updated. If the underlying data set is
+ * modified, a new PagedList / DataSource pair must be created to represent the new data.
  * <h4>Loading Pages</h4>
  * PagedList queries data from its DataSource in response to loading hints. {@link PagedListAdapter}
  * calls {@link PagedList#loadAround(int)} to load content as the user scrolls in a RecyclerView.
@@ -71,18 +65,23 @@
  * copy changes, invalidate the previous DataSource, and a new one wrapping the new state of the
  * snapshot can be created.
  * <h4>Implementing a DataSource</h4>
- * To implement, extend either the {@link KeyedDataSource}, or {@link PositionalDataSource}
- * subclass. Choose based on whether each load operation is based on the position of the data in the
- * list.
+ * To implement, extend one of the subclasses: {@link PageKeyedDataSource},
+ * {@link ItemKeyedDataSource}, or {@link PositionalDataSource}.
  * <p>
- * Use {@link KeyedDataSource} if you need to use data from item {@code N-1} to load item
+ * Use {@link PageKeyedDataSource} if pages you load embed keys for loading adjacent pages. For
+ * example a network response that returns some items, and a next/previous page links.
+ * <p>
+ * Use {@link ItemKeyedDataSource} if you need to use data from item {@code N-1} to load item
  * {@code N}. For example, if requesting the backend for the next comments in the list
  * requires the ID or timestamp of the most recent loaded comment, or if querying the next users
  * from a name-sorted database query requires the name and unique ID of the previous.
  * <p>
- * Use {@link PositionalDataSource} if you can load arbitrary pages based solely on position
- * information, and can provide a fixed item count. PositionalDataSource supports querying pages at
- * arbitrary positions, so can provide data to PagedLists in arbitrary order.
+ * Use {@link PositionalDataSource} if you can load pages of a requested size at arbitrary
+ * positions, and provide a fixed item count. PositionalDataSource supports querying pages at
+ * arbitrary positions, so can provide data to PagedLists in arbitrary order. Note that
+ * PositionalDataSource is required to respect page size for efficient tiling. If you want to
+ * override page size (e.g. when network page size constraints are only known at runtime), use one
+ * of the other DataSource classes.
  * <p>
  * Because a {@code null} item indicates a placeholder in {@link PagedList}, DataSource may not
  * return {@code null} items in lists that it loads. This is so that users of the PagedList
@@ -118,8 +117,13 @@
         /**
          * Create a DataSource.
          * <p>
-         * The DataSource should invalidate itself if the snapshot is no longer valid, and a new
-         * DataSource should be queried from the Factory.
+         * The DataSource should invalidate itself if the snapshot is no longer valid. If a
+         * DataSource becomes invalid, the only way to query more data is to create a new DataSource
+         * from the Factory.
+         * <p>
+         * {@link LivePagedListBuilder} for example will construct a new PagedList and DataSource
+         * when the current DataSource is invalidated, and pass the new PagedList through the
+         * {@code LiveData<PagedList>} to observers.
          *
          * @return the new DataSource.
          */
@@ -137,150 +141,39 @@
      */
     abstract boolean isContiguous();
 
-    /**
-     * Callback for DataSource initial loading methods to return data and position/count
-     * information.
-     * <p>
-     * A callback can be called only once, and will throw if called again.
-     * <p>
-     * It is always valid for a DataSource loading method that takes a callback to stash the
-     * callback and call it later. This enables DataSources to be fully asynchronous, and to handle
-     * temporary, recoverable error states (such as a network error that can be retried).
-     *
-     * @param <T> Type of items being loaded.
-     */
-    public static class InitialLoadCallback<T> extends LoadCallback<T> {
-        private final int mPageSize;
-
-        InitialLoadCallback(@LoadCountType int countType, int pageSize,
-                DataSource dataSource, PageResult.Receiver<T> receiver) {
-            super(PageResult.INIT, countType, dataSource, receiver);
-            mPageSize = pageSize;
-            if (mPageSize < 1) {
-                throw new IllegalArgumentException("Page size must be non-negative");
-            }
-        }
-
-        /**
-         * Called to pass initial load state from a DataSource.
-         * <p>
-         * Call this method from your DataSource's {@code loadInitial} function to return data,
-         * and inform how many placeholders should be shown before and after. If counting is cheap
-         * to compute (for example, if a network load returns the information regardless), it's
-         * recommended to pass data back through this method.
-         *
-         * @param data List of items loaded from the DataSource. If this is empty, the DataSource
-         *             is treated as empty, and no further loads will occur.
-         * @param position Position of the item at the front of the list, relative to the total
-         *                 count. If there are {@code N} items before the items in data that can be
-         *                 loaded from this DataSource, pass {@code N}.
-         * @param totalCount Total number of items that may be returned from this DataSource.
-         *                   Includes the number in the initial {@code data} parameter
-         *                   as well as any items that can be loaded in front or behind of
-         *                   {@code data}.
-         */
-        public void onResult(@NonNull List<T> data, int position, int totalCount) {
+    static class BaseLoadCallback<T> {
+        static void validateInitialLoadParams(@NonNull List<?> data, int position, int totalCount) {
             if (position < 0) {
                 throw new IllegalArgumentException("Position must be non-negative");
             }
             if (data.size() + position > totalCount) {
                 throw new IllegalArgumentException(
-                        "List size + position too large; last item in list beyond totalCount");
+                        "List size + position too large, last item in list beyond totalCount.");
             }
             if (data.size() == 0 && totalCount > 0) {
                 throw new IllegalArgumentException(
                         "Initial result cannot be empty if items are present in data set.");
             }
-            if (mCountType == LOAD_COUNT_REQUIRED_TILED
-                    && position + data.size() != totalCount
-                    && data.size() % mPageSize != 0) {
-                throw new IllegalArgumentException("PositionalDataSource requires initial load size"
-                        + " to be a multiple of page size to support internal tiling.");
-            }
-
-            int trailingUnloadedCount = totalCount - position - data.size();
-            if (mCountType == LOAD_COUNT_REQUIRED_TILED || mCountType == LOAD_COUNT_ACCEPTED) {
-                dispatchResultToReceiver(new PageResult<>(
-                        data, position, trailingUnloadedCount, 0));
-            } else {
-                dispatchResultToReceiver(new PageResult<>(data, position));
-            }
         }
 
-        /**
-         * Called to pass initial load state from a DataSource without supporting placeholders.
-         * <p>
-         * Call this method from your DataSource's {@code loadInitial} function to return data,
-         * if position is known but total size is not. If counting is not expensive, consider
-         * calling the three parameter variant: {@link #onResult(List, int, int)}.
-         *
-         * @param data List of items loaded from the DataSource. If this is empty, the DataSource
-         *             is treated as empty, and no further loads will occur.
-         * @param position Position of the item at the front of the list. If there are {@code N}
-         *                 items before the items in data that can be provided by this DataSource,
-         *                 pass {@code N}.
-         */
-        void onResult(@NonNull List<T> data, int position) {
-            // not counting, don't need to check mAcceptCount
-            dispatchResultToReceiver(new PageResult<>(
-                    data, 0, 0, position));
-        }
-    }
-
-    @Retention(SOURCE)
-    @IntDef({LOAD_COUNT_PREVENTED, LOAD_COUNT_ACCEPTED, LOAD_COUNT_REQUIRED_TILED})
-    @interface LoadCountType {}
-    static final int LOAD_COUNT_PREVENTED = 0;
-    static final int LOAD_COUNT_ACCEPTED = 1;
-    static final int LOAD_COUNT_REQUIRED_TILED = 2;
-
-    /**
-     * Callback for DataSource loading methods to return data.
-     * <p>
-     * A callback can be called only once, and will throw if called again.
-     * <p>
-     * It is always valid for a DataSource loading method that takes a callback to stash the
-     * callback and call it later. This enables DataSources to be fully asynchronous, and to handle
-     * temporary, recoverable error states (such as a network error that can be retried).
-     *
-     * @param <T> Type of items being loaded.
-     */
-    public static class LoadCallback<T> {
         @PageResult.ResultType
         final int mResultType;
-        @LoadCountType
-        final int mCountType;
         private final DataSource mDataSource;
         private final PageResult.Receiver<T> mReceiver;
 
-        private int mPositionOffset = 0;
-
         // mSignalLock protects mPostExecutor, and mHasSignalled
         private final Object mSignalLock = new Object();
         private Executor mPostExecutor = null;
         private boolean mHasSignalled = false;
 
-        private LoadCallback(@PageResult.ResultType int resultType, @LoadCountType int countType,
-                DataSource dataSource, PageResult.Receiver<T> receiver) {
+        BaseLoadCallback(@NonNull DataSource dataSource, @PageResult.ResultType int resultType,
+                @Nullable Executor mainThreadExecutor, @NonNull PageResult.Receiver<T> receiver) {
+            mDataSource = dataSource;
             mResultType = resultType;
-            mCountType = countType;
-            mDataSource = dataSource;
-            mReceiver = receiver;
-        }
-
-        LoadCallback(int type, Executor mainThreadExecutor,
-                DataSource dataSource, PageResult.Receiver<T> receiver) {
-            mResultType = type;
-            mCountType = LOAD_COUNT_PREVENTED;
             mPostExecutor = mainThreadExecutor;
-            mDataSource = dataSource;
             mReceiver = receiver;
         }
 
-        void setPositionOffset(int positionOffset) {
-            mPositionOffset = positionOffset;
-        }
-
         void setPostExecutor(Executor postExecutor) {
             synchronized (mSignalLock) {
                 mPostExecutor = postExecutor;
@@ -288,20 +181,16 @@
         }
 
         /**
-         * Called to pass loaded data from a DataSource.
-         * <p>
-         * Call this method from your DataSource's {@code load} methods to return data.
+         * Call before verifying args, or dispatching actul results
          *
-         * @param data List of items loaded from the DataSource.
+         * @return true if DataSource was invalid, and invalid result dispatched
          */
-        public void onResult(@NonNull List<T> data) {
-            if (mCountType == LOAD_COUNT_REQUIRED_TILED && !data.isEmpty()) {
-                throw new IllegalArgumentException(
-                        "PositionalDataSource requires calling the three argument version of"
-                                + " InitialLoadCallback.onResult() to pass position information");
+        boolean dispatchInvalidResultIfInvalid() {
+            if (mDataSource.isInvalid()) {
+                dispatchResultToReceiver(PageResult.<T>getInvalidResult());
+                return true;
             }
-            dispatchResultToReceiver(new PageResult<>(
-                    data, 0, 0, mPositionOffset));
+            return false;
         }
 
         void dispatchResultToReceiver(final @NonNull PageResult<T> result) {
@@ -309,15 +198,12 @@
             synchronized (mSignalLock) {
                 if (mHasSignalled) {
                     throw new IllegalStateException(
-                            "LoadCallback already dispatched, cannot dispatch again.");
+                            "callback.onResult already called, cannot call again.");
                 }
                 mHasSignalled = true;
                 executor = mPostExecutor;
             }
 
-            final PageResult<T> resolvedResult =
-                    mDataSource.isInvalid() ? PageResult.<T>getInvalidResult() : result;
-
             if (executor != null) {
                 executor.execute(new Runnable() {
                     @Override
diff --git a/paging/common/src/main/java/android/arch/paging/ItemKeyedDataSource.java b/paging/common/src/main/java/android/arch/paging/ItemKeyedDataSource.java
new file mode 100644
index 0000000..cb8247b
--- /dev/null
+++ b/paging/common/src/main/java/android/arch/paging/ItemKeyedDataSource.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.arch.paging;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Incremental data loader for paging keyed content, where loaded content uses previously loaded
+ * items as input to future loads.
+ * <p>
+ * Implement a DataSource using ItemKeyedDataSource if you need to use data from item {@code N - 1}
+ * to load item {@code N}. This is common, for example, in sorted database queries where
+ * attributes of the item such just before the next query define how to execute it.
+ * <p>
+ * The {@code InMemoryByItemRepository} in the
+ * <a href="https://github.com/googlesamples/android-architecture-components/blob/master/PagingWithNetworkSample/README.md">PagingWithNetworkSample</a>
+ * shows how to implement a network ItemKeyedDataSource using
+ * <a href="https://square.github.io/retrofit/">Retrofit</a>, while
+ * handling swipe-to-refresh, network errors, and retry.
+ *
+ * @param <Key> Type of data used to query Value types out of the DataSource.
+ * @param <Value> Type of items being loaded by the DataSource.
+ */
+public abstract class ItemKeyedDataSource<Key, Value> extends ContiguousDataSource<Key, Value> {
+
+    /**
+     * Holder object for inputs to {@link #loadInitial(LoadInitialParams, LoadInitialCallback)}.
+     *
+     * @param <Key> Type of data used to query Value types out of the DataSource.
+     */
+    @SuppressWarnings("WeakerAccess")
+    public static class LoadInitialParams<Key> {
+        /**
+         * Load items around this key, or at the beginning of the data set if {@code null} is
+         * passed.
+         * <p>
+         * Note that this key is generally a hint, and may be ignored if you want to always load
+         * from the beginning.
+         */
+        @Nullable
+        public final Key requestedInitialKey;
+
+        /**
+         * Requested number of items to load.
+         * <p>
+         * Note that this may be larger than available data.
+         */
+        public final int requestedLoadSize;
+
+        /**
+         * Defines whether placeholders are enabled, and whether the total count passed to
+         * {@link LoadInitialCallback#onResult(List, int, int)} will be ignored.
+         */
+        public final boolean placeholdersEnabled;
+
+
+        LoadInitialParams(@Nullable Key requestedInitialKey, int requestedLoadSize,
+                boolean placeholdersEnabled) {
+            this.requestedInitialKey = requestedInitialKey;
+            this.requestedLoadSize = requestedLoadSize;
+            this.placeholdersEnabled = placeholdersEnabled;
+        }
+    }
+
+    /**
+     * Holder object for inputs to {@link #loadBefore(LoadParams, LoadCallback)}
+     * and {@link #loadAfter(LoadParams, LoadCallback)}.
+     *
+     * @param <Key> Type of data used to query Value types out of the DataSource.
+     */
+    @SuppressWarnings("WeakerAccess")
+    public static class LoadParams<Key> {
+        /**
+         * Load items before/after this key.
+         * <p>
+         * Returned data must begin directly adjacent to this position.
+         */
+        public final Key key;
+        /**
+         * Requested number of items to load.
+         * <p>
+         * Returned page can be of this size, but it may be altered if that is easier, e.g. a
+         * network data source where the backend defines page size.
+         */
+        public final int requestedLoadSize;
+
+        LoadParams(Key key, int requestedLoadSize) {
+            this.key = key;
+            this.requestedLoadSize = requestedLoadSize;
+        }
+    }
+
+    /**
+     * Callback for {@link #loadInitial(LoadInitialParams, LoadInitialCallback)}
+     * to return data and, optionally, position/count information.
+     * <p>
+     * A callback can be called only once, and will throw if called again.
+     * <p>
+     * If you can compute the number of items in the data set before and after the loaded range,
+     * call the three parameter {@link #onResult(List, int, int)} to pass that information. You
+     * can skip passing this information by calling the single parameter {@link #onResult(List)},
+     * either if it's difficult to compute, or if {@link LoadInitialParams#placeholdersEnabled} is
+     * {@code false}, so the positioning information will be ignored.
+     * <p>
+     * It is always valid for a DataSource loading method that takes a callback to stash the
+     * callback and call it later. This enables DataSources to be fully asynchronous, and to handle
+     * temporary, recoverable error states (such as a network error that can be retried).
+     *
+     * @param <Value> Type of items being loaded.
+     */
+    public static class LoadInitialCallback<Value> extends LoadCallback<Value> {
+        private final boolean mCountingEnabled;
+        LoadInitialCallback(@NonNull ItemKeyedDataSource dataSource, boolean countingEnabled,
+                @NonNull PageResult.Receiver<Value> receiver) {
+            super(dataSource, PageResult.INIT, null, receiver);
+            mCountingEnabled = countingEnabled;
+        }
+
+        /**
+         * Called to pass initial load state from a DataSource.
+         * <p>
+         * Call this method from your DataSource's {@code loadInitial} function to return data,
+         * and inform how many placeholders should be shown before and after. If counting is cheap
+         * to compute (for example, if a network load returns the information regardless), it's
+         * recommended to pass data back through this method.
+         * <p>
+         * It is always valid to pass a different amount of data than what is requested. Pass an
+         * empty list if there is no more data to load.
+         *
+         * @param data List of items loaded from the DataSource. If this is empty, the DataSource
+         *             is treated as empty, and no further loads will occur.
+         * @param position Position of the item at the front of the list. If there are {@code N}
+         *                 items before the items in data that can be loaded from this DataSource,
+         *                 pass {@code N}.
+         * @param totalCount Total number of items that may be returned from this DataSource.
+         *                   Includes the number in the initial {@code data} parameter
+         *                   as well as any items that can be loaded in front or behind of
+         *                   {@code data}.
+         */
+        public void onResult(@NonNull List<Value> data, int position, int totalCount) {
+            if (!dispatchInvalidResultIfInvalid()) {
+                validateInitialLoadParams(data, position, totalCount);
+
+                int trailingUnloadedCount = totalCount - position - data.size();
+                if (mCountingEnabled) {
+                    dispatchResultToReceiver(new PageResult<>(
+                            data, position, trailingUnloadedCount, 0));
+                } else {
+                    dispatchResultToReceiver(new PageResult<>(data, position));
+                }
+            }
+        }
+    }
+
+    /**
+     * Callback for ItemKeyedDataSource {@link #loadBefore(LoadParams, LoadCallback)}
+     * and {@link #loadAfter(LoadParams, LoadCallback)} to return data.
+     * <p>
+     * A callback can be called only once, and will throw if called again.
+     * <p>
+     * It is always valid for a DataSource loading method that takes a callback to stash the
+     * callback and call it later. This enables DataSources to be fully asynchronous, and to handle
+     * temporary, recoverable error states (such as a network error that can be retried).
+     *
+     * @param <Value> Type of items being loaded.
+     */
+    public static class LoadCallback<Value> extends BaseLoadCallback<Value> {
+        LoadCallback(@NonNull ItemKeyedDataSource dataSource, @PageResult.ResultType int type,
+                @Nullable Executor mainThreadExecutor,
+                @NonNull PageResult.Receiver<Value> receiver) {
+            super(dataSource, type, mainThreadExecutor, receiver);
+        }
+
+        /**
+         * Called to pass loaded data from a DataSource.
+         * <p>
+         * Call this method from your ItemKeyedDataSource's
+         * {@link #loadBefore(LoadParams, LoadCallback)} and
+         * {@link #loadAfter(LoadParams, LoadCallback)} methods to return data.
+         * <p>
+         * Call this from {@link #loadInitial(LoadInitialParams, LoadInitialCallback)} to
+         * initialize without counting available data, or supporting placeholders.
+         * <p>
+         * It is always valid to pass a different amount of data than what is requested. Pass an
+         * empty list if there is no more data to load.
+         *
+         * @param data List of items loaded from the ItemKeyedDataSource.
+         */
+        public void onResult(@NonNull List<Value> data) {
+            if (!dispatchInvalidResultIfInvalid()) {
+                dispatchResultToReceiver(new PageResult<>(data, 0, 0, 0));
+            }
+        }
+    }
+
+    @Nullable
+    @Override
+    final Key getKey(int position, Value item) {
+        if (item == null) {
+            return null;
+        }
+
+        return getKey(item);
+    }
+
+    @Override
+    final void dispatchLoadInitial(@Nullable Key key, int initialLoadSize, int pageSize,
+            boolean enablePlaceholders, @NonNull Executor mainThreadExecutor,
+            @NonNull PageResult.Receiver<Value> receiver) {
+        LoadInitialCallback<Value> callback =
+                new LoadInitialCallback<>(this, enablePlaceholders, receiver);
+        loadInitial(new LoadInitialParams<>(key, initialLoadSize, enablePlaceholders), callback);
+
+        // If initialLoad's callback is not called within the body, we force any following calls
+        // to post to the UI thread. This constructor may be run on a background thread, but
+        // after constructor, mutation must happen on UI thread.
+        callback.setPostExecutor(mainThreadExecutor);
+    }
+
+    @Override
+    final void dispatchLoadAfter(int currentEndIndex, @NonNull Value currentEndItem,
+            int pageSize, @NonNull Executor mainThreadExecutor,
+            @NonNull PageResult.Receiver<Value> receiver) {
+        loadAfter(new LoadParams<>(getKey(currentEndItem), pageSize),
+                new LoadCallback<>(this, PageResult.APPEND, mainThreadExecutor, receiver));
+    }
+
+    @Override
+    final void dispatchLoadBefore(int currentBeginIndex, @NonNull Value currentBeginItem,
+            int pageSize, @NonNull Executor mainThreadExecutor,
+            @NonNull PageResult.Receiver<Value> receiver) {
+        loadBefore(new LoadParams<>(getKey(currentBeginItem), pageSize),
+                new LoadCallback<>(this, PageResult.PREPEND, mainThreadExecutor, receiver));
+    }
+
+    /**
+     * Load initial data.
+     * <p>
+     * This method is called first to initialize a PagedList with data. If it's possible to count
+     * the items that can be loaded by the DataSource, it's recommended to pass the loaded data to
+     * the callback via the three-parameter
+     * {@link LoadInitialCallback#onResult(List, int, int)}. This enables PagedLists
+     * presenting data from this source to display placeholders to represent unloaded items.
+     * <p>
+     * {@link LoadInitialParams#requestedInitialKey} and {@link LoadInitialParams#requestedLoadSize}
+     * are hints, not requirements, so they may be altered or ignored. Note that ignoring the
+     * {@code requestedInitialKey} can prevent subsequent PagedList/DataSource pairs from
+     * initializing at the same location. If your data source never invalidates (for example,
+     * loading from the network without the network ever signalling that old data must be reloaded),
+     * it's fine to ignore the {@code initialLoadKey} and always start from the beginning of the
+     * data set.
+     *
+     * @param params Parameters for initial load, including initial key and requested size.
+     * @param callback Callback that receives initial load data.
+     */
+    public abstract void loadInitial(@NonNull LoadInitialParams<Key> params,
+            @NonNull LoadInitialCallback<Value> callback);
+
+    /**
+     * Load list data after the key specified in {@link LoadParams#key LoadParams.key}.
+     * <p>
+     * It's valid to return a different list size than the page size if it's easier, e.g. if your
+     * backend defines page sizes. It is generally safer to increase the number loaded than reduce.
+     * <p>
+     * Data may be passed synchronously during the loadAfter method, or deferred and called at a
+     * later time. Further loads going down will be blocked until the callback is called.
+     * <p>
+     * If data cannot be loaded (for example, if the request is invalid, or the data would be stale
+     * and inconsistent, it is valid to call {@link #invalidate()} to invalidate the data source,
+     * and prevent further loading.
+     *
+     * @param params Parameters for the load, including the key to load after, and requested size.
+     * @param callback Callback that receives loaded data.
+     */
+    public abstract void loadAfter(@NonNull LoadParams<Key> params,
+            @NonNull LoadCallback<Value> callback);
+
+    /**
+     * Load list data before the key specified in {@link LoadParams#key LoadParams.key}.
+     * <p>
+     * It's valid to return a different list size than the page size if it's easier, e.g. if your
+     * backend defines page sizes. It is generally safer to increase the number loaded than reduce.
+     * <p>
+     * <p class="note"><strong>Note:</strong> Data returned will be prepended just before the key
+     * passed, so if you vary size, ensure that the last item is adjacent to the passed key.
+     * <p>
+     * Data may be passed synchronously during the loadBefore method, or deferred and called at a
+     * later time. Further loads going up will be blocked until the callback is called.
+     * <p>
+     * If data cannot be loaded (for example, if the request is invalid, or the data would be stale
+     * and inconsistent, it is valid to call {@link #invalidate()} to invalidate the data source,
+     * and prevent further loading.
+     *
+     * @param params Parameters for the load, including the key to load before, and requested size.
+     * @param callback Callback that receives loaded data.
+     */
+    public abstract void loadBefore(@NonNull LoadParams<Key> params,
+            @NonNull LoadCallback<Value> callback);
+
+    /**
+     * Return a key associated with the given item.
+     * <p>
+     * If your ItemKeyedDataSource is loading from a source that is sorted and loaded by a unique
+     * integer ID, you would return {@code item.getID()} here. This key can then be passed to
+     * {@link #loadBefore(LoadParams, LoadCallback)} or
+     * {@link #loadAfter(LoadParams, LoadCallback)} to load additional items adjacent to the item
+     * passed to this function.
+     * <p>
+     * If your key is more complex, such as when you're sorting by name, then resolving collisions
+     * with integer ID, you'll need to return both. In such a case you would use a wrapper class,
+     * such as {@code Pair<String, Integer>} or, in Kotlin,
+     * {@code data class Key(val name: String, val id: Int)}
+     *
+     * @param item Item to get the key from.
+     * @return Key associated with given item.
+     */
+    @NonNull
+    public abstract Key getKey(@NonNull Value item);
+}
diff --git a/paging/common/src/main/java/android/arch/paging/KeyedDataSource.java b/paging/common/src/main/java/android/arch/paging/KeyedDataSource.java
deleted file mode 100644
index b6656f3..0000000
--- a/paging/common/src/main/java/android/arch/paging/KeyedDataSource.java
+++ /dev/null
@@ -1,151 +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 android.arch.paging;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-import java.util.List;
-/**
- * Incremental data loader for paging keyed content, where loaded content uses previously loaded
- * items as input to future loads.
- * <p>
- * Implement a DataSource using KeyedDataSource if you need to use data from item {@code N - 1}
- * to load item {@code N}. This is common, for example, in sorted database queries where
- * attributes of the item such just before the next query define how to execute it.
- *
- * @param <Key> Type of data used to query Value types out of the DataSource.
- * @param <Value> Type of items being loaded by the DataSource.
- */
-public abstract class KeyedDataSource<Key, Value> extends ContiguousDataSource<Key, Value> {
-    @Override
-    final void loadAfter(int currentEndIndex, @NonNull Value currentEndItem, int pageSize,
-            @NonNull LoadCallback<Value> callback) {
-        loadAfter(getKey(currentEndItem), pageSize, callback);
-    }
-
-    @Override
-    final void loadBefore(int currentBeginIndex, @NonNull Value currentBeginItem, int pageSize,
-            @NonNull LoadCallback<Value> callback) {
-        loadBefore(getKey(currentBeginItem), pageSize, callback);
-    }
-
-    @Nullable
-    @Override
-    final Key getKey(int position, Value item) {
-        if (item == null) {
-            return null;
-        }
-
-        return getKey(item);
-    }
-
-
-    /**
-     * Load initial data.
-     * <p>
-     * This method is called first to initialize a PagedList with data. If it's possible to count
-     * the items that can be loaded by the DataSource, it's recommended to pass the loaded data to
-     * the callback via the three-parameter
-     * {@link DataSource.InitialLoadCallback#onResult(List, int, int)}. This enables PagedLists
-     * presenting data from this source to display placeholders to represent unloaded items.
-     * <p>
-     * {@code initialLoadKey} and {@code requestedLoadSize} are hints, not requirements, so if it is
-     * difficult or impossible to respect them, they may be altered. Note that ignoring the
-     * {@code initialLoadKey} can prevent subsequent PagedList/DataSource pairs from initializing at
-     * the same location. If your data source never invalidates (for example, loading from the
-     * network without the network ever signalling that old data must be reloaded), it's fine to
-     * ignore the {@code initialLoadKey} and always start from the beginning of the data set.
-     *
-     * @param initialLoadKey Load items around this key, or at the beginning of the data set if null
-     *                       is passed.
-     * @param requestedLoadSize Suggested number of items to load.
-     * @param enablePlaceholders Signals whether counting is requested. If false, you can
-     *                           potentially save work by calling the single-parameter variant of
-     *                           {@link DataSource.LoadCallback#onResult(List)} and not counting the
-     *                           number of items in the data set.
-     * @param callback DataSource.LoadCallback that receives initial load data.
-     */
-    @Override
-    public abstract void loadInitial(@Nullable Key initialLoadKey, int requestedLoadSize,
-            boolean enablePlaceholders, @NonNull InitialLoadCallback<Value> callback);
-
-    /**
-     * Load list data after the specified item.
-     * <p>
-     * It's valid to return a different list size than the page size, if it's easier for this data
-     * source. It is generally safer to increase the number loaded than reduce.
-     * <p>
-     * Data may be passed synchronously during the loadAfter method, or deferred and called at a
-     * later time. Further loads going down will be blocked until the callback is called.
-     * <p>
-     * If data cannot be loaded (for example, if the request is invalid, or the data would be stale
-     * and inconsistent, it is valid to call {@link #invalidate()} to invalidate the data source,
-     * and prevent further loading.
-     *
-     * @param currentEndKey Load items after this key. May be null on initial load, to indicate load
-     *                      from beginning.
-     * @param pageSize Suggested number of items to load.
-     * @param callback DataSource.LoadCallback that receives loaded data.
-     */
-    public abstract void loadAfter(@NonNull Key currentEndKey, int pageSize,
-            @NonNull LoadCallback<Value> callback);
-
-    /**
-     * Load data before the currently loaded content.
-     * <p>
-     * It's valid to return a different list size than the page size, if it's easier for this data
-     * source. It is generally safer to increase the number loaded than reduce. Note that the last
-     * item returned must be directly adjacent to the key passed, so varying size from the pageSize
-     * requested should effectively grow or shrink the list by modifying the beginning, not the end.
-     * <p>
-     * Data may be passed synchronously during the loadBefore method, or deferred and called at a
-     * later time. Further loads going up will be blocked until the callback is called.
-     * <p>
-     * If data cannot be loaded (for example, if the request is invalid, or the data would be stale
-     * and inconsistent, it is valid to call {@link #invalidate()} to invalidate the data source,
-     * and prevent further loading.
-     * <p class="note"><strong>Note:</strong> Data must be returned in the order it will be
-     * presented in the list.
-     *
-     * @param currentBeginKey Load items before this key.
-     * @param pageSize Suggested number of items to load.
-     * @param callback DataSource.LoadCallback that receives loaded data.
-     */
-    public abstract void loadBefore(@NonNull Key currentBeginKey, int pageSize,
-            @NonNull LoadCallback<Value> callback);
-
-    /**
-     * Return a key associated with the given item.
-     * <p>
-     * If your KeyedDataSource is loading from a source that is sorted and loaded by a unique
-     * integer ID, you would return {@code item.getID()} here. This key can then be passed to
-     * {@link #loadBefore(Object, int, LoadCallback)} or
-     * {@link #loadAfter(Object, int, LoadCallback)} to load additional items adjacent to the item
-     * passed to this function.
-     * <p>
-     * If your key is more complex, such as when you're sorting by name, then resolving collisions
-     * with integer ID, you'll need to return both. In such a case you would use a wrapper class,
-     * such as {@code Pair<String, Integer>} or, in Kotlin,
-     * {@code data class Key(val name: String, val id: Int)}
-     *
-     * @param item Item to get the key from.
-     * @return Key associated with given item.
-     */
-    @NonNull
-    public abstract Key getKey(@NonNull Value item);
-}
diff --git a/paging/common/src/main/java/android/arch/paging/ListDataSource.java b/paging/common/src/main/java/android/arch/paging/ListDataSource.java
index b6f366a..1482a91 100644
--- a/paging/common/src/main/java/android/arch/paging/ListDataSource.java
+++ b/paging/common/src/main/java/android/arch/paging/ListDataSource.java
@@ -29,22 +29,23 @@
     }
 
     @Override
-    public void loadInitial(int requestedStartPosition, int requestedLoadSize, int pageSize,
-            @NonNull InitialLoadCallback<T> callback) {
+    public void loadInitial(@NonNull LoadInitialParams params,
+            @NonNull LoadInitialCallback<T> callback) {
         final int totalCount = mList.size();
 
-        final int firstLoadPosition = computeFirstLoadPosition(
-                requestedStartPosition, requestedLoadSize, pageSize, totalCount);
-        final int firstLoadSize = Math.min(totalCount - firstLoadPosition, requestedLoadSize);
+        final int position = computeInitialLoadPosition(params, totalCount);
+        final int loadSize = computeInitialLoadSize(params, position, totalCount);
 
         // for simplicity, we could return everything immediately,
         // but we tile here since it's expected behavior
-        List<T> sublist = mList.subList(firstLoadPosition, firstLoadPosition + firstLoadSize);
-        callback.onResult(sublist, firstLoadPosition, totalCount);
+        List<T> sublist = mList.subList(position, position + loadSize);
+        callback.onResult(sublist, position, totalCount);
     }
 
     @Override
-    public void loadRange(int startPosition, int count, @NonNull LoadCallback<T> callback) {
-        callback.onResult(mList.subList(startPosition, startPosition + count));
+    public void loadRange(@NonNull LoadRangeParams params,
+            @NonNull LoadRangeCallback<T> callback) {
+        callback.onResult(mList.subList(params.startPosition,
+                params.startPosition + params.loadSize));
     }
 }
diff --git a/paging/common/src/main/java/android/arch/paging/PageKeyedDataSource.java b/paging/common/src/main/java/android/arch/paging/PageKeyedDataSource.java
new file mode 100644
index 0000000..a10ecee
--- /dev/null
+++ b/paging/common/src/main/java/android/arch/paging/PageKeyedDataSource.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.arch.paging;
+
+import android.support.annotation.GuardedBy;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Incremental data loader for page-keyed content, where requests return keys for next/previous
+ * pages.
+ * <p>
+ * Implement a DataSource using PageKeyedDataSource if you need to use data from page {@code N - 1}
+ * to load page {@code N}. This is common, for example, in network APIs that include a next/previous
+ * link or key with each page load.
+ * <p>
+ * The {@code InMemoryByPageRepository} in the
+ * <a href="https://github.com/googlesamples/android-architecture-components/blob/master/PagingWithNetworkSample/README.md">PagingWithNetworkSample</a>
+ * shows how to implement a network PageKeyedDataSource using
+ * <a href="https://square.github.io/retrofit/">Retrofit</a>, while
+ * handling swipe-to-refresh, network errors, and retry.
+ *
+ * @param <Key> Type of data used to query Value types out of the DataSource.
+ * @param <Value> Type of items being loaded by the DataSource.
+ */
+public abstract class PageKeyedDataSource<Key, Value> extends ContiguousDataSource<Key, Value> {
+    private final Object mKeyLock = new Object();
+
+    @Nullable
+    @GuardedBy("mKeyLock")
+    private Key mNextKey = null;
+
+    @Nullable
+    @GuardedBy("mKeyLock")
+    private Key mPreviousKey = null;
+
+    private void initKeys(@Nullable Key previousKey, @Nullable Key nextKey) {
+        synchronized (mKeyLock) {
+            mPreviousKey = previousKey;
+            mNextKey = nextKey;
+        }
+    }
+
+    private void setPreviousKey(@Nullable Key previousKey) {
+        synchronized (mKeyLock) {
+            mPreviousKey = previousKey;
+        }
+    }
+
+    private void setNextKey(@Nullable Key nextKey) {
+        synchronized (mKeyLock) {
+            mNextKey = nextKey;
+        }
+    }
+
+    private @Nullable Key getPreviousKey() {
+        synchronized (mKeyLock) {
+            return mPreviousKey;
+        }
+    }
+
+    private @Nullable Key getNextKey() {
+        synchronized (mKeyLock) {
+            return mNextKey;
+        }
+    }
+
+    /**
+     * Holder object for inputs to {@link #loadInitial(LoadInitialParams, LoadInitialCallback)}.
+     *
+     * @param <Key> Type of data used to query pages.
+     */
+    @SuppressWarnings("WeakerAccess")
+    public static class LoadInitialParams<Key> {
+        /**
+         * Requested number of items to load.
+         * <p>
+         * Note that this may be larger than available data.
+         */
+        public final int requestedLoadSize;
+
+        /**
+         * Defines whether placeholders are enabled, and whether the total count passed to
+         * {@link LoadInitialCallback#onResult(List, int, int, Key, Key)} will be ignored.
+         */
+        public final boolean placeholdersEnabled;
+
+
+        LoadInitialParams(int requestedLoadSize,
+                boolean placeholdersEnabled) {
+            this.requestedLoadSize = requestedLoadSize;
+            this.placeholdersEnabled = placeholdersEnabled;
+        }
+    }
+
+    /**
+     * Holder object for inputs to {@link #loadBefore(LoadParams, LoadCallback)} and
+     * {@link #loadAfter(LoadParams, LoadCallback)}.
+     *
+     * @param <Key> Type of data used to query pages.
+     */
+    @SuppressWarnings("WeakerAccess")
+    public static class LoadParams<Key> {
+        /**
+         * Load items before/after this key.
+         * <p>
+         * Returned data must begin directly adjacent to this position.
+         */
+        public final Key key;
+
+        /**
+         * Requested number of items to load.
+         * <p>
+         * Returned page can be of this size, but it may be altered if that is easier, e.g. a
+         * network data source where the backend defines page size.
+         */
+        public final int requestedLoadSize;
+
+        LoadParams(Key key, int requestedLoadSize) {
+            this.key = key;
+            this.requestedLoadSize = requestedLoadSize;
+        }
+    }
+
+    /**
+     * Callback for {@link #loadInitial(LoadInitialParams, LoadInitialCallback)}
+     * to return data and, optionally, position/count information.
+     * <p>
+     * A callback can be called only once, and will throw if called again.
+     * <p>
+     * If you can compute the number of items in the data set before and after the loaded range,
+     * call the five parameter {@link #onResult(List, int, int, Object, Object)} to pass that
+     * information. You can skip passing this information by calling the three parameter
+     * {@link #onResult(List, Object, Object)}, either if it's difficult to compute, or if
+     * {@link LoadInitialParams#placeholdersEnabled} is {@code false}, so the positioning
+     * information will be ignored.
+     * <p>
+     * It is always valid for a DataSource loading method that takes a callback to stash the
+     * callback and call it later. This enables DataSources to be fully asynchronous, and to handle
+     * temporary, recoverable error states (such as a network error that can be retried).
+     *
+     * @param <Key> Type of data used to query pages.
+     * @param <Value> Type of items being loaded.
+     */
+    public static class LoadInitialCallback<Key, Value> extends BaseLoadCallback<Value> {
+        private final PageKeyedDataSource<Key, Value> mDataSource;
+        private final boolean mCountingEnabled;
+        LoadInitialCallback(@NonNull PageKeyedDataSource<Key, Value> dataSource,
+                boolean countingEnabled, @NonNull PageResult.Receiver<Value> receiver) {
+            super(dataSource, PageResult.INIT, null, receiver);
+            mDataSource = dataSource;
+            mCountingEnabled = countingEnabled;
+        }
+
+        /**
+         * Called to pass initial load state from a DataSource.
+         * <p>
+         * Call this method from your DataSource's {@code loadInitial} function to return data,
+         * and inform how many placeholders should be shown before and after. If counting is cheap
+         * to compute (for example, if a network load returns the information regardless), it's
+         * recommended to pass data back through this method.
+         * <p>
+         * It is always valid to pass a different amount of data than what is requested. Pass an
+         * empty list if there is no more data to load.
+         *
+         * @param data List of items loaded from the DataSource. If this is empty, the DataSource
+         *             is treated as empty, and no further loads will occur.
+         * @param position Position of the item at the front of the list. If there are {@code N}
+         *                 items before the items in data that can be loaded from this DataSource,
+         *                 pass {@code N}.
+         * @param totalCount Total number of items that may be returned from this DataSource.
+         *                   Includes the number in the initial {@code data} parameter
+         *                   as well as any items that can be loaded in front or behind of
+         *                   {@code data}.
+         */
+        public void onResult(@NonNull List<Value> data, int position, int totalCount,
+                @Nullable Key previousPageKey, @Nullable Key nextPageKey) {
+            if (!dispatchInvalidResultIfInvalid()) {
+                validateInitialLoadParams(data, position, totalCount);
+
+                // setup keys before dispatching data, so guaranteed to be ready
+                mDataSource.initKeys(previousPageKey, nextPageKey);
+
+                int trailingUnloadedCount = totalCount - position - data.size();
+                if (mCountingEnabled) {
+                    dispatchResultToReceiver(new PageResult<>(
+                            data, position, trailingUnloadedCount, 0));
+                } else {
+                    dispatchResultToReceiver(new PageResult<>(data, position));
+                }
+            }
+        }
+
+        /**
+         * Called to pass loaded data from a DataSource.
+         * <p>
+         * Call this from {@link #loadInitial(LoadInitialParams, LoadInitialCallback)} to
+         * initialize without counting available data, or supporting placeholders.
+         * <p>
+         * It is always valid to pass a different amount of data than what is requested. Pass an
+         * empty list if there is no more data to load.
+         *
+         * @param data List of items loaded from the PageKeyedDataSource.
+         * @param previousPageKey Key for page before the initial load result, or {@code null} if no
+         *                        more data can be loaded before.
+         * @param nextPageKey Key for page after the initial load result, or {@code null} if no
+         *                        more data can be loaded after.
+         */
+        public void onResult(@NonNull List<Value> data, @Nullable Key previousPageKey,
+                @Nullable Key nextPageKey) {
+            if (!dispatchInvalidResultIfInvalid()) {
+                mDataSource.initKeys(previousPageKey, nextPageKey);
+                dispatchResultToReceiver(new PageResult<>(data, 0, 0, 0));
+            }
+        }
+    }
+
+    /**
+     * Callback for PageKeyedDataSource {@link #loadBefore(LoadParams, LoadCallback)} and
+     * {@link #loadAfter(LoadParams, LoadCallback)} to return data.
+     * <p>
+     * A callback can be called only once, and will throw if called again.
+     * <p>
+     * It is always valid for a DataSource loading method that takes a callback to stash the
+     * callback and call it later. This enables DataSources to be fully asynchronous, and to handle
+     * temporary, recoverable error states (such as a network error that can be retried).
+     *
+     * @param <Key> Type of data used to query pages.
+     * @param <Value> Type of items being loaded.
+     */
+    public static class LoadCallback<Key, Value> extends BaseLoadCallback<Value> {
+        private final PageKeyedDataSource<Key, Value> mDataSource;
+        LoadCallback(@NonNull PageKeyedDataSource<Key, Value> dataSource,
+                @PageResult.ResultType int type, @Nullable Executor mainThreadExecutor,
+                @NonNull PageResult.Receiver<Value> receiver) {
+            super(dataSource, type, mainThreadExecutor, receiver);
+            mDataSource = dataSource;
+        }
+
+        /**
+         * Called to pass loaded data from a DataSource.
+         * <p>
+         * Call this method from your PageKeyedDataSource's
+         * {@link #loadBefore(LoadParams, LoadCallback)} and
+         * {@link #loadAfter(LoadParams, LoadCallback)} methods to return data.
+         * <p>
+         * It is always valid to pass a different amount of data than what is requested. Pass an
+         * empty list if there is no more data to load.
+         * <p>
+         * Pass the key for the subsequent page to load to adjacentPageKey. For example, if you've
+         * loaded a page in {@link #loadBefore(LoadParams, LoadCallback)}, pass the key for the
+         * previous page, or {@code null} if the loaded page is the first. If in
+         * {@link #loadAfter(LoadParams, LoadCallback)}, pass the key for the next page, or
+         * {@code null} if the loaded page is the last.
+         *
+         * @param data List of items loaded from the PageKeyedDataSource.
+         * @param adjacentPageKey Key for subsequent page load (previous page in {@link #loadBefore}
+         *                        / next page in {@link #loadAfter}), or {@code null} if there are
+         *                        no more pages to load in the current load direction.
+         */
+        public void onResult(@NonNull List<Value> data, @Nullable Key adjacentPageKey) {
+            if (!dispatchInvalidResultIfInvalid()) {
+                if (mResultType == PageResult.APPEND) {
+                    mDataSource.setNextKey(adjacentPageKey);
+                } else {
+                    mDataSource.setPreviousKey(adjacentPageKey);
+                }
+                dispatchResultToReceiver(new PageResult<>(data, 0, 0, 0));
+            }
+        }
+    }
+
+    @Nullable
+    @Override
+    final Key getKey(int position, Value item) {
+        // don't attempt to persist keys, since we currently don't pass them to initial load
+        return null;
+    }
+
+    @Override
+    final void dispatchLoadInitial(@Nullable Key key, int initialLoadSize, int pageSize,
+            boolean enablePlaceholders, @NonNull Executor mainThreadExecutor,
+            @NonNull PageResult.Receiver<Value> receiver) {
+        LoadInitialCallback<Key, Value> callback =
+                new LoadInitialCallback<>(this, enablePlaceholders, receiver);
+        loadInitial(new LoadInitialParams<Key>(initialLoadSize, enablePlaceholders), callback);
+
+        // If initialLoad's callback is not called within the body, we force any following calls
+        // to post to the UI thread. This constructor may be run on a background thread, but
+        // after constructor, mutation must happen on UI thread.
+        callback.setPostExecutor(mainThreadExecutor);
+    }
+
+
+    @Override
+    final void dispatchLoadAfter(int currentEndIndex, @NonNull Value currentEndItem,
+            int pageSize, @NonNull Executor mainThreadExecutor,
+            @NonNull PageResult.Receiver<Value> receiver) {
+        @Nullable Key key = getNextKey();
+        if (key != null) {
+            loadAfter(new LoadParams<>(key, pageSize),
+                    new LoadCallback<>(this, PageResult.APPEND, mainThreadExecutor, receiver));
+        }
+    }
+
+    @Override
+    final void dispatchLoadBefore(int currentBeginIndex, @NonNull Value currentBeginItem,
+            int pageSize, @NonNull Executor mainThreadExecutor,
+            @NonNull PageResult.Receiver<Value> receiver) {
+        @Nullable Key key = getPreviousKey();
+        if (key != null) {
+            loadBefore(new LoadParams<>(key, pageSize),
+                    new LoadCallback<>(this, PageResult.PREPEND, mainThreadExecutor, receiver));
+        }
+    }
+
+    /**
+     * Load initial data.
+     * <p>
+     * This method is called first to initialize a PagedList with data. If it's possible to count
+     * the items that can be loaded by the DataSource, it's recommended to pass the loaded data to
+     * the callback via the three-parameter
+     * {@link LoadInitialCallback#onResult(List, int, int, Object, Object)}. This enables PagedLists
+     * presenting data from this source to display placeholders to represent unloaded items.
+     * <p>
+     * {@link LoadInitialParams#requestedLoadSize} is a hint, not a requirement, so it may be may be
+     * altered or ignored.
+     *
+     * @param params Parameters for initial load, including requested load size.
+     * @param callback Callback that receives initial load data.
+     */
+    public abstract void loadInitial(@NonNull LoadInitialParams<Key> params,
+            @NonNull LoadInitialCallback<Key, Value> callback);
+
+    /**
+     * Prepend page with the key specified by {@link LoadParams#key LoadParams.key}.
+     * <p>
+     * It's valid to return a different list size than the page size if it's easier, e.g. if your
+     * backend defines page sizes. It is generally safer to increase the number loaded than reduce.
+     * <p>
+     * Data may be passed synchronously during the load method, or deferred and called at a
+     * later time. Further loads going down will be blocked until the callback is called.
+     * <p>
+     * If data cannot be loaded (for example, if the request is invalid, or the data would be stale
+     * and inconsistent, it is valid to call {@link #invalidate()} to invalidate the data source,
+     * and prevent further loading.
+     *
+     * @param params Parameters for the load, including the key for the new page, and requested load
+     *               size.
+     * @param callback Callback that receives loaded data.
+     */
+    public abstract void loadBefore(@NonNull LoadParams<Key> params,
+            @NonNull LoadCallback<Key, Value> callback);
+
+    /**
+     * Append page with the key specified by {@link LoadParams#key LoadParams.key}.
+     * <p>
+     * It's valid to return a different list size than the page size if it's easier, e.g. if your
+     * backend defines page sizes. It is generally safer to increase the number loaded than reduce.
+     * <p>
+     * Data may be passed synchronously during the load method, or deferred and called at a
+     * later time. Further loads going down will be blocked until the callback is called.
+     * <p>
+     * If data cannot be loaded (for example, if the request is invalid, or the data would be stale
+     * and inconsistent, it is valid to call {@link #invalidate()} to invalidate the data source,
+     * and prevent further loading.
+     *
+     * @param params Parameters for the load, including the key for the new page, and requested load
+     *               size.
+     * @param callback Callback that receives loaded data.
+     */
+    public abstract void loadAfter(@NonNull LoadParams<Key> params,
+            @NonNull LoadCallback<Key, Value> callback);
+}
diff --git a/paging/common/src/main/java/android/arch/paging/PagedList.java b/paging/common/src/main/java/android/arch/paging/PagedList.java
index 70d4075..c6de5c5 100644
--- a/paging/common/src/main/java/android/arch/paging/PagedList.java
+++ b/paging/common/src/main/java/android/arch/paging/PagedList.java
@@ -578,7 +578,8 @@
      * If data is supplied by a {@link PositionalDataSource}, the item returned from
      * <code>get(i)</code> has a position of <code>i + getPositionOffset()</code>.
      * <p>
-     * If the DataSource is a {@link KeyedDataSource}, and thus doesn't use positions, returns 0.
+     * If the DataSource is a {@link ItemKeyedDataSource} or {@link PageKeyedDataSource}, it
+     * doesn't use positions, returns 0.
      */
     public int getPositionOffset() {
         return mStorage.getPositionOffset();
@@ -602,7 +603,8 @@
      * GC'd.
      *
      * @param previousSnapshot Snapshot previously captured from this List, or null.
-     * @param callback         LoadCallback to dispatch to.
+     * @param callback Callback to dispatch to.
+     *
      * @see #removeWeakCallback(Callback)
      */
     @SuppressWarnings("WeakerAccess")
@@ -637,7 +639,7 @@
     /**
      * Removes a previously added callback.
      *
-     * @param callback LoadCallback, previously added.
+     * @param callback Callback, previously added.
      * @see #addWeakCallback(List, Callback)
      */
     @SuppressWarnings("WeakerAccess")
@@ -680,7 +682,7 @@
      * Dispatch updates since the non-empty snapshot was taken.
      *
      * @param snapshot Non-empty snapshot.
-     * @param callback LoadCallback for updates that have occurred since snapshot.
+     * @param callback Callback for updates that have occurred since snapshot.
      */
     abstract void dispatchUpdatesSinceSnapshot(@NonNull PagedList<T> snapshot,
             @NonNull Callback callback);
@@ -857,12 +859,14 @@
             }
 
             /**
-             * Defines how many items to load when first load occurs, if you are using a
-             * {@link KeyedDataSource}.
+             * Defines how many items to load when first load occurs.
              * <p>
              * This value is typically larger than page size, so on first load data there's a large
              * enough range of content loaded to cover small scrolls.
              * <p>
+             * When using a {@link PositionalDataSource}, the initial load size will be coerced to
+             * an integer multiple of pageSize, to enable efficient tiling.
+             * <p>
              * If not set, defaults to three times page size.
              *
              * @param initialLoadSizeHint Number of items to load while initializing the PagedList.
@@ -874,7 +878,6 @@
                 return this;
             }
 
-
             /**
              * Creates a {@link Config} with the given parameters.
              *
@@ -905,13 +908,32 @@
     /**
      * Signals when a PagedList has reached the end of available data.
      * <p>
-     * This can be used to implement paging from the network into a local database - when the
-     * database has no more data to present, a BoundaryCallback can be used to fetch more data.
+     * When local storage is a cache of network data, it's common to set up a streaming pipeline:
+     * Network data is paged into the database, database is paged into UI. Paging from the database
+     * to UI can be done with a {@code LiveData<PagedList>}, but it's still necessary to know when
+     * to trigger network loads.
      * <p>
-     * If an instance is shared across multiple PagedLists (e.g. when passed to
+     * BoundaryCallback does this signaling - when a DataSource runs out of data at the end of
+     * the list, {@link #onItemAtEndLoaded(Object)} is called, and you can start an async network
+     * load that will write the result directly to the database. Because the database is being
+     * observed, the UI bound to the {@code LiveData<PagedList>} will update automatically to
+     * account for the new items.
+     * <p>
+     * Note that a BoundaryCallback instance shared across multiple PagedLists (e.g. when passed to
      * {@link LivePagedListBuilder#setBoundaryCallback}), the callbacks may be issued multiple
      * times. If for example {@link #onItemAtEndLoaded(Object)} triggers a network load, it should
      * avoid triggering it again while the load is ongoing.
+     * <p>
+     * BoundaryCallback only passes the item at front or end of the list. Number of items is not
+     * passed, since it may not be fully computed by the DataSource if placeholders are not
+     * supplied. Keys are not known because the BoundaryCallback is independent of the
+     * DataSource-specific keys, which may be different for local vs remote storage.
+     * <p>
+     * The database + network Repository in the
+     * <a href="https://github.com/googlesamples/android-architecture-components/blob/master/PagingWithNetworkSample/README.md">PagingWithNetworkSample</a>
+     * shows how to implement a network BoundaryCallback using
+     * <a href="https://square.github.io/retrofit/">Retrofit</a>, while
+     * handling swipe-to-refresh, network errors, and retry.
      *
      * @param <T> Type loaded by the PagedList.
      */
@@ -920,7 +942,7 @@
         /**
          * Called when zero items are returned from an initial load of the PagedList's data source.
          */
-        public abstract void onZeroItemsLoaded();
+        public void onZeroItemsLoaded() {}
 
         /**
          * Called when the item at the front of the PagedList has been loaded, and access has
@@ -930,7 +952,7 @@
          *
          * @param itemAtFront The first item of PagedList
          */
-        public abstract void onItemAtFrontLoaded(@NonNull T itemAtFront);
+        public void onItemAtFrontLoaded(@NonNull T itemAtFront) {}
 
         /**
          * Called when the item at the end of the PagedList has been loaded, and access has
@@ -940,6 +962,6 @@
          *
          * @param itemAtEnd The first item of PagedList
          */
-        public abstract void onItemAtEndLoaded(@NonNull T itemAtEnd);
+        public void onItemAtEndLoaded(@NonNull T itemAtEnd) {}
     }
 }
diff --git a/paging/common/src/main/java/android/arch/paging/PositionalDataSource.java b/paging/common/src/main/java/android/arch/paging/PositionalDataSource.java
index 5dd3a83..780bcf6 100644
--- a/paging/common/src/main/java/android/arch/paging/PositionalDataSource.java
+++ b/paging/common/src/main/java/android/arch/paging/PositionalDataSource.java
@@ -21,17 +21,23 @@
 import android.support.annotation.WorkerThread;
 
 import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
- * Position-based data loader for a fixed-size, countable data set, supporting loads at arbitrary
- * positions.
+ * Position-based data loader for a fixed-size, countable data set, supporting fixed-size loads at
+ * arbitrary page positions.
  * <p>
- * Extend PositionalDataSource if you can support counting your data set, and loading based on
- * position information.
+ * Extend PositionalDataSource if you can load pages of a requested size at arbitrary
+ * positions, and provide a fixed item count. If your data source can't support loading arbitrary
+ * requested page sizes (e.g. when network page size constraints are only known at runtime), use
+ * either {@link PageKeyedDataSource} or {@link ItemKeyedDataSource} instead.
  * <p>
  * Note that unless {@link PagedList.Config#enablePlaceholders placeholders are disabled}
- * PositionalDataSource requires counting the size of the dataset. This allows pages to be tiled in
+ * PositionalDataSource requires counting the size of the data set. This allows pages to be tiled in
  * at arbitrary, non-contiguous locations based upon what the user observes in a {@link PagedList}.
+ * If placeholders are disabled, initialize with the two parameter
+ * {@link LoadInitialCallback#onResult(List, int)}.
  * <p>
  * Room can generate a Factory of PositionalDataSources for you:
  * <pre>
@@ -46,42 +52,269 @@
 public abstract class PositionalDataSource<T> extends DataSource<Integer, T> {
 
     /**
+     * Holder object for inputs to {@link #loadInitial(LoadInitialParams, LoadInitialCallback)}.
+     */
+    @SuppressWarnings("WeakerAccess")
+    public static class LoadInitialParams {
+        /**
+         * Initial load position requested.
+         * <p>
+         * Note that this may not be within the bounds of your data set, it may need to be adjusted
+         * before you execute your load.
+         */
+        public final int requestedStartPosition;
+
+        /**
+         * Requested number of items to load.
+         * <p>
+         * Note that this may be larger than available data.
+         */
+        public final int requestedLoadSize;
+
+        /**
+         * Defines page size acceptable for return values.
+         * <p>
+         * List of items passed to the callback must be an integer multiple of page size.
+         */
+        public final int pageSize;
+
+        /**
+         * Defines whether placeholders are enabled, and whether the total count passed to
+         * {@link LoadInitialCallback#onResult(List, int, int)} will be ignored.
+         */
+        public final boolean placeholdersEnabled;
+
+        LoadInitialParams(
+                int requestedStartPosition,
+                int requestedLoadSize,
+                int pageSize,
+                boolean placeholdersEnabled) {
+            this.requestedStartPosition = requestedStartPosition;
+            this.requestedLoadSize = requestedLoadSize;
+            this.pageSize = pageSize;
+            this.placeholdersEnabled = placeholdersEnabled;
+        }
+    }
+
+    /**
+     * Holder object for inputs to {@link #loadRange(LoadRangeParams, LoadRangeCallback)}.
+     */
+    @SuppressWarnings("WeakerAccess")
+    public static class LoadRangeParams {
+        /**
+         * Start position of data to load.
+         * <p>
+         * Returned data must start at this position.
+         */
+        public final int startPosition;
+        /**
+         * Number of items to load.
+         * <p>
+         * Returned data must be of this size, unless at end of the list.
+         */
+        public final int loadSize;
+
+        LoadRangeParams(int startPosition, int loadSize) {
+            this.startPosition = startPosition;
+            this.loadSize = loadSize;
+        }
+    }
+
+    /**
+     * Callback for {@link #loadInitial(LoadInitialParams, LoadInitialCallback)}
+     * to return data, position, and count.
+     * <p>
+     * A callback can be called only once, and will throw if called again.
+     * <p>
+     * It is always valid for a DataSource loading method that takes a callback to stash the
+     * callback and call it later. This enables DataSources to be fully asynchronous, and to handle
+     * temporary, recoverable error states (such as a network error that can be retried).
+     *
+     * @param <T> Type of items being loaded.
+     */
+    public static class LoadInitialCallback<T> extends BaseLoadCallback<T> {
+        private final boolean mCountingEnabled;
+        private final int mPageSize;
+
+        LoadInitialCallback(@NonNull PositionalDataSource dataSource, boolean countingEnabled,
+                int pageSize, PageResult.Receiver<T> receiver) {
+            super(dataSource, PageResult.INIT, null, receiver);
+            mCountingEnabled = countingEnabled;
+            mPageSize = pageSize;
+            if (mPageSize < 1) {
+                throw new IllegalArgumentException("Page size must be non-negative");
+            }
+        }
+
+        /**
+         * Called to pass initial load state from a DataSource.
+         * <p>
+         * Call this method from your DataSource's {@code loadInitial} function to return data,
+         * and inform how many placeholders should be shown before and after. If counting is cheap
+         * to compute (for example, if a network load returns the information regardless), it's
+         * recommended to pass the total size to the totalCount parameter. If placeholders are not
+         * requested (when {@link LoadInitialParams#placeholdersEnabled} is false), you can instead
+         * call {@link #onResult(List, int)}.
+         *
+         * @param data List of items loaded from the DataSource. If this is empty, the DataSource
+         *             is treated as empty, and no further loads will occur.
+         * @param position Position of the item at the front of the list. If there are {@code N}
+         *                 items before the items in data that can be loaded from this DataSource,
+         *                 pass {@code N}.
+         * @param totalCount Total number of items that may be returned from this DataSource.
+         *                   Includes the number in the initial {@code data} parameter
+         *                   as well as any items that can be loaded in front or behind of
+         *                   {@code data}.
+         */
+        public void onResult(@NonNull List<T> data, int position, int totalCount) {
+            if (!dispatchInvalidResultIfInvalid()) {
+                validateInitialLoadParams(data, position, totalCount);
+                if (position + data.size() != totalCount
+                        && data.size() % mPageSize != 0) {
+                    throw new IllegalArgumentException("PositionalDataSource requires initial load"
+                            + " size to be a multiple of page size to support internal tiling.");
+                }
+
+                if (mCountingEnabled) {
+                    int trailingUnloadedCount = totalCount - position - data.size();
+                    dispatchResultToReceiver(
+                            new PageResult<>(data, position, trailingUnloadedCount, 0));
+                } else {
+                    // Only occurs when wrapped as contiguous
+                    dispatchResultToReceiver(new PageResult<>(data, position));
+                }
+            }
+        }
+
+        /**
+         * Called to pass initial load state from a DataSource without total count,
+         * when placeholders aren't requested.
+         * <p class="note"><strong>Note:</strong> This method can only be called when placeholders
+         * are disabled ({@link LoadInitialParams#placeholdersEnabled} is false).
+         * <p>
+         * Call this method from your DataSource's {@code loadInitial} function to return data,
+         * if position is known but total size is not. If placeholders are requested, call the three
+         * parameter variant: {@link #onResult(List, int, int)}.
+         *
+         * @param data List of items loaded from the DataSource. If this is empty, the DataSource
+         *             is treated as empty, and no further loads will occur.
+         * @param position Position of the item at the front of the list. If there are {@code N}
+         *                 items before the items in data that can be provided by this DataSource,
+         *                 pass {@code N}.
+         */
+        @SuppressWarnings("WeakerAccess")
+        public void onResult(@NonNull List<T> data, int position) {
+            if (!dispatchInvalidResultIfInvalid()) {
+                if (position < 0) {
+                    throw new IllegalArgumentException("Position must be non-negative");
+                }
+                if (data.isEmpty() && position != 0) {
+                    throw new IllegalArgumentException(
+                            "Initial result cannot be empty if items are present in data set.");
+                }
+                if (mCountingEnabled) {
+                    throw new IllegalStateException("Placeholders requested, but totalCount not"
+                            + " provided. Please call the three-parameter onResult method, or"
+                            + " disable placeholders in the PagedList.Config");
+                }
+                dispatchResultToReceiver(new PageResult<>(data, position));
+            }
+        }
+    }
+
+    /**
+     * Callback for PositionalDataSource {@link #loadRange(LoadRangeParams, LoadRangeCallback)}
+     * to return data.
+     * <p>
+     * A callback can be called only once, and will throw if called again.
+     * <p>
+     * It is always valid for a DataSource loading method that takes a callback to stash the
+     * callback and call it later. This enables DataSources to be fully asynchronous, and to handle
+     * temporary, recoverable error states (such as a network error that can be retried).
+     *
+     * @param <T> Type of items being loaded.
+     */
+    public static class LoadRangeCallback<T> extends BaseLoadCallback<T> {
+        private final int mPositionOffset;
+        LoadRangeCallback(@NonNull PositionalDataSource dataSource, int positionOffset,
+                Executor mainThreadExecutor, PageResult.Receiver<T> receiver) {
+            super(dataSource, PageResult.TILE, mainThreadExecutor, receiver);
+            mPositionOffset = positionOffset;
+        }
+
+        /**
+         * Called to pass loaded data from {@link #loadRange(LoadRangeParams, LoadRangeCallback)}.
+         *
+         * @param data List of items loaded from the DataSource. Must be same size as requested,
+         *             unless at end of list.
+         */
+        public void onResult(@NonNull List<T> data) {
+            if (!dispatchInvalidResultIfInvalid()) {
+                dispatchResultToReceiver(new PageResult<>(
+                        data, 0, 0, mPositionOffset));
+            }
+        }
+    }
+
+    final void dispatchLoadInitial(boolean acceptCount,
+            int requestedStartPosition, int requestedLoadSize, int pageSize,
+            @NonNull Executor mainThreadExecutor, @NonNull PageResult.Receiver<T> receiver) {
+        LoadInitialCallback<T> callback =
+                new LoadInitialCallback<>(this, acceptCount, pageSize, receiver);
+
+        LoadInitialParams params = new LoadInitialParams(
+                requestedStartPosition, requestedLoadSize, pageSize, acceptCount);
+        loadInitial(params, callback);
+
+        // If initialLoad's callback is not called within the body, we force any following calls
+        // to post to the UI thread. This constructor may be run on a background thread, but
+        // after constructor, mutation must happen on UI thread.
+        callback.setPostExecutor(mainThreadExecutor);
+    }
+
+    final void dispatchLoadRange(int startPosition, int count,
+            @NonNull Executor mainThreadExecutor, @NonNull PageResult.Receiver<T> receiver) {
+        LoadRangeCallback<T> callback =
+                new LoadRangeCallback<>(this, startPosition, mainThreadExecutor, receiver);
+        if (count == 0) {
+            callback.onResult(Collections.<T>emptyList());
+        } else {
+            loadRange(new LoadRangeParams(startPosition, count), callback);
+        }
+    }
+
+    /**
      * Load initial list data.
      * <p>
      * This method is called to load the initial page(s) from the DataSource.
      * <p>
      * Result list must be a multiple of pageSize to enable efficient tiling.
      *
-     * @param requestedStartPosition Initial load position requested. Note that this may not be
-     *                               within the bounds of your data set, it should be corrected
-     *                               before you make your query.
-     * @param requestedLoadSize Requested number of items to load. Note that this may be larger than
-     *                          available data.
-     * @param pageSize Defines page size acceptable for return values. List of items passed to the
-     *                 callback must be an integer multiple of page size.
-     * @param callback DataSource.InitialLoadCallback that receives initial load data, including
+     * @param params Parameters for initial load, including requested start position, load size, and
+     *               page size.
+     * @param callback Callback that receives initial load data, including
      *                 position and total data set size.
      */
     @WorkerThread
-    public abstract void loadInitial(int requestedStartPosition, int requestedLoadSize,
-            int pageSize, @NonNull InitialLoadCallback<T> callback);
+    public abstract void loadInitial(
+            @NonNull LoadInitialParams params,
+            @NonNull LoadInitialCallback<T> callback);
 
     /**
      * Called to load a range of data from the DataSource.
      * <p>
      * This method is called to load additional pages from the DataSource after the
-     * InitialLoadCallback passed to loadInitial has initialized a PagedList.
+     * LoadInitialCallback passed to dispatchLoadInitial has initialized a PagedList.
      * <p>
-     * Unlike {@link #loadInitial(int, int, int, InitialLoadCallback)}, this method must return the
-     * number of items requested, at the position requested.
+     * Unlike {@link #loadInitial(LoadInitialParams, LoadInitialCallback)}, this method must return
+     * the number of items requested, at the position requested.
      *
-     * @param startPosition Initial load position.
-     * @param count Number of items to load.
-     * @param callback DataSource.LoadCallback that receives loaded data.
+     * @param params Parameters for load, including start position and load size.
+     * @param callback Callback that receives loaded data.
      */
     @WorkerThread
-    public abstract void loadRange(int startPosition, int count,
-            @NonNull LoadCallback<T> callback);
+    public abstract void loadRange(@NonNull LoadRangeParams params,
+            @NonNull LoadRangeCallback<T> callback);
 
     @Override
     boolean isContiguous() {
@@ -93,11 +326,58 @@
         return new ContiguousWithoutPlaceholdersWrapper<>(this);
     }
 
-    static int computeFirstLoadPosition(int position, int firstLoadSize, int pageSize, int size) {
+    /**
+     * Helper for computing an initial position in
+     * {@link #loadInitial(LoadInitialParams, LoadInitialCallback)} when total data set size can be
+     * computed ahead of loading.
+     * <p>
+     * The value computed by this function will do bounds checking, page alignment, and positioning
+     * based on initial load size requested.
+     * <p>
+     * Example usage in a PositionalDataSource subclass:
+     * <pre>
+     * class ItemDataSource extends PositionalDataSource&lt;Item> {
+     *     private int computeCount() {
+     *         // actual count code here
+     *     }
+     *
+     *     private List&lt;Item> loadRangeInternal(int startPosition, int loadCount) {
+     *         // actual load code here
+     *     }
+     *
+     *     {@literal @}Override
+     *     public void loadInitial({@literal @}NonNull LoadInitialParams params,
+     *             {@literal @}NonNull LoadInitialCallback&lt;Item> callback) {
+     *         int totalCount = computeCount();
+     *         int position = computeInitialLoadPosition(params, totalCount);
+     *         int loadSize = computeInitialLoadSize(params, position, totalCount);
+     *         callback.onResult(loadRangeInternal(position, loadSize), position, totalCount);
+     *     }
+     *
+     *     {@literal @}Override
+     *     public void loadRange({@literal @}NonNull LoadRangeParams params,
+     *             {@literal @}NonNull LoadRangeCallback&lt;Item> callback) {
+     *         callback.onResult(loadRangeInternal(params.startPosition, params.loadSize));
+     *     }
+     * }</pre>
+     *
+     * @param params Params passed to {@link #loadInitial(LoadInitialParams, LoadInitialCallback)},
+     *               including page size, and requested start/loadSize.
+     * @param totalCount Total size of the data set.
+     * @return Position to start loading at.
+     *
+     * @see #computeInitialLoadSize(LoadInitialParams, int, int)
+     */
+    public static int computeInitialLoadPosition(@NonNull LoadInitialParams params,
+            int totalCount) {
+        int position = params.requestedStartPosition;
+        int initialLoadSize = params.requestedLoadSize;
+        int pageSize = params.pageSize;
+
         int roundedPageStart = Math.round(position / pageSize) * pageSize;
 
         // maximum start pos is that which will encompass end of list
-        int maximumLoadPage = ((size - firstLoadSize + pageSize - 1) / pageSize) * pageSize;
+        int maximumLoadPage = ((totalCount - initialLoadSize + pageSize - 1) / pageSize) * pageSize;
         roundedPageStart = Math.min(maximumLoadPage, roundedPageStart);
 
         // minimum start position is 0
@@ -106,6 +386,56 @@
         return roundedPageStart;
     }
 
+    /**
+     * Helper for computing an initial load size in
+     * {@link #loadInitial(LoadInitialParams, LoadInitialCallback)} when total data set size can be
+     * computed ahead of loading.
+     * <p>
+     * This function takes the requested load size, and bounds checks it against the value returned
+     * by {@link #computeInitialLoadPosition(LoadInitialParams, int)}.
+     * <p>
+     * Example usage in a PositionalDataSource subclass:
+     * <pre>
+     * class ItemDataSource extends PositionalDataSource&lt;Item> {
+     *     private int computeCount() {
+     *         // actual count code here
+     *     }
+     *
+     *     private List&lt;Item> loadRangeInternal(int startPosition, int loadCount) {
+     *         // actual load code here
+     *     }
+     *
+     *     {@literal @}Override
+     *     public void loadInitial({@literal @}NonNull LoadInitialParams params,
+     *             {@literal @}NonNull LoadInitialCallback&lt;Item> callback) {
+     *         int totalCount = computeCount();
+     *         int position = computeInitialLoadPosition(params, totalCount);
+     *         int loadSize = computeInitialLoadSize(params, position, totalCount);
+     *         callback.onResult(loadRangeInternal(position, loadSize), position, totalCount);
+     *     }
+     *
+     *     {@literal @}Override
+     *     public void loadRange({@literal @}NonNull LoadRangeParams params,
+     *             {@literal @}NonNull LoadRangeCallback&lt;Item> callback) {
+     *         callback.onResult(loadRangeInternal(params.startPosition, params.loadSize));
+     *     }
+     * }</pre>
+     *
+     * @param params Params passed to {@link #loadInitial(LoadInitialParams, LoadInitialCallback)},
+     *               including page size, and requested start/loadSize.
+     * @param initialLoadPosition Value returned by
+     *                          {@link #computeInitialLoadPosition(LoadInitialParams, int)}
+     * @param totalCount Total size of the data set.
+     * @return Number of items to load.
+     *
+     * @see #computeInitialLoadPosition(LoadInitialParams, int)
+     */
+    @SuppressWarnings("WeakerAccess")
+    public static int computeInitialLoadSize(@NonNull LoadInitialParams params,
+            int initialLoadPosition, int totalCount) {
+        return Math.min(totalCount - initialLoadPosition, params.requestedLoadSize);
+    }
+
     @SuppressWarnings("deprecation")
     static class ContiguousWithoutPlaceholdersWrapper<Value>
             extends ContiguousDataSource<Integer, Value> {
@@ -119,34 +449,42 @@
         }
 
         @Override
-        public void loadInitial(@Nullable Integer position, int initialLoadSize,
-                boolean enablePlaceholders, @NonNull InitialLoadCallback<Value> callback) {
+        void dispatchLoadInitial(@Nullable Integer position, int initialLoadSize, int pageSize,
+                boolean enablePlaceholders, @NonNull Executor mainThreadExecutor,
+                @NonNull PageResult.Receiver<Value> receiver) {
             final int convertPosition = position == null ? 0 : position;
 
             // Note enablePlaceholders will be false here, but we don't have a way to communicate
             // this to PositionalDataSource. This is fine, because only the list and its position
-            // offset will be consumed by the InitialLoadCallback.
-            mPositionalDataSource.loadInitial(
-                    convertPosition, initialLoadSize, initialLoadSize, callback);
+            // offset will be consumed by the LoadInitialCallback.
+            mPositionalDataSource.dispatchLoadInitial(false, convertPosition, initialLoadSize,
+                    pageSize, mainThreadExecutor, receiver);
         }
 
         @Override
-        void loadAfter(int currentEndIndex, @NonNull Value currentEndItem, int pageSize,
-                @NonNull LoadCallback<Value> callback) {
+        void dispatchLoadAfter(int currentEndIndex, @NonNull Value currentEndItem, int pageSize,
+                @NonNull Executor mainThreadExecutor,
+                @NonNull PageResult.Receiver<Value> receiver) {
             int startIndex = currentEndIndex + 1;
-            mPositionalDataSource.loadRange(startIndex, pageSize, callback);
+            mPositionalDataSource.dispatchLoadRange(
+                    startIndex, pageSize, mainThreadExecutor, receiver);
         }
 
         @Override
-        void loadBefore(int currentBeginIndex, @NonNull Value currentBeginItem, int pageSize,
-                @NonNull LoadCallback<Value> callback) {
+        void dispatchLoadBefore(int currentBeginIndex, @NonNull Value currentBeginItem,
+                int pageSize, @NonNull Executor mainThreadExecutor,
+                @NonNull PageResult.Receiver<Value> receiver) {
+
             int startIndex = currentBeginIndex - 1;
             if (startIndex < 0) {
-                callback.onResult(Collections.<Value>emptyList());
+                // trigger empty list load
+                mPositionalDataSource.dispatchLoadRange(
+                        startIndex, 0, mainThreadExecutor, receiver);
             } else {
                 int loadSize = Math.min(pageSize, startIndex + 1);
                 startIndex = startIndex - loadSize + 1;
-                mPositionalDataSource.loadRange(startIndex, loadSize, callback);
+                mPositionalDataSource.dispatchLoadRange(
+                        startIndex, loadSize, mainThreadExecutor, receiver);
             }
         }
 
diff --git a/paging/common/src/main/java/android/arch/paging/TiledDataSource.java b/paging/common/src/main/java/android/arch/paging/TiledDataSource.java
index 27aeda0..77695e5 100644
--- a/paging/common/src/main/java/android/arch/paging/TiledDataSource.java
+++ b/paging/common/src/main/java/android/arch/paging/TiledDataSource.java
@@ -46,18 +46,17 @@
     public abstract List<T> loadRange(int startPosition, int count);
 
     @Override
-    public void loadInitial(int requestedStartPosition, int requestedLoadSize, int pageSize,
-            @NonNull InitialLoadCallback<T> callback) {
+    public void loadInitial(@NonNull LoadInitialParams params,
+            @NonNull LoadInitialCallback<T> callback) {
         int totalCount = countItems();
         if (totalCount == 0) {
-            callback.onResult(Collections.<T>emptyList());
+            callback.onResult(Collections.<T>emptyList(), 0, 0);
             return;
         }
 
         // bound the size requested, based on known count
-        final int firstLoadPosition = computeFirstLoadPosition(
-                requestedStartPosition, requestedLoadSize, pageSize, totalCount);
-        final int firstLoadSize = Math.min(totalCount - firstLoadPosition, requestedLoadSize);
+        final int firstLoadPosition = computeInitialLoadPosition(params, totalCount);
+        final int firstLoadSize = computeInitialLoadSize(params, firstLoadPosition, totalCount);
 
         // convert from legacy behavior
         List<T> list = loadRange(firstLoadPosition, firstLoadSize);
@@ -69,8 +68,9 @@
     }
 
     @Override
-    public void loadRange(int startPosition, int count, @NonNull LoadCallback<T> callback) {
-        List<T> list = loadRange(startPosition, count);
+    public void loadRange(@NonNull LoadRangeParams params,
+            @NonNull LoadRangeCallback<T> callback) {
+        List<T> list = loadRange(params.startPosition, params.loadSize);
         if (list != null) {
             callback.onResult(list);
         } else {
diff --git a/paging/common/src/main/java/android/arch/paging/TiledPagedList.java b/paging/common/src/main/java/android/arch/paging/TiledPagedList.java
index 652b489..f7aae98 100644
--- a/paging/common/src/main/java/android/arch/paging/TiledPagedList.java
+++ b/paging/common/src/main/java/android/arch/paging/TiledPagedList.java
@@ -92,15 +92,8 @@
             final int idealStart = position - firstLoadSize / 2;
             final int roundedPageStart = Math.max(0, Math.round(idealStart / pageSize) * pageSize);
 
-            DataSource.InitialLoadCallback<T> callback = new DataSource.InitialLoadCallback<>(
-                            DataSource.LOAD_COUNT_REQUIRED_TILED,
-                    mConfig.pageSize, mDataSource, mReceiver);
-            mDataSource.loadInitial(roundedPageStart, firstLoadSize, pageSize, callback);
-
-            // If initialLoad's callback is not called within the body, we force any following calls
-            // to post to the UI thread. This constructor may be run on a background thread, but
-            // after constructor, mutation must happen on UI thread.
-            callback.setPostExecutor(mMainThreadExecutor);
+            mDataSource.dispatchLoadInitial(true, roundedPageStart, firstLoadSize,
+                    pageSize, mMainThreadExecutor, mReceiver);
         }
     }
 
@@ -185,10 +178,8 @@
                 } else {
                     int startPosition = pageIndex * pageSize;
                     int count = Math.min(pageSize, mStorage.size() - startPosition);
-                    DataSource.LoadCallback<T> callback = new DataSource.LoadCallback<>(
-                            PageResult.TILE, mMainThreadExecutor, mDataSource, mReceiver);
-                    callback.setPositionOffset(startPosition);
-                    mDataSource.loadRange(startPosition, count, callback);
+                    mDataSource.dispatchLoadRange(
+                            startPosition, count, mMainThreadExecutor, mReceiver);
                 }
             }
         });
diff --git a/paging/common/src/test/java/android/arch/paging/AsyncListDataSource.kt b/paging/common/src/test/java/android/arch/paging/AsyncListDataSource.kt
index 48d6e29..e1c113d 100644
--- a/paging/common/src/test/java/android/arch/paging/AsyncListDataSource.kt
+++ b/paging/common/src/test/java/android/arch/paging/AsyncListDataSource.kt
@@ -18,19 +18,18 @@
 
 class AsyncListDataSource<T>(list: List<T>)
     : PositionalDataSource<T>() {
-    val workItems: MutableList<() -> Unit> = ArrayList()
+    private val workItems: MutableList<() -> Unit> = ArrayList()
     private val listDataSource = ListDataSource(list)
 
-    override fun loadInitial(requestedStartPosition: Int, requestedLoadSize: Int, pageSize: Int,
-            callback: InitialLoadCallback<T>) {
+    override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<T>) {
         workItems.add {
-            listDataSource.loadInitial(requestedStartPosition, requestedLoadSize, pageSize, callback)
+            listDataSource.loadInitial(params, callback)
         }
     }
 
-    override fun loadRange(startPosition: Int, count: Int, callback: LoadCallback<T>) {
+    override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<T>) {
         workItems.add {
-            listDataSource.loadRange(startPosition, count, callback)
+            listDataSource.loadRange(params, callback)
         }
     }
 
diff --git a/paging/common/src/test/java/android/arch/paging/ContiguousPagedListTest.kt b/paging/common/src/test/java/android/arch/paging/ContiguousPagedListTest.kt
index 5ae0f9f..cc53c1b 100644
--- a/paging/common/src/test/java/android/arch/paging/ContiguousPagedListTest.kt
+++ b/paging/common/src/test/java/android/arch/paging/ContiguousPagedListTest.kt
@@ -27,7 +27,7 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.Mockito.verifyZeroInteractions
-
+import java.util.concurrent.Executor
 
 @RunWith(Parameterized::class)
 class ContiguousPagedListTest(private val mCounted: Boolean) {
@@ -44,33 +44,56 @@
 
     private inner class TestSource(val listData: List<Item> = ITEMS)
             : ContiguousDataSource<Int, Item>() {
-        override fun loadInitial(key: Int?, initialLoadSize: Int,
-                enablePlaceholders: Boolean, callback: InitialLoadCallback<Item>) {
+        override fun dispatchLoadInitial(
+                key: Int?,
+                initialLoadSize: Int,
+                pageSize: Int,
+                enablePlaceholders: Boolean,
+                mainThreadExecutor: Executor,
+                receiver: PageResult.Receiver<Item>) {
 
             val convertPosition = key ?: 0
-            val loadPosition = Math.max(0, (convertPosition - initialLoadSize / 2))
-
-            val data = getClampedRange(loadPosition, loadPosition + initialLoadSize)
-
+            val position = Math.max(0, (convertPosition - initialLoadSize / 2))
+            val data = getClampedRange(position, position + initialLoadSize)
+            val trailingUnloadedCount = listData.size - position - data.size
 
             if (enablePlaceholders && mCounted) {
-                callback.onResult(data, loadPosition, listData.size)
+                receiver.onPageResult(PageResult.INIT,
+                        PageResult(data, position, trailingUnloadedCount, 0))
             } else {
                 // still must pass offset, even if not counted
-                callback.onResult(data, loadPosition)
+                receiver.onPageResult(PageResult.INIT,
+                        PageResult(data, position))
             }
         }
 
-        override fun loadAfter(currentEndIndex: Int, currentEndItem: Item, pageSize: Int,
-                callback: LoadCallback<Item>) {
+        override fun dispatchLoadAfter(
+                currentEndIndex: Int,
+                currentEndItem: Item,
+                pageSize: Int,
+                mainThreadExecutor: Executor,
+                receiver: PageResult.Receiver<Item>) {
             val startIndex = currentEndIndex + 1
-            callback.onResult(getClampedRange(startIndex, startIndex + pageSize))
+            val data = getClampedRange(startIndex, startIndex + pageSize)
+
+            mainThreadExecutor.execute {
+                receiver.onPageResult(PageResult.APPEND, PageResult(data, 0, 0, 0))
+            }
         }
 
-        override fun loadBefore(currentBeginIndex: Int, currentBeginItem: Item, pageSize: Int,
-                callback: LoadCallback<Item>) {
+        override fun dispatchLoadBefore(
+                currentBeginIndex: Int,
+                currentBeginItem: Item,
+                pageSize: Int,
+                mainThreadExecutor: Executor,
+                receiver: PageResult.Receiver<Item>) {
+
             val startIndex = currentBeginIndex - 1
-            callback.onResult(getClampedRange(startIndex - pageSize + 1, startIndex + 1))
+            val data = getClampedRange(startIndex - pageSize + 1, startIndex + 1)
+
+            mainThreadExecutor.execute {
+                receiver.onPageResult(PageResult.PREPEND, PageResult(data, 0, 0, 0))
+            }
         }
 
         override fun getKey(position: Int, item: Item?): Int {
@@ -95,7 +118,6 @@
                     actual.storageCount)
             assertEquals(start, actual.leadingNullCount)
             assertEquals(expectedTrailing, actual.trailingNullCount)
-
         } else {
             assertEquals(ITEMS.subList(start, start + count), actual)
 
@@ -116,8 +138,8 @@
             initLoadSize: Int = 40,
             prefetchDistance: Int = 20,
             listData: List<Item> = ITEMS,
-            boundaryCallback: PagedList.BoundaryCallback<Item>? = null)
-            : ContiguousPagedList<Int, Item> {
+            boundaryCallback: PagedList.BoundaryCallback<Item>? = null
+    ): ContiguousPagedList<Int, Item> {
         return ContiguousPagedList(
                 TestSource(listData), mMainThread, mBackgroundThread, boundaryCallback,
                 PagedList.Config.Builder()
@@ -294,6 +316,8 @@
         val pagedList = ContiguousPagedList(
                 dataSource, mMainThread, mBackgroundThread, null,
                 PagedList.Config.Builder().setPageSize(10).build(), null)
+        val callback = mock(PagedList.Callback::class.java)
+        pagedList.addWeakCallback(null, callback)
 
         assertTrue(pagedList.isEmpty())
         drain()
@@ -302,11 +326,14 @@
         assertTrue(pagedList.isEmpty())
         mBackgroundThread.executeAll()
         assertTrue(pagedList.isEmpty())
+        verifyZeroInteractions(callback)
 
         // Data source defers callbacks until flush, which posts result to main thread
         mMainThread.executeAll()
         assertFalse(pagedList.isEmpty())
-
+        // callback onInsert called once with initial size
+        verify(callback).onInserted(0, pagedList.size)
+        verifyNoMoreInteractions(callback)
     }
 
     @Test
@@ -367,7 +394,6 @@
                 initLoadSize = 20, prefetchDistance = 5, boundaryCallback = boundaryCallback)
         verifyRange(80, 20, pagedList)
 
-
         // nothing yet
         verifyZeroInteractions(boundaryCallback)
         drain()
@@ -380,7 +406,6 @@
         verify(boundaryCallback).onItemAtEndLoaded(ITEMS.last())
         verifyNoMoreInteractions(boundaryCallback)
 
-
         // prepending doesn't trigger callback...
         pagedList.loadAround(if (mCounted) 80 else 0)
         drain()
diff --git a/paging/common/src/test/java/android/arch/paging/TestExecutor.kt b/paging/common/src/test/java/android/arch/paging/Executors.kt
similarity index 79%
rename from paging/common/src/test/java/android/arch/paging/TestExecutor.kt
rename to paging/common/src/test/java/android/arch/paging/Executors.kt
index 7034aa0..e1c45a7 100644
--- a/paging/common/src/test/java/android/arch/paging/TestExecutor.kt
+++ b/paging/common/src/test/java/android/arch/paging/Executors.kt
@@ -16,14 +16,15 @@
 
 package android.arch.paging
 
+import org.junit.Assert.fail
 import java.util.LinkedList
 import java.util.concurrent.Executor
 
 class TestExecutor : Executor {
     private val mTasks = LinkedList<Runnable>()
 
-    override fun execute(command: Runnable) {
-        mTasks.add(command)
+    override fun execute(runnable: Runnable) {
+        mTasks.add(runnable)
     }
 
     internal fun executeAll(): Boolean {
@@ -37,3 +38,9 @@
         return consumed
     }
 }
+
+class FailExecutor(val string: String = "Executor expected to be unused") : Executor {
+    override fun execute(runnable: Runnable?) {
+        fail(string)
+    }
+}
diff --git a/paging/common/src/test/java/android/arch/paging/KeyedDataSourceTest.kt b/paging/common/src/test/java/android/arch/paging/ItemKeyedDataSourceTest.kt
similarity index 60%
rename from paging/common/src/test/java/android/arch/paging/KeyedDataSourceTest.kt
rename to paging/common/src/test/java/android/arch/paging/ItemKeyedDataSourceTest.kt
index 82ad9ac..4998d06 100644
--- a/paging/common/src/test/java/android/arch/paging/KeyedDataSourceTest.kt
+++ b/paging/common/src/test/java/android/arch/paging/ItemKeyedDataSourceTest.kt
@@ -19,6 +19,7 @@
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
 import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -29,7 +30,7 @@
 import org.mockito.Mockito.verifyNoMoreInteractions
 
 @RunWith(JUnit4::class)
-class KeyedDataSourceTest {
+class ItemKeyedDataSourceTest {
 
     // ----- STANDARD -----
 
@@ -41,10 +42,8 @@
         val captor = ArgumentCaptor.forClass(PageResult::class.java)
                 as ArgumentCaptor<PageResult<Item>>
 
-        val callback = DataSource.InitialLoadCallback(
-                DataSource.LOAD_COUNT_ACCEPTED, /* ignored page size */ 10, dataSource, receiver)
-
-        dataSource.loadInitial(key, initialLoadSize, enablePlaceholders, callback)
+        dataSource.dispatchLoadInitial(key, initialLoadSize,
+                /* ignored pageSize */ 10, enablePlaceholders, FailExecutor(), receiver)
 
         verify(receiver).onPageResult(anyInt(), captor.capture())
         verifyNoMoreInteractions(receiver)
@@ -91,7 +90,7 @@
     fun loadInitial_nullKey() {
         val dataSource = ItemDataSource()
 
-        // loadInitial(null, count) == loadInitial(count)
+        // dispatchLoadInitial(null, count) == dispatchLoadInitial(count)
         val result = loadInitial(dataSource, null, 10, true)
 
         assertEquals(0, result.leadingNulls)
@@ -121,7 +120,7 @@
     fun loadInitial_disablePlaceholders() {
         val dataSource = ItemDataSource()
 
-        // loadInitial(key, count) == null padding, loadAfter(key, count), null padding
+        // dispatchLoadInitial(key, count) == null padding, loadAfter(key, count), null padding
         val key = dataSource.getKey(ITEMS_BY_NAME_ID[49])
         val result = loadInitial(dataSource, key, 10, false)
 
@@ -134,7 +133,7 @@
     fun loadInitial_uncounted() {
         val dataSource = ItemDataSource(counted = false)
 
-        // loadInitial(key, count) == null padding, loadAfter(key, count), null padding
+        // dispatchLoadInitial(key, count) == null padding, loadAfter(key, count), null padding
         val key = dataSource.getKey(ITEMS_BY_NAME_ID[49])
         val result = loadInitial(dataSource, key, 10, true)
 
@@ -147,7 +146,7 @@
     fun loadInitial_nullKey_uncounted() {
         val dataSource = ItemDataSource(counted = false)
 
-        // loadInitial(null, count) == loadInitial(count)
+        // dispatchLoadInitial(null, count) == dispatchLoadInitial(count)
         val result = loadInitial(dataSource, null, 10, true)
 
         assertEquals(0, result.leadingNulls)
@@ -161,7 +160,7 @@
     fun loadInitial_empty() {
         val dataSource = ItemDataSource(items = ArrayList())
 
-        // loadInitial(key, count) == null padding, loadAfter(key, count), null padding
+        // dispatchLoadInitial(key, count) == null padding, loadAfter(key, count), null padding
         val key = dataSource.getKey(ITEMS_BY_NAME_ID[49])
         val result = loadInitial(dataSource, key, 10, true)
 
@@ -186,9 +185,11 @@
     fun loadBefore() {
         val dataSource = ItemDataSource()
         @Suppress("UNCHECKED_CAST")
-        val callback = mock(DataSource.LoadCallback::class.java) as DataSource.LoadCallback<Item>
+        val callback = mock(ItemKeyedDataSource.LoadCallback::class.java)
+                as ItemKeyedDataSource.LoadCallback<Item>
 
-        dataSource.loadBefore(5, ITEMS_BY_NAME_ID[5], 5, callback)
+        dataSource.loadBefore(
+                ItemKeyedDataSource.LoadParams(dataSource.getKey(ITEMS_BY_NAME_ID[5]), 5), callback)
 
         @Suppress("UNCHECKED_CAST")
         val argument = ArgumentCaptor.forClass(List::class.java) as ArgumentCaptor<List<Item>>
@@ -207,32 +208,33 @@
 
     internal class ItemDataSource(private val counted: Boolean = true,
                                   private val items: List<Item> = ITEMS_BY_NAME_ID)
-            : KeyedDataSource<Key, Item>() {
-        override fun loadInitial(initialLoadKey: Key?, initialLoadSize: Int,
-                enablePlaceholders: Boolean, callback: InitialLoadCallback<Item>) {
-            val key = initialLoadKey ?: Key("", Integer.MAX_VALUE)
-            val start = Math.max(0, findFirstIndexAfter(key) - initialLoadSize / 2)
-            val endExclusive = Math.min(start + initialLoadSize, items.size)
+            : ItemKeyedDataSource<Key, Item>() {
 
+        override fun loadInitial(
+                params: LoadInitialParams<Key>,
+                callback: LoadInitialCallback<Item>) {
+            val key = params.requestedInitialKey ?: Key("", Integer.MAX_VALUE)
+            val start = Math.max(0, findFirstIndexAfter(key) - params.requestedLoadSize / 2)
+            val endExclusive = Math.min(start + params.requestedLoadSize, items.size)
 
-            if (enablePlaceholders && counted) {
+            if (params.placeholdersEnabled && counted) {
                 callback.onResult(items.subList(start, endExclusive), start, items.size)
             } else {
                 callback.onResult(items.subList(start, endExclusive))
             }
         }
 
-        override fun loadAfter(currentEndKey: Key, pageSize: Int, callback: LoadCallback<Item>) {
-            val start = findFirstIndexAfter(currentEndKey)
-            val endExclusive = Math.min(start + pageSize, items.size)
+        override fun loadAfter(params: LoadParams<Key>, callback: LoadCallback<Item>) {
+            val start = findFirstIndexAfter(params.key)
+            val endExclusive = Math.min(start + params.requestedLoadSize, items.size)
 
             callback.onResult(items.subList(start, endExclusive))
         }
 
-        override fun loadBefore(currentBeginKey: Key, pageSize: Int, callback: LoadCallback<Item>) {
-            val firstIndexBefore = findFirstIndexBefore(currentBeginKey)
+        override fun loadBefore(params: LoadParams<Key>, callback: LoadCallback<Item>) {
+            val firstIndexBefore = findFirstIndexBefore(params.key)
             val endExclusive = Math.max(0, firstIndexBefore + 1)
-            val start = Math.max(0, firstIndexBefore - pageSize + 1)
+            val start = Math.max(0, firstIndexBefore - params.requestedLoadSize + 1)
 
             callback.onResult(items.subList(start, endExclusive))
         }
@@ -254,16 +256,94 @@
         }
     }
 
+    private fun performLoadInitial(
+            invalidateDataSource: Boolean = false,
+            callbackInvoker: (callback: ItemKeyedDataSource.LoadInitialCallback<String>) -> Unit) {
+        val dataSource = object : ItemKeyedDataSource<String, String>() {
+            override fun getKey(item: String): String {
+                return ""
+            }
+
+            override fun loadInitial(
+                    params: LoadInitialParams<String>,
+                    callback: LoadInitialCallback<String>) {
+                if (invalidateDataSource) {
+                    // invalidate data source so it's invalid when onResult() called
+                    invalidate()
+                }
+                callbackInvoker(callback)
+            }
+
+            override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<String>) {
+                fail("loadAfter not expected")
+            }
+
+            override fun loadBefore(params: LoadParams<String>, callback: LoadCallback<String>) {
+                fail("loadBefore not expected")
+            }
+        }
+
+        ContiguousPagedList<String, String>(
+                dataSource, FailExecutor(), FailExecutor(), null,
+                PagedList.Config.Builder()
+                        .setPageSize(10)
+                        .build(),
+                "")
+    }
+
+    @Test
+    fun loadInitialCallbackSuccess() = performLoadInitial {
+        // LoadInitialCallback correct usage
+        it.onResult(listOf("a", "b"), 0, 2)
+    }
+
+    @Test
+    fun loadInitialCallbackNotPageSizeMultiple() = performLoadInitial {
+        // Keyed LoadInitialCallback *can* accept result that's not a multiple of page size
+        val elevenLetterList = List(11) { "" + 'a' + it }
+        it.onResult(elevenLetterList, 0, 12)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun loadInitialCallbackListTooBig() = performLoadInitial {
+        // LoadInitialCallback can't accept pos + list > totalCount
+        it.onResult(listOf("a", "b", "c"), 0, 2)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun loadInitialCallbackPositionTooLarge() = performLoadInitial {
+        // LoadInitialCallback can't accept pos + list > totalCount
+        it.onResult(listOf("a", "b"), 1, 2)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun loadInitialCallbackPositionNegative() = performLoadInitial {
+        // LoadInitialCallback can't accept negative position
+        it.onResult(listOf("a", "b", "c"), -1, 2)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun loadInitialCallbackEmptyCannotHavePlaceholders() = performLoadInitial {
+        // LoadInitialCallback can't accept empty result unless data set is empty
+        it.onResult(emptyList(), 0, 2)
+    }
+
+    @Test
+    fun initialLoadCallbackInvalidThreeArg() = performLoadInitial(invalidateDataSource = true) {
+        // LoadInitialCallback doesn't throw on invalid args if DataSource is invalid
+        it.onResult(emptyList(), 0, 1)
+    }
+
     companion object {
-        private val ITEM_COMPARATOR = compareBy<Item>( {it.name} ).thenByDescending( {it.id} )
-        private val KEY_COMPARATOR = compareBy<Key>( {it.name} ).thenByDescending( {it.id} )
+        private val ITEM_COMPARATOR = compareBy<Item>({ it.name }).thenByDescending({ it.id })
+        private val KEY_COMPARATOR = compareBy<Key>({ it.name }).thenByDescending({ it.id })
 
         private val ITEMS_BY_NAME_ID = List(100) {
             val names = Array(10) { "f" + ('a' + it) }
             Item(names[it % 10],
-                 it,
-                 Math.random() * 1000,
-                 (Math.random() * 200).toInt().toString() + " fake st.")
+                    it,
+                    Math.random() * 1000,
+                    (Math.random() * 200).toInt().toString() + " fake st.")
         }.sortedWith(ITEM_COMPARATOR)
     }
 }
diff --git a/paging/common/src/test/java/android/arch/paging/PageKeyedDataSourceTest.kt b/paging/common/src/test/java/android/arch/paging/PageKeyedDataSourceTest.kt
new file mode 100644
index 0000000..d4bbbb5
--- /dev/null
+++ b/paging/common/src/test/java/android/arch/paging/PageKeyedDataSourceTest.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.arch.paging
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class PageKeyedDataSourceTest {
+    private val mMainThread = TestExecutor()
+    private val mBackgroundThread = TestExecutor()
+
+    internal data class Item(val name: String)
+
+    internal data class Page(val prev: String?, val data: List<Item>, val next: String?)
+
+    internal class ItemDataSource(val data: Map<String, Page> = PAGE_MAP)
+            : PageKeyedDataSource<String, Item>() {
+
+        private fun getPage(key: String): Page = data[key]!!
+
+        override fun loadInitial(
+                params: LoadInitialParams<String>,
+                callback: LoadInitialCallback<String, Item>) {
+            val page = getPage(INIT_KEY)
+            callback.onResult(page.data, page.prev, page.next)
+        }
+
+        override fun loadBefore(params: LoadParams<String>, callback: LoadCallback<String, Item>) {
+            val page = getPage(params.key)
+            callback.onResult(page.data, page.prev)
+        }
+
+        override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<String, Item>) {
+            val page = getPage(params.key)
+            callback.onResult(page.data, page.next)
+        }
+    }
+
+    @Test
+    fun loadFullVerify() {
+        // validate paging entire ItemDataSource results in full, correctly ordered data
+        val pagedList = ContiguousPagedList<String, Item>(ItemDataSource(),
+                mMainThread, mBackgroundThread,
+                null, PagedList.Config.Builder().setPageSize(100).build(), null)
+
+        // validate initial load
+        assertEquals(PAGE_MAP[INIT_KEY]!!.data, pagedList)
+
+        // flush the remaining loads
+        for (i in 0..PAGE_MAP.keys.size) {
+            pagedList.loadAround(0)
+            pagedList.loadAround(pagedList.size - 1)
+            drain()
+        }
+
+        // validate full load
+        assertEquals(ITEM_LIST, pagedList)
+    }
+
+    private fun performLoadInitial(invalidateDataSource: Boolean = false,
+            callbackInvoker:
+                    (callback: PageKeyedDataSource.LoadInitialCallback<String, String>) -> Unit) {
+        val dataSource = object : PageKeyedDataSource<String, String>() {
+            override fun loadInitial(
+                    params: LoadInitialParams<String>,
+                    callback: LoadInitialCallback<String, String>) {
+                if (invalidateDataSource) {
+                    // invalidate data source so it's invalid when onResult() called
+                    invalidate()
+                }
+                callbackInvoker(callback)
+            }
+
+            override fun loadBefore(
+                    params: LoadParams<String>,
+                    callback: LoadCallback<String, String>) {
+                fail("loadBefore not expected")
+            }
+
+            override fun loadAfter(
+                    params: LoadParams<String>,
+                    callback: LoadCallback<String, String>) {
+                fail("loadAfter not expected")
+            }
+        }
+
+        ContiguousPagedList<String, String>(
+                dataSource, FailExecutor(), FailExecutor(), null,
+                PagedList.Config.Builder()
+                        .setPageSize(10)
+                        .build(),
+                "")
+    }
+
+    @Test
+    fun loadInitialCallbackSuccess() = performLoadInitial {
+        // LoadInitialCallback correct usage
+        it.onResult(listOf("a", "b"), 0, 2, null, null)
+    }
+
+    @Test
+    fun loadInitialCallbackNotPageSizeMultiple() = performLoadInitial {
+        // Keyed LoadInitialCallback *can* accept result that's not a multiple of page size
+        val elevenLetterList = List(11) { "" + 'a' + it }
+        it.onResult(elevenLetterList, 0, 12, null, null)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun loadInitialCallbackListTooBig() = performLoadInitial {
+        // LoadInitialCallback can't accept pos + list > totalCount
+        it.onResult(listOf("a", "b", "c"), 0, 2, null, null)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun loadInitialCallbackPositionTooLarge() = performLoadInitial {
+        // LoadInitialCallback can't accept pos + list > totalCount
+        it.onResult(listOf("a", "b"), 1, 2, null, null)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun loadInitialCallbackPositionNegative() = performLoadInitial {
+        // LoadInitialCallback can't accept negative position
+        it.onResult(listOf("a", "b", "c"), -1, 2, null, null)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun loadInitialCallbackEmptyCannotHavePlaceholders() = performLoadInitial {
+        // LoadInitialCallback can't accept empty result unless data set is empty
+        it.onResult(emptyList(), 0, 2, null, null)
+    }
+
+    @Test
+    fun initialLoadCallbackInvalidThreeArg() = performLoadInitial(invalidateDataSource = true) {
+        // LoadInitialCallback doesn't throw on invalid args if DataSource is invalid
+        it.onResult(emptyList(), 0, 1, null, null)
+    }
+
+    companion object {
+        // first load is 2nd page to ensure we test prepend as well as append behavior
+        private val INIT_KEY: String = "key 2"
+        private val PAGE_MAP: Map<String, Page>
+        private val ITEM_LIST: List<Item>
+
+        init {
+            val map = HashMap<String, Page>()
+            val list = ArrayList<Item>()
+            val pageCount = 5
+            for (i in 1..pageCount) {
+                val data = List(4) { Item("name $i $it") }
+                list.addAll(data)
+
+                val key = "key $i"
+                val prev = if (i > 1) ("key " + (i - 1)) else null
+                val next = if (i < pageCount) ("key " + (i + 1)) else null
+                map.put(key, Page(prev, data, next))
+            }
+            PAGE_MAP = map
+            ITEM_LIST = list
+        }
+    }
+
+    private fun drain() {
+        var executed: Boolean
+        do {
+            executed = mBackgroundThread.executeAll()
+            executed = mMainThread.executeAll() || executed
+        } while (executed)
+    }
+}
diff --git a/paging/common/src/test/java/android/arch/paging/PagedStorageTest.kt b/paging/common/src/test/java/android/arch/paging/PagedStorageTest.kt
index 8fb54e0..9b53f62 100644
--- a/paging/common/src/test/java/android/arch/paging/PagedStorageTest.kt
+++ b/paging/common/src/test/java/android/arch/paging/PagedStorageTest.kt
@@ -48,7 +48,6 @@
         val storage = PagedStorage(2, createPage("a", "b"), 2)
         storage.appendPage(createPage("c", "d"), callback)
 
-
         assertArrayEquals(arrayOf(null, null, "a", "b", "c", "d"), storage.toArray())
         verify(callback).onPageAppended(4, 2, 0)
         verifyNoMoreInteractions(callback)
@@ -106,7 +105,6 @@
         val storage = PagedStorage(0, createPage("c", "d"), 2)
         storage.prependPage(createPage("a", "b"), callback)
 
-
         assertArrayEquals(arrayOf("a", "b", "c", "d", null, null), storage.toArray())
         verify(callback).onPagePrepended(0, 0, 2)
         verifyNoMoreInteractions(callback)
@@ -361,7 +359,6 @@
         storage.allocatePlaceholders(0, 2, 1, callback)
     }
 
-
     @Test(expected = IllegalArgumentException::class)
     fun allocatePlaceholders_cannotAdoptPageSize() {
         val callback = mock(PagedStorage.Callback::class.java)
diff --git a/paging/common/src/test/java/android/arch/paging/PositionalDataSourceTest.kt b/paging/common/src/test/java/android/arch/paging/PositionalDataSourceTest.kt
index 34e0a57..1113777 100644
--- a/paging/common/src/test/java/android/arch/paging/PositionalDataSourceTest.kt
+++ b/paging/common/src/test/java/android/arch/paging/PositionalDataSourceTest.kt
@@ -17,34 +17,170 @@
 package android.arch.paging
 
 import org.junit.Assert.assertEquals
+import org.junit.Assert.fail
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 
 @RunWith(JUnit4::class)
 class PositionalDataSourceTest {
-    @Test
-    fun computeFirstLoadPositionZero() {
-        assertEquals(0, PositionalDataSource.computeFirstLoadPosition(0, 30, 10, 100))
+    private fun computeInitialLoadPos(
+            requestedStartPosition: Int,
+            requestedLoadSize: Int,
+            pageSize: Int,
+            totalCount: Int): Int {
+        val params = PositionalDataSource.LoadInitialParams(
+                requestedStartPosition, requestedLoadSize, pageSize, true)
+        return PositionalDataSource.computeInitialLoadPosition(params, totalCount)
     }
 
     @Test
-    fun computeFirstLoadPositionRequestedPositionIncluded() {
-        assertEquals(10, PositionalDataSource.computeFirstLoadPosition(10, 10, 10, 100))
+    fun computeInitialLoadPositionZero() {
+        assertEquals(0, computeInitialLoadPos(
+                requestedStartPosition = 0,
+                requestedLoadSize = 30,
+                pageSize = 10,
+                totalCount = 100))
     }
 
     @Test
-    fun computeFirstLoadPositionRound() {
-        assertEquals(10, PositionalDataSource.computeFirstLoadPosition(13, 30, 10, 100))
+    fun computeInitialLoadPositionRequestedPositionIncluded() {
+        assertEquals(10, computeInitialLoadPos(
+                requestedStartPosition = 10,
+                requestedLoadSize = 10,
+                pageSize = 10,
+                totalCount = 100))
     }
 
     @Test
-    fun computeFirstLoadPositionEndAdjusted() {
-        assertEquals(70, PositionalDataSource.computeFirstLoadPosition(99, 30, 10, 100))
+    fun computeInitialLoadPositionRound() {
+        assertEquals(10, computeInitialLoadPos(
+                requestedStartPosition = 13,
+                requestedLoadSize = 30,
+                pageSize = 10,
+                totalCount = 100))
     }
 
     @Test
-    fun computeFirstLoadPositionEndAdjustedAndAligned() {
-        assertEquals(70, PositionalDataSource.computeFirstLoadPosition(99, 35, 10, 100))
+    fun computeInitialLoadPositionEndAdjusted() {
+        assertEquals(70, computeInitialLoadPos(
+                requestedStartPosition = 99,
+                requestedLoadSize = 30,
+                pageSize = 10,
+                totalCount = 100))
+    }
+
+    @Test
+    fun computeInitialLoadPositionEndAdjustedAndAligned() {
+        assertEquals(70, computeInitialLoadPos(
+                requestedStartPosition = 99,
+                requestedLoadSize = 35,
+                pageSize = 10,
+                totalCount = 100))
+    }
+
+    private fun performLoadInitial(
+            enablePlaceholders: Boolean = true,
+            invalidateDataSource: Boolean = false,
+            callbackInvoker: (callback: PositionalDataSource.LoadInitialCallback<String>) -> Unit) {
+        val dataSource = object : PositionalDataSource<String>() {
+            override fun loadInitial(
+                    params: LoadInitialParams,
+                    callback: LoadInitialCallback<String>) {
+                if (invalidateDataSource) {
+                    // invalidate data source so it's invalid when onResult() called
+                    invalidate()
+                }
+                callbackInvoker(callback)
+            }
+
+            override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<String>) {
+                fail("loadRange not expected")
+            }
+        }
+
+        val config = PagedList.Config.Builder()
+                .setPageSize(10)
+                .setEnablePlaceholders(enablePlaceholders)
+                .build()
+        if (enablePlaceholders) {
+            TiledPagedList(dataSource, FailExecutor(), FailExecutor(), null, config, 0)
+        } else {
+            ContiguousPagedList(dataSource.wrapAsContiguousWithoutPlaceholders(),
+                    FailExecutor(), FailExecutor(), null, config, null)
+        }
+    }
+
+    @Test
+    fun initialLoadCallbackSuccess() = performLoadInitial {
+        // LoadInitialCallback correct usage
+        it.onResult(listOf("a", "b"), 0, 2)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun initialLoadCallbackNotPageSizeMultiple() = performLoadInitial {
+        // Positional LoadInitialCallback can't accept result that's not a multiple of page size
+        val elevenLetterList = List(11) { "" + 'a' + it }
+        it.onResult(elevenLetterList, 0, 12)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun initialLoadCallbackListTooBig() = performLoadInitial {
+        // LoadInitialCallback can't accept pos + list > totalCount
+        it.onResult(listOf("a", "b", "c"), 0, 2)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun initialLoadCallbackPositionTooLarge() = performLoadInitial {
+        // LoadInitialCallback can't accept pos + list > totalCount
+        it.onResult(listOf("a", "b"), 1, 2)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun initialLoadCallbackPositionNegative() = performLoadInitial {
+        // LoadInitialCallback can't accept negative position
+        it.onResult(listOf("a", "b", "c"), -1, 2)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun initialLoadCallbackEmptyCannotHavePlaceholders() = performLoadInitial {
+        // LoadInitialCallback can't accept empty result unless data set is empty
+        it.onResult(emptyList(), 0, 2)
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun initialLoadCallbackRequireTotalCount() = performLoadInitial(enablePlaceholders = true) {
+        // LoadInitialCallback requires 3 args when placeholders enabled
+        it.onResult(listOf("a", "b"), 0)
+    }
+
+    @Test
+    fun initialLoadCallbackSuccessTwoArg() = performLoadInitial(enablePlaceholders = false) {
+        // LoadInitialCallback correct 2 arg usage
+        it.onResult(listOf("a", "b"), 0)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun initialLoadCallbackPosNegativeTwoArg() = performLoadInitial(enablePlaceholders = false) {
+        // LoadInitialCallback can't accept negative position
+        it.onResult(listOf("a", "b"), -1)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun initialLoadCallbackEmptyWithOffset() = performLoadInitial(enablePlaceholders = false) {
+        // LoadInitialCallback can't accept empty result unless pos is 0
+        it.onResult(emptyList(), 1)
+    }
+
+    @Test
+    fun initialLoadCallbackInvalidTwoArg() = performLoadInitial(invalidateDataSource = true) {
+        // LoadInitialCallback doesn't throw on invalid args if DataSource is invalid
+        it.onResult(emptyList(), 1)
+    }
+
+    @Test
+    fun initialLoadCallbackInvalidThreeArg() = performLoadInitial(invalidateDataSource = true) {
+        // LoadInitialCallback doesn't throw on invalid args if DataSource is invalid
+        it.onResult(emptyList(), 0, 1)
     }
 }
diff --git a/paging/common/src/test/java/android/arch/paging/TiledDataSourceTest.kt b/paging/common/src/test/java/android/arch/paging/TiledDataSourceTest.kt
index fe8b9e8..f41e6a6 100644
--- a/paging/common/src/test/java/android/arch/paging/TiledDataSourceTest.kt
+++ b/paging/common/src/test/java/android/arch/paging/TiledDataSourceTest.kt
@@ -31,15 +31,12 @@
 @RunWith(JUnit4::class)
 class TiledDataSourceTest {
 
-    fun TiledDataSource<String>.loadInitial(startPosition: Int, count: Int, pageSize: Int)
-            : List<String> {
+    fun TiledDataSource<String>.loadInitial(
+            startPosition: Int, count: Int, pageSize: Int): List<String> {
         @Suppress("UNCHECKED_CAST")
         val receiver = mock(PageResult.Receiver::class.java) as PageResult.Receiver<String>
 
-        val callback = DataSource.InitialLoadCallback(
-                DataSource.LOAD_COUNT_REQUIRED_TILED, pageSize, this, receiver)
-
-        this.loadInitial(startPosition, count, pageSize, callback)
+        this.dispatchLoadInitial(true, startPosition, count, pageSize, FailExecutor(), receiver)
 
         @Suppress("UNCHECKED_CAST")
         val argument = ArgumentCaptor.forClass(PageResult::class.java)
@@ -69,7 +66,7 @@
 
     @Test
     fun loadInitialTooLong() {
-        val list = List(26) { "" + 'a' + it}
+        val list = List(26) { "" + 'a' + it }
         class AlphabetDataSource : TiledDataSource<String>() {
             override fun countItems(): Int {
                 return list.size
diff --git a/paging/common/src/test/java/android/arch/paging/TiledPagedListTest.kt b/paging/common/src/test/java/android/arch/paging/TiledPagedListTest.kt
index 3e2a60d..9069a1a 100644
--- a/paging/common/src/test/java/android/arch/paging/TiledPagedListTest.kt
+++ b/paging/common/src/test/java/android/arch/paging/TiledPagedListTest.kt
@@ -21,7 +21,6 @@
 import org.junit.Assert.assertNull
 import org.junit.Assert.assertSame
 import org.junit.Assert.assertTrue
-import org.junit.Assert.fail
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -399,74 +398,6 @@
         verifyNoMoreInteractions(boundaryCallback)
     }
 
-    private fun performInitialLoad(
-            callbackInvoker: (callback: DataSource.InitialLoadCallback<String>) -> Unit) {
-        val dataSource = object: PositionalDataSource<String>() {
-            override fun loadInitial(requestedStartPosition: Int, requestedLoadSize: Int,
-                    pageSize: Int, callback: InitialLoadCallback<String>) {
-                callbackInvoker(callback)
-            }
-            override fun loadRange(startPosition: Int, count: Int, callback: LoadCallback<String>) {
-                fail("loadRange not expected")
-            }
-        }
-        TiledPagedList(
-                dataSource, mMainThread, mBackgroundThread, null,
-                PagedList.Config.Builder()
-                        .setPageSize(PAGE_SIZE)
-                        .build(),
-                0)
-    }
-
-    @Test
-    fun initialLoadCallbackSuccess() = performInitialLoad {
-        // InitialLoadCallback correct usage
-        it.onResult(listOf("a", "b"), 0, 2)
-    }
-
-    @Test
-    fun initialLoadCallbackEmptySuccess() = performInitialLoad {
-        // InitialLoadCallback correct usage - empty special case
-        it.onResult(emptyList())
-    }
-
-    @Test(expected = IllegalArgumentException::class)
-    fun initialLoadCallbackNotPageSizeMultiple() = performInitialLoad {
-        // Positional InitialLoadCallback can't accept result that's not a multiple of page size
-        val elevenLetterList = List(11) { "" + 'a' + it }
-        it.onResult(elevenLetterList, 0, 12)
-    }
-
-    @Test(expected = IllegalArgumentException::class)
-    fun initialLoadCallbackMissingPlaceholders() = performInitialLoad {
-        // Positional InitialLoadCallback can't accept list-only call
-        it.onResult(listOf("a", "b"))
-    }
-
-    @Test(expected = IllegalArgumentException::class)
-    fun initialLoadCallbackListTooBig() = performInitialLoad {
-        // InitialLoadCallback can't accept pos + list > totalCount
-        it.onResult(listOf("a", "b", "c"), 0, 2)
-    }
-
-    @Test(expected = IllegalArgumentException::class)
-    fun initialLoadCallbackPositionTooLarge() = performInitialLoad {
-        // InitialLoadCallback can't accept pos + list > totalCount
-        it.onResult(listOf("a", "b"), 1, 2)
-    }
-
-    @Test(expected = IllegalArgumentException::class)
-    fun initialLoadCallbackPositionNegative() = performInitialLoad {
-        // InitialLoadCallback can't accept negative position
-        it.onResult(listOf("a", "b", "c"), -1, 2)
-    }
-
-    @Test(expected = IllegalArgumentException::class)
-    fun initialLoadCallbackEmptyCannotHavePlaceholders() = performInitialLoad {
-        // Positional InitialLoadCallback can't accept empty result unless data set is empty
-        it.onResult(emptyList(), 0, 2)
-    }
-
     private fun drain() {
         var executed: Boolean
         do {
diff --git a/paging/integration-tests/testapp/build.gradle b/paging/integration-tests/testapp/build.gradle
index fb19ba0..99c2ef6 100644
--- a/paging/integration-tests/testapp/build.gradle
+++ b/paging/integration-tests/testapp/build.gradle
@@ -15,8 +15,6 @@
  */
 apply plugin: 'com.android.application'
 
-project.ext.noDocs = true
-
 android {
     compileSdkVersion tools.current_sdk
     buildToolsVersion tools.build_tools_version
@@ -45,20 +43,19 @@
 }
 
 dependencies {
-    implementation project(':arch:runtime')
-    implementation project(':arch:common')
-    implementation project(':paging:common')
-    implementation project(':lifecycle:extensions')
-    implementation project(':lifecycle:runtime')
-    implementation project(':lifecycle:common')
-    implementation project(':paging:runtime')
+    implementation(project(":arch:runtime"))
+    implementation(project(":arch:common"))
+    implementation(project(":paging:common"))
+    implementation(project(":lifecycle:extensions"))
+    implementation(project(":lifecycle:runtime"))
+    implementation(project(":lifecycle:common"))
+    implementation(project(":paging:runtime"))
     implementation 'com.android.support:multidex:1.0.1'
 
     implementation libs.support.recyclerview, libs.support_exclude_config
     implementation libs.support.app_compat, libs.support_exclude_config
 }
 
-createAndroidCheckstyle(project)
 tasks['check'].dependsOn(tasks['connectedCheck'])
 
 uploadArchives.enabled = false
diff --git a/paging/integration-tests/testapp/src/main/java/android/arch/paging/integration/testapp/ItemDataSource.java b/paging/integration-tests/testapp/src/main/java/android/arch/paging/integration/testapp/ItemDataSource.java
index bbbfabb..c53d361 100644
--- a/paging/integration-tests/testapp/src/main/java/android/arch/paging/integration/testapp/ItemDataSource.java
+++ b/paging/integration-tests/testapp/src/main/java/android/arch/paging/integration/testapp/ItemDataSource.java
@@ -56,35 +56,19 @@
         return items;
     }
 
-    // TODO: open up this API in PositionalDataSource?
-    private static int computeFirstLoadPosition(int position, int firstLoadSize,
-            int pageSize, int size) {
-        int roundedPageStart = Math.round(position / pageSize) * pageSize;
-
-        // minimum start position is 0
-        roundedPageStart = Math.max(0, roundedPageStart);
-
-        // maximum start pos is that which will encompass end of list
-        int maximumLoadPage = ((size - firstLoadSize + pageSize - 1) / pageSize) * pageSize;
-        roundedPageStart = Math.min(maximumLoadPage, roundedPageStart);
-
-        return roundedPageStart;
+    @Override
+    public void loadInitial(@NonNull LoadInitialParams params,
+            @NonNull LoadInitialCallback<Item> callback) {
+        int position = computeInitialLoadPosition(params, COUNT);
+        int loadSize = computeInitialLoadSize(params, position, COUNT);
+        List<Item> data = loadRangeInternal(position, loadSize);
+        callback.onResult(data, position, COUNT);
     }
 
     @Override
-    public void loadInitial(int requestedStartPosition, int requestedLoadSize,
-            int pageSize, @NonNull InitialLoadCallback<Item> callback) {
-        requestedStartPosition = computeFirstLoadPosition(
-                requestedStartPosition, requestedLoadSize, pageSize, COUNT);
-
-        requestedLoadSize = Math.min(COUNT - requestedStartPosition, requestedLoadSize);
-        List<Item> data = loadRangeInternal(requestedStartPosition, requestedLoadSize);
-        callback.onResult(data, requestedStartPosition, COUNT);
-    }
-
-    @Override
-    public void loadRange(int startPosition, int count, @NonNull LoadCallback<Item> callback) {
-        List<Item> data = loadRangeInternal(startPosition, count);
+    public void loadRange(@NonNull LoadRangeParams params,
+            @NonNull LoadRangeCallback<Item> callback) {
+        List<Item> data = loadRangeInternal(params.startPosition, params.loadSize);
         callback.onResult(data);
     }
 }
diff --git a/paging/runtime/build.gradle b/paging/runtime/build.gradle
index 187acb9..1a2bd2d 100644
--- a/paging/runtime/build.gradle
+++ b/paging/runtime/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -30,25 +31,21 @@
 }
 
 dependencies {
-    api project(":arch:runtime")
-    api project(":paging:common")
-    api project(":lifecycle:runtime")
-    api project(':lifecycle:extensions')
+    api(project(":arch:runtime"))
+    api(project(":paging:common"))
+    api(project(":lifecycle:runtime"))
+    api(project(":lifecycle:extensions"))
 
     api libs.support.recyclerview, libs.support_exclude_config
 
-    androidTestImplementation libs.junit
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.kotlin.stdlib
-
+    androidTestImplementation(JUNIT)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(KOTLIN_STDLIB)
 }
 
-createAndroidCheckstyle(project)
-createKotlinCheckstyle(project)
-
 supportLibrary {
     name = "Android Lifecycle Extensions"
     publish = true
diff --git a/paging/runtime/lint-baseline.xml b/paging/runtime/lint-baseline.xml
deleted file mode 100644
index 2cadde1..0000000
--- a/paging/runtime/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0">
-
-</issues>
diff --git a/paging/runtime/src/androidTest/java/android/arch/paging/PagedListAdapterHelperTest.kt b/paging/runtime/src/androidTest/java/android/arch/paging/PagedListAdapterHelperTest.kt
index d3a910d..d50b8d9 100644
--- a/paging/runtime/src/androidTest/java/android/arch/paging/PagedListAdapterHelperTest.kt
+++ b/paging/runtime/src/androidTest/java/android/arch/paging/PagedListAdapterHelperTest.kt
@@ -41,7 +41,6 @@
     private val mDiffThread = TestExecutor()
     private val mPageLoadingThread = TestExecutor()
 
-
     private fun <T> createHelper(listUpdateCallback: ListUpdateCallback,
                                  diffCallback: DiffCallback<T>): PagedListAdapterHelper<T> {
         return PagedListAdapterHelper(listUpdateCallback,
diff --git a/paging/runtime/src/androidTest/java/android/support/v7/recyclerview/extensions/ListAdapterHelperTest.kt b/paging/runtime/src/androidTest/java/android/support/v7/recyclerview/extensions/ListAdapterHelperTest.kt
index 433f4c1..85521af 100644
--- a/paging/runtime/src/androidTest/java/android/support/v7/recyclerview/extensions/ListAdapterHelperTest.kt
+++ b/paging/runtime/src/androidTest/java/android/support/v7/recyclerview/extensions/ListAdapterHelperTest.kt
@@ -114,7 +114,6 @@
         verifyNoMoreInteractions(callback)
         drain()
         verifyNoMoreInteractions(callback)
-
     }
 
     private fun drain() {
diff --git a/paging/runtime/src/main/java/android/arch/paging/LivePagedListBuilder.java b/paging/runtime/src/main/java/android/arch/paging/LivePagedListBuilder.java
index b0fddba..f2d09cc 100644
--- a/paging/runtime/src/main/java/android/arch/paging/LivePagedListBuilder.java
+++ b/paging/runtime/src/main/java/android/arch/paging/LivePagedListBuilder.java
@@ -88,9 +88,21 @@
     }
 
     /**
-     * Sets a {@link PagedList.BoundaryCallback} on each PagedList created.
+     * Sets a {@link PagedList.BoundaryCallback} on each PagedList created, typically used to load
+     * additional data from network when paging from local storage.
      * <p>
-     * This can be used to
+     * Pass a BoundaryCallback to listen to when the PagedList runs out of data to load. If this
+     * method is not called, or {@code null} is passed, you will not be notified when each
+     * DataSource runs out of data to provide to its PagedList.
+     * <p>
+     * If you are paging from a DataSource.Factory backed by local storage, you can set a
+     * BoundaryCallback to know when there is no more information to page from local storage.
+     * This is useful to page from the network when local storage is a cache of network data.
+     * <p>
+     * Note that when using a BoundaryCallback with a {@code LiveData<PagedList>}, method calls
+     * on the callback may be dispatched multiple times - one for each PagedList/DataSource
+     * pair. If loading network data from a BoundaryCallback, you should prevent multiple
+     * dispatches of the same method from triggering multiple simultaneous network loads.
      *
      * @param boundaryCallback The boundary callback for listening to PagedList load state.
      * @return this
@@ -106,6 +118,8 @@
     /**
      * Sets executor which will be used for background loading of pages.
      * <p>
+     * If not set, defaults to the Arch components I/O thread.
+     * <p>
      * Does not affect initial load, which will be always be done on done on the Arch components
      * I/O thread.
      *
diff --git a/percent/build.gradle b/percent/build.gradle
index ccee3d2..7d5a651 100644
--- a/percent/build.gradle
+++ b/percent/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,10 +7,10 @@
 }
 
 dependencies {
-    api project(':support-compat')
+    api(project(":support-compat"))
 
-    androidTestImplementation libs.test_runner,   { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core, { exclude module: 'support-annotations' }
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
 }
 
 android {
diff --git a/percent/lint-baseline.xml b/percent/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/percent/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/persistence/db-framework/api/1.0.0.txt b/persistence/db-framework/api/1.0.0.txt
index f460993..7051765 100644
--- a/persistence/db-framework/api/1.0.0.txt
+++ b/persistence/db-framework/api/1.0.0.txt
@@ -1,6 +1,6 @@
 package android.arch.persistence.db.framework {
 
-  public final class FrameworkSQLiteOpenHelperFactory {
+  public final class FrameworkSQLiteOpenHelperFactory implements android.arch.persistence.db.SupportSQLiteOpenHelper.Factory {
     ctor public FrameworkSQLiteOpenHelperFactory();
     method public android.arch.persistence.db.SupportSQLiteOpenHelper create(android.arch.persistence.db.SupportSQLiteOpenHelper.Configuration);
   }
diff --git a/persistence/db-framework/build.gradle b/persistence/db-framework/build.gradle
index 8607bf6..6ce2b94 100644
--- a/persistence/db-framework/build.gradle
+++ b/persistence/db-framework/build.gradle
@@ -30,11 +30,9 @@
 
 dependencies {
     api libs.support.annotations
-    api project(":persistence:db")
+    api(project(":persistence:db"))
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Support SQLite - Framework Implementation"
     publish = true
diff --git a/persistence/db-framework/lint-baseline.xml b/persistence/db-framework/lint-baseline.xml
deleted file mode 100644
index 2cadde1..0000000
--- a/persistence/db-framework/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0">
-
-</issues>
diff --git a/persistence/db-framework/src/main/java/android/arch/persistence/db/framework/FrameworkSQLiteProgram.java b/persistence/db-framework/src/main/java/android/arch/persistence/db/framework/FrameworkSQLiteProgram.java
index 6c2bb72..73c98c6 100644
--- a/persistence/db-framework/src/main/java/android/arch/persistence/db/framework/FrameworkSQLiteProgram.java
+++ b/persistence/db-framework/src/main/java/android/arch/persistence/db/framework/FrameworkSQLiteProgram.java
@@ -60,7 +60,7 @@
     }
 
     @Override
-    public void close() throws Exception {
+    public void close() {
         mDelegate.close();
     }
 }
diff --git a/persistence/db-framework/src/main/java/android/arch/persistence/db/framework/FrameworkSQLiteStatement.java b/persistence/db-framework/src/main/java/android/arch/persistence/db/framework/FrameworkSQLiteStatement.java
index 53a04bd..ccb5614 100644
--- a/persistence/db-framework/src/main/java/android/arch/persistence/db/framework/FrameworkSQLiteStatement.java
+++ b/persistence/db-framework/src/main/java/android/arch/persistence/db/framework/FrameworkSQLiteStatement.java
@@ -90,7 +90,7 @@
     }
 
     @Override
-    public void close() throws Exception {
+    public void close() {
         mDelegate.close();
     }
 }
diff --git a/persistence/db/api/1.0.0.txt b/persistence/db/api/1.0.0.txt
index 0e7aea9..f96f17a 100644
--- a/persistence/db/api/1.0.0.txt
+++ b/persistence/db/api/1.0.0.txt
@@ -8,7 +8,7 @@
     method public java.lang.String getSql();
   }
 
-  public abstract interface SupportSQLiteDatabase {
+  public abstract interface SupportSQLiteDatabase implements java.io.Closeable {
     method public abstract void beginTransaction();
     method public abstract void beginTransactionNonExclusive();
     method public abstract void beginTransactionWithListener(android.database.sqlite.SQLiteTransactionListener);
@@ -85,7 +85,7 @@
     method public abstract android.arch.persistence.db.SupportSQLiteOpenHelper create(android.arch.persistence.db.SupportSQLiteOpenHelper.Configuration);
   }
 
-  public abstract interface SupportSQLiteProgram {
+  public abstract interface SupportSQLiteProgram implements java.io.Closeable {
     method public abstract void bindBlob(int, byte[]);
     method public abstract void bindDouble(int, double);
     method public abstract void bindLong(int, long);
diff --git a/persistence/db/build.gradle b/persistence/db/build.gradle
index 085676d..6f5c7f5 100644
--- a/persistence/db/build.gradle
+++ b/persistence/db/build.gradle
@@ -32,8 +32,6 @@
     api libs.support.annotations
 }
 
-createAndroidCheckstyle(project)
-
 // Used by testCompile in room-compiler
 android.libraryVariants.all { variant ->
     def name = variant.buildType.name
diff --git a/persistence/db/lint-baseline.xml b/persistence/db/lint-baseline.xml
deleted file mode 100644
index 2cadde1..0000000
--- a/persistence/db/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0">
-
-</issues>
diff --git a/persistence/db/src/main/java/android/arch/persistence/db/SupportSQLiteProgram.java b/persistence/db/src/main/java/android/arch/persistence/db/SupportSQLiteProgram.java
index c6d43cc..38c1ac1 100644
--- a/persistence/db/src/main/java/android/arch/persistence/db/SupportSQLiteProgram.java
+++ b/persistence/db/src/main/java/android/arch/persistence/db/SupportSQLiteProgram.java
@@ -16,16 +16,14 @@
 
 package android.arch.persistence.db;
 
-import android.annotation.TargetApi;
-import android.os.Build;
+import java.io.Closeable;
 
 /**
  * An interface to map the behavior of {@link android.database.sqlite.SQLiteProgram}.
  */
 
-@TargetApi(Build.VERSION_CODES.KITKAT)
 @SuppressWarnings("unused")
-public interface SupportSQLiteProgram extends AutoCloseable {
+public interface SupportSQLiteProgram extends Closeable {
     /**
      * Bind a NULL value to this statement. The value remains bound until
      * {@link #clearBindings} is called.
diff --git a/preference-leanback/api/current.txt b/preference-leanback/api/current.txt
index 7bae10d..4703ae3 100644
--- a/preference-leanback/api/current.txt
+++ b/preference-leanback/api/current.txt
@@ -50,7 +50,7 @@
     method public void setTitle(java.lang.CharSequence);
   }
 
-  public abstract class LeanbackSettingsFragment extends android.app.Fragment {
+  public abstract class LeanbackSettingsFragment extends android.app.Fragment implements android.support.v14.preference.PreferenceFragment.OnPreferenceDisplayDialogCallback android.support.v14.preference.PreferenceFragment.OnPreferenceStartFragmentCallback android.support.v14.preference.PreferenceFragment.OnPreferenceStartScreenCallback {
     ctor public LeanbackSettingsFragment();
     method public boolean onPreferenceDisplayDialog(android.support.v14.preference.PreferenceFragment, android.support.v7.preference.Preference);
     method public abstract void onPreferenceStartInitialScreen();
diff --git a/preference-leanback/build.gradle b/preference-leanback/build.gradle
index 85d2577..f4d2fd6 100644
--- a/preference-leanback/build.gradle
+++ b/preference-leanback/build.gradle
@@ -6,12 +6,12 @@
 }
 
 dependencies {
-    api project(':support-v4')
-    api project(':appcompat-v7')
-    api project(':recyclerview-v7')
-    api project(':preference-v7')
-    api project(':preference-v14')
-    api project(':leanback-v17')
+    api(project(":support-v4"))
+    api(project(":appcompat-v7"))
+    api(project(":recyclerview-v7"))
+    api(project(":preference-v7"))
+    api(project(":preference-v14"))
+    api(project(":leanback-v17"))
 }
 
 android {
diff --git a/recommendation/build.gradle b/recommendation/build.gradle
index f6adcb9..83fa375 100644
--- a/recommendation/build.gradle
+++ b/recommendation/build.gradle
@@ -6,7 +6,7 @@
 }
 
 dependencies {
-    api project(':support-annotations')
+    api(project(":support-annotations"))
 }
 
 android {
diff --git a/recommendation/lint-baseline.xml b/recommendation/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/recommendation/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/recyclerview-selection/build.gradle b/recyclerview-selection/build.gradle
index ab1ab23..06dc730 100644
--- a/recyclerview-selection/build.gradle
+++ b/recyclerview-selection/build.gradle
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
+
 plugins {
     id("SupportAndroidLibraryPlugin")
 }
@@ -23,14 +25,13 @@
     api project(':support-annotations')
     api project(':support-compat')
 
-    androidTestImplementation libs.junit
-    androidTestImplementation libs.test_runner,   { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core, { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(JUNIT)
 }
 
-
 android {
     defaultConfig {
         minSdkVersion 14
diff --git a/recyclerview-selection/lint-baseline.xml b/recyclerview-selection/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/recyclerview-selection/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MouseInputHandler.java b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MouseInputHandler.java
index 0b4ea2c..b6fe36b 100644
--- a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MouseInputHandler.java
+++ b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MouseInputHandler.java
@@ -30,9 +30,9 @@
 import androidx.recyclerview.selection.ItemDetailsLookup.ItemDetails;
 
 /**
- * A MotionInputHandler that provides the high-level glue for mouse/stylus driven selection. This
+ * A MotionInputHandler that provides the high-level glue for mouse driven selection. This
  * class works with {@link RecyclerView}, {@link GestureRouter}, and {@link GestureSelectionHelper}
- * to provide robust user drive selection support.
+ * to provide robust user driven selection support.
  */
 final class MouseInputHandler<K> extends MotionInputHandler<K> {
 
diff --git a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionHelperBuilder.java b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionHelperBuilder.java
index abdefaf..127a511 100644
--- a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionHelperBuilder.java
+++ b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionHelperBuilder.java
@@ -88,8 +88,7 @@
     };
 
     private int[] mBandToolTypes = new int[] {
-        MotionEvent.TOOL_TYPE_MOUSE,
-        MotionEvent.TOOL_TYPE_STYLUS
+        MotionEvent.TOOL_TYPE_MOUSE
     };
 
     public SelectionHelperBuilder(
@@ -296,7 +295,7 @@
             eventRouter.register(toolType, gestureHelper);
         }
 
-        // Provides high level glue for binding mouse/stylus events and gestures
+        // Provides high level glue for binding mouse events and gestures
         // to selection framework.
         MouseInputHandler<K> mouseHandler = new MouseInputHandler<>(
                 selectionHelper,
diff --git a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionStorage.java b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionStorage.java
index 81db30f..454a76b 100644
--- a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionStorage.java
+++ b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionStorage.java
@@ -139,7 +139,7 @@
         }
     }
 
-    private @Nullable Selection<String> readStringSelection(@Nullable Bundle state) {
+    private @Nullable Selection<String> readStringSelection(Bundle state) {
         @Nullable ArrayList<String> stored =
                 state.getStringArrayList(EXTRA_SAVED_SELECTION_ENTRIES);
         if (stored == null) {
@@ -151,7 +151,7 @@
         return selection;
     }
 
-    private @Nullable Selection<Long> readLongSelection(@Nullable Bundle state) {
+    private @Nullable Selection<Long> readLongSelection(Bundle state) {
         @Nullable long[] stored = state.getLongArray(EXTRA_SAVED_SELECTION_ENTRIES);
         if (stored == null) {
             return null;
diff --git a/room/common/build.gradle b/room/common/build.gradle
index 21441a2..05b63c9 100644
--- a/room/common/build.gradle
+++ b/room/common/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension;
@@ -24,12 +25,10 @@
 
 dependencies {
     compile libs.support.annotations
-    testCompile libs.junit
-    testCompile libs.mockito_core
+    testCompile(JUNIT)
+    testCompile(MOCKITO_CORE)
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Room-Common"
     publish = true
diff --git a/room/common/src/main/java/android/arch/persistence/room/Database.java b/room/common/src/main/java/android/arch/persistence/room/Database.java
index f12d1b9..14e722f 100644
--- a/room/common/src/main/java/android/arch/persistence/room/Database.java
+++ b/room/common/src/main/java/android/arch/persistence/room/Database.java
@@ -34,7 +34,7 @@
  * <pre>
  * // User and Book are classes annotated with {@literal @}Entity.
  * {@literal @}Database(version = 1, entities = {User.class, Book.class})
- * abstract class AppDatabase extends RoomDatabase() {
+ * abstract class AppDatabase extends RoomDatabase {
  *     // BookDao is a class annotated with {@literal @}Dao.
  *     abstract public BookDao bookDao();
  *     // UserDao is a class annotated with {@literal @}Dao.
diff --git a/room/compiler/build.gradle b/room/compiler/build.gradle
index eb9628c..57ff63f 100644
--- a/room/compiler/build.gradle
+++ b/room/compiler/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -26,13 +27,11 @@
     test.java.srcDirs += 'src/tests/kotlin'
     main.java.srcDirs += antlrOut
 }
-project.ext.noDocs = true
-version = LibraryVersions.ROOM.toString()
 
 // Temporary hack to stop AS to adding two guavas into test's classpath
 configurations.all {
     resolutionStrategy {
-        force libs.guava
+        force GUAVA
     }
 }
 
@@ -40,20 +39,20 @@
     // taken from ButterKnife
     def logger = new com.android.build.gradle.internal.LoggerWrapper(project.logger)
     def sdkHandler = new com.android.build.gradle.internal.SdkHandler(project, logger)
-    compile project(":room:common")
-    compile project(":room:migration")
-    compile libs.kotlin.stdlib
-    compile libs.auto_common
-    compile libs.javapoet
-    compile libs.antlr
-    compile libs.xerial
-    compile libs.apache.commons.codec
-    testCompile libs.google_compile_testing
+    compile(project(":room:common"))
+    compile(project(":room:migration"))
+    compile(KOTLIN_STDLIB)
+    compile(AUTO_COMMON)
+    compile(JAVAPOET)
+    compile(ANTLR)
+    compile(XERIAL)
+    compile(APACHE_COMMONS_CODEC)
+    testCompile(GOOGLE_COMPILE_TESTING)
     testCompile project(":paging:common")
-    testCompile libs.junit
-    testCompile libs.ij_annotations
-    testCompile libs.jsr250
-    testCompile libs.mockito_core
+    testCompile(JUNIT)
+    testCompile(INTELLIJ_ANNOTATIONS)
+    testCompile(JSR250)
+    testCompile(MOCKITO_CORE)
     testCompile fileTree(dir: "${sdkHandler.sdkFolder}/platforms/android-$tools.current_sdk/",
             include : "android.jar")
     testCompile fileTree(dir: "${new File(project(":room:runtime").buildDir, "libJar")}",
@@ -77,11 +76,10 @@
 tasks.findByName("compileKotlin").dependsOn(":room:runtime:jarDebug")
 tasks.findByName("compileKotlin").dependsOn(":persistence:db:jarDebug")
 
-createKotlinCheckstyle(project)
-
 supportLibrary {
     name = "Android Room Compiler"
     publish = true
+    generateDocs = false
     mavenVersion = LibraryVersions.ROOM
     mavenGroup = LibraryGroups.ROOM
     inceptionYear = "2017"
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/RoomProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/RoomProcessor.kt
index 76051c8..57070fd 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/RoomProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/RoomProcessor.kt
@@ -27,7 +27,6 @@
 import com.google.auto.common.MoreElements
 import com.google.common.collect.SetMultimap
 import java.io.File
-import javax.annotation.processing.SupportedSourceVersion
 import javax.lang.model.SourceVersion
 import javax.lang.model.element.Element
 
@@ -49,8 +48,9 @@
     }
 
     class DatabaseProcessingStep(context: Context) : ContextBoundProcessingStep(context) {
-        override fun process(elementsByAnnotation: SetMultimap<Class<out Annotation>, Element>)
-                : MutableSet<Element> {
+        override fun process(
+                elementsByAnnotation: SetMultimap<Class<out Annotation>, Element>
+        ): MutableSet<Element> {
             // TODO multi step support
             val databases = elementsByAnnotation[Database::class.java]
                     ?.map {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/element_ext.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/element_ext.kt
index a74031d..5f61e21 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/element_ext.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/element_ext.kt
@@ -69,15 +69,13 @@
 // compiler/src/main/java/dagger/internal/codegen/ConfigurationAnnotations.java
 private val TO_LIST_OF_TYPES = object
     : SimpleAnnotationValueVisitor6<List<TypeMirror>, Void?>() {
-    override fun visitArray(values: MutableList<out AnnotationValue>?, p: Void?)
-            : List<TypeMirror> {
+    override fun visitArray(values: MutableList<out AnnotationValue>?, p: Void?): List<TypeMirror> {
         return values?.map {
             val tmp = TO_TYPE.visit(it)
             tmp
         }?.filterNotNull() ?: emptyList()
     }
 
-
     override fun defaultAction(o: Any?, p: Void?): List<TypeMirror>? {
         return emptyList()
     }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt
index 066bd1f..367c926 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt
@@ -33,59 +33,59 @@
 
 object SupportDbTypeNames {
     val DB: ClassName = ClassName.get("android.arch.persistence.db", "SupportSQLiteDatabase")
-    val SQLITE_STMT : ClassName =
+    val SQLITE_STMT: ClassName =
             ClassName.get("android.arch.persistence.db", "SupportSQLiteStatement")
-    val SQLITE_OPEN_HELPER : ClassName =
+    val SQLITE_OPEN_HELPER: ClassName =
             ClassName.get("android.arch.persistence.db", "SupportSQLiteOpenHelper")
-    val SQLITE_OPEN_HELPER_CALLBACK : ClassName =
+    val SQLITE_OPEN_HELPER_CALLBACK: ClassName =
             ClassName.get("android.arch.persistence.db", "SupportSQLiteOpenHelper.Callback")
-    val SQLITE_OPEN_HELPER_FACTORY : ClassName =
+    val SQLITE_OPEN_HELPER_FACTORY: ClassName =
             ClassName.get("android.arch.persistence.db", "SupportSQLiteOpenHelper.Factory")
-    val SQLITE_OPEN_HELPER_CONFIG : ClassName =
+    val SQLITE_OPEN_HELPER_CONFIG: ClassName =
             ClassName.get("android.arch.persistence.db", "SupportSQLiteOpenHelper.Configuration")
-    val SQLITE_OPEN_HELPER_CONFIG_BUILDER : ClassName =
+    val SQLITE_OPEN_HELPER_CONFIG_BUILDER: ClassName =
             ClassName.get("android.arch.persistence.db",
                     "SupportSQLiteOpenHelper.Configuration.Builder")
 }
 
 object RoomTypeNames {
     val STRING_UTIL: ClassName = ClassName.get("android.arch.persistence.room.util", "StringUtil")
-    val CURSOR_CONVERTER : ClassName =
+    val CURSOR_CONVERTER: ClassName =
             ClassName.get("android.arch.persistence.room", "CursorConverter")
-    val ROOM : ClassName = ClassName.get("android.arch.persistence.room", "Room")
-    val ROOM_DB : ClassName = ClassName.get("android.arch.persistence.room", "RoomDatabase")
-    val ROOM_DB_CONFIG : ClassName = ClassName.get("android.arch.persistence.room",
+    val ROOM: ClassName = ClassName.get("android.arch.persistence.room", "Room")
+    val ROOM_DB: ClassName = ClassName.get("android.arch.persistence.room", "RoomDatabase")
+    val ROOM_DB_CONFIG: ClassName = ClassName.get("android.arch.persistence.room",
             "DatabaseConfiguration")
-    val INSERTION_ADAPTER : ClassName =
+    val INSERTION_ADAPTER: ClassName =
             ClassName.get("android.arch.persistence.room", "EntityInsertionAdapter")
-    val DELETE_OR_UPDATE_ADAPTER : ClassName =
+    val DELETE_OR_UPDATE_ADAPTER: ClassName =
             ClassName.get("android.arch.persistence.room", "EntityDeletionOrUpdateAdapter")
-    val SHARED_SQLITE_STMT : ClassName =
+    val SHARED_SQLITE_STMT: ClassName =
             ClassName.get("android.arch.persistence.room", "SharedSQLiteStatement")
-    val INVALIDATION_TRACKER : ClassName =
+    val INVALIDATION_TRACKER: ClassName =
             ClassName.get("android.arch.persistence.room", "InvalidationTracker")
-    val INVALIDATION_OBSERVER : ClassName =
+    val INVALIDATION_OBSERVER: ClassName =
             ClassName.get("android.arch.persistence.room.InvalidationTracker", "Observer")
-    val ROOM_SQL_QUERY : ClassName =
+    val ROOM_SQL_QUERY: ClassName =
             ClassName.get("android.arch.persistence.room", "RoomSQLiteQuery")
-    val OPEN_HELPER : ClassName =
+    val OPEN_HELPER: ClassName =
             ClassName.get("android.arch.persistence.room", "RoomOpenHelper")
     val OPEN_HELPER_DELEGATE: ClassName =
             ClassName.get("android.arch.persistence.room", "RoomOpenHelper.Delegate")
-    val TABLE_INFO : ClassName =
+    val TABLE_INFO: ClassName =
             ClassName.get("android.arch.persistence.room.util", "TableInfo")
-    val TABLE_INFO_COLUMN : ClassName =
+    val TABLE_INFO_COLUMN: ClassName =
             ClassName.get("android.arch.persistence.room.util", "TableInfo.Column")
-    val TABLE_INFO_FOREIGN_KEY : ClassName =
+    val TABLE_INFO_FOREIGN_KEY: ClassName =
             ClassName.get("android.arch.persistence.room.util", "TableInfo.ForeignKey")
-    val TABLE_INFO_INDEX : ClassName =
+    val TABLE_INFO_INDEX: ClassName =
             ClassName.get("android.arch.persistence.room.util", "TableInfo.Index")
-    val LIMIT_OFFSET_DATA_SOURCE : ClassName =
+    val LIMIT_OFFSET_DATA_SOURCE: ClassName =
             ClassName.get("android.arch.persistence.room.paging", "LimitOffsetDataSource")
 }
 
 object ArchTypeNames {
-    val APP_EXECUTOR : ClassName =
+    val APP_EXECUTOR: ClassName =
             ClassName.get("android.arch.core.executor", "ArchTaskExecutor")
 }
 
@@ -96,18 +96,17 @@
             ClassName.get("android.arch.paging", "TiledDataSource")
     val LIVE_PAGED_LIST_PROVIDER: ClassName =
             ClassName.get("android.arch.paging", "LivePagedListProvider")
-
 }
 
 object LifecyclesTypeNames {
     val LIVE_DATA: ClassName = ClassName.get("android.arch.lifecycle", "LiveData")
-    val COMPUTABLE_LIVE_DATA : ClassName = ClassName.get("android.arch.lifecycle",
+    val COMPUTABLE_LIVE_DATA: ClassName = ClassName.get("android.arch.lifecycle",
             "ComputableLiveData")
 }
 
 object AndroidTypeNames {
-    val CURSOR : ClassName = ClassName.get("android.database", "Cursor")
-    val ARRAY_MAP : ClassName = ClassName.get("android.support.v4.util", "ArrayMap")
+    val CURSOR: ClassName = ClassName.get("android.database", "Cursor")
+    val ARRAY_MAP: ClassName = ClassName.get("android.support.v4.util", "ArrayMap")
 }
 
 object CommonTypeNames {
@@ -133,7 +132,7 @@
             "EmptyResultSetException")
 }
 
-fun TypeName.defaultValue() : String {
+fun TypeName.defaultValue(): String {
     return if (!isPrimitive) {
         "null"
     } else if (this == TypeName.BOOLEAN) {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/string_ext.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/string_ext.kt
index 9b07e27..52594db 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/string_ext.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/string_ext.kt
@@ -14,27 +14,27 @@
  * limitations under the License.
  */
 
-private fun String.toCamelCase() : String {
+private fun String.toCamelCase(): String {
     val split = this.split("_")
     if (split.isEmpty()) return ""
     if (split.size == 1) return split[0].capitalize()
     return split.joinToCamelCase()
 }
 
-private fun String.toCamelCaseAsVar() : String {
+private fun String.toCamelCaseAsVar(): String {
     val split = this.split("_")
     if (split.isEmpty()) return ""
     if (split.size == 1) return split[0]
     return split.joinToCamelCaseAsVar()
 }
 
-private fun List<String>.joinToCamelCase(): String = when(size) {
+private fun List<String>.joinToCamelCase(): String = when (size) {
     0 -> throw IllegalArgumentException("invalid section size, cannot be zero")
     1 -> this[0].toCamelCase()
-    else -> this.map {it.toCamelCase()}.joinToString("")
+    else -> this.map { it.toCamelCase() }.joinToString("")
 }
 
-private fun List<String>.joinToCamelCaseAsVar(): String = when(size) {
+private fun List<String>.joinToCamelCaseAsVar(): String = when (size) {
     0 -> throw IllegalArgumentException("invalid section size, cannot be zero")
     1 -> this[0].toCamelCaseAsVar()
     else -> get(0).toCamelCaseAsVar() + drop(1).joinToCamelCase()
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/type_mirror_ext.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/type_mirror_ext.kt
index 97cd051..13779e9 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/type_mirror_ext.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/type_mirror_ext.kt
@@ -23,8 +23,8 @@
 import javax.lang.model.type.TypeKind.SHORT
 import javax.lang.model.type.TypeMirror
 
-fun TypeMirror.defaultValue() : String {
-    return when(this.kind) {
+fun TypeMirror.defaultValue(): String {
+    return when (this.kind) {
         BOOLEAN -> "false"
         BYTE, SHORT, INT, LONG, CHAR, FLOAT, DOUBLE -> "0"
         else -> "null"
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/log/RLog.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/log/RLog.kt
index 10614ce..9832996 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/log/RLog.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/log/RLog.kt
@@ -27,8 +27,8 @@
 import javax.tools.Diagnostic.Kind.NOTE
 import javax.tools.Diagnostic.Kind.WARNING
 
-class RLog(val messager : Messager, val suppressedWarnings : Set<Warning>,
-           val defaultElement : Element?) {
+class RLog(val messager: Messager, val suppressedWarnings: Set<Warning>,
+           val defaultElement: Element?) {
     private fun String.safeFormat(vararg args: Any): String {
         try {
             return format(args)
@@ -90,7 +90,7 @@
 
         fun hasErrors() = messages.containsKey(Diagnostic.Kind.ERROR)
 
-        fun writeTo(env : ProcessingEnvironment) {
+        fun writeTo(env: ProcessingEnvironment) {
             messages.forEach { pair ->
                 val kind = pair.key
                 pair.value.forEach {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt
index d165b55..affa8c9 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt
@@ -99,14 +99,15 @@
         if (tableName != null) {
             val tableAlias = ctx.table_alias()?.text
             if (tableName !in withClauseNames) {
-                tableNames.add(Table(unescapeIdentifier(tableName),
-                                     unescapeIdentifier(tableAlias ?: tableName)))
+                tableNames.add(Table(
+                        unescapeIdentifier(tableName),
+                        unescapeIdentifier(tableAlias ?: tableName)))
             }
         }
         return super.visitTable_or_subquery(ctx)
     }
 
-    private fun unescapeIdentifier(text : String) : String {
+    private fun unescapeIdentifier(text: String): String {
         val trimmed = text.trim()
         if (trimmed.startsWith("`") && trimmed.endsWith('`')) {
             return unescapeIdentifier(trimmed.substring(1, trimmed.length - 1))
@@ -155,7 +156,7 @@
             }
         }
 
-        fun isValidIdentifier(input : String) : Boolean =
+        fun isValidIdentifier(input: String): Boolean =
                 input.isNotBlank() && INVALID_IDENTIFIER_CHARS.none { input.contains(it) }
     }
 }
@@ -180,9 +181,9 @@
     INTEGER,
     REAL,
     BLOB;
-    fun getTypeMirrors(env : ProcessingEnvironment) : List<TypeMirror>? {
+    fun getTypeMirrors(env: ProcessingEnvironment): List<TypeMirror>? {
         val typeUtils = env.typeUtils
-        return when(this) {
+        return when (this) {
             TEXT -> listOf(env.elementUtils.getTypeElement("java.lang.String").asType())
             INTEGER -> withBoxedTypes(env, TypeKind.INT, TypeKind.BYTE, TypeKind.CHAR,
                     TypeKind.BOOLEAN, TypeKind.LONG, TypeKind.SHORT)
@@ -193,7 +194,7 @@
         }
     }
 
-    private fun withBoxedTypes(env : ProcessingEnvironment, vararg primitives : TypeKind) :
+    private fun withBoxedTypes(env: ProcessingEnvironment, vararg primitives: TypeKind):
             List<TypeMirror> {
         return primitives.flatMap {
             val primitiveType = env.typeUtils.getPrimitiveType(it)
@@ -203,8 +204,8 @@
 
     companion object {
         // converts from ColumnInfo#SQLiteTypeAffinity
-        fun fromAnnotationValue(value : Int) : SQLTypeAffinity? {
-            return when(value) {
+        fun fromAnnotationValue(value: Int): SQLTypeAffinity? {
+            return when (value) {
                 ColumnInfo.BLOB -> BLOB
                 ColumnInfo.INTEGER -> INTEGER
                 ColumnInfo.REAL -> REAL
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/preconditions/Checks.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/preconditions/Checks.kt
index dad5c1c..588ce94 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/preconditions/Checks.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/preconditions/Checks.kt
@@ -63,7 +63,7 @@
         return !failed
     }
 
-    fun notBlank(value: String?, element: Element, msg: String, vararg args: Any) : Boolean {
+    fun notBlank(value: String?, element: Element, msg: String, vararg args: Any): Boolean {
         return check(value != null && value.isNotBlank(), element, msg, args)
     }
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/Context.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/Context.kt
index 4e84be3..def5107 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/Context.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/Context.kt
@@ -27,12 +27,12 @@
 import javax.lang.model.element.Element
 import javax.lang.model.type.TypeMirror
 
-class Context private constructor(val processingEnv: ProcessingEnvironment,
-                                  val logger: RLog,
-                                  private val typeConverters
-                                        : CustomConverterProcessor.ProcessResult,
-                                  private val inheritedAdapterStore: TypeAdapterStore?,
-                                  val cache: Cache) {
+class Context private constructor(
+        val processingEnv: ProcessingEnvironment,
+        val logger: RLog,
+        private val typeConverters: CustomConverterProcessor.ProcessResult,
+        private val inheritedAdapterStore: TypeAdapterStore?,
+        val cache: Cache) {
     val checker: Checks = Checks(logger)
     val COMMON_TYPES: Context.CommonTypes = Context.CommonTypes(processingEnv)
 
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/CustomConverterProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/CustomConverterProcessor.kt
index 1ed245d..622621d 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/CustomConverterProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/CustomConverterProcessor.kt
@@ -58,7 +58,7 @@
                         ?.toListOfClassTypes()
                         ?.filter {
                             MoreTypes.isType(it)
-                        }?.mapTo(LinkedHashSet(), {it}) ?: LinkedHashSet<TypeMirror>()
+                        }?.mapTo(LinkedHashSet(), { it }) ?: LinkedHashSet<TypeMirror>()
                 val converters = classes
                         .flatMap {
                             CustomConverterProcessor(context, MoreTypes.asTypeElement(it))
@@ -71,7 +71,7 @@
             } ?: ProcessResult.EMPTY
         }
 
-        fun reportDuplicates(context: Context, converters : List<CustomTypeConverter>) {
+        fun reportDuplicates(context: Context, converters: List<CustomTypeConverter>) {
             val groupedByFrom = converters.groupBy { it.from.typeName() }
             groupedByFrom.forEach {
                 it.value.groupBy { it.to.typeName() }.forEach {
@@ -106,8 +106,8 @@
         }.filterNotNull()
     }
 
-    private fun processMethod(container: DeclaredType, methodElement: ExecutableElement)
-            : CustomTypeConverter? {
+    private fun processMethod(
+            container: DeclaredType, methodElement: ExecutableElement): CustomTypeConverter? {
         val asMember = context.processingEnv.typeUtils.asMemberOf(container, methodElement)
         val executableType = MoreTypes.asExecutable(asMember)
         val returnType = executableType.returnType
@@ -136,10 +136,12 @@
     /**
      * Order of classes is important hence they are a LinkedHashSet not a set.
      */
-    open class ProcessResult(val classes: LinkedHashSet<TypeMirror>,
-                             val converters: List<CustomTypeConverterWrapper>) {
+    open class ProcessResult(
+            val classes: LinkedHashSet<TypeMirror>,
+            val converters: List<CustomTypeConverterWrapper>
+    ) {
         object EMPTY : ProcessResult(LinkedHashSet(), emptyList())
-        operator fun plus(other : ProcessResult) : ProcessResult {
+        operator fun plus(other: ProcessResult): ProcessResult {
             val newClasses = LinkedHashSet<TypeMirror>()
             newClasses.addAll(classes)
             newClasses.addAll(other.classes)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/DaoProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/DaoProcessor.kt
index c705eef..5e273b6 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/DaoProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/DaoProcessor.kt
@@ -36,8 +36,8 @@
 import javax.lang.model.element.TypeElement
 import javax.lang.model.type.DeclaredType
 
-class DaoProcessor(baseContext : Context, val element: TypeElement, val dbType: DeclaredType,
-                   val dbVerifier : DatabaseVerifier?) {
+class DaoProcessor(baseContext: Context, val element: TypeElement, val dbType: DeclaredType,
+                   val dbVerifier: DatabaseVerifier?) {
     val context = baseContext.fork(element)
 
     companion object {
@@ -45,7 +45,7 @@
                 Update::class)
     }
 
-    fun process() : Dao {
+    fun process(): Dao {
         context.checker.hasAnnotation(element, android.arch.persistence.room.Dao::class,
                 ProcessorErrors.DAO_MUST_BE_ANNOTATED_WITH_DAO)
         context.checker.check(element.hasAnyOf(ABSTRACT) || element.kind == ElementKind.INTERFACE,
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/DatabaseProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/DatabaseProcessor.kt
index 90b24e1..30acbf4 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/DatabaseProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/DatabaseProcessor.kt
@@ -39,7 +39,6 @@
 import javax.lang.model.element.TypeElement
 import javax.lang.model.type.TypeMirror
 
-
 class DatabaseProcessor(baseContext: Context, val element: TypeElement) {
     val context = baseContext.fork(element)
 
@@ -175,7 +174,7 @@
     }
 
     private fun validateUniqueDaoClasses(dbElement: TypeElement, daoMethods: List<DaoMethod>,
-                                         entities : List<Entity>) {
+                                         entities: List<Entity>) {
         val entityTypeNames = entities.map { it.typeName }.toSet()
         daoMethods.groupBy { it.dao.typeName }
                 .forEach {
@@ -189,8 +188,8 @@
                         context.logger.e(dbElement, error)
                     }
                 }
-        val check = fun(element : Element, dao : Dao,
-                        typeName : TypeName?) {
+        val check = fun(element: Element, dao: Dao,
+                        typeName: TypeName?) {
             typeName?.let {
                 if (!entityTypeNames.contains(typeName)) {
                     context.logger.e(element,
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt
index 405c6b1..fc0df44 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt
@@ -57,7 +57,7 @@
             doProcess()
         })
     }
-    private fun doProcess() : Entity {
+    private fun doProcess(): Entity {
         context.checker.hasAnnotation(element, android.arch.persistence.room.Entity::class,
                 ProcessorErrors.ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY)
         val pojo = PojoProcessor(
@@ -151,7 +151,7 @@
     private fun checkIndicesForForeignKeys(entityForeignKeys: List<ForeignKey>,
                                            primaryKey: PrimaryKey,
                                            indices: List<Index>) {
-        fun covers(columnNames: List<String>, fields : List<Field>) : Boolean =
+        fun covers(columnNames: List<String>, fields: List<Field>): Boolean =
             fields.size >= columnNames.size && columnNames.withIndex().all {
                 fields[it.index].columnName == it.value
             }
@@ -238,8 +238,8 @@
         }.filterNotNull()
     }
 
-    private fun findAndValidatePrimaryKey(fields: List<Field>, embeddedFields: List<EmbeddedField>)
-            : PrimaryKey {
+    private fun findAndValidatePrimaryKey(
+            fields: List<Field>, embeddedFields: List<EmbeddedField>): PrimaryKey {
         val candidates = collectPrimaryKeysFromEntityAnnotations(element, fields) +
                 collectPrimaryKeysFromPrimaryKeyAnnotations(fields) +
                 collectPrimaryKeysFromEmbeddedFields(embeddedFields)
@@ -311,9 +311,8 @@
     /**
      * Check classes for @Entity(primaryKeys = ?).
      */
-    private fun collectPrimaryKeysFromEntityAnnotations(typeElement: TypeElement,
-                                                        availableFields: List<Field>)
-            : List<PrimaryKey> {
+    private fun collectPrimaryKeysFromEntityAnnotations(
+            typeElement: TypeElement, availableFields: List<Field>): List<PrimaryKey> {
         val myPkeys = MoreElements.getAnnotationMirror(typeElement,
                 android.arch.persistence.room.Entity::class.java).orNull()?.let {
             val primaryKeyColumns = AnnotationMirrors.getAnnotationValue(it, "primaryKeys")
@@ -348,8 +347,8 @@
         return superPKeys + myPkeys
     }
 
-    private fun collectPrimaryKeysFromEmbeddedFields(embeddedFields: List<EmbeddedField>)
-            : List<PrimaryKey> {
+    private fun collectPrimaryKeysFromEmbeddedFields(
+            embeddedFields: List<EmbeddedField>): List<PrimaryKey> {
         return embeddedFields.map { embeddedField ->
             MoreElements.getAnnotationMirror(embeddedField.field.element,
                     android.arch.persistence.room.PrimaryKey::class.java).orNull()?.let {
@@ -367,8 +366,8 @@
 
     // start from my element and check if anywhere in the list we can find the only well defined
     // pkey, if so, use it.
-    private fun choosePrimaryKey(candidates: List<PrimaryKey>, typeElement: TypeElement)
-            : PrimaryKey {
+    private fun choosePrimaryKey(
+            candidates: List<PrimaryKey>, typeElement: TypeElement): PrimaryKey {
         // If 1 of these primary keys is declared in this class, then it is the winner. Just print
         //    a note for the others.
         // If 0 is declared, check the parent.
@@ -398,7 +397,8 @@
         }
     }
 
-    private fun validateAndCreateIndices(inputs: List<IndexInput>, pojo: Pojo): List<Index> {
+    private fun validateAndCreateIndices(
+            inputs: List<IndexInput>, pojo: Pojo): List<Index> {
         // check for columns
         val indices = inputs.map { input ->
             context.checker.check(input.columnNames.isNotEmpty(), element,
@@ -448,8 +448,8 @@
     }
 
     // check if parent is an Entity, if so, report its annotation indices
-    private fun loadSuperIndices(typeMirror: TypeMirror?, tableName: String, inherit: Boolean)
-            : List<IndexInput> {
+    private fun loadSuperIndices(
+            typeMirror: TypeMirror?, tableName: String, inherit: Boolean): List<IndexInput> {
         if (typeMirror == null || typeMirror.kind == TypeKind.NONE) {
             return emptyList()
         }
@@ -480,8 +480,7 @@
     }
 
     companion object {
-        private fun extractTableName(element: TypeElement, annotation: AnnotationMirror)
-                : String {
+        private fun extractTableName(element: TypeElement, annotation: AnnotationMirror): String {
             val annotationValue = AnnotationMirrors
                     .getAnnotationValue(annotation, "tableName").value.toString()
             return if (annotationValue == "") {
@@ -491,8 +490,8 @@
             }
         }
 
-        private fun extractIndices(annotation: AnnotationMirror, tableName: String)
-                : List<IndexInput> {
+        private fun extractIndices(
+                annotation: AnnotationMirror, tableName: String): List<IndexInput> {
             val arrayOfIndexAnnotations = AnnotationMirrors.getAnnotationValue(annotation,
                     "indices")
             return INDEX_LIST_VISITOR.visit(arrayOfIndexAnnotations, tableName)
@@ -500,8 +499,10 @@
 
         private val INDEX_LIST_VISITOR = object
             : SimpleAnnotationValueVisitor6<List<IndexInput>, String>() {
-            override fun visitArray(values: MutableList<out AnnotationValue>?, tableName: String)
-                    : List<IndexInput> {
+            override fun visitArray(
+                    values: MutableList<out AnnotationValue>?,
+                    tableName: String
+            ): List<IndexInput> {
                 return values?.map {
                     INDEX_VISITOR.visit(it, tableName)
                 }?.filterNotNull() ?: emptyList<IndexInput>()
@@ -534,8 +535,10 @@
 
         private val FOREIGN_KEY_LIST_VISITOR = object
             : SimpleAnnotationValueVisitor6<List<ForeignKeyInput>, Void?>() {
-            override fun visitArray(values: MutableList<out AnnotationValue>?, void: Void?)
-                    : List<ForeignKeyInput> {
+            override fun visitArray(
+                    values: MutableList<out AnnotationValue>?,
+                    void: Void?
+            ): List<ForeignKeyInput> {
                 return values?.map {
                     FOREIGN_KEY_VISITOR.visit(it)
                 }?.filterNotNull() ?: emptyList<ForeignKeyInput>()
@@ -576,7 +579,11 @@
     /**
      * ForeignKey, before it is processed in the context of a database.
      */
-    data class ForeignKeyInput(val parent : TypeMirror, val parentColumns : List<String>,
-                     val childColumns : List<String>, val onDelete : ForeignKeyAction?,
-                     val onUpdate : ForeignKeyAction?, val deferred : Boolean)
+    data class ForeignKeyInput(
+            val parent: TypeMirror,
+            val parentColumns: List<String>,
+            val childColumns: List<String>,
+            val onDelete: ForeignKeyAction?,
+            val onUpdate: ForeignKeyAction?,
+            val deferred: Boolean)
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/FieldProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/FieldProcessor.kt
index 8677bf6..f03d7da 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/FieldProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/FieldProcessor.kt
@@ -42,10 +42,10 @@
                 ColumnInfo::class.java)
         val name = element.simpleName.toString()
         val columnName: String
-        val affinity : SQLTypeAffinity?
+        val affinity: SQLTypeAffinity?
         val collate: Collate?
         val fieldPrefix = fieldParent?.prefix ?: ""
-        val indexed : Boolean
+        val indexed: Boolean
         if (columnInfoAnnotation.isPresent) {
             val nameInAnnotation = AnnotationMirrors
                     .getAnnotationValue(columnInfoAnnotation.get(), "name")
@@ -61,7 +61,7 @@
                         .getAnnotationValue(columnInfoAnnotation.get(), "typeAffinity")
                         .getAsInt(ColumnInfo.UNDEFINED)!!
                 SQLTypeAffinity.fromAnnotationValue(userDefinedAffinity)
-            } catch (ex : NumberFormatException) {
+            } catch (ex: NumberFormatException) {
                 null
             }
 
@@ -71,7 +71,6 @@
             indexed = AnnotationMirrors
                     .getAnnotationValue(columnInfoAnnotation.get(), "index")
                     .getAsBoolean(false)
-
         } else {
             columnName = fieldPrefix + name
             affinity = null
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/InsertionMethodProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/InsertionMethodProcessor.kt
index dba4a87..02b191c 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/InsertionMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/InsertionMethodProcessor.kt
@@ -134,7 +134,7 @@
             setOf(Type.INSERT_VOID, Type.INSERT_ID_ARRAY, Type.INSERT_ID_ARRAY_BOX,
                     Type.INSERT_ID_LIST)
         }
-        fun acceptableTypes(params : List<ShortcutQueryParameter>) : Set<InsertionMethod.Type> {
+        fun acceptableTypes(params: List<ShortcutQueryParameter>): Set<InsertionMethod.Type> {
             if (params.isEmpty()) {
                 return VOID_SET
             }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/PojoProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/PojoProcessor.kt
index f4cd5f3..cb63b6d 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/PojoProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/PojoProcessor.kt
@@ -73,13 +73,12 @@
         val PROCESSED_ANNOTATIONS = listOf(ColumnInfo::class, Embedded::class,
                     Relation::class)
     }
-    fun process() : Pojo {
+    fun process(): Pojo {
         return context.cache.pojos.get(Cache.PojoKey(element, bindingScope, parent), {
             referenceStack.add(element.qualifiedName)
             try {
                 doProcess()
-            }
-            finally {
+            } finally {
                 referenceStack.remove(element.qualifiedName)
             }
         })
@@ -198,8 +197,8 @@
                 constructor = constructor)
     }
 
-    private fun chooseConstructor(myFields: List<Field>, embedded: List<EmbeddedField>)
-            : Constructor? {
+    private fun chooseConstructor(
+            myFields: List<Field>, embedded: List<EmbeddedField>): Constructor? {
         val constructors = ElementFilter.constructorsIn(element.enclosedElements)
                 .filterNot { it.hasAnnotation(Ignore::class) || it.hasAnyOf(PRIVATE) }
         val fieldMap = myFields.associateBy { it.name }
@@ -294,8 +293,8 @@
         }
     }
 
-    private fun processEmbeddedField(declaredType: DeclaredType?, variableElement: VariableElement)
-            : EmbeddedField? {
+    private fun processEmbeddedField(
+            declaredType: DeclaredType?, variableElement: VariableElement): EmbeddedField? {
 
         val asTypeElement = MoreTypes.asTypeElement(variableElement.asType())
 
@@ -308,14 +307,15 @@
                 ?.toString()
                 ?: ""
         val inheritedPrefix = parent?.prefix ?: ""
-        val embeddedField = Field(variableElement,
-                                  variableElement.simpleName.toString(),
-                                  type = context
-                                          .processingEnv
-                                          .typeUtils
-                                          .asMemberOf(declaredType, variableElement),
-                                  affinity = null,
-                                  parent = parent)
+        val embeddedField = Field(
+                variableElement,
+                variableElement.simpleName.toString(),
+                type = context
+                        .processingEnv
+                        .typeUtils
+                        .asMemberOf(declaredType, variableElement),
+                affinity = null,
+                parent = parent)
         val subParent = EmbeddedField(
                 field = embeddedField,
                 prefix = inheritedPrefix + fieldPrefix,
@@ -329,10 +329,10 @@
         return subParent
     }
 
-    private fun processRelationField(myFields : List<Field>, container: DeclaredType?,
-                                     relationElement: VariableElement)
-            : android.arch.persistence.room.vo.Relation? {
-
+    private fun processRelationField(
+            myFields: List<Field>, container: DeclaredType?,
+            relationElement: VariableElement
+    ): android.arch.persistence.room.vo.Relation? {
         val asTypeElement = MoreTypes.asTypeElement(
                 MoreElements.asVariable(relationElement).asType())
 
@@ -376,15 +376,15 @@
         val typeArgElement = MoreTypes.asTypeElement(typeArg)
         val entityClassInput = AnnotationMirrors
                 .getAnnotationValue(annotation, "entity").toClassType()
-        val pojo : Pojo
-        val entity : Entity
+        val pojo: Pojo
+        val entity: Entity
         if (entityClassInput == null
                 || MoreTypes.isTypeOf(Any::class.java, entityClassInput)) {
             entity = EntityProcessor(context, typeArgElement, referenceStack).process()
             pojo = entity
         } else {
             entity = EntityProcessor(context, MoreTypes.asTypeElement(entityClassInput),
-                                     referenceStack).process()
+                    referenceStack).process()
             pojo = PojoProcessor(
                     baseContext = context,
                     element = typeArgElement,
@@ -417,7 +417,7 @@
 
         val projection = AnnotationMirrors.getAnnotationValue(annotation, "projection")
                 .getAsStringList()
-        if(projection.isNotEmpty()) {
+        if (projection.isNotEmpty()) {
             val missingColumns = projection.filterNot { columnName ->
                 entity.fields.any { columnName == it.columnName }
             }
@@ -497,7 +497,7 @@
     }
 
     private fun assignSetters(fields: List<Field>, setterCandidates: List<ExecutableElement>,
-                              constructor : Constructor?) {
+                              constructor: Constructor?) {
         fields.forEach { field ->
             assignSetter(field, setterCandidates, constructor)
         }
@@ -580,9 +580,10 @@
         }
     }
 
-    private fun verifyAndChooseOneFrom(candidates: List<ExecutableElement>?,
-                                       reportAmbiguity: (List<String>) -> Unit)
-            : ExecutableElement? {
+    private fun verifyAndChooseOneFrom(
+            candidates: List<ExecutableElement>?,
+            reportAmbiguity: (List<String>) -> Unit
+    ): ExecutableElement? {
         if (candidates == null) {
             return null
         }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
index 4752478..f00cfa3 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
@@ -40,8 +40,8 @@
     val TRANSACTION_REFERENCE_DOCS = "https://developer.android.com/reference/android/arch/" +
             "persistence/room/Transaction.html"
 
-    fun insertionMethodReturnTypeMismatch(definedReturn : TypeName,
-                                          expectedReturnTypes : List<TypeName>) : String {
+    fun insertionMethodReturnTypeMismatch(definedReturn: TypeName,
+                                          expectedReturnTypes: List<TypeName>): String {
         return "Method returns $definedReturn but it should return one of the following: `" +
                 expectedReturnTypes.joinToString(", ") + "`. If you want to return the list of" +
                 " row ids from the query, your insertion method can receive only 1 parameter."
@@ -208,7 +208,7 @@
     }
 
     fun pojoMissingNonNull(pojoTypeName: TypeName, missingPojoFields: List<String>,
-                           allQueryColumns: List<String>) : String {
+                           allQueryColumns: List<String>): String {
         return """
         The columns returned by the query does not have the fields
         [${missingPojoFields.joinToString(",")}] in $pojoTypeName even though they are
@@ -301,8 +301,7 @@
                 " field in $grandParent."
     }
 
-    fun droppedEmbeddedIndex(entityName: String, fieldPath: String, grandParent: String)
-            : String {
+    fun droppedEmbeddedIndex(entityName: String, fieldPath: String, grandParent: String): String {
         return "Indices defined in $entityName will be dropped when it is merged into" +
                 " $grandParent ($fieldPath). You can re-declare them in $grandParent."
     }
@@ -323,14 +322,14 @@
 
     val RELATION_NOT_COLLECTION = "Fields annotated with @Relation must be a List or Set."
 
-    fun relationCannotFindEntityField(entityName : String, columnName: String,
-                                      availableColumns: List<String>) : String {
+    fun relationCannotFindEntityField(entityName: String, columnName: String,
+                                      availableColumns: List<String>): String {
         return "Cannot find the child entity column `$columnName` in $entityName." +
                 " Options: ${availableColumns.joinToString(", ")}"
     }
 
-    fun relationCannotFindParentEntityField(entityName : String, columnName: String,
-                                            availableColumns: List<String>) : String {
+    fun relationCannotFindParentEntityField(entityName: String, columnName: String,
+                                            availableColumns: List<String>): String {
         return "Cannot find the parent entity column `$columnName` in $entityName." +
                 " Options: ${availableColumns.joinToString(", ")}"
     }
@@ -340,8 +339,8 @@
     val CANNOT_FIND_TYPE = "Cannot find type."
 
     fun relationAffinityMismatch(parentColumn: String, childColumn: String,
-                                 parentAffinity : SQLTypeAffinity?,
-                                 childAffinity : SQLTypeAffinity?) : String {
+                                 parentAffinity: SQLTypeAffinity?,
+                                 childAffinity: SQLTypeAffinity?): String {
         return """
         The affinity of parent column ($parentColumn : $parentAffinity) does not match the type
         affinity of the child column ($childColumn : $childAffinity).
@@ -353,8 +352,8 @@
         it.java.simpleName
     }
 
-    fun relationBadProject(entityQName : String, missingColumnNames : List<String>,
-                           availableColumnNames : List<String>) : String {
+    fun relationBadProject(entityQName: String, missingColumnNames: List<String>,
+                           availableColumnNames: List<String>): String {
         return """
         $entityQName does not have the following columns: ${missingColumnNames.joinToString(",")}.
         Available columns are: ${availableColumnNames.joinToString(",")}
@@ -368,7 +367,7 @@
     val INVALID_FOREIGN_KEY_ACTION = "Invalid foreign key action. It must be one of the constants" +
             " defined in ForeignKey.Action"
 
-    fun foreignKeyNotAnEntity(className : String) : String {
+    fun foreignKeyNotAnEntity(className: String): String {
         return """
         Classes referenced in Foreign Key annotations must be @Entity classes. $className is not
         an entity
@@ -382,9 +381,9 @@
                 " Available column names:${allColumns.joinToString(", ")}"
     }
 
-    fun foreignKeyParentColumnDoesNotExist(parentEntity : String,
+    fun foreignKeyParentColumnDoesNotExist(parentEntity: String,
                                            missingColumn: String,
-                                           allColumns : List<String>): String {
+                                           allColumns: List<String>): String {
         return "($missingColumn) does not exist in $parentEntity. Available columns are" +
                 " ${allColumns.joinToString(",")}"
     }
@@ -393,8 +392,8 @@
 
     val FOREIGN_KEY_EMPTY_PARENT_COLUMN_LIST = "Must specify at least 1 column name for the parent"
 
-    fun foreignKeyColumnNumberMismatch(childColumns : List<String>, parentColumns : List<String>)
-            : String {
+    fun foreignKeyColumnNumberMismatch(
+            childColumns: List<String>, parentColumns: List<String>): String {
         return """
                 Number of child columns in foreign key must match number of parent columns.
                 Child reference has ${childColumns.joinToString(",")} and parent reference has
@@ -402,16 +401,15 @@
                """.trim()
     }
 
-    fun foreignKeyMissingParentEntityInDatabase(parentTable : String, childEntity : String)
-            : String {
+    fun foreignKeyMissingParentEntityInDatabase(parentTable: String, childEntity: String): String {
         return """
                 $parentTable table referenced in the foreign keys of $childEntity does not exist in
                 the database. Maybe you forgot to add the referenced entity in the entities list of
                 the @Database annotation?""".trim()
     }
 
-    fun foreignKeyMissingIndexInParent(parentEntity : String, parentColumns: List<String>,
-                                       childEntity : String, childColumns: List<String>): String {
+    fun foreignKeyMissingIndexInParent(parentEntity: String, parentColumns: List<String>,
+                                       childEntity: String, childColumns: List<String>): String {
         return """
                 $childEntity has a foreign key (${childColumns.joinToString(",")}) that references
                 $parentEntity (${parentColumns.joinToString(",")}) but $parentEntity does not have
@@ -422,7 +420,7 @@
                """.trim()
     }
 
-    fun foreignKeyMissingIndexInChildColumns(childColumns: List<String>) : String {
+    fun foreignKeyMissingIndexInChildColumns(childColumns: List<String>): String {
         return """
                 (${childColumns.joinToString(",")}) column(s) reference a foreign key but
                 they are not part of an index. This may trigger full table scans whenever parent
@@ -431,7 +429,7 @@
                """.trim()
     }
 
-    fun foreignKeyMissingIndexInChildColumn(childColumn: String) : String {
+    fun foreignKeyMissingIndexInChildColumn(childColumn: String): String {
         return """
                 $childColumn column references a foreign key but it is not part of an index. This
                 may trigger full table scans whenever parent table is modified so you are highly
@@ -439,7 +437,7 @@
                """.trim()
     }
 
-    fun shortcutEntityIsNotInDatabase(database : String, dao : String, entity : String) : String {
+    fun shortcutEntityIsNotInDatabase(database: String, dao: String, entity: String): String {
         return """
                 $dao is part of $database but this entity is not in the database. Maybe you forgot
                 to add $entity to the entities section of the @Database?
@@ -448,8 +446,8 @@
     val MISSING_ROOM_RXJAVA2_ARTIFACT = "To use RxJava2 features, you must add `rxjava2`" +
             " artifact from Room as a dependency. android.arch.persistence.room:rxjava2:<version>"
 
-    fun ambigiousConstructor(pojo : String, paramName:String, matchingFields : List<String>)
-            : String {
+    fun ambigiousConstructor(
+            pojo: String, paramName: String, matchingFields: List<String>): String {
         return """
             Ambiguous constructor. The parameter ($paramName) in $pojo matches multiple fields:
             [${matchingFields.joinToString(",")}]. If you don't want to use this constructor,
@@ -475,7 +473,7 @@
 
     val PAGING_SPECIFY_DATA_SOURCE_TYPE = "For now, Room only supports TiledDataSource class."
 
-    fun primaryKeyNull(field: String): String{
+    fun primaryKeyNull(field: String): String {
         return "You must annotate primary keys with @NonNull. \"$field\" is nullable. SQLite " +
                 "considers this a " +
                 "bug and Room does not allow it. See SQLite docs for details: " +
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ShortcutMethodProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ShortcutMethodProcessor.kt
index 95d16f5..c13b818 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ShortcutMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ShortcutMethodProcessor.kt
@@ -28,27 +28,28 @@
 /**
  * Common functionality for shortcut method processors
  */
-class ShortcutMethodProcessor(baseContext : Context,
+class ShortcutMethodProcessor(baseContext: Context,
                               val containing: DeclaredType,
                               val executableElement: ExecutableElement) {
     val context = baseContext.fork(executableElement)
     private val asMember = context.processingEnv.typeUtils.asMemberOf(containing, executableElement)
     private val executableType = MoreTypes.asExecutable(asMember)
 
-    fun extractAnnotation(klass : KClass<out Annotation>,
-                          errorMsg : String) : AnnotationMirror? {
+    fun extractAnnotation(klass: KClass<out Annotation>,
+                          errorMsg: String): AnnotationMirror? {
         val annotation = MoreElements.getAnnotationMirror(executableElement,
                 klass.java).orNull()
         context.checker.check(annotation != null, executableElement, errorMsg)
         return annotation
     }
 
-    fun extractReturnType() : TypeMirror {
+    fun extractReturnType(): TypeMirror {
         return executableType.returnType
     }
 
-    fun extractParams(missingParamError: String)
-            : Pair<Map<String, Entity>, List<ShortcutQueryParameter>> {
+    fun extractParams(
+            missingParamError: String
+    ): Pair<Map<String, Entity>, List<ShortcutQueryParameter>> {
         val params = executableElement.parameters
                 .map { ShortcutParameterProcessor(
                         baseContext = context,
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ShortcutParameterProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ShortcutParameterProcessor.kt
index 4f66920..6ccd12a 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ShortcutParameterProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ShortcutParameterProcessor.kt
@@ -30,7 +30,7 @@
 /**
  * Processes parameters of methods that are annotated with Insert, Delete.
  */
-class ShortcutParameterProcessor(baseContext : Context,
+class ShortcutParameterProcessor(baseContext: Context,
                                  val containing: DeclaredType,
                                  val element: VariableElement) {
     val context = baseContext.fork(element)
@@ -53,13 +53,12 @@
     }
 
     @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
-    fun extractEntityType(typeMirror: TypeMirror) : Pair<TypeMirror?, Boolean> {
+    fun extractEntityType(typeMirror: TypeMirror): Pair<TypeMirror?, Boolean> {
 
         val elementUtils = context.processingEnv.elementUtils
         val typeUtils = context.processingEnv.typeUtils
 
-        fun verifyAndPair(entityType: TypeMirror, isMultiple : Boolean)
-                : Pair<TypeMirror?, Boolean> {
+        fun verifyAndPair(entityType: TypeMirror, isMultiple: Boolean): Pair<TypeMirror?, Boolean> {
             if (!MoreTypes.isType(entityType)) {
                 return Pair(null, isMultiple)
             }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/SuppressWarningProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/SuppressWarningProcessor.kt
index e2215d9..9edf2f9 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/SuppressWarningProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/SuppressWarningProcessor.kt
@@ -44,8 +44,8 @@
     }
 
     private object VISITOR : SimpleAnnotationValueVisitor6<Set<Warning>, String>() {
-        override fun visitArray(values: List<AnnotationValue>?, elementName: String?)
-                : Set<Warning> {
+        override fun visitArray(values: List<AnnotationValue>?, elementName: String?
+        ): Set<Warning> {
             return values?.map {
                 Warning.fromPublicKey(it.value.toString())
             }?.filterNotNull()?.toSet() ?: emptySet()
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/UpdateMethodProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/UpdateMethodProcessor.kt
index 452ea4a..27211ce 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/UpdateMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/UpdateMethodProcessor.kt
@@ -25,9 +25,10 @@
 import javax.lang.model.element.ExecutableElement
 import javax.lang.model.type.DeclaredType
 
-class UpdateMethodProcessor(baseContext: Context,
-                              val containing: DeclaredType,
-                              val executableElement: ExecutableElement) {
+class UpdateMethodProcessor(
+        baseContext: Context,
+        val containing: DeclaredType,
+        val executableElement: ExecutableElement) {
     val context = baseContext.fork(executableElement)
 
     fun process(): UpdateMethod {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/cache/Cache.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/cache/Cache.kt
index 37f6c6d..0ef5dde 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/cache/Cache.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/cache/Cache.kt
@@ -40,7 +40,7 @@
 
     inner class Bucket<K, T>(source: Bucket<K, T>?) {
         private val entries: MutableMap<FullKey<K>, T> = source?.entries ?: mutableMapOf()
-        fun get(key : K, calculate: () -> T): T {
+        fun get(key: K, calculate: () -> T): T {
             val fullKey = FullKey(converters, suppressedWarnings, key)
             return entries.getOrPut(fullKey, {
                 calculate()
@@ -56,15 +56,18 @@
     /**
      * Key for Pojo cache
      */
-    data class PojoKey(val element: Element, val scope : FieldProcessor.BindingScope,
-                       val parent : EmbeddedField?)
+    data class PojoKey(
+            val element: Element,
+            val scope: FieldProcessor.BindingScope,
+            val parent: EmbeddedField?)
 
     /**
      * Internal key representation with adapters & warnings included.
      * <p>
      * Converters are kept in a linked set since the order is important for the TypeAdapterStore.
      */
-    private data class FullKey<T>(val converters: LinkedHashSet<TypeMirror>,
-                               val suppressedWarnings: Set<Warning>,
-                               val key: T)
+    private data class FullKey<T>(
+            val converters: LinkedHashSet<TypeMirror>,
+            val suppressedWarnings: Set<Warning>,
+            val key: T)
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/CodeGenScope.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/CodeGenScope.kt
index 64e4f48..59c2283 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/CodeGenScope.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/CodeGenScope.kt
@@ -22,29 +22,29 @@
 /**
  * Defines a code generation scope where we can provide temporary variables, global variables etc
  */
-class CodeGenScope(val writer : ClassWriter) {
+class CodeGenScope(val writer: ClassWriter) {
     private var tmpVarIndices = mutableMapOf<String, Int>()
-    private var builder : CodeBlock.Builder? = null
+    private var builder: CodeBlock.Builder? = null
     companion object {
         const val TMP_VAR_DEFAULT_PREFIX = "_tmp"
         const val CLASS_PROPERTY_PREFIX = "__"
         @VisibleForTesting
-        fun _tmpVar(index:Int) = _tmpVar(TMP_VAR_DEFAULT_PREFIX, index)
-        fun _tmpVar(prefix : String, index:Int) = "$prefix${if(index == 0) "" else "_$index"}"
+        fun _tmpVar(index: Int) = _tmpVar(TMP_VAR_DEFAULT_PREFIX, index)
+        fun _tmpVar(prefix: String, index: Int) = "$prefix${if (index == 0) "" else "_$index"}"
     }
 
-    fun builder() : CodeBlock.Builder {
+    fun builder(): CodeBlock.Builder {
         if (builder == null) {
             builder = CodeBlock.builder()
         }
         return builder!!
     }
 
-    fun getTmpVar() : String {
+    fun getTmpVar(): String {
         return getTmpVar(TMP_VAR_DEFAULT_PREFIX)
     }
 
-    fun getTmpVar(prefix : String) : String {
+    fun getTmpVar(prefix: String): String {
         if (!prefix.startsWith("_")) {
             throw IllegalArgumentException("tmp variable prefixes should start with _")
         }
@@ -62,7 +62,7 @@
     /**
      * copies all variable indices but excludes generated code.
      */
-    fun fork() : CodeGenScope {
+    fun fork(): CodeGenScope {
         val forked = CodeGenScope(writer)
         forked.tmpVarIndices.putAll(tmpVarIndices)
         return forked
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/ObservableQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/ObservableQueryResultBinderProvider.kt
index 89b0072..d64ef4b 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/ObservableQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/ObservableQueryResultBinderProvider.kt
@@ -29,12 +29,12 @@
  */
 abstract class ObservableQueryResultBinderProvider(val context: Context)
     : QueryResultBinderProvider {
-    protected abstract fun extractTypeArg(declared: DeclaredType) : TypeMirror
+    protected abstract fun extractTypeArg(declared: DeclaredType): TypeMirror
     protected abstract fun create(typeArg: TypeMirror,
                                   resultAdapter: QueryResultAdapter?,
-                                  tableNames : Set<String>) : QueryResultBinder
+                                  tableNames: Set<String>): QueryResultBinder
 
-    override final fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
+    final override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
         val typeArg = extractTypeArg(declared)
         val adapter = context.typeAdapterStore.findQueryResultAdapter(typeArg, query)
         val tableNames = ((adapter?.accessedTableNames() ?: emptyList()) +
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/QueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/QueryResultBinderProvider.kt
index b76be3e..ccc3597 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/QueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/QueryResultBinderProvider.kt
@@ -21,6 +21,6 @@
 import javax.lang.model.type.DeclaredType
 
 interface QueryResultBinderProvider {
-    fun provide(declared : DeclaredType, query: ParsedQuery) : QueryResultBinder
-    fun matches(declared: DeclaredType) : Boolean
+    fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder
+    fun matches(declared: DeclaredType): Boolean
 }
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/TypeAdapterStore.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/TypeAdapterStore.kt
index 5b94111..dcd5ee6 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/TypeAdapterStore.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/TypeAdapterStore.kt
@@ -62,7 +62,7 @@
 import com.google.auto.common.MoreElements
 import com.google.auto.common.MoreTypes
 import com.google.common.annotations.VisibleForTesting
-import java.util.LinkedList;
+import java.util.LinkedList
 import javax.lang.model.type.ArrayType
 import javax.lang.model.type.TypeKind
 import javax.lang.model.type.TypeMirror
@@ -72,16 +72,16 @@
  * Holds all type adapters and can create on demand composite type adapters to convert a type into a
  * database column.
  */
-class TypeAdapterStore private constructor(val context: Context,
-                                           /**
-                                            * first type adapter has the highest priority
-                                            */
-                                           private val columnTypeAdapters: List<ColumnTypeAdapter>,
-                                           /**
-                                            * first converter has the highest priority
-                                            */
-                                           private val typeConverters: List<TypeConverter>) {
-
+class TypeAdapterStore private constructor(
+        val context: Context,
+        /**
+         * first type adapter has the highest priority
+         */
+        private val columnTypeAdapters: List<ColumnTypeAdapter>,
+        /**
+         * first converter has the highest priority
+         */
+        private val typeConverters: List<TypeConverter>) {
 
     companion object {
         fun copy(context: Context, store: TypeAdapterStore): TypeAdapterStore {
@@ -147,8 +147,10 @@
     /**
      * Searches 1 way to bind a value into a statement.
      */
-    fun findStatementValueBinder(input: TypeMirror, affinity: SQLTypeAffinity?)
-            : StatementValueBinder? {
+    fun findStatementValueBinder(
+            input: TypeMirror,
+            affinity: SQLTypeAffinity?
+    ): StatementValueBinder? {
         if (input.kind == TypeKind.ERROR) {
             return null
         }
@@ -218,8 +220,7 @@
      * Finds a two way converter, if you need 1 way, use findStatementValueBinder or
      * findCursorValueReader.
      */
-    fun findColumnTypeAdapter(out: TypeMirror, affinity: SQLTypeAffinity?)
-            : ColumnTypeAdapter? {
+    fun findColumnTypeAdapter(out: TypeMirror, affinity: SQLTypeAffinity?): ColumnTypeAdapter? {
         if (out.kind == TypeKind.ERROR) {
             return null
         }
@@ -236,8 +237,8 @@
                 fromCursor)
     }
 
-    private fun findDirectAdapterFor(out: TypeMirror, affinity: SQLTypeAffinity?)
-            : ColumnTypeAdapter? {
+    private fun findDirectAdapterFor(
+            out: TypeMirror, affinity: SQLTypeAffinity?): ColumnTypeAdapter? {
         val adapter = getAllColumnAdapters(out).firstOrNull {
             affinity == null || it.typeAffinity == affinity
         }
@@ -259,8 +260,7 @@
         }
     }
 
-    fun findQueryResultAdapter(typeMirror: TypeMirror, query: ParsedQuery)
-            : QueryResultAdapter? {
+    fun findQueryResultAdapter(typeMirror: TypeMirror, query: ParsedQuery): QueryResultAdapter? {
         if (typeMirror.kind == TypeKind.ERROR) {
             return null
         }
@@ -382,8 +382,8 @@
         return findTypeConverter(input, listOf(output))
     }
 
-    private fun findTypeConverter(inputs: List<TypeMirror>, outputs: List<TypeMirror>)
-            : TypeConverter? {
+    private fun findTypeConverter(
+            inputs: List<TypeMirror>, outputs: List<TypeMirror>): TypeConverter? {
         if (inputs.isEmpty()) {
             return null
         }
@@ -397,8 +397,7 @@
         val excludes = arrayListOf<TypeMirror>()
 
         val queue = LinkedList<TypeConverter>()
-        fun exactMatch(candidates: List<TypeConverter>)
-                : TypeConverter? {
+        fun exactMatch(candidates: List<TypeConverter>): TypeConverter? {
             return candidates.firstOrNull {
                 outputs.any { output -> types.isSameType(output, it.to) }
             }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/InstantQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/InstantQueryResultBinderProvider.kt
index af03a88..c7d1e2d 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/InstantQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/InstantQueryResultBinderProvider.kt
@@ -23,7 +23,7 @@
 import android.arch.persistence.room.solver.query.result.QueryResultBinder
 import javax.lang.model.type.DeclaredType
 
-class InstantQueryResultBinderProvider(val context : Context) : QueryResultBinderProvider {
+class InstantQueryResultBinderProvider(val context: Context) : QueryResultBinderProvider {
     override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
         return InstantQueryResultBinder(
                 context.typeAdapterStore.findQueryResultAdapter(declared, query))
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
index 650ec19..b62eabd 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
@@ -25,7 +25,7 @@
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
-class LiveDataQueryResultBinderProvider(context : Context)
+class LiveDataQueryResultBinderProvider(context: Context)
     : ObservableQueryResultBinderProvider(context) {
     private val liveDataTypeMirror: TypeMirror? by lazy {
         context.processingEnv.elementUtils
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
index 0bd3fb1..11b824f 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
@@ -22,7 +22,6 @@
 import android.arch.persistence.room.processor.Context
 import android.arch.persistence.room.processor.ProcessorErrors
 import android.arch.persistence.room.solver.QueryResultBinderProvider
-import android.arch.persistence.room.solver.query.result.InstantQueryResultBinder
 import android.arch.persistence.room.solver.query.result.QueryResultBinder
 import android.arch.persistence.room.solver.query.result.RxCallableQueryResultBinder
 import javax.lang.model.type.DeclaredType
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/ArrayQueryParameterAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/ArrayQueryParameterAdapter.kt
index 9cafb23..12756d8 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/ArrayQueryParameterAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/ArrayQueryParameterAdapter.kt
@@ -26,7 +26,7 @@
 /**
  * Binds ARRAY(T) (e.g. int[]) into String[] args of a query.
  */
-class ArrayQueryParameterAdapter(val bindAdapter : StatementValueBinder)
+class ArrayQueryParameterAdapter(val bindAdapter: StatementValueBinder)
             : QueryParameterAdapter(true) {
     override fun bindToStmt(inputVarName: String, stmtVarName: String, startIndexVarName: String,
                             scope: CodeGenScope) {
@@ -41,7 +41,7 @@
         }
     }
 
-    override fun getArgCount(inputVarName: String, outputVarName : String, scope: CodeGenScope) {
+    override fun getArgCount(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
         scope.builder()
                 .addStatement("final $T $L = $L.length", TypeName.INT, outputVarName, inputVarName)
     }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/BasicQueryParameterAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/BasicQueryParameterAdapter.kt
index 11521f2..41ab2cf 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/BasicQueryParameterAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/BasicQueryParameterAdapter.kt
@@ -22,7 +22,7 @@
 /**
  * Knows how to convert a query parameter into arguments
  */
-class BasicQueryParameterAdapter(val bindAdapter : StatementValueBinder)
+class BasicQueryParameterAdapter(val bindAdapter: StatementValueBinder)
             : QueryParameterAdapter(false) {
     override fun bindToStmt(inputVarName: String, stmtVarName: String, startIndexVarName: String,
                             scope: CodeGenScope) {
@@ -31,7 +31,7 @@
         }
     }
 
-    override fun getArgCount(inputVarName: String, outputVarName : String, scope: CodeGenScope) {
+    override fun getArgCount(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
         throw UnsupportedOperationException("should not call getArgCount on basic adapters." +
                 "It is always one.")
     }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/CollectionQueryParameterAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/CollectionQueryParameterAdapter.kt
index 7e0b206..00c350a 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/CollectionQueryParameterAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/CollectionQueryParameterAdapter.kt
@@ -26,7 +26,7 @@
 /**
  * Binds Collection<T> (e.g. List<T>) into String[] query args.
  */
-class CollectionQueryParameterAdapter(val bindAdapter : StatementValueBinder)
+class CollectionQueryParameterAdapter(val bindAdapter: StatementValueBinder)
             : QueryParameterAdapter(true) {
     override fun bindToStmt(inputVarName: String, stmtVarName: String, startIndexVarName: String,
                             scope: CodeGenScope) {
@@ -41,7 +41,7 @@
         }
     }
 
-    override fun getArgCount(inputVarName: String, outputVarName : String, scope: CodeGenScope) {
+    override fun getArgCount(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
         scope.builder()
                 .addStatement("final $T $L = $L.size()", TypeName.INT, outputVarName, inputVarName)
     }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/QueryParameterAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/QueryParameterAdapter.kt
index b93659e..a42bfee 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/QueryParameterAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/parameter/QueryParameterAdapter.kt
@@ -25,11 +25,14 @@
     /**
      * Must bind the value into the statement at the given index.
      */
-    abstract fun bindToStmt(inputVarName: String, stmtVarName: String, startIndexVarName: String,
-                         scope: CodeGenScope)
+    abstract fun bindToStmt(
+            inputVarName: String,
+            stmtVarName: String,
+            startIndexVarName: String,
+            scope: CodeGenScope)
 
     /**
      * Should declare and set the given value with the count
      */
-    abstract fun getArgCount(inputVarName: String, outputVarName : String, scope : CodeGenScope)
+    abstract fun getArgCount(inputVarName: String, outputVarName: String, scope: CodeGenScope)
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/CursorQueryResultBinder.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/CursorQueryResultBinder.kt
index 06ec339..fede566 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/CursorQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/CursorQueryResultBinder.kt
@@ -21,13 +21,12 @@
 import android.arch.persistence.room.ext.N
 import android.arch.persistence.room.ext.T
 import android.arch.persistence.room.solver.CodeGenScope
-import android.arch.persistence.room.writer.DaoWriter
 import com.squareup.javapoet.FieldSpec
 
 class CursorQueryResultBinder : QueryResultBinder(NO_OP_RESULT_ADAPTER) {
     override fun convertAndReturn(roomSQLiteQueryVar: String,
                                   dbField: FieldSpec,
-                                  inTransaction : Boolean,
+                                  inTransaction: Boolean,
                                   scope: CodeGenScope) {
         val builder = scope.builder()
         val transactionWrapper = if (inTransaction) {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/FlowableQueryResultBinder.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/FlowableQueryResultBinder.kt
index e1a75b5..f4f1d43 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/FlowableQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/FlowableQueryResultBinder.kt
@@ -39,7 +39,7 @@
     : BaseObservableQueryResultBinder(adapter) {
     override fun convertAndReturn(roomSQLiteQueryVar: String,
                                   dbField: FieldSpec,
-                                  inTransaction : Boolean,
+                                  inTransaction: Boolean,
                                   scope: CodeGenScope) {
         val callableImpl = TypeSpec.anonymousClassBuilder("").apply {
             val typeName = typeArg.typeName()
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/InstantQueryResultBinder.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/InstantQueryResultBinder.kt
index c18bf2d..b9623c1 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/InstantQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/InstantQueryResultBinder.kt
@@ -27,9 +27,9 @@
  * Instantly runs and returns the query.
  */
 class InstantQueryResultBinder(adapter: QueryResultAdapter?) : QueryResultBinder(adapter) {
-    override fun convertAndReturn(roomSQLiteQueryVar : String,
+    override fun convertAndReturn(roomSQLiteQueryVar: String,
                                   dbField: FieldSpec,
-                                  inTransaction : Boolean,
+                                  inTransaction: Boolean,
                                   scope: CodeGenScope) {
         val transactionWrapper = if (inTransaction) {
             scope.builder().transactionWrapper(dbField)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/LiveDataQueryResultBinder.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/LiveDataQueryResultBinder.kt
index 0ef8a93..1191ae3 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/LiveDataQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/LiveDataQueryResultBinder.kt
@@ -40,10 +40,12 @@
                                 adapter: QueryResultAdapter?)
     : BaseObservableQueryResultBinder(adapter) {
     @Suppress("JoinDeclarationAndAssignment")
-    override fun convertAndReturn(roomSQLiteQueryVar : String,
-                                  dbField: FieldSpec,
-                                  inTransaction : Boolean,
-                                  scope: CodeGenScope) {
+    override fun convertAndReturn(
+            roomSQLiteQueryVar: String,
+            dbField: FieldSpec,
+            inTransaction: Boolean,
+            scope: CodeGenScope
+    ) {
         val typeName = typeArg.typeName()
 
         val liveDataImpl = TypeSpec.anonymousClassBuilder("").apply {
@@ -67,10 +69,14 @@
         }
     }
 
-    private fun createComputeMethod(roomSQLiteQueryVar: String, typeName: TypeName,
-                                    observerField: FieldSpec, dbField: FieldSpec,
-                                    inTransaction: Boolean,
-                                    scope: CodeGenScope): MethodSpec {
+    private fun createComputeMethod(
+            roomSQLiteQueryVar: String,
+            typeName: TypeName,
+            observerField: FieldSpec,
+            dbField: FieldSpec,
+            inTransaction: Boolean,
+            scope: CodeGenScope
+    ): MethodSpec {
         return MethodSpec.methodBuilder("compute").apply {
             addAnnotation(Override::class.java)
             addModifiers(Modifier.PROTECTED)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/LivePagedListQueryResultBinder.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/LivePagedListQueryResultBinder.kt
index c10f9fb..ceb946e 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/LivePagedListQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/LivePagedListQueryResultBinder.kt
@@ -31,10 +31,12 @@
     : QueryResultBinder(tiledDataSourceQueryResultBinder.listAdapter) {
     @Suppress("HasPlatformType")
     val typeName = tiledDataSourceQueryResultBinder.itemTypeName
-    override fun convertAndReturn(roomSQLiteQueryVar: String,
-                                  dbField: FieldSpec,
-                                  inTransaction : Boolean,
-                                  scope: CodeGenScope) {
+    override fun convertAndReturn(
+            roomSQLiteQueryVar: String,
+            dbField: FieldSpec,
+            inTransaction: Boolean,
+            scope: CodeGenScope
+    ) {
         scope.builder().apply {
             val pagedListProvider = TypeSpec
                     .anonymousClassBuilder("").apply {
@@ -50,11 +52,12 @@
         }
     }
 
-    private fun createCreateDataSourceMethod(roomSQLiteQueryVar: String,
-                                             dbField: FieldSpec,
-                                             inTransaction : Boolean,
-                                             scope: CodeGenScope): MethodSpec
-            = MethodSpec.methodBuilder("createDataSource").apply {
+    private fun createCreateDataSourceMethod(
+            roomSQLiteQueryVar: String,
+            dbField: FieldSpec,
+            inTransaction: Boolean,
+            scope: CodeGenScope
+    ): MethodSpec = MethodSpec.methodBuilder("createDataSource").apply {
         addAnnotation(Override::class.java)
         addModifiers(Modifier.PROTECTED)
         returns(tiledDataSourceQueryResultBinder.typeName)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/QueryResultAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/QueryResultAdapter.kt
index aaf17cd..2f6ca75 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/QueryResultAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/QueryResultAdapter.kt
@@ -21,10 +21,9 @@
 /**
  * Gets a Cursor and converts it into the return type of a method annotated with @Query.
  */
-abstract class QueryResultAdapter(val rowAdapter : RowAdapter?) {
+abstract class QueryResultAdapter(val rowAdapter: RowAdapter?) {
     abstract fun convert(outVarName: String, cursorVarName: String, scope: CodeGenScope)
     fun accessedTableNames(): List<String> {
         return (rowAdapter as? PojoRowAdapter)?.relationTableNames() ?: emptyList<String>()
     }
-
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/QueryResultBinder.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/QueryResultBinder.kt
index 652de46..a77d97f 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/QueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/QueryResultBinder.kt
@@ -33,6 +33,6 @@
      */
     abstract fun convertAndReturn(roomSQLiteQueryVar: String,
                                   dbField: FieldSpec,
-                                  inTransaction : Boolean,
+                                  inTransaction: Boolean,
                                   scope: CodeGenScope)
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/RowAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/RowAdapter.kt
index 581baf2..cb25d97 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/RowAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/RowAdapter.kt
@@ -24,11 +24,11 @@
  * <p>
  * An instance of this is created for each usage so that it can keep local variables.
  */
-abstract class RowAdapter(val out : TypeMirror) {
+abstract class RowAdapter(val out: TypeMirror) {
     /**
      * Called when cursor variable is ready, good place to put initialization code.
      */
-    open fun onCursorReady(cursorVarName: String, scope : CodeGenScope) {}
+    open fun onCursorReady(cursorVarName: String, scope: CodeGenScope) {}
 
     /**
      * Called to convert a single row.
@@ -39,5 +39,5 @@
      * Called when the cursor is finished. It is important to return null if no operation is
      * necessary so that caller can understand that we can do lazy loading.
      */
-    open fun onCursorFinished() : ((scope : CodeGenScope) -> Unit)? = null
+    open fun onCursorFinished(): ((scope: CodeGenScope) -> Unit)? = null
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/RxCallableQueryResultBinder.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/RxCallableQueryResultBinder.kt
index 1ab91e8..2aba076 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/RxCallableQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/RxCallableQueryResultBinder.kt
@@ -42,7 +42,7 @@
     : QueryResultBinder(adapter) {
     override fun convertAndReturn(roomSQLiteQueryVar: String,
                                   dbField: FieldSpec,
-                                  inTransaction : Boolean,
+                                  inTransaction: Boolean,
                                   scope: CodeGenScope) {
         val callable = TypeSpec.anonymousClassBuilder("").apply {
             val typeName = typeArg.typeName()
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/TiledDataSourceQueryResultBinder.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/TiledDataSourceQueryResultBinder.kt
index 2281cfb..733fdee 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/TiledDataSourceQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/TiledDataSourceQueryResultBinder.kt
@@ -31,15 +31,15 @@
 import com.squareup.javapoet.TypeSpec
 import javax.lang.model.element.Modifier
 
-class TiledDataSourceQueryResultBinder(val listAdapter : ListQueryResultAdapter?,
-                                       val tableNames : List<String>)
+class TiledDataSourceQueryResultBinder(val listAdapter: ListQueryResultAdapter?,
+                                       val tableNames: List<String>)
             : QueryResultBinder(listAdapter) {
-    val itemTypeName : TypeName = listAdapter?.rowAdapter?.out?.typeName() ?: TypeName.OBJECT
-    val typeName : ParameterizedTypeName = ParameterizedTypeName.get(
+    val itemTypeName: TypeName = listAdapter?.rowAdapter?.out?.typeName() ?: TypeName.OBJECT
+    val typeName: ParameterizedTypeName = ParameterizedTypeName.get(
             RoomTypeNames.LIMIT_OFFSET_DATA_SOURCE, itemTypeName)
     override fun convertAndReturn(roomSQLiteQueryVar: String,
                                   dbField: FieldSpec,
-                                  inTransaction : Boolean,
+                                  inTransaction: Boolean,
                                   scope: CodeGenScope) {
         val tableNamesList = tableNames.joinToString(",") { "\"$it\"" }
         val spec = TypeSpec.anonymousClassBuilder("$N, $L, $L, $L",
@@ -52,7 +52,7 @@
         }
     }
 
-    fun createConvertRowsMethod(scope : CodeGenScope): MethodSpec =
+    fun createConvertRowsMethod(scope: CodeGenScope): MethodSpec =
             MethodSpec.methodBuilder("convertRows").apply {
                 addAnnotation(Override::class.java)
                 addModifiers(Modifier.PROTECTED)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/TransactionWrapper.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/TransactionWrapper.kt
index 30d02ee..b48f179 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/TransactionWrapper.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/TransactionWrapper.kt
@@ -30,7 +30,7 @@
     fun endTransactionWithControlFlow()
 }
 
-fun MethodSpec.Builder.transactionWrapper(dbField : FieldSpec) = object : TransactionWrapper {
+fun MethodSpec.Builder.transactionWrapper(dbField: FieldSpec) = object : TransactionWrapper {
     override fun beginTransactionWithControlFlow() {
         addStatement("$N.beginTransaction()", dbField)
         beginControlFlow("try")
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/BoxedBooleanToBoxedIntConverter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
index 552da9e..70030a8 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
@@ -43,7 +43,6 @@
                         scope.builder().addStatement("$L = $L == null ? null : $L != 0",
                                 outputVarName, inputVarName, inputVarName)
                     }
-
                 }
         )
     }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt
index 1b34b46..debc59a 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt
@@ -25,13 +25,15 @@
 /**
  * Adapters for all boxed primitives that has direct cursor mappings.
  */
-open class BoxedPrimitiveColumnTypeAdapter(boxed : TypeMirror,
-                                           val primitiveAdapter : PrimitiveColumnTypeAdapter)
-            : ColumnTypeAdapter(boxed, primitiveAdapter.typeAffinity) {
+open class BoxedPrimitiveColumnTypeAdapter(
+        boxed: TypeMirror,
+        val primitiveAdapter: PrimitiveColumnTypeAdapter
+) : ColumnTypeAdapter(boxed, primitiveAdapter.typeAffinity) {
     companion object {
-        fun createBoxedPrimitiveAdapters(processingEnvironment: ProcessingEnvironment,
-                                    primitiveAdapters : List<PrimitiveColumnTypeAdapter>)
-                : List<ColumnTypeAdapter> {
+        fun createBoxedPrimitiveAdapters(
+                processingEnvironment: ProcessingEnvironment,
+                primitiveAdapters: List<PrimitiveColumnTypeAdapter>
+        ): List<ColumnTypeAdapter> {
 
             return primitiveAdapters.map {
                 BoxedPrimitiveColumnTypeAdapter(
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/ByteArrayColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/ByteArrayColumnTypeAdapter.kt
index 014ea44..5de76de 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/ByteArrayColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/ByteArrayColumnTypeAdapter.kt
@@ -22,7 +22,7 @@
 import javax.annotation.processing.ProcessingEnvironment
 import javax.lang.model.type.TypeKind
 
-class ByteArrayColumnTypeAdapter(env : ProcessingEnvironment) : ColumnTypeAdapter(
+class ByteArrayColumnTypeAdapter(env: ProcessingEnvironment) : ColumnTypeAdapter(
         out = env.typeUtils.getArrayType(env.typeUtils.getPrimitiveType(TypeKind.BYTE)),
         typeAffinity = SQLTypeAffinity.BLOB) {
     override fun readFromCursor(outVarName: String, cursorVarName: String, indexVarName: String,
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CompositeTypeConverter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CompositeTypeConverter.kt
index 86a5272..b02709a 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CompositeTypeConverter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CompositeTypeConverter.kt
@@ -24,7 +24,7 @@
 /**
  * combines 2 type converters
  */
-class CompositeTypeConverter(val conv1 : TypeConverter, val conv2 : TypeConverter) : TypeConverter(
+class CompositeTypeConverter(val conv1: TypeConverter, val conv2: TypeConverter) : TypeConverter(
         conv1.from, conv2.to) {
     override fun convert(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
         scope.builder().apply {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CursorValueReader.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CursorValueReader.kt
index e6726cd..9293143 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CursorValueReader.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CursorValueReader.kt
@@ -25,8 +25,8 @@
  * see: StatementValueBinder
  */
 interface CursorValueReader {
-    fun affinity() : SQLTypeAffinity
-    fun typeMirror() : TypeMirror
-    fun readFromCursor(outVarName : String, cursorVarName: String, indexVarName: String,
+    fun affinity(): SQLTypeAffinity
+    fun typeMirror(): TypeMirror
+    fun readFromCursor(outVarName: String, cursorVarName: String, indexVarName: String,
                                 scope: CodeGenScope)
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CustomTypeConverterWrapper.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CustomTypeConverterWrapper.kt
index b4c7dc2..c127203 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CustomTypeConverterWrapper.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/CustomTypeConverterWrapper.kt
@@ -46,7 +46,7 @@
         }
     }
 
-    fun typeConverter(scope: CodeGenScope) : FieldSpec {
+    fun typeConverter(scope: CodeGenScope): FieldSpec {
         val baseName = (custom.typeName as ClassName).simpleName().decapitalize()
         return scope.writer.getOrCreateField(object : ClassWriter.SharedFieldSpec(
                 baseName, custom.typeName) {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/NoOpConverter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/NoOpConverter.kt
index e803d30..c37698b 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/NoOpConverter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/NoOpConverter.kt
@@ -28,7 +28,7 @@
  * the query. Not having this would require us to special case handle String, String[], List<String>
  * etc.
  */
-class NoOpConverter(type : TypeMirror) : TypeConverter(
+class NoOpConverter(type: TypeMirror) : TypeConverter(
         type, type) {
     override fun convert(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
         scope.builder()
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/PrimitiveColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/PrimitiveColumnTypeAdapter.kt
index c04e7bb..69cc0f8 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/PrimitiveColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/PrimitiveColumnTypeAdapter.kt
@@ -37,16 +37,17 @@
 open class PrimitiveColumnTypeAdapter(out: PrimitiveType,
                                       val cursorGetter: String,
                                       val stmtSetter: String,
-                                      typeAffinity : SQLTypeAffinity)
+                                      typeAffinity: SQLTypeAffinity)
         : ColumnTypeAdapter(out, typeAffinity) {
-    val cast =  if (cursorGetter == "get${out.typeName().toString().capitalize()}")
+    val cast = if (cursorGetter == "get${out.typeName().toString().capitalize()}")
                     ""
                 else
                     "(${out.typeName()}) "
 
     companion object {
-        fun createPrimitiveAdapters(processingEnvironment: ProcessingEnvironment)
-                : List<PrimitiveColumnTypeAdapter> {
+        fun createPrimitiveAdapters(
+                processingEnvironment: ProcessingEnvironment
+        ): List<PrimitiveColumnTypeAdapter> {
             return listOf(
                     Triple(INT, "getInt", "bindLong"),
                     Triple(SHORT, "getShort", "bindLong"),
@@ -60,7 +61,7 @@
                         out = processingEnvironment.typeUtils.getPrimitiveType(it.first),
                         cursorGetter = it.second,
                         stmtSetter = it.third,
-                        typeAffinity = when(it.first) {
+                        typeAffinity = when (it.first) {
                             INT, SHORT, BYTE, LONG, CHAR -> SQLTypeAffinity.INTEGER
                             FLOAT, DOUBLE -> REAL
                             else -> throw IllegalArgumentException("invalid type")
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/StatementValueBinder.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/StatementValueBinder.kt
index c898268..d83c145 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/StatementValueBinder.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/StatementValueBinder.kt
@@ -24,7 +24,7 @@
  * see: CursorValueReader
  */
 interface StatementValueBinder {
-    fun typeMirror() : TypeMirror
+    fun typeMirror(): TypeMirror
     fun bindToStmt(stmtName: String, indexVarName: String, valueVarName: String,
                             scope: CodeGenScope)
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/TypeConverter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/TypeConverter.kt
index 134daf4..67b70dc 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/TypeConverter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/types/TypeConverter.kt
@@ -17,7 +17,6 @@
 package android.arch.persistence.room.solver.types
 
 import android.arch.persistence.room.solver.CodeGenScope
-import com.squareup.javapoet.TypeName
 import javax.lang.model.type.TypeMirror
 
 /**
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/ColumnInfo.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/ColumnInfo.kt
index e249871..652860b 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/ColumnInfo.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/ColumnInfo.kt
@@ -21,4 +21,4 @@
 /**
  * Represents a column in a query response
  */
-data class ColumnInfo(val name : String, val type : SQLTypeAffinity)
+data class ColumnInfo(val name: String, val type: SQLTypeAffinity)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/DatabaseVerificaitonErrors.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/DatabaseVerificaitonErrors.kt
index a744894..6b133b4 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/DatabaseVerificaitonErrors.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/DatabaseVerificaitonErrors.kt
@@ -19,19 +19,19 @@
 import java.sql.SQLException
 
 object DatabaseVerificaitonErrors {
-    private val CANNOT_CREATE_TABLE : String = "Create table statement had an error: %s"
-    fun cannotCreateTable(exception: SQLException) : String {
+    private val CANNOT_CREATE_TABLE: String = "Create table statement had an error: %s"
+    fun cannotCreateTable(exception: SQLException): String {
         return CANNOT_CREATE_TABLE.format(exception.message)
     }
 
-    private val CANNOT_VERIFY_QUERY : String = "There is a problem with the query: %s"
-    fun cannotVerifyQuery(exception: SQLException) : String {
+    private val CANNOT_VERIFY_QUERY: String = "There is a problem with the query: %s"
+    fun cannotVerifyQuery(exception: SQLException): String {
         return CANNOT_VERIFY_QUERY.format(exception.message)
     }
 
-    private val CANNOT_CREATE_SQLITE_CONNECTION : String = "Room cannot create an SQLite" +
+    private val CANNOT_CREATE_SQLITE_CONNECTION: String = "Room cannot create an SQLite" +
             " connection to verify the queries. Query verification will be disabled. Error: %s"
-    fun cannotCreateConnection(exception: Exception) : String {
+    fun cannotCreateConnection(exception: Exception): String {
         return CANNOT_CREATE_SQLITE_CONNECTION.format(exception.message)
     }
 
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/DatabaseVerifier.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/DatabaseVerifier.kt
index 11acbdf..d384c3c 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/DatabaseVerifier.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/DatabaseVerifier.kt
@@ -33,7 +33,7 @@
  * This class is also used to resolve the return types.
  */
 class DatabaseVerifier private constructor(
-        val connection : Connection, val context : Context, val entities : List<Entity>) {
+        val connection: Connection, val context: Context, val entities: List<Entity>) {
     companion object {
         private const val CONNECTION_URL = "jdbc:sqlite::memory:"
 
@@ -54,11 +54,11 @@
         /**
          * Tries to create a verifier but returns null if it cannot find the driver.
          */
-        fun create(context: Context, element: Element, entities: List<Entity>) : DatabaseVerifier? {
+        fun create(context: Context, element: Element, entities: List<Entity>): DatabaseVerifier? {
             return try {
                 val connection = JDBC.createConnection(CONNECTION_URL, java.util.Properties())
                 DatabaseVerifier(connection, context, entities)
-            } catch (ex : Exception) {
+            } catch (ex: Exception) {
                 context.logger.w(Warning.CANNOT_CREATE_VERIFICATION_DATABASE, element,
                         DatabaseVerificaitonErrors.cannotCreateConnection(ex))
                 null
@@ -76,7 +76,7 @@
                 DriverManager.getDriver(CONNECTION_URL)?.let {
                     DriverManager.deregisterDriver(it)
                 }
-            } catch (t : Throwable) {
+            } catch (t: Throwable) {
                 System.err.println("Room: cannot unregister driver ${t.message}")
             }
         }
@@ -88,11 +88,11 @@
         }
     }
 
-    fun analyze(sql : String) : QueryResultInfo {
+    fun analyze(sql: String): QueryResultInfo {
         return try {
             val stmt = connection.prepareStatement(sql)
             QueryResultInfo(stmt.columnInfo())
-        } catch (ex : SQLException) {
+        } catch (ex: SQLException) {
             QueryResultInfo(emptyList(), ex)
         }
     }
@@ -101,7 +101,7 @@
         if (!connection.isClosed) {
             try {
                 connection.close()
-            } catch (t : Throwable) {
+            } catch (t: Throwable) {
                 //ignore.
                 context.logger.d("failed to close the database connection ${t.message}")
             }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/QueryResultInfo.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/QueryResultInfo.kt
index 4a99243..41b348f 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/QueryResultInfo.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/QueryResultInfo.kt
@@ -24,4 +24,4 @@
  * This information is obtained by preparing the query against an in memory database at compile
  * time.
  */
-data class QueryResultInfo(val columns : List<ColumnInfo>, val error : SQLException? = null)
+data class QueryResultInfo(val columns: List<ColumnInfo>, val error: SQLException? = null)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/jdbc_ext.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/jdbc_ext.kt
index 5ae9d6a..47b9442 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/jdbc_ext.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/verifier/jdbc_ext.kt
@@ -33,10 +33,10 @@
     return result
 }
 
-private fun <T> PreparedStatement.map(f : (Int, ResultSetMetaData) ->  T) : List<T> {
+private fun <T> PreparedStatement.map(f: (Int, ResultSetMetaData) -> T): List<T> {
     val columnCount = try {
         metaData.columnCount
-    } catch (ex : SQLException) {
+    } catch (ex: SQLException) {
         // ignore, no-result query
         0
     }
@@ -48,10 +48,10 @@
     return map { index, data -> data.getColumnName(index) }
 }
 
-private fun PreparedStatement.tryGetAffinity(columnIndex : Int) : SQLTypeAffinity {
+private fun PreparedStatement.tryGetAffinity(columnIndex: Int): SQLTypeAffinity {
     return try {
         SQLTypeAffinity.valueOf(metaData.getColumnTypeName(columnIndex).capitalize())
-    } catch (ex : IllegalArgumentException) {
+    } catch (ex: IllegalArgumentException) {
         SQLTypeAffinity.NULL
     }
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Constructor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Constructor.kt
index fdc2a11..112c9b4 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Constructor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Constructor.kt
@@ -22,9 +22,9 @@
  * For each Entity / Pojo we process has a constructor. It might be the empty constructor or a
  * constructor with fields.
  */
-data class Constructor(val element : ExecutableElement, val params : List<Param>) {
+data class Constructor(val element: ExecutableElement, val params: List<Param>) {
 
-    fun hasField(field : Field) : Boolean {
+    fun hasField(field: Field): Boolean {
         return params.any {
             when (it) {
                 is FieldParam -> it.field === field
@@ -34,18 +34,16 @@
         }
     }
 
-    class FieldParam(val field : Field) : Param(ParamType.FIELD) {
+    class FieldParam(val field: Field) : Param(ParamType.FIELD) {
         override fun log(): String = field.getPath()
-
     }
 
     class EmbeddedParam(val embedded: EmbeddedField) : Param(ParamType.EMBEDDED) {
         override fun log(): String = embedded.field.getPath()
-
     }
 
-    abstract class Param(val type : ParamType) {
-        abstract fun log() : String;
+    abstract class Param(val type: ParamType) {
+        abstract fun log(): String
     }
 
     enum class ParamType {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/CustomTypeConverter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/CustomTypeConverter.kt
index 5a1f0e6..3bbae96 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/CustomTypeConverter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/CustomTypeConverter.kt
@@ -27,7 +27,7 @@
  * Generated when we parse a method annotated with TypeConverter.
  */
 data class CustomTypeConverter(val type: TypeMirror,
-                               val method : ExecutableElement,
+                               val method: ExecutableElement,
                                val from: TypeMirror, val to: TypeMirror) {
     val typeName: TypeName by lazy { type.typeName() }
     val fromTypeName: TypeName by lazy { from.typeName() }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Dao.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Dao.kt
index 57d7598..d0ef212 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Dao.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Dao.kt
@@ -21,25 +21,25 @@
 import javax.lang.model.element.TypeElement
 import javax.lang.model.type.DeclaredType
 
-data class Dao(val element : TypeElement, val type : DeclaredType,
+data class Dao(val element: TypeElement, val type: DeclaredType,
                val queryMethods: List<QueryMethod>,
-               val insertionMethods : List<InsertionMethod>,
-               val deletionMethods : List<DeletionMethod>,
-               val updateMethods : List<UpdateMethod>,
-               val transactionMethods : List<TransactionMethod>,
-               val constructorParamType : TypeName?) {
+               val insertionMethods: List<InsertionMethod>,
+               val deletionMethods: List<DeletionMethod>,
+               val updateMethods: List<UpdateMethod>,
+               val transactionMethods: List<TransactionMethod>,
+               val constructorParamType: TypeName?) {
     // parsed dao might have a suffix if it is used in multiple databases.
-    private var suffix : String? = null
-    fun setSuffix(newSuffix : String) {
+    private var suffix: String? = null
+    fun setSuffix(newSuffix: String) {
         if (this.suffix != null) {
             throw IllegalStateException("cannot set suffix twice")
         }
         this.suffix = if (newSuffix == "") "" else "_$newSuffix"
     }
 
-    val typeName : ClassName by lazy { ClassName.get(element) }
+    val typeName: ClassName by lazy { ClassName.get(element) }
 
-    val shortcutMethods : List<ShortcutMethod> by lazy {
+    val shortcutMethods: List<ShortcutMethod> by lazy {
         deletionMethods + updateMethods
     }
 
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/DaoMethod.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/DaoMethod.kt
index bd5e6b8..bf134ad 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/DaoMethod.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/DaoMethod.kt
@@ -21,4 +21,4 @@
 /**
  * References a method that returns a dao in a Database
  */
-data class DaoMethod(val element : Element, val name : String, val dao : Dao)
+data class DaoMethod(val element: Element, val name: String, val dao: Dao)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Database.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Database.kt
index b118a32..02e83b3 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Database.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Database.kt
@@ -34,7 +34,7 @@
                     val daoMethods: List<DaoMethod>,
                     val version: Int,
                     val exportSchema: Boolean,
-                    val enableForeignKeys : Boolean) {
+                    val enableForeignKeys: Boolean) {
     val typeName: ClassName by lazy { ClassName.get(element) }
 
     private val implClassName by lazy {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/DeletionMethod.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/DeletionMethod.kt
index c4adc54..e122c85 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/DeletionMethod.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/DeletionMethod.kt
@@ -17,8 +17,9 @@
 
 import javax.lang.model.element.ExecutableElement
 
-class DeletionMethod(element: ExecutableElement, name: String,
-                          entities: Map<String, Entity>, returnCount : Boolean,
-                          parameters: List<ShortcutQueryParameter>) : ShortcutMethod(
-        element, name, entities, returnCount, parameters
-)
+class DeletionMethod(
+        element: ExecutableElement,
+        name: String,
+        entities: Map<String, Entity>, returnCount: Boolean,
+        parameters: List<ShortcutQueryParameter>
+) : ShortcutMethod(element, name, entities, returnCount, parameters)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/EmbeddedField.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/EmbeddedField.kt
index 55e9cc4..55539a2 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/EmbeddedField.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/EmbeddedField.kt
@@ -23,8 +23,8 @@
  * Used when a field is embedded inside an Entity or Pojo.
  */
 // used in cache matching, must stay as a data class or implement equals
-data class EmbeddedField(val field : Field, val prefix : String = "",
-                         val parent : EmbeddedField?) {
+data class EmbeddedField(val field: Field, val prefix: String = "",
+                         val parent: EmbeddedField?) {
     val getter by lazy { field.getter }
     val setter by lazy { field.setter }
     val nonNull = field.element.hasAnnotation(NonNull::class)
@@ -33,7 +33,7 @@
         parent?.mRootParent ?: this
     }
 
-    fun isDescendantOf(other : EmbeddedField) : Boolean {
+    fun isDescendantOf(other: EmbeddedField): Boolean {
         if (parent == other) {
             return true
         } else if (parent == null) {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Entity.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Entity.kt
index 06e7484..48592bd 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Entity.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Entity.kt
@@ -33,7 +33,7 @@
         createTableQuery(tableName)
     }
 
-    fun createTableQuery(tableName : String) : String {
+    fun createTableQuery(tableName: String): String {
         val definitions = (fields.map {
             val autoIncrement = primaryKey.autoGenerateId && primaryKey.fields.contains(it)
             it.databaseDefinition(autoIncrement)
@@ -41,7 +41,7 @@
         return "CREATE TABLE IF NOT EXISTS `$tableName` (${definitions.joinToString(", ")})"
     }
 
-    private fun createForeignKeyDefinitions() : List<String> {
+    private fun createForeignKeyDefinitions(): List<String> {
         return foreignKeys.map { it.databaseDefinition() }
     }
 
@@ -59,12 +59,12 @@
     fun toBundle(): EntityBundle = EntityBundle(
             tableName,
             createTableQuery(BundleUtil.TABLE_NAME_PLACEHOLDER),
-            fields.map {it.toBundle()},
+            fields.map { it.toBundle() },
             primaryKey.toBundle(),
             indices.map { it.toBundle() },
             foreignKeys.map { it.toBundle() })
 
-    fun isUnique(columns: List<String>) : Boolean {
+    fun isUnique(columns: List<String>): Boolean {
         return if (primaryKey.columnNames.size == columns.size
                 && primaryKey.columnNames.containsAll(columns)) {
             true
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Field.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Field.kt
index fa0575a..838016e 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Field.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Field.kt
@@ -35,7 +35,7 @@
                  * embedded child of the main Pojo*/
                  val parent: EmbeddedField? = null,
                  // index might be removed when being merged into an Entity
-                 var indexed : Boolean = false) {
+                 var indexed: Boolean = false) {
     lateinit var getter: FieldGetter
     lateinit var setter: FieldSetter
     // binds the field into a statement
@@ -50,7 +50,7 @@
     /**
      * Used when reporting errors on duplicate names
      */
-    fun getPath() : String {
+    fun getPath(): String {
         return if (parent == null) {
             name
         } else {
@@ -58,7 +58,7 @@
         }
     }
 
-    private val pathWithDotNotation : String by lazy {
+    private val pathWithDotNotation: String by lazy {
         if (parent == null) {
             name
         } else {
@@ -111,7 +111,7 @@
     /**
      * definition to be used in create query
      */
-    fun databaseDefinition(autoIncrementPKey : Boolean) : String {
+    fun databaseDefinition(autoIncrementPKey: Boolean): String {
         val columnSpec = StringBuilder("")
         if (autoIncrementPKey) {
             columnSpec.append(" PRIMARY KEY AUTOINCREMENT")
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/FieldGetter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/FieldGetter.kt
index 6713c2c..70a9bc3 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/FieldGetter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/FieldGetter.kt
@@ -22,7 +22,7 @@
 import com.squareup.javapoet.TypeName
 import javax.lang.model.type.TypeMirror
 
-data class FieldGetter(val name : String, val type : TypeMirror, val callType: CallType) {
+data class FieldGetter(val name: String, val type: TypeMirror, val callType: CallType) {
     fun writeGet(ownerVar: String, outVar: String, builder: CodeBlock.Builder) {
         val stmt = when (callType) {
             CallType.FIELD -> "final $T $L = $L.$L"
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/FieldWithIndex.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/FieldWithIndex.kt
index 6ef6979..b30dcc9 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/FieldWithIndex.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/FieldWithIndex.kt
@@ -23,9 +23,9 @@
  * If we are sure that the field will be there at compile time, we set it to always Exists so that
  * the generated code does not check for -1 column indices.
  */
-data class FieldWithIndex(val field : Field, val indexVar : String, val alwaysExists : Boolean) {
+data class FieldWithIndex(val field: Field, val indexVar: String, val alwaysExists: Boolean) {
     companion object {
-        fun byOrder(fields : List<Field>) : List<FieldWithIndex> {
+        fun byOrder(fields: List<Field>): List<FieldWithIndex> {
             return fields.mapIndexed { index, field ->
                 FieldWithIndex(field = field,
                         indexVar = "${index + 1}",
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/ForeignKeyAction.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/ForeignKeyAction.kt
index 1b85910..c6ed9da 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/ForeignKeyAction.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/ForeignKeyAction.kt
@@ -21,7 +21,7 @@
 /**
  * Compiler representation of ForeignKey#Action.
  */
-enum class ForeignKeyAction(val annotationValue : Int, val sqlName : String) {
+enum class ForeignKeyAction(val annotationValue: Int, val sqlName: String) {
     NO_ACTION(ForeignKey.NO_ACTION, "NO ACTION"),
     RESTRICT(ForeignKey.RESTRICT, "RESTRICT"),
     SET_NULL(ForeignKey.SET_NULL, "SET NULL"),
@@ -31,6 +31,6 @@
         private val mapping by lazy {
             ForeignKeyAction.values().associateBy { it.annotationValue }
         }
-        fun fromAnnotationValue(value : Int?) = mapping[value]
+        fun fromAnnotationValue(value: Int?) = mapping[value]
     }
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Index.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Index.kt
index 0bee2e0..694c627 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Index.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Index.kt
@@ -22,12 +22,12 @@
 /**
  * Represents a processed index.
  */
-data class Index(val name : String, val unique : Boolean, val fields : List<Field>) {
+data class Index(val name: String, val unique: Boolean, val fields: List<Field>) {
     companion object {
         // should match the value in TableInfo.Index.DEFAULT_PREFIX
         const val DEFAULT_PREFIX = "index_"
     }
-    fun createQuery(tableName : String) : String {
+    fun createQuery(tableName: String): String {
         val uniqueSQL = if (unique) {
             "UNIQUE"
         } else {
@@ -39,7 +39,7 @@
             """.trimIndent().replace("\n", " ")
     }
 
-    val columnNames by lazy { fields.map {it.columnName} }
+    val columnNames by lazy { fields.map { it.columnName } }
 
     fun toBundle(): IndexBundle = IndexBundle(name, unique, fields.map { it.columnName },
             createQuery(BundleUtil.TABLE_NAME_PLACEHOLDER))
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/InsertionMethod.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/InsertionMethod.kt
index ad3688d..19573cf 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/InsertionMethod.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/InsertionMethod.kt
@@ -29,7 +29,7 @@
                            val entities: Map<String, Entity>, val returnType: TypeMirror,
                            val insertionType: Type?,
                            val parameters: List<ShortcutQueryParameter>) {
-    fun insertMethodTypeFor(param : ShortcutQueryParameter) : Type {
+    fun insertMethodTypeFor(param: ShortcutQueryParameter): Type {
         return if (insertionType == Type.INSERT_VOID || insertionType == null) {
             Type.INSERT_VOID
         } else if (!param.isMultiple) {
@@ -41,7 +41,7 @@
 
     enum class Type(
             // methodName matches EntityInsertionAdapter methods
-            val methodName : String, val returnTypeName : TypeName) {
+            val methodName: String, val returnTypeName: TypeName) {
         INSERT_VOID("insert", TypeName.VOID), // return void
         INSERT_SINGLE_ID("insertAndReturnId", TypeName.LONG), // return long
         INSERT_ID_ARRAY("insertAndReturnIdsArray",
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Pojo.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Pojo.kt
index acc63af..629c6b8 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Pojo.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/Pojo.kt
@@ -18,7 +18,6 @@
 
 import android.arch.persistence.room.ext.typeName
 import com.squareup.javapoet.TypeName
-import javax.lang.model.element.ElementKind
 import javax.lang.model.element.TypeElement
 import javax.lang.model.type.DeclaredType
 
@@ -26,8 +25,8 @@
  * A class is turned into a Pojo if it is used in a query response.
  */
 // TODO make data class when move to kotlin 1.1
-open class Pojo(val element : TypeElement, val type: DeclaredType, val fields : List<Field>,
+open class Pojo(val element: TypeElement, val type: DeclaredType, val fields: List<Field>,
                 val embeddedFields: List<EmbeddedField>, val relations: List<Relation>,
-                val constructor : Constructor? = null) {
+                val constructor: Constructor? = null) {
     val typeName: TypeName by lazy { type.typeName() }
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/PrimaryKey.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/PrimaryKey.kt
index 9735668..d1a2c21 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/PrimaryKey.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/PrimaryKey.kt
@@ -21,13 +21,13 @@
 /**
  * Represents a PrimaryKey for an Entity.
  */
-data class PrimaryKey(val declaredIn : Element?, val fields: List<Field>,
+data class PrimaryKey(val declaredIn: Element?, val fields: List<Field>,
                       val autoGenerateId: Boolean) {
     companion object {
         val MISSING = PrimaryKey(null, emptyList(), false)
     }
 
-    val columnNames by lazy { fields.map {it.columnName} }
+    val columnNames by lazy { fields.map { it.columnName } }
 
     fun toHumanReadableString(): String {
         return "PrimaryKey[" +
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/QueryMethod.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/QueryMethod.kt
index a6b8cb7..482a1c4 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/QueryMethod.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/QueryMethod.kt
@@ -29,8 +29,8 @@
  */
 data class QueryMethod(val element: ExecutableElement, val query: ParsedQuery, val name: String,
                        val returnType: TypeMirror, val parameters: List<QueryParameter>,
-                       val inTransaction : Boolean,
-                       val queryResultBinder : QueryResultBinder) {
+                       val inTransaction: Boolean,
+                       val queryResultBinder: QueryResultBinder) {
     val sectionToParamMapping by lazy {
         query.bindSections.map {
             if (it.text.trim() == "?") {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/QueryParameter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/QueryParameter.kt
index 60ab55e..cca25ae 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/QueryParameter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/QueryParameter.kt
@@ -23,4 +23,4 @@
  * Holds the parameter for a {@link QueryMethod}.
  */
 data class QueryParameter(val name: String, val type: TypeMirror,
-                          val queryParamAdapter : QueryParameterAdapter?)
+                          val queryParamAdapter: QueryParameterAdapter?)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/RelationCollector.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/RelationCollector.kt
index c11091c..bc296fc 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/RelationCollector.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/RelationCollector.kt
@@ -49,13 +49,13 @@
  * Internal class that is used to manage fetching 1/N to N relationships.
  */
 data class RelationCollector(val relation: Relation,
-                             val affinity : SQLTypeAffinity,
+                             val affinity: SQLTypeAffinity,
                              val mapTypeName: ParameterizedTypeName,
                              val keyTypeName: TypeName,
                              val collectionTypeName: ParameterizedTypeName,
                              val queryWriter: QueryWriter,
                              val rowAdapter: RowAdapter,
-                             val loadAllQuery : ParsedQuery) {
+                             val loadAllQuery: ParsedQuery) {
     // set when writing the code generator in writeInitCode
     lateinit var varName: String
 
@@ -67,8 +67,8 @@
     }
 
     // called after reading each item to extract the key if it exists
-    fun writeReadParentKeyCode(cursorVarName: String, itemVar : String,
-                               fieldsWithIndices : List<FieldWithIndex>, scope: CodeGenScope) {
+    fun writeReadParentKeyCode(cursorVarName: String, itemVar: String,
+                               fieldsWithIndices: List<FieldWithIndex>, scope: CodeGenScope) {
         val indexVar = fieldsWithIndices.firstOrNull {
             it.field === relation.parentField
         }?.indexVar
@@ -123,8 +123,10 @@
     }
 
     companion object {
-        fun createCollectors(baseContext : Context, relations: List<Relation>)
-                : List<RelationCollector> {
+        fun createCollectors(
+                baseContext: Context,
+                relations: List<Relation>
+        ): List<RelationCollector> {
             return relations.map { relation ->
                 // decide on the affinity
                 val context = baseContext.fork(relation.field.element)
@@ -194,7 +196,7 @@
                 )
 
                 // row adapter that matches full response
-                fun getDefaultRowAdapter() : RowAdapter? {
+                fun getDefaultRowAdapter(): RowAdapter? {
                     return context.typeAdapterStore.findRowAdapter(relation.pojo.type, parsedQuery)
                 }
                 val rowAdapter = if (relation.projection.size == 1 && resultInfo != null &&
@@ -246,7 +248,7 @@
             }
         }
 
-        private fun keyTypeFor(context : Context, affinity: SQLTypeAffinity): TypeName {
+        private fun keyTypeFor(context: Context, affinity: SQLTypeAffinity): TypeName {
             return when (affinity) {
                 SQLTypeAffinity.INTEGER -> TypeName.LONG.box()
                 SQLTypeAffinity.REAL -> TypeName.DOUBLE.box()
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/ShortcutQueryParameter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/ShortcutQueryParameter.kt
index 29fc759..db8a0f5 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/ShortcutQueryParameter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/vo/ShortcutQueryParameter.kt
@@ -26,7 +26,7 @@
     /**
      * Method name in entity insertion or update adapter.
      */
-    fun handleMethodName() : String {
+    fun handleMethodName(): String {
         return if (isMultiple) {
             "handleMultiple"
         } else {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/DaoWriter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/DaoWriter.kt
index 0bb9c19..5125444 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/DaoWriter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/DaoWriter.kt
@@ -115,8 +115,8 @@
         return builder
     }
 
-    private fun createPreparedDeleteOrUpdateQueries(preparedDeleteQueries: List<QueryMethod>)
-            : List<PreparedStmtQuery> {
+    private fun createPreparedDeleteOrUpdateQueries(
+            preparedDeleteQueries: List<QueryMethod>): List<PreparedStmtQuery> {
         return preparedDeleteQueries.map { method ->
             val fieldSpec = getOrCreateField(PreparedStatementField(method))
             val queryWriter = QueryWriter(method)
@@ -128,9 +128,11 @@
         }
     }
 
-    private fun createPreparedDeleteQueryMethodBody(method: QueryMethod,
-                                                    preparedStmtField: FieldSpec,
-                                                    queryWriter: QueryWriter): MethodSpec {
+    private fun createPreparedDeleteQueryMethodBody(
+            method: QueryMethod,
+            preparedStmtField: FieldSpec,
+            queryWriter: QueryWriter
+    ): MethodSpec {
         val scope = CodeGenScope(this)
         val methodBuilder = overrideWithoutAnnotations(method.element, declaredDao).apply {
             val stmtName = scope.getTmpVar("_stmt")
@@ -278,9 +280,10 @@
                 }.filterNotNull()
     }
 
-    private fun createInsertionMethodBody(method: InsertionMethod,
-                                          insertionAdapters: Map<String, Pair<FieldSpec, TypeSpec>>)
-            : CodeBlock {
+    private fun createInsertionMethodBody(
+            method: InsertionMethod,
+            insertionAdapters: Map<String, Pair<FieldSpec, TypeSpec>>
+    ): CodeBlock {
         val insertionType = method.insertionType
         if (insertionAdapters.isEmpty() || insertionType == null) {
             return CodeBlock.builder().build()
@@ -346,9 +349,10 @@
         })
     }
 
-    private fun <T : ShortcutMethod> createShortcutMethods(methods: List<T>, methodPrefix: String,
-                                                           implCallback: (T, Entity) -> TypeSpec)
-            : List<PreparedStmtQuery> {
+    private fun <T : ShortcutMethod> createShortcutMethods(
+            methods: List<T>, methodPrefix: String,
+            implCallback: (T, Entity) -> TypeSpec
+    ): List<PreparedStmtQuery> {
         return methods.map { method ->
             val entities = method.entities
 
@@ -368,9 +372,10 @@
         }.filterNotNull()
     }
 
-    private fun createDeleteOrUpdateMethodBody(method: ShortcutMethod,
-                                               adapters: Map<String, Pair<FieldSpec, TypeSpec>>)
-            : CodeBlock {
+    private fun createDeleteOrUpdateMethodBody(
+            method: ShortcutMethod,
+            adapters: Map<String, Pair<FieldSpec, TypeSpec>>
+    ): CodeBlock {
         if (adapters.isEmpty()) {
             return CodeBlock.builder().build()
         }
@@ -434,7 +439,6 @@
                 addStatement("$N.endTransaction()", dbField)
             }
             endControlFlow()
-
         }
         return scope.builder().build()
     }
@@ -454,7 +458,7 @@
     }
 
     private fun overrideWithoutAnnotations(elm: ExecutableElement,
-                                           owner : DeclaredType): MethodSpec.Builder {
+                                           owner: DeclaredType): MethodSpec.Builder {
         val baseSpec = MethodSpec.overriding(elm, owner, processingEnv.typeUtils).build()
         return MethodSpec.methodBuilder(baseSpec.name).apply {
             addAnnotation(Override::class.java)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/DatabaseWriter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/DatabaseWriter.kt
index e40bd71..7755a61 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/DatabaseWriter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/DatabaseWriter.kt
@@ -39,7 +39,7 @@
 /**
  * Writes implementation of classes that were annotated with @Database.
  */
-class DatabaseWriter(val database : Database) : ClassWriter(database.implTypeName) {
+class DatabaseWriter(val database: Database) : ClassWriter(database.implTypeName) {
     override fun createTypeSpecBuilder(): TypeSpec.Builder {
         val builder = TypeSpec.classBuilder(database.implTypeName)
         builder.apply {
@@ -64,7 +64,7 @@
         }.build()
     }
 
-    private fun  addDaoImpls(builder: TypeSpec.Builder) {
+    private fun addDaoImpls(builder: TypeSpec.Builder) {
         val scope = CodeGenScope(this)
         builder.apply {
             database.daoMethods.forEach { method ->
@@ -78,7 +78,7 @@
         }
     }
 
-    private fun createDaoGetter(field: FieldSpec, method: DaoMethod) : MethodSpec {
+    private fun createDaoGetter(field: FieldSpec, method: DaoMethod): MethodSpec {
         return MethodSpec.overriding(MoreElements.asExecutable(method.element)).apply {
             beginControlFlow("if ($N != null)", field).apply {
                 addStatement("return $N", field)
@@ -97,7 +97,7 @@
         }.build()
     }
 
-    private fun createCreateOpenHelper() : MethodSpec {
+    private fun createCreateOpenHelper(): MethodSpec {
         val scope = CodeGenScope(this)
         return MethodSpec.methodBuilder("createOpenHelper").apply {
             addModifiers(Modifier.PROTECTED)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityCursorConverterWriter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityCursorConverterWriter.kt
index a83d191..a96e23c 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityCursorConverterWriter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityCursorConverterWriter.kt
@@ -23,7 +23,6 @@
 import android.arch.persistence.room.ext.T
 import android.arch.persistence.room.solver.CodeGenScope
 import android.arch.persistence.room.vo.Entity
-import android.arch.persistence.room.vo.Field
 import android.arch.persistence.room.vo.EmbeddedField
 import android.arch.persistence.room.vo.FieldWithIndex
 import com.squareup.javapoet.CodeBlock
@@ -58,8 +57,7 @@
         }
     }
 
-    private fun buildConvertMethodBody(writer: ClassWriter, cursorParam: ParameterSpec)
-            : CodeBlock {
+    private fun buildConvertMethodBody(writer: ClassWriter, cursorParam: ParameterSpec): CodeBlock {
         val scope = CodeGenScope(writer)
         val entityVar = scope.getTmpVar("_entity")
         scope.builder().apply {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityInsertionAdapterWriter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityInsertionAdapterWriter.kt
index cd3e771..26ff47b 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityInsertionAdapterWriter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityInsertionAdapterWriter.kt
@@ -32,7 +32,7 @@
 import javax.lang.model.element.Modifier.PUBLIC
 
 class EntityInsertionAdapterWriter(val entity: Entity, val onConflict: String) {
-    fun createAnonymous(classWriter: ClassWriter, dbParam : String): TypeSpec {
+    fun createAnonymous(classWriter: ClassWriter, dbParam: String): TypeSpec {
         @Suppress("RemoveSingleExpressionStringTemplate")
         return TypeSpec.anonymousClassBuilder("$L", dbParam).apply {
             superclass(
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityUpdateAdapterWriter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityUpdateAdapterWriter.kt
index b5711dc..8dee8e1 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityUpdateAdapterWriter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/EntityUpdateAdapterWriter.kt
@@ -31,7 +31,7 @@
 import com.squareup.javapoet.TypeSpec
 import javax.lang.model.element.Modifier.PUBLIC
 
-class EntityUpdateAdapterWriter(val entity: Entity, val onConflict : String) {
+class EntityUpdateAdapterWriter(val entity: Entity, val onConflict: String) {
     fun createAnonymous(classWriter: ClassWriter, dbParam: String): TypeSpec {
         @Suppress("RemoveSingleExpressionStringTemplate")
         return TypeSpec.anonymousClassBuilder("$L", dbParam).apply {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/FieldReadWriteWriter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/FieldReadWriteWriter.kt
index 8df3feb..4aa795a 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/FieldReadWriteWriter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/FieldReadWriteWriter.kt
@@ -64,9 +64,10 @@
          * them. This work is done here instead of parsing because the result may include arbitrary
          * fields.
          */
-        private fun createNodeTree(rootVar: String,
-                           fieldsWithIndices: List<FieldWithIndex>,
-                           scope: CodeGenScope): Node {
+        private fun createNodeTree(
+                rootVar: String,
+                fieldsWithIndices: List<FieldWithIndex>,
+                scope: CodeGenScope): Node {
             val allParents = getAllParents(fieldsWithIndices.map { it.field })
             val rootNode = Node(rootVar, null)
             rootNode.directFields = fieldsWithIndices.filter { it.field.parent == null }
@@ -88,9 +89,12 @@
             return rootNode
         }
 
-        fun bindToStatement(ownerVar: String, stmtParamVar: String,
-                            fieldsWithIndices: List<FieldWithIndex>,
-                            scope: CodeGenScope) {
+        fun bindToStatement(
+                ownerVar: String,
+                stmtParamVar: String,
+                fieldsWithIndices: List<FieldWithIndex>,
+                scope: CodeGenScope
+        ) {
             fun visitNode(node: Node) {
                 fun bindWithDescendants() {
                     node.directFields.forEach {
@@ -133,9 +137,13 @@
          * reading statement since we may never read if the cursor does not have necessary
          * columns.
          */
-        private fun construct(outVar : String, constructor : Constructor?, typeName : TypeName,
-                              localVariableNames : Map<String, FieldWithIndex>,
-                              localEmbeddeds: List<Node>, scope: CodeGenScope) {
+        private fun construct(
+                outVar: String,
+                constructor: Constructor?,
+                typeName: TypeName,
+                localVariableNames: Map<String, FieldWithIndex>,
+                localEmbeddeds: List<Node>, scope: CodeGenScope
+        ) {
             if (constructor == null) {
                 // best hope code generation
                 scope.builder().apply {
@@ -144,7 +152,7 @@
                 return
             }
             val variableNames = constructor.params.map { param ->
-                when(param) {
+                when (param) {
                     is Constructor.FieldParam -> localVariableNames.entries.firstOrNull {
                         it.value.field === param.field
                     }?.key
@@ -154,7 +162,7 @@
                     else -> null
                 }
             }
-            val args = variableNames.joinToString(",") { it ?: "null"}
+            val args = variableNames.joinToString(",") { it ?: "null" }
             scope.builder().apply {
                 addStatement("$L = new $T($L)", outVar, typeName, args)
             }
@@ -163,12 +171,14 @@
         /**
          * Reads the row into the given variable. It does not declare it but constructs it.
          */
-        fun readFromCursor(outVar: String,
-                           outPojo : Pojo,
-                           cursorVar: String,
-                           fieldsWithIndices: List<FieldWithIndex>,
-                           scope: CodeGenScope,
-                           relationCollectors : List<RelationCollector>) {
+        fun readFromCursor(
+                outVar: String,
+                outPojo: Pojo,
+                cursorVar: String,
+                fieldsWithIndices: List<FieldWithIndex>,
+                scope: CodeGenScope,
+                relationCollectors: List<RelationCollector>
+        ) {
             fun visitNode(node: Node) {
                 val fieldParent = node.fieldParent
                 fun readNode() {
@@ -248,7 +258,6 @@
                             } else {
                                 "( ${it.indexVar} == -1 || $cursorVar.isNull(${it.indexVar}))"
                             }
-
                         }
                         scope.builder().apply {
                             beginControlFlow("if (! ($L))", allNullCheck).apply {
@@ -326,7 +335,7 @@
     /**
      * Reads the value into a temporary local variable.
      */
-    fun readIntoTmpVar(cursorVar: String, scope: CodeGenScope) : String {
+    fun readIntoTmpVar(cursorVar: String, scope: CodeGenScope): String {
         val tmpField = scope.getTmpVar("_tmp${field.name.capitalize()}")
         val typeName = field.getter.type.typeName()
         scope.builder().apply {
@@ -353,7 +362,8 @@
             // root for me
             val varName: String,
             // set if I'm a FieldParent
-            val fieldParent: EmbeddedField?) {
+            val fieldParent: EmbeddedField?
+    ) {
         // whom do i belong
         var parentNode: Node? = null
         // these fields are my direct fields
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/PreparedStatementWriter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/PreparedStatementWriter.kt
index 9c3e612..7982ace 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/PreparedStatementWriter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/PreparedStatementWriter.kt
@@ -29,7 +29,7 @@
  * Creates anonymous classes for RoomTypeNames#SHARED_SQLITE_STMT.
  */
 class PreparedStatementWriter(val queryWriter: QueryWriter) {
-    fun createAnonymous(classWriter: ClassWriter, dbParam : FieldSpec): TypeSpec {
+    fun createAnonymous(classWriter: ClassWriter, dbParam: FieldSpec): TypeSpec {
         val scope = CodeGenScope(classWriter)
         @Suppress("RemoveSingleExpressionStringTemplate")
         return TypeSpec.anonymousClassBuilder("$N", dbParam).apply {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/QueryWriter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/QueryWriter.kt
index a2c7e62..d99e989 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/QueryWriter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/QueryWriter.kt
@@ -36,9 +36,9 @@
 /**
  * Writes the SQL query and arguments for a QueryMethod.
  */
-class QueryWriter constructor(val parameters : List<QueryParameter>,
-                              val sectionToParamMapping : List<Pair<Section, QueryParameter?>>,
-                              val query : ParsedQuery) {
+class QueryWriter constructor(val parameters: List<QueryParameter>,
+                              val sectionToParamMapping: List<Pair<Section, QueryParameter?>>,
+                              val query: ParsedQuery) {
 
     constructor(queryMethod: QueryMethod) : this(queryMethod.parameters,
             queryMethod.sectionToParamMapping, queryMethod.query) {
@@ -50,13 +50,16 @@
         bindArgs(outRoomSQLiteQueryVar, listSizeVars, scope)
     }
 
-    fun prepareQuery(outSqlQueryName: String, scope: CodeGenScope)
-            : List<Pair<QueryParameter, String>> {
+    fun prepareQuery(
+            outSqlQueryName: String, scope: CodeGenScope): List<Pair<QueryParameter, String>> {
         return createSqlQueryAndArgs(outSqlQueryName, null, scope)
     }
 
-    private fun createSqlQueryAndArgs(outSqlQueryName: String, outArgsName: String?,
-                                      scope: CodeGenScope): List<Pair<QueryParameter, String>> {
+    private fun createSqlQueryAndArgs(
+            outSqlQueryName: String,
+            outArgsName: String?,
+            scope: CodeGenScope
+    ): List<Pair<QueryParameter, String>> {
         val listSizeVars = arrayListOf<Pair<QueryParameter, String>>()
         val varargParams = parameters
                 .filter { it.queryParamAdapter?.isMultiple ?: false }
@@ -118,8 +121,11 @@
         return listSizeVars
     }
 
-    fun bindArgs(outArgsName: String, listSizeVars : List<Pair<QueryParameter, String>>,
-                         scope: CodeGenScope) {
+    fun bindArgs(
+            outArgsName: String,
+            listSizeVars: List<Pair<QueryParameter, String>>,
+            scope: CodeGenScope
+    ) {
         if (parameters.isEmpty()) {
             return
         }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/SQLiteOpenHelperWriter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/SQLiteOpenHelperWriter.kt
index bdc601f..16fcd9c 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/SQLiteOpenHelperWriter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/SQLiteOpenHelperWriter.kt
@@ -35,8 +35,8 @@
 /**
  * Create an open helper using SupportSQLiteOpenHelperFactory
  */
-class SQLiteOpenHelperWriter(val database : Database) {
-    fun write(outVar : String, configuration : ParameterSpec, scope: CodeGenScope) {
+class SQLiteOpenHelperWriter(val database: Database) {
+    fun write(outVar: String, configuration: ParameterSpec, scope: CodeGenScope) {
         scope.builder().apply {
             val sqliteConfigVar = scope.getTmpVar("_sqliteConfig")
             val callbackVar = scope.getTmpVar("_openCallback")
@@ -61,7 +61,7 @@
         }
     }
 
-    private fun createOpenCallback(scope: CodeGenScope) : TypeSpec {
+    private fun createOpenCallback(scope: CodeGenScope): TypeSpec {
         return TypeSpec.anonymousClassBuilder(L, database.version).apply {
             superclass(RoomTypeNames.OPEN_HELPER_DELEGATE)
             addMethod(createCreateAllTables())
@@ -106,7 +106,7 @@
         }.build()
     }
 
-    private fun createCreateAllTables() : MethodSpec {
+    private fun createCreateAllTables(): MethodSpec {
         return MethodSpec.methodBuilder("createAllTables").apply {
             addModifiers(PUBLIC)
             addParameter(SupportDbTypeNames.DB, "_db")
@@ -116,7 +116,7 @@
         }.build()
     }
 
-    private fun createDropAllTables() : MethodSpec {
+    private fun createDropAllTables(): MethodSpec {
         return MethodSpec.methodBuilder("dropAllTables").apply {
             addModifiers(PUBLIC)
             addParameter(SupportDbTypeNames.DB, "_db")
@@ -140,12 +140,12 @@
     }
 
     @VisibleForTesting
-    fun createQuery(entity : Entity) : String {
+    fun createQuery(entity: Entity): String {
         return entity.createTableQuery
     }
 
     @VisibleForTesting
-    fun createDropTableQuery(entity: Entity) : String {
+    fun createDropTableQuery(entity: Entity): String {
         return "DROP TABLE IF EXISTS `${entity.tableName}`"
     }
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/TableInfoValidationWriter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/TableInfoValidationWriter.kt
index e54f986..3c67475 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/TableInfoValidationWriter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/writer/TableInfoValidationWriter.kt
@@ -33,8 +33,8 @@
 import java.util.HashMap
 import java.util.HashSet
 
-class TableInfoValidationWriter(val entity : Entity) {
-    fun write(dbParam : ParameterSpec, scope : CodeGenScope) {
+class TableInfoValidationWriter(val entity: Entity) {
+    fun write(dbParam: ParameterSpec, scope: CodeGenScope) {
         val suffix = entity.tableName.stripNonJava().capitalize()
         val expectedInfoVar = scope.getTmpVar("_info$suffix")
         scope.builder().apply {
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt
index 6d3e194..1d31354 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt
@@ -110,7 +110,7 @@
     }
 
     @Test
-    fun  indexedVariablesError() {
+    fun indexedVariablesError() {
         assertErrors("select * from users where name like ?",
                 ParserErrors.ANONYMOUS_BIND_ARGUMENT)
         assertErrors("select * from users where name like ? or last_name like ?",
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/BaseDaoTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/BaseDaoTest.kt
index ae648f7..19430af 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/BaseDaoTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/BaseDaoTest.kt
@@ -140,7 +140,7 @@
         }
     }
 
-    fun baseDao(code : String, handler : (Dao) -> Unit) {
+    fun baseDao(code: String, handler: (Dao) -> Unit) {
         val baseClass = """
             package foo.bar;
             import android.arch.persistence.room.*;
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/BaseEntityParserTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/BaseEntityParserTest.kt
index 7893200..bd09a11 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/BaseEntityParserTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/BaseEntityParserTest.kt
@@ -25,7 +25,6 @@
 import com.google.common.truth.Truth
 import com.google.testing.compile.CompileTester
 import com.google.testing.compile.JavaFileObjects
-import com.google.testing.compile.JavaSourceSubjectFactory
 import com.google.testing.compile.JavaSourcesSubjectFactory
 import javax.tools.JavaFileObject
 
@@ -42,10 +41,10 @@
     }
 
     fun singleEntity(input: String, attributes: Map<String, String> = mapOf(),
-                     baseClass : String = "",
-                     jfos : List<JavaFileObject> = emptyList(),
+                     baseClass: String = "",
+                     jfos: List<JavaFileObject> = emptyList(),
                      handler: (Entity, TestInvocation) -> Unit): CompileTester {
-        val attributesReplacement : String
+        val attributesReplacement: String
         if (attributes.isEmpty()) {
             attributesReplacement = ""
         } else {
@@ -53,7 +52,7 @@
                     attributes.entries.map { "${it.key} = ${it.value}" }.joinToString(",") +
                     ")".trimIndent()
         }
-        val baseClassReplacement : String
+        val baseClassReplacement: String
         if (baseClass == "") {
             baseClassReplacement = ""
         } else {
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/CustomConverterProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/CustomConverterProcessorTest.kt
index 6b8dbaf..067773a 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/CustomConverterProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/CustomConverterProcessorTest.kt
@@ -60,8 +60,7 @@
 
     @Test
     fun validCase() {
-        singleClass(createConverter(TypeName.SHORT.box(), TypeName.CHAR.box()))
-        { converter, _ ->
+        singleClass(createConverter(TypeName.SHORT.box(), TypeName.CHAR.box())) { converter, _ ->
             assertThat(converter?.fromTypeName, `is`(TypeName.SHORT.box()))
             assertThat(converter?.toTypeName, `is`(TypeName.CHAR.box()))
         }.compilesWithoutError()
@@ -222,21 +221,24 @@
 
     @Test
     fun checkDuplicates() {
-        singleClass(createConverter(TypeName.SHORT.box(), TypeName.CHAR.box(), duplicate = true))
-        { converter, _ ->
+        singleClass(
+                createConverter(TypeName.SHORT.box(), TypeName.CHAR.box(), duplicate = true)
+        ) { converter, _ ->
             assertThat(converter?.fromTypeName, `is`(TypeName.SHORT.box()))
             assertThat(converter?.toTypeName, `is`(TypeName.CHAR.box()))
         }.failsToCompile().withErrorContaining("Multiple methods define the same conversion")
     }
 
-    private fun createConverter(from: TypeName, to: TypeName,
-                                typeVariables: List<TypeVariableName> = emptyList(),
-                                duplicate : Boolean = false)
-            : JavaFileObject {
+    private fun createConverter(
+            from: TypeName,
+            to: TypeName,
+            typeVariables: List<TypeVariableName> = emptyList(),
+            duplicate: Boolean = false
+    ): JavaFileObject {
         val code = TypeSpec.classBuilder(CONVERTER).apply {
             addTypeVariables(typeVariables)
             addModifiers(Modifier.PUBLIC)
-            fun buildMethod(name : String) = MethodSpec.methodBuilder(name).apply {
+            fun buildMethod(name: String) = MethodSpec.methodBuilder(name).apply {
                 addAnnotation(TypeConverter::class.java)
                 addModifiers(Modifier.PUBLIC)
                 returns(to)
@@ -256,9 +258,10 @@
                 "package ${CONVERTER.packageName()};\n$code")
     }
 
-    private fun singleClass(vararg jfo: JavaFileObject,
-                            handler: (CustomTypeConverter?, TestInvocation) -> Unit)
-            : CompileTester {
+    private fun singleClass(
+            vararg jfo: JavaFileObject,
+            handler: (CustomTypeConverter?, TestInvocation) -> Unit
+    ): CompileTester {
         return simpleRun(*((jfo.toList() + CONTAINER).toTypedArray())) { invocation ->
             val processed = CustomConverterProcessor.findConverters(invocation.context,
                     invocation.processingEnv.elementUtils.getTypeElement("foo.bar.Container"))
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DaoProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DaoProcessorTest.kt
index 55f335d..9207cf3 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DaoProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DaoProcessorTest.kt
@@ -36,7 +36,7 @@
 import org.junit.runners.Parameterized
 
 @RunWith(Parameterized::class)
-class DaoProcessorTest(val enableVerification : Boolean) {
+class DaoProcessorTest(val enableVerification: Boolean) {
     companion object {
         const val DAO_PREFIX = """
             package foo.bar;
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DatabaseProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DatabaseProcessorTest.kt
index 40e9a96..d192c8f 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DatabaseProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DatabaseProcessorTest.kt
@@ -201,8 +201,7 @@
                     @Query("SELECT * FROM nonExistentTable")
                     public java.util.List<Book> loadAllBooks();
                 }
-                """)){ _, _ ->
-
+                """)) { _, _ ->
         }.failsToCompile().withErrorContaining("no such table: nonExistentTable")
     }
 
@@ -247,8 +246,7 @@
                     @Query("SELECT nonExistingField FROM Book")
                     public java.util.List<Book> loadAllBooks();
                 }
-                """)){ _, _ ->
-
+                """)) { _, _ ->
         }.compilesWithoutError()
     }
 
@@ -294,7 +292,7 @@
                     abstract UserDao userDao();
                     abstract UserDao userDao2();
                 }
-                """, USER, USER_DAO){ _, _ -> }
+                """, USER, USER_DAO) { _, _ -> }
                 .failsToCompile()
                 .withErrorContaining(ProcessorErrors.DAO_METHOD_CONFLICTS_WITH_OTHERS)
                 .and()
@@ -312,7 +310,7 @@
                 public abstract class MyDb extends RoomDatabase {
                     abstract UserDao userDao();
                 }
-                """, USER, USER_DAO) {db, invocation ->
+                """, USER, USER_DAO) { db, invocation ->
             assertThat(DatabaseProcessor(invocation.context, db.element)
                     .context.logger.suppressedWarnings, `is`(setOf(Warning.CURSOR_MISMATCH)))
         }.compilesWithoutError()
@@ -347,8 +345,7 @@
                 @Database(entities = {Entity1.class, Entity2.class}, version = 42)
                 public abstract class MyDb extends RoomDatabase {
                 }
-                """, entity1, entity2){ _, _ ->
-
+                """, entity1, entity2) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.duplicateIndexInDatabase("index_name",
                         listOf("foo.bar.Entity1 > index_name", "foo.bar.Entity2 > index_name"))
@@ -374,8 +371,7 @@
                 @Database(entities = {Entity1.class}, version = 42)
                 public abstract class MyDb extends RoomDatabase {
                 }
-                """, entity1, COMMON.USER){ _, _ ->
-
+                """, entity1, COMMON.USER) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.foreignKeyMissingParentEntityInDatabase("User", "foo.bar.Entity1")
         )
@@ -400,8 +396,7 @@
                 @Database(entities = {Entity1.class, User.class}, version = 42)
                 public abstract class MyDb extends RoomDatabase {
                 }
-                """, entity1, COMMON.USER){ _, _ ->
-
+                """, entity1, COMMON.USER) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.foreignKeyMissingIndexInParent(
                         parentEntity = COMMON.USER_TYPE_NAME.toString(),
@@ -444,8 +439,7 @@
                 @Database(entities = {Entity1.class, Entity2.class}, version = 42)
                 public abstract class MyDb extends RoomDatabase {
                 }
-                """, entity1, entity2){ _, _ ->
-
+                """, entity1, entity2) { _, _ ->
         }.compilesWithoutError()
     }
 
@@ -481,7 +475,7 @@
                 @Database(entities = {Entity1.class, Entity2.class}, version = 42)
                 public abstract class MyDb extends RoomDatabase {
                 }
-                """, entity1, entity2){ _, _ ->
+                """, entity1, entity2) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.foreignKeyParentColumnDoesNotExist("foo.bar.Entity2",
                         "anotherName2", listOf("uid", "anotherName"))
@@ -521,7 +515,7 @@
                 @Database(entities = {Entity1.class, Entity2.class}, version = 42)
                 public abstract class MyDb extends RoomDatabase {
                 }
-                """, entity1, entity2){ _, _ ->
+                """, entity1, entity2) { _, _ ->
         }.compilesWithoutError()
     }
 
@@ -532,7 +526,7 @@
                 public abstract class MyDb extends RoomDatabase {
                     abstract BookDao bookDao();
                 }
-                """, USER, USER_DAO, BOOK, BOOK_DAO){ _, _ ->
+                """, USER, USER_DAO, BOOK, BOOK_DAO) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.shortcutEntityIsNotInDatabase(
                         database = "foo.bar.MyDb",
@@ -566,7 +560,7 @@
                         public static java.util.Date foo(Long input) {return null;}
                     }
                 }
-                """, USER, USER_DAO){ db, _ ->
+                """, USER, USER_DAO) { db, _ ->
             val userDao = db.daoMethods.first().dao
             val insertionMethod = userDao.insertionMethods.find { it.name == "insert" }
             assertThat(insertionMethod, notNullValue())
@@ -597,7 +591,7 @@
                 public abstract class MyDb extends RoomDatabase {
                     public abstract UserDao userDao();
                 }
-                """, USER, USER_DAO){ db, _ ->
+                """, USER, USER_DAO) { db, _ ->
             val userDao = db.daoMethods.first().dao
             val loadOne = userDao.queryMethods.find { it.name == "loadOnePojo" }
             assertThat(loadOne, notNullValue())
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DeletionMethodProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DeletionMethodProcessorTest.kt
index 864ea9b..40546e8 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DeletionMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/DeletionMethodProcessorTest.kt
@@ -36,5 +36,4 @@
                          executableElement: ExecutableElement): DeletionMethod {
         return DeletionMethodProcessor(baseContext, containing, executableElement).process()
     }
-
 }
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityNameMatchingVariationsTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityNameMatchingVariationsTest.kt
index e6a2ff3..00dde74 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityNameMatchingVariationsTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityNameMatchingVariationsTest.kt
@@ -38,7 +38,7 @@
     companion object {
         @JvmStatic
         @Parameterized.Parameters(name = "{0}")
-        fun params() : List<Triple<String, String, String>> {
+        fun params(): List<Triple<String, String, String>> {
             val result = arrayListOf<Triple<String, String, String>>()
             arrayListOf("x", "_x", "mX").forEach { field ->
                 arrayListOf("getX", "x").forEach { getter ->
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt
index 631f511..95c70ca 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt
@@ -277,7 +277,6 @@
                 @PrimaryKey
                 public java.util.Date myDate;
                 """) { _, _ ->
-
         }.failsToCompile().withErrorContaining(ProcessorErrors.CANNOT_FIND_COLUMN_TYPE_ADAPTER)
     }
 
@@ -338,7 +337,7 @@
         }.compilesWithoutError()
     }
 
-    private fun fieldsByName(entity : Pojo, vararg fieldNames : String) : List<Field> {
+    private fun fieldsByName(entity: Pojo, vararg fieldNames: String): List<Field> {
         return fieldNames
                 .map { name -> entity.fields.find { it.name == name } }
                 .filterNotNull()
@@ -438,9 +437,10 @@
                 """
                 , annotation) { entity, _ ->
             assertThat(entity.indices, `is`(
-                    listOf(Index(name = "index_MyEntity_foo_id",
+                    listOf(Index(
+                            name = "index_MyEntity_foo_id",
                             unique = true,
-                           fields = fieldsByName(entity, "foo", "id")))
+                            fields = fieldsByName(entity, "foo", "id")))
             ))
         }.compilesWithoutError()
     }
@@ -663,7 +663,6 @@
                             unique = false,
                             fields = fieldsByName(entity, "name"))))
         }.compilesWithoutError().withWarningCount(0)
-
     }
 
     @Test
@@ -880,7 +879,6 @@
                 baseClass = "foo.bar.Base",
                 jfos = listOf(parent)) { entity, _ ->
             assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("baseId"))
-
         }.compilesWithoutError().withWarningCount(0)
     }
 
@@ -1033,7 +1031,7 @@
     }
 
     @Test
-    fun primaryKey_embedded(){
+    fun primaryKey_embedded() {
         singleEntity(
                 """
                 public int id;
@@ -1054,7 +1052,7 @@
     }
 
     @Test
-    fun primaryKey_embeddedInherited(){
+    fun primaryKey_embeddedInherited() {
         val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
                 """
                 package foo.bar;
@@ -1231,7 +1229,7 @@
     }
 
     @Test
-    fun primaryKey_nullableEmbedded(){
+    fun primaryKey_nullableEmbedded() {
         singleEntity(
                 """
                 public int id;
@@ -1249,7 +1247,7 @@
     }
 
     @Test
-    fun primaryKey_nullableEmbeddedObject(){
+    fun primaryKey_nullableEmbeddedObject() {
         singleEntity(
                 """
                 public int id;
@@ -1270,7 +1268,7 @@
     }
 
     @Test
-    fun primaryKey_nullableEmbeddedObject_multipleParents(){
+    fun primaryKey_nullableEmbeddedObject_multipleParents() {
         singleEntity(
                 """
                 public int id;
@@ -1297,7 +1295,7 @@
     }
 
     @Test
-    fun primaryKey_nullableEmbeddedInherited(){
+    fun primaryKey_nullableEmbeddedInherited() {
         val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
                 """
                 package foo.bar;
@@ -1495,7 +1493,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ _, _ ->
+        ) { _, _ ->
         }.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_FOREIGN_KEY_ACTION)
     }
 
@@ -1515,7 +1513,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ _, _ ->
+        ) { _, _ ->
         }.failsToCompile().withErrorContaining("cannot find symbol")
     }
 
@@ -1535,7 +1533,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.NOT_AN_ENTITY)
-        ){ _, _ ->
+        ) { _, _ ->
         }.failsToCompile().withErrorContaining(ProcessorErrors.foreignKeyNotAnEntity(
                 COMMON.NOT_AN_ENTITY_TYPE_NAME.toString()))
     }
@@ -1556,7 +1554,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ _, _ ->
+        ) { _, _ ->
         }.failsToCompile().withErrorContaining(ProcessorErrors.foreignKeyChildColumnDoesNotExist(
                 "namex", listOf("id", "name")))
     }
@@ -1577,7 +1575,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ _, _ ->
+        ) { _, _ ->
         }.failsToCompile().withErrorContaining(ProcessorErrors.foreignKeyColumnNumberMismatch(
                 listOf("name", "id"), listOf("lastName")))
     }
@@ -1598,7 +1596,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ _, _ ->
+        ) { _, _ ->
         }.failsToCompile().withErrorContaining(ProcessorErrors.FOREIGN_KEY_EMPTY_CHILD_COLUMN_LIST)
     }
 
@@ -1618,7 +1616,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ _, _ ->
+        ) { _, _ ->
         }.failsToCompile().withErrorContaining(ProcessorErrors.FOREIGN_KEY_EMPTY_PARENT_COLUMN_LIST)
     }
 
@@ -1641,7 +1639,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ entity, _ ->
+        ) { entity, _ ->
             assertThat(entity.foreignKeys.size, `is`(1))
             val fKey = entity.foreignKeys.first()
             assertThat(fKey.parentTable, `is`("User"))
@@ -1748,7 +1746,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ entity, _ ->
+        ) { entity, _ ->
             assertThat(entity.indices, `is`(emptyList()))
         }.compilesWithoutError().withWarningContaining(
                 ProcessorErrors.foreignKeyMissingIndexInChildColumn("name"))
@@ -1771,7 +1769,7 @@
                 String lName;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ entity, _ ->
+        ) { entity, _ ->
             assertThat(entity.indices, `is`(emptyList()))
         }.compilesWithoutError().withWarningContaining(
                 ProcessorErrors.foreignKeyMissingIndexInChildColumns(listOf("lName", "name")))
@@ -1796,7 +1794,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ entity, _ ->
+        ) { entity, _ ->
             assertThat(entity.indices, `is`(emptyList()))
         }.compilesWithoutWarnings()
     }
@@ -1807,7 +1805,7 @@
                 """
                 @Embedded
                 MyEntity myEntity;
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyEntity -> foo.bar.MyEntity"))
@@ -1826,7 +1824,7 @@
                     @Relation(parentColumn = "pojoId", entityColumn = "entityId")
                     MyEntity myEntity;
                 }
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyEntity -> foo.bar.MyEntity.A -> foo.bar.MyEntity"))
@@ -1843,7 +1841,7 @@
                     @Embedded
                     MyEntity myEntity;
                 }
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyEntity -> foo.bar.MyEntity.A -> foo.bar.MyEntity"))
@@ -1875,7 +1873,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ _, _ ->
+        ) { _, _ ->
         }.compilesWithoutError()
     }
 
@@ -1889,7 +1887,7 @@
                 String name;
                 """,
                 attributes = annotation, jfos = listOf(COMMON.USER)
-        ){ _, _ ->
+        ) { _, _ ->
         }.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_TABLE_NAME)
     }
 
@@ -1903,7 +1901,7 @@
                 String name;
                 """,
                 jfos = listOf(COMMON.USER)
-        ){ _, _ ->
+        ) { _, _ ->
         }.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_COLUMN_NAME)
     }
 }
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/InsertionMethodProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/InsertionMethodProcessorTest.kt
index ffb07ed..51f81db 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/InsertionMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/InsertionMethodProcessorTest.kt
@@ -55,8 +55,8 @@
                 abstract class MyClass {
                 """
         const val DAO_SUFFIX = "}"
-        val USER_TYPE_NAME : TypeName = COMMON.USER_TYPE_NAME
-        val BOOK_TYPE_NAME : TypeName = ClassName.get("foo.bar", "Book")
+        val USER_TYPE_NAME: TypeName = COMMON.USER_TYPE_NAME
+        val BOOK_TYPE_NAME: TypeName = ClassName.get("foo.bar", "Book")
     }
 
     @Test
@@ -387,9 +387,10 @@
         }
     }
 
-    fun singleInsertMethod(vararg input: String,
-                          handler: (InsertionMethod, TestInvocation) -> Unit):
-            CompileTester {
+    fun singleInsertMethod(
+            vararg input: String,
+            handler: (InsertionMethod, TestInvocation) -> Unit
+    ): CompileTester {
         return assertAbout(JavaSourcesSubjectFactory.javaSources())
                 .that(listOf(JavaFileObjects.forSourceString("foo.bar.MyClass",
                         DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/PojoProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/PojoProcessorTest.kt
index 6fdb300..bf34b4c 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/PojoProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/PojoProcessorTest.kt
@@ -523,7 +523,7 @@
                     affinity = SQLTypeAffinity.TEXT,
                     columnName = "foo",
                     parent = null,
-                    indexed =  false
+                    indexed = false
             )
             val fakeEmbedded = EmbeddedField(fakeField, "", null)
 
@@ -562,7 +562,7 @@
         singleRun(pojoCode) { pojo ->
             val param = pojo.constructor?.params?.first()
             assertThat(param, instanceOf(Constructor.FieldParam::class.java))
-            assertThat((param as Constructor.FieldParam).field.name,  `is`("mName"))
+            assertThat((param as Constructor.FieldParam).field.name, `is`("mName"))
             assertThat(pojo.fields.find { it.name == "mName" }?.setter?.callType,
                     `is`(CallType.CONSTRUCTOR))
         }.compilesWithoutError()
@@ -579,7 +579,7 @@
         singleRun(pojoCode) { pojo ->
             val param = pojo.constructor?.params?.first()
             assertThat(param, instanceOf(Constructor.FieldParam::class.java))
-            assertThat((param as Constructor.FieldParam).field.name,  `is`("mName"))
+            assertThat((param as Constructor.FieldParam).field.name, `is`("mName"))
             assertThat(pojo.fields.find { it.name == "mName" }?.setter?.callType,
                     `is`(CallType.CONSTRUCTOR))
         }.compilesWithoutError()
@@ -714,7 +714,7 @@
                 """
                 @Embedded
                 MyPojo myPojo;
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyPojo -> foo.bar.MyPojo"))
@@ -736,7 +736,7 @@
                     @Embedded
                     MyPojo myPojo;
                 }
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyPojo -> foo.bar.MyPojo.MyEntity -> foo.bar.MyPojo"))
@@ -754,7 +754,7 @@
                     @Embedded
                     MyPojo myPojo;
                 }
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo"))
@@ -770,7 +770,7 @@
                     @Embedded
                     MyPojo myPojo;
                 }
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo"))
@@ -790,7 +790,7 @@
                     @Embedded
                     MyPojo myPojo;
                 }
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo.B -> foo.bar.MyPojo"))
@@ -810,7 +810,7 @@
                     @Embedded
                     A a;
                 }
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyPojo.A -> foo.bar.MyPojo.B -> foo.bar.MyPojo.A"))
@@ -836,7 +836,7 @@
                     @Embedded
                     MyPojo myPojo;
                 }
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyPojo -> foo.bar.MyPojo.C -> foo.bar.MyPojo"))
@@ -862,20 +862,20 @@
                 }
                 static class C {
                 }
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
                         "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo"))
     }
 
-    fun singleRun(code: String, vararg jfos:JavaFileObject, handler: (Pojo) -> Unit)
-            : CompileTester {
+    fun singleRun(
+            code: String, vararg jfos: JavaFileObject, handler: (Pojo) -> Unit): CompileTester {
         return singleRun(code, *jfos) { pojo, _ ->
             handler(pojo)
         }
     }
 
-    fun singleRun(code: String, vararg jfos:JavaFileObject,
+    fun singleRun(code: String, vararg jfos: JavaFileObject,
                   handler: (Pojo, TestInvocation) -> Unit): CompileTester {
         val pojoJFO = """
                 $HEADER
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/ShortcutMethodProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/ShortcutMethodProcessorTest.kt
index c4ef416..7a332ea 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/ShortcutMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/ShortcutMethodProcessorTest.kt
@@ -55,7 +55,7 @@
                 """
         const val DAO_SUFFIX = "}"
         val USER_TYPE_NAME: TypeName = COMMON.USER_TYPE_NAME
-        val BOOK_TYPE_NAME : TypeName = ClassName.get("foo.bar", "Book")
+        val BOOK_TYPE_NAME: TypeName = ClassName.get("foo.bar", "Book")
     }
 
     @Test
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/solver/CustomTypeConverterResolutionTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/solver/CustomTypeConverterResolutionTest.kt
index 545556e..d9b4997 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/solver/CustomTypeConverterResolutionTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/solver/CustomTypeConverterResolutionTest.kt
@@ -49,7 +49,7 @@
 
 @RunWith(JUnit4::class)
 class CustomTypeConverterResolutionTest {
-    fun TypeSpec.toJFO() : JavaFileObject {
+    fun TypeSpec.toJFO(): JavaFileObject {
         return JavaFileObjects.forSourceString("foo.bar.${this.name}",
                 "package foo.bar;\n" + toString())
     }
@@ -168,15 +168,15 @@
         run(entity.toJFO(), dao.toJFO(), database.toJFO()).compilesWithoutError()
     }
 
-    fun run(vararg jfos : JavaFileObject): CompileTester {
+    fun run(vararg jfos: JavaFileObject): CompileTester {
         return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
                 .that(jfos.toList() + CUSTOM_TYPE_JFO + CUSTOM_TYPE_CONVERTER_JFO)
                 .processedWith(RoomProcessor())
     }
 
-    private fun createEntity(hasCustomField : Boolean = false,
-                             hasConverters : Boolean = false,
-                             hasConverterOnField : Boolean = false) : TypeSpec {
+    private fun createEntity(hasCustomField: Boolean = false,
+                             hasConverters: Boolean = false,
+                             hasConverterOnField: Boolean = false): TypeSpec {
         if (hasConverterOnField && hasConverters) {
             throw IllegalArgumentException("cannot have both converters")
         }
@@ -199,8 +199,8 @@
         }.build()
     }
 
-    private fun createDatabase(hasConverters : Boolean = false,
-                               hasDao : Boolean = false) : TypeSpec {
+    private fun createDatabase(hasConverters: Boolean = false,
+                               hasDao: Boolean = false): TypeSpec {
         return TypeSpec.classBuilder(DB).apply {
             addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
             superclass(RoomTypeNames.ROOM_DB)
@@ -225,11 +225,11 @@
         }.build()
     }
 
-    private fun createDao(hasConverters : Boolean = false,
-                          hasQueryReturningEntity : Boolean = false,
-                          hasQueryWithCustomParam : Boolean = false,
-                          hasMethodConverters : Boolean = false,
-                          hasParameterConverters : Boolean = false) : TypeSpec {
+    private fun createDao(hasConverters: Boolean = false,
+                          hasQueryReturningEntity: Boolean = false,
+                          hasQueryWithCustomParam: Boolean = false,
+                          hasMethodConverters: Boolean = false,
+                          hasParameterConverters: Boolean = false): TypeSpec {
         val annotationCount = listOf(hasMethodConverters, hasConverters, hasParameterConverters)
                 .map { if (it) 1 else 0 }.sum()
         if (annotationCount > 1) {
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/solver/TypeAdapterStoreTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/solver/TypeAdapterStoreTest.kt
index 78284b4..0148d2a 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/solver/TypeAdapterStoreTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/solver/TypeAdapterStoreTest.kt
@@ -182,7 +182,6 @@
                     invocation.context.COMMON_TYPES.STRING)
             assertThat(converter, notNullValue())
             assertThat(store.reverse(converter!!), `is`(binders[1]))
-
         }.compilesWithoutError()
     }
 
@@ -368,7 +367,6 @@
                             addStatement("$L = $T.toBoolean($L)", outputVarName, from, inputVarName)
                         }
                     }
-
                 },
                 object : TypeConverter(tBoolean, tPoint) {
                     override fun convert(inputVarName: String, outputVarName: String,
@@ -393,7 +391,6 @@
                             addStatement("// convert Date to Long")
                         }
                     }
-
                 },
                 object : TypeConverter(tLong, tDate) {
                     override fun convert(inputVarName: String, outputVarName: String,
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/TestInvocation.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/TestInvocation.kt
index b97628e..86b6e01 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/TestInvocation.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/TestInvocation.kt
@@ -26,7 +26,7 @@
                           val roundEnv: RoundEnvironment) {
     val context = Context(processingEnv)
 
-    fun typeElement(qName: String) : TypeElement {
+    fun typeElement(qName: String): TypeElement {
         return processingEnv.elementUtils.getTypeElement(qName)
     }
 }
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/TestProcessor.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/TestProcessor.kt
index 16c0048..6dfa2e4 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/TestProcessor.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/TestProcessor.kt
@@ -27,8 +27,8 @@
 class TestProcessor(val handlers: List<(TestInvocation) -> Boolean>,
                     val annotations: MutableSet<String>) : AbstractProcessor() {
     var count = 0
-    override fun process(annotations: MutableSet<out TypeElement>, roundEnv: RoundEnvironment)
-            : Boolean {
+    override fun process(
+            annotations: MutableSet<out TypeElement>, roundEnv: RoundEnvironment): Boolean {
         return handlers.getOrNull(count++)?.invoke(
                     TestInvocation(processingEnv, annotations, roundEnv)) ?: true
     }
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/test_util.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/test_util.kt
index 2616627..4d100b3 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/test_util.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/testing/test_util.kt
@@ -95,7 +95,7 @@
     return CodeGenScope(Mockito.mock(ClassWriter::class.java))
 }
 
-fun simpleRun(vararg jfos : JavaFileObject, f: (TestInvocation) -> Unit): CompileTester {
+fun simpleRun(vararg jfos: JavaFileObject, f: (TestInvocation) -> Unit): CompileTester {
     return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
             .that(jfos.toList() + JavaFileObjects.forSourceString("foo.bar.MyClass",
                     """
@@ -115,12 +115,12 @@
                     .build())
 }
 
-fun loadJavaCode(fileName : String, qName : String) : JavaFileObject {
+fun loadJavaCode(fileName: String, qName: String): JavaFileObject {
     val contents = File("src/test/data/$fileName").readText(Charsets.UTF_8)
     return JavaFileObjects.forSourceString(qName, contents)
 }
 
-fun createVerifierFromEntities(invocation: TestInvocation) : DatabaseVerifier {
+fun createVerifierFromEntities(invocation: TestInvocation): DatabaseVerifier {
     val entities = invocation.roundEnv.getElementsAnnotatedWith(Entity::class.java).map {
         EntityProcessor(invocation.context, MoreElements.asType(it)).process()
     }
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/verifier/DatabaseVerifierTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/verifier/DatabaseVerifierTest.kt
index ef5c4ef..e144e2b 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/verifier/DatabaseVerifierTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/verifier/DatabaseVerifierTest.kt
@@ -235,6 +235,5 @@
                 .filter { it.second > 0 }
                 .sortedBy { it.second }
                 .map { it.first }
-
     }
 }
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/vo/IndexTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/vo/IndexTest.kt
index c1ac029..04e43f8 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/vo/IndexTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/vo/IndexTest.kt
@@ -42,7 +42,7 @@
         ))
     }
 
-    private fun mockField(columnName : String): Field {
+    private fun mockField(columnName: String): Field {
         val (element, type) = mockElementAndType()
         return Field(
                 element = element,
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/DaoWriterTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/DaoWriterTest.kt
index 6d2bda3..96d1e3a 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/DaoWriterTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/DaoWriterTest.kt
@@ -72,7 +72,7 @@
         )
     }
 
-    fun singleDao(vararg jfo : JavaFileObject): CompileTester {
+    fun singleDao(vararg jfo: JavaFileObject): CompileTester {
         return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
                 .that(jfo.toList() + COMMON.USER + COMMON.MULTI_PKEY_ENTITY + COMMON.BOOK +
                         COMMON.LIVE_DATA + COMMON.COMPUTABLE_LIVE_DATA)
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/DatabaseWriterTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/DatabaseWriterTest.kt
index 9a3252f..824d2d0 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/DatabaseWriterTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/DatabaseWriterTest.kt
@@ -42,9 +42,9 @@
         )
     }
 
-    private fun singleDb(vararg jfo : JavaFileObject): CompileTester {
+    private fun singleDb(vararg jfo: JavaFileObject): CompileTester {
         return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
-                .that(jfo.toList() + COMMON.USER +  COMMON.LIVE_DATA + COMMON.COMPUTABLE_LIVE_DATA)
+                .that(jfo.toList() + COMMON.USER + COMMON.LIVE_DATA + COMMON.COMPUTABLE_LIVE_DATA)
                 .processedWith(RoomProcessor())
     }
 }
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/EntityCursorConverterWriterTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/EntityCursorConverterWriterTest.kt
index 31a3f18..a01033e 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/EntityCursorConverterWriterTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/EntityCursorConverterWriterTest.kt
@@ -78,20 +78,20 @@
                 """.trimIndent())
     }
 
-    fun generateAndMatch(input: String, output : String,
+    fun generateAndMatch(input: String, output: String,
                          attributes: Map<String, String> = mapOf()) {
         generate(input, attributes)
                 .compilesWithoutError()
                 .and()
                 .generatesSources(JavaFileObjects.forSourceString(
                         "foo.bar.MyEntity_CursorConverter",
-                        listOf(OUT_PREFIX,output,OUT_SUFFIX).joinToString("\n")))
+                        listOf(OUT_PREFIX, output, OUT_SUFFIX).joinToString("\n")))
     }
 
-    fun generate(input: String, attributes: Map<String, String> = mapOf()) : CompileTester {
+    fun generate(input: String, attributes: Map<String, String> = mapOf()): CompileTester {
         return singleEntity(input, attributes) { entity, invocation ->
-            val className = ClassName.get("foo.bar","MyContainerClass")
-            val writer = object : ClassWriter(className){
+            val className = ClassName.get("foo.bar", "MyContainerClass")
+            val writer = object : ClassWriter(className) {
                 override fun createTypeSpecBuilder(): TypeSpec.Builder {
                     getOrCreateMethod(EntityCursorConverterWriter(entity))
                     return TypeSpec.classBuilder(className).apply {
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/SQLiteOpenHelperWriterTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/SQLiteOpenHelperWriterTest.kt
index 2e86a00..4d68231 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/SQLiteOpenHelperWriterTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/writer/SQLiteOpenHelperWriterTest.kt
@@ -132,7 +132,7 @@
 
     fun singleEntity(input: String, attributes: Map<String, String> = mapOf(),
                      handler: (Database, TestInvocation) -> Unit): CompileTester {
-        val attributesReplacement : String
+        val attributesReplacement: String
         if (attributes.isEmpty()) {
             attributesReplacement = ""
         } else {
diff --git a/room/integration-tests/kotlintestapp/build.gradle b/room/integration-tests/kotlintestapp/build.gradle
index f1f5139..f444018 100644
--- a/room/integration-tests/kotlintestapp/build.gradle
+++ b/room/integration-tests/kotlintestapp/build.gradle
@@ -13,12 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+import static android.support.dependencies.DependenciesKt.*
+
 apply plugin: 'com.android.application'
 apply plugin: 'kotlin-kapt'
 apply plugin: 'kotlin-android'
 
-project.ext.noDocs = true
-
 android {
     compileSdkVersion tools.current_sdk
     buildToolsVersion tools.build_tools_version
@@ -57,21 +58,21 @@
 }
 
 dependencies {
-    implementation project(":room:common")
-    implementation project(":persistence:db")
-    implementation project(":persistence:db-framework")
-    implementation project(':room:runtime')
-    implementation project(':arch:runtime')
+    implementation(project(":room:common"))
+    implementation(project(":persistence:db"))
+    implementation(project(":persistence:db-framework"))
+    implementation(project(":room:runtime"))
+    implementation(project(":arch:runtime"))
 
     implementation libs.support.app_compat, libs.support_exclude_config
     kapt project(":room:compiler")
     kaptAndroidTest project(":room:compiler")
 
-    androidTestImplementation(libs.test_runner) {
+    androidTestImplementation(TEST_RUNNER) {
         exclude module: 'support-annotations'
         exclude module: 'hamcrest-core'
     }
-    androidTestImplementation(libs.espresso_core, {
+    androidTestImplementation(ESPRESSO_CORE, {
         exclude group: 'com.android.support', module: 'support-annotations'
         exclude module: "hamcrest-core"
     })
@@ -82,12 +83,10 @@
     androidTestImplementation project(':room:testing')
     androidTestImplementation project(':room:rxjava2')
     androidTestImplementation project(':arch:core-testing')
-    androidTestImplementation libs.rx_java
-    testImplementation libs.mockito_core
+    androidTestImplementation(RX_JAVA)
+    testImplementation(MOCKITO_CORE)
 }
 
-createAndroidCheckstyle(project)
-createKotlinCheckstyle(project)
 tasks['check'].dependsOn(tasks['connectedCheck'])
 
 uploadArchives.enabled = false
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/dao/DerivedDao.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/dao/DerivedDao.kt
index 01e8167..5245a01 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/dao/DerivedDao.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/dao/DerivedDao.kt
@@ -20,7 +20,6 @@
 import android.arch.persistence.room.Query
 import android.arch.persistence.room.integration.kotlintestapp.vo.Author
 
-
 @Dao
 interface DerivedDao : BaseDao<Author> {
 
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
index 4265e19..b684923 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
@@ -33,7 +33,6 @@
 import java.io.FileNotFoundException
 import java.io.IOException
 
-
 class MigrationKotlinTest {
 
     @get:Rule
@@ -58,7 +57,6 @@
         } catch (exception: FileNotFoundException) {
             assertThat<String>(exception.message, containsString("Cannot find"))
         }
-
     }
 
     @Test
@@ -244,7 +242,6 @@
         assertThat<String>(throwable!!.message, containsString("Migration failed"))
     }
 
-
     internal val MIGRATION_1_2: Migration = object : Migration(1, 2) {
         override fun migrate(database: SupportSQLiteDatabase) {
             database.execSQL("CREATE TABLE IF NOT EXISTS `Entity2` (`id` INTEGER NOT NULL,"
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/vo/BookAuthor.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/vo/BookAuthor.kt
index 4fc661c..5a21f40 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/vo/BookAuthor.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/vo/BookAuthor.kt
@@ -19,7 +19,6 @@
 import android.arch.persistence.room.Entity
 import android.arch.persistence.room.ForeignKey
 
-
 @Entity(foreignKeys = arrayOf(
         ForeignKey(entity = Book::class,
                 parentColumns = arrayOf("bookId"),
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/vo/BookWithPublisher.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/vo/BookWithPublisher.kt
index 6516c23..418a0e2 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/vo/BookWithPublisher.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/android/arch/persistence/room/integration/kotlintestapp/vo/BookWithPublisher.kt
@@ -18,6 +18,5 @@
 
 import android.arch.persistence.room.Embedded
 
-
 data class BookWithPublisher(val bookId: String, val title: String,
                              @Embedded val publisher: Publisher)
diff --git a/room/integration-tests/testapp/build.gradle b/room/integration-tests/testapp/build.gradle
index b063595..d1da195 100644
--- a/room/integration-tests/testapp/build.gradle
+++ b/room/integration-tests/testapp/build.gradle
@@ -13,9 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-apply plugin: 'com.android.application'
 
-project.ext.noDocs = true
+import static android.support.dependencies.DependenciesKt.*
+
+apply plugin: 'com.android.application'
 
 android {
     compileSdkVersion tools.current_sdk
@@ -55,18 +56,18 @@
 }
 
 dependencies {
-    implementation project(":room:common")
-    implementation project(":persistence:db")
-    implementation project(":persistence:db-framework")
-    implementation project(':room:runtime')
-    implementation project(':arch:runtime')
-    implementation project(':arch:common')
-    implementation project(':paging:common')
-    implementation project(':lifecycle:extensions')
-    implementation project(':lifecycle:runtime')
-    implementation project(':lifecycle:common')
-    implementation project(':room:rxjava2')
-    implementation project(':paging:runtime')
+    implementation(project(":room:common"))
+    implementation(project(":persistence:db"))
+    implementation(project(":persistence:db-framework"))
+    implementation(project(":room:runtime"))
+    implementation(project(":arch:runtime"))
+    implementation(project(":arch:common"))
+    implementation(project(":paging:common"))
+    implementation(project(":lifecycle:extensions"))
+    implementation(project(":lifecycle:runtime"))
+    implementation(project(":lifecycle:common"))
+    implementation(project(":room:rxjava2"))
+    implementation(project(":paging:runtime"))
 
     implementation libs.support.recyclerview, libs.support_exclude_config
     implementation libs.support.app_compat, libs.support_exclude_config
@@ -74,26 +75,21 @@
     androidTestAnnotationProcessor project(":room:compiler")
 
     // IJ's gradle integration just cannot figure this out ...
-    androidTestImplementation project(':lifecycle:extensions')
-    androidTestImplementation project(':lifecycle:common')
-    androidTestImplementation project(':lifecycle:runtime')
-    androidTestImplementation project(':room:testing')
-    androidTestImplementation project(':room:rxjava2')
-    androidTestImplementation project(':arch:core-testing')
-    androidTestImplementation libs.rx_java
-    androidTestImplementation(libs.test_runner) {
-        exclude module: 'support-annotations'
-    }
-    androidTestImplementation(libs.espresso_core, {
-        exclude group: 'com.android.support', module: 'support-annotations'
-    })
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it's own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it's own MockMaker
+    androidTestImplementation(project(":lifecycle:extensions"))
+    androidTestImplementation(project(":lifecycle:common"))
+    androidTestImplementation(project(":lifecycle:runtime"))
+    androidTestImplementation(project(":room:testing"))
+    androidTestImplementation(project(":room:rxjava2"))
+    androidTestImplementation(project(":arch:core-testing"))
+    androidTestImplementation(RX_JAVA)
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it's own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it's own MockMaker
 
-    testImplementation libs.junit
+    testImplementation(JUNIT)
 }
 
-createAndroidCheckstyle(project)
 tasks['check'].dependsOn(tasks['connectedCheck'])
 
 uploadArchives.enabled = false
diff --git a/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/database/LastNameAscCustomerDataSource.java b/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/database/LastNameAscCustomerDataSource.java
index 2db543b..6278bc2 100644
--- a/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/database/LastNameAscCustomerDataSource.java
+++ b/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/database/LastNameAscCustomerDataSource.java
@@ -16,10 +16,9 @@
 package android.arch.persistence.room.integration.testapp.database;
 
 import android.arch.paging.DataSource;
-import android.arch.paging.KeyedDataSource;
+import android.arch.paging.ItemKeyedDataSource;
 import android.arch.persistence.room.InvalidationTracker;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 
 import java.util.Collections;
 import java.util.List;
@@ -28,7 +27,7 @@
 /**
  * Sample Room keyed data source.
  */
-public class LastNameAscCustomerDataSource extends KeyedDataSource<String, Customer> {
+public class LastNameAscCustomerDataSource extends ItemKeyedDataSource<String, Customer> {
     private final CustomerDao mCustomerDao;
     @SuppressWarnings("FieldCanBeLocal")
     private final InvalidationTracker.Observer mObserver;
@@ -76,13 +75,14 @@
     }
 
     @Override
-    public void loadInitial(@Nullable String customerName, int initialLoadSize,
-            boolean enablePlaceholders, @NonNull InitialLoadCallback<Customer> callback) {
+    public void loadInitial(@NonNull LoadInitialParams<String> params,
+            @NonNull LoadInitialCallback<Customer> callback) {
+        String customerName = params.requestedInitialKey;
         List<Customer> list;
         if (customerName != null) {
             // initial keyed load - load before 'customerName',
             // and load after last item in before list
-            int pageSize = initialLoadSize / 2;
+            int pageSize = params.requestedLoadSize / 2;
             String key = customerName;
             list = mCustomerDao.customerNameLoadBefore(key, pageSize);
             Collections.reverse(list);
@@ -91,10 +91,10 @@
             }
             list.addAll(mCustomerDao.customerNameLoadAfter(key, pageSize));
         } else {
-            list = mCustomerDao.customerNameInitial(initialLoadSize);
+            list = mCustomerDao.customerNameInitial(params.requestedLoadSize);
         }
 
-        if (enablePlaceholders && !list.isEmpty()) {
+        if (params.placeholdersEnabled && !list.isEmpty()) {
             String firstKey = getKey(list.get(0));
             String lastKey = getKey(list.get(list.size() - 1));
 
@@ -108,16 +108,18 @@
     }
 
     @Override
-    public void loadAfter(@NonNull String currentEndKey, int pageSize,
+    public void loadAfter(@NonNull LoadParams<String> params,
             @NonNull LoadCallback<Customer> callback) {
-        callback.onResult(mCustomerDao.customerNameLoadAfter(currentEndKey, pageSize));
+        callback.onResult(mCustomerDao.customerNameLoadAfter(params.key, params.requestedLoadSize));
     }
 
     @Override
-    public void loadBefore(@NonNull String currentBeginKey, int pageSize,
+    public void loadBefore(@NonNull LoadParams<String> params,
             @NonNull LoadCallback<Customer> callback) {
-        List<Customer> list = mCustomerDao.customerNameLoadBefore(currentBeginKey, pageSize);
+        List<Customer> list = mCustomerDao.customerNameLoadBefore(
+                params.key, params.requestedLoadSize);
         Collections.reverse(list);
         callback.onResult(list);
     }
 }
+
diff --git a/room/migration/build.gradle b/room/migration/build.gradle
index 086aac7..acadb71 100644
--- a/room/migration/build.gradle
+++ b/room/migration/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension;
@@ -26,12 +27,12 @@
     test.java.srcDirs += 'src/tests/kotlin'
 }
 dependencies {
-    compile project(":room:common")
-    compile libs.kotlin.stdlib
-    compile libs.gson
-    testCompile libs.junit
-    testCompile libs.ij_annotations
-    testCompile libs.mockito_core
+    compile(project(":room:common"))
+    compile(KOTLIN_STDLIB)
+    compile(GSON)
+    testCompile(JUNIT)
+    testCompile(INTELLIJ_ANNOTATIONS)
+    testCompile(MOCKITO_CORE)
 }
 
 supportLibrary {
diff --git a/room/runtime/build.gradle b/room/runtime/build.gradle
index 0570fe8..8a91ac7 100644
--- a/room/runtime/build.gradle
+++ b/room/runtime/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -33,27 +34,24 @@
 }
 
 dependencies {
-    api project(":room:common")
-    api project(":persistence:db-framework")
-    api project(":persistence:db")
-    api project(":arch:runtime")
+    api(project(":room:common"))
+    api(project(":persistence:db-framework"))
+    api(project(":persistence:db"))
+    api(project(":arch:runtime"))
     compileOnly project(":paging:common")
     compileOnly project(":lifecycle:runtime")
     compileOnly project(":lifecycle:extensions")
     api libs.support.core_utils, libs.support_exclude_config
 
-    testImplementation project(":arch:core-testing")
-    testImplementation libs.junit
-    testImplementation libs.mockito_core
-    testImplementation libs.support.annotations
+    testImplementation(project(":arch:core-testing"))
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
 
-    androidTestImplementation libs.junit
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
+    androidTestImplementation(JUNIT)
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
 }
 
-createAndroidCheckstyle(project)
-
 // Used by testCompile in room-compiler
 android.libraryVariants.all { variant ->
     def name = variant.buildType.name
diff --git a/room/runtime/lint-baseline.xml b/room/runtime/lint-baseline.xml
deleted file mode 100644
index 2cadde1..0000000
--- a/room/runtime/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0">
-
-</issues>
diff --git a/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java b/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java
index 8c94024..2a108f9 100644
--- a/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java
+++ b/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java
@@ -90,7 +90,7 @@
      * @param configuration The database configuration.
      */
     @CallSuper
-    public void init(DatabaseConfiguration configuration) {
+    public void init(@NonNull DatabaseConfiguration configuration) {
         mOpenHelper = createOpenHelper(configuration);
         mCallbacks = configuration.callbacks;
         mAllowMainThreadQueries = configuration.allowMainThreadQueries;
@@ -101,6 +101,7 @@
      *
      * @return The SQLite open helper used by this database.
      */
+    @NonNull
     public SupportSQLiteOpenHelper getOpenHelper() {
         return mOpenHelper;
     }
@@ -113,6 +114,7 @@
      * @param config The configuration of the Room database.
      * @return A new SupportSQLiteOpenHelper to be used while connecting to the database.
      */
+    @NonNull
     protected abstract SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration config);
 
     /**
@@ -122,6 +124,7 @@
      *
      * @return Creates a new InvalidationTracker.
      */
+    @NonNull
     protected abstract InvalidationTracker createInvalidationTracker();
 
     /**
@@ -199,7 +202,7 @@
      * @param sql The query to compile.
      * @return The compiled query.
      */
-    public SupportSQLiteStatement compileStatement(String sql) {
+    public SupportSQLiteStatement compileStatement(@NonNull String sql) {
         assertNotMainThread();
         return mOpenHelper.getWritableDatabase().compileStatement(sql);
     }
@@ -238,7 +241,7 @@
      *
      * @param body The piece of code to execute.
      */
-    public void runInTransaction(Runnable body) {
+    public void runInTransaction(@NonNull Runnable body) {
         beginTransaction();
         try {
             body.run();
@@ -256,7 +259,7 @@
      * @param <V>  The type of the return value.
      * @return The value returned from the {@link Callable}.
      */
-    public <V> V runInTransaction(Callable<V> body) {
+    public <V> V runInTransaction(@NonNull Callable<V> body) {
         beginTransaction();
         try {
             V result = body.call();
@@ -278,7 +281,7 @@
      *
      * @param db The database instance.
      */
-    protected void internalInitInvalidationTracker(SupportSQLiteDatabase db) {
+    protected void internalInitInvalidationTracker(@NonNull SupportSQLiteDatabase db) {
         mInvalidationTracker.internalInit(db);
     }
 
@@ -290,6 +293,7 @@
      *
      * @return The invalidation tracker for the database.
      */
+    @NonNull
     public InvalidationTracker getInvalidationTracker() {
         return mInvalidationTracker;
     }
@@ -365,7 +369,7 @@
          * @return this
          */
         @NonNull
-        public Builder<T> addMigrations(Migration... migrations) {
+        public Builder<T> addMigrations(@NonNull Migration... migrations) {
             mMigrationContainer.addMigrations(migrations);
             return this;
         }
@@ -471,7 +475,7 @@
          *
          * @param migrations List of available migrations.
          */
-        public void addMigrations(Migration... migrations) {
+        public void addMigrations(@NonNull Migration... migrations) {
             for (Migration migration : migrations) {
                 addMigration(migration);
             }
diff --git a/room/runtime/src/main/java/android/arch/persistence/room/RoomSQLiteQuery.java b/room/runtime/src/main/java/android/arch/persistence/room/RoomSQLiteQuery.java
index a8defd4..a10cc52 100644
--- a/room/runtime/src/main/java/android/arch/persistence/room/RoomSQLiteQuery.java
+++ b/room/runtime/src/main/java/android/arch/persistence/room/RoomSQLiteQuery.java
@@ -209,7 +209,7 @@
     }
 
     @Override
-    public void close() throws Exception {
+    public void close() {
         // no-op. not calling release because it is internal API.
     }
 
diff --git a/room/rxjava2/build.gradle b/room/rxjava2/build.gradle
index efdfc48..1b012dd 100644
--- a/room/rxjava2/build.gradle
+++ b/room/rxjava2/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -29,18 +30,16 @@
 }
 
 dependencies {
-    api project(":room:common")
-    api project(":room:runtime")
-    api project(":arch:runtime")
+    api(project(":room:common"))
+    api(project(":room:runtime"))
+    api(project(":arch:runtime"))
     api libs.support.core_utils, libs.support_exclude_config
-    api libs.rx_java
-    testImplementation libs.junit
-    testImplementation libs.mockito_core
-    testImplementation project(":arch:core-testing")
+    api(RX_JAVA)
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
+    testImplementation(project(":arch:core-testing"))
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Room RXJava2"
     publish = true
diff --git a/room/rxjava2/lint-baseline.xml b/room/rxjava2/lint-baseline.xml
deleted file mode 100644
index 2cadde1..0000000
--- a/room/rxjava2/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0">
-
-</issues>
diff --git a/room/testing/build.gradle b/room/testing/build.gradle
index 876300a..b71c8bc 100644
--- a/room/testing/build.gradle
+++ b/room/testing/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 import android.support.SupportLibraryExtension
@@ -29,18 +30,16 @@
 }
 
 dependencies {
-    api project(":room:common")
-    api project(":room:runtime")
-    api project(":persistence:db")
-    api project(":persistence:db-framework")
-    api project(":room:migration")
-    api project(":arch:runtime")
+    api(project(":room:common"))
+    api(project(":room:runtime"))
+    api(project(":persistence:db"))
+    api(project(":persistence:db-framework"))
+    api(project(":room:migration"))
+    api(project(":arch:runtime"))
     api libs.support.core_utils, libs.support_exclude_config
-    api libs.junit
+    api(JUNIT)
 }
 
-createAndroidCheckstyle(project)
-
 supportLibrary {
     name = "Android Room Testing"
     publish = true
diff --git a/samples/Support13Demos/build.gradle b/samples/Support13Demos/build.gradle
index 99175b3..ba2c2e4 100644
--- a/samples/Support13Demos/build.gradle
+++ b/samples/Support13Demos/build.gradle
@@ -1,7 +1,7 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':support-v13')
+    implementation(project(":support-v13"))
 }
 
 android {
diff --git a/samples/Support4Demos/build.gradle b/samples/Support4Demos/build.gradle
index 8e76229..3257e6a 100644
--- a/samples/Support4Demos/build.gradle
+++ b/samples/Support4Demos/build.gradle
@@ -1,7 +1,7 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':support-v4')
+    implementation(project(":support-v4"))
 }
 
 android {
diff --git a/samples/Support7Demos/build.gradle b/samples/Support7Demos/build.gradle
index 14d128a..6b2468b 100644
--- a/samples/Support7Demos/build.gradle
+++ b/samples/Support7Demos/build.gradle
@@ -1,12 +1,12 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':appcompat-v7')
-    implementation project(':cardview-v7')
-    implementation project(':gridlayout-v7')
-    implementation project(':mediarouter-v7')
-    implementation project(':palette-v7')
-    implementation project(':recyclerview-v7')
+    implementation(project(":appcompat-v7"))
+    implementation(project(":cardview-v7"))
+    implementation(project(":gridlayout-v7"))
+    implementation(project(":mediarouter-v7"))
+    implementation(project(":palette-v7"))
+    implementation(project(":recyclerview-v7"))
     implementation project(':recyclerview-selection')
 }
 
diff --git a/samples/SupportAnimationDemos/build.gradle b/samples/SupportAnimationDemos/build.gradle
index 23e5030..bb86bd5 100644
--- a/samples/SupportAnimationDemos/build.gradle
+++ b/samples/SupportAnimationDemos/build.gradle
@@ -1,7 +1,7 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':support-dynamic-animation')
+    implementation(project(":support-dynamic-animation"))
 }
 
 android {
diff --git a/samples/SupportAppNavigation/build.gradle b/samples/SupportAppNavigation/build.gradle
index 35a9d73..b242576 100644
--- a/samples/SupportAppNavigation/build.gradle
+++ b/samples/SupportAppNavigation/build.gradle
@@ -17,7 +17,7 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':support-v4')
+    implementation(project(":support-v4"))
 }
 
 android {
diff --git a/samples/SupportCarDemos/OWNERS b/samples/SupportCarDemos/OWNERS
new file mode 100644
index 0000000..42ef8d4
--- /dev/null
+++ b/samples/SupportCarDemos/OWNERS
@@ -0,0 +1,2 @@
+ajchen@google.com
+yaoyx@google.com
\ No newline at end of file
diff --git a/samples/SupportCarDemos/build.gradle b/samples/SupportCarDemos/build.gradle
new file mode 100644
index 0000000..efd8550
--- /dev/null
+++ b/samples/SupportCarDemos/build.gradle
@@ -0,0 +1,32 @@
+apply plugin: 'com.android.application'
+
+dependencies {
+    implementation project(':car')
+}
+
+android {
+    compileSdkVersion project.ext.currentSdk
+
+    defaultConfig {
+        minSdkVersion 24
+        targetSdkVersion project.ext.currentSdk
+    }
+
+    signingConfigs {
+        debug {
+            // Use a local debug keystore to avoid build server issues.
+            storeFile project.rootProject.init.debugKeystore
+        }
+    }
+
+    lintOptions {
+        abortOnError true
+        check 'NewApi'
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+}
+
diff --git a/samples/SupportCarDemos/src/main/AndroidManifest.xml b/samples/SupportCarDemos/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c32fcf4
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/AndroidManifest.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.androidx.car">
+
+    <application android:label="@string/activity_sample_code"
+            android:supportsRtl="true"
+            android:icon="@drawable/app_sample_code"
+            android:theme="@style/CarTheme">
+
+        <activity android:name=".SupportCarDemoActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".PagedListViewActivity"
+                  android:label="PagedListView"
+                  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>
+
+        <activity android:name=".ListItemActivity"
+                  android:label="ListItem"
+                  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/ListItemActivity.java b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/ListItemActivity.java
new file mode 100644
index 0000000..6aa5ba6
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/ListItemActivity.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.androidx.car;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Point;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import androidx.car.widget.ListItem;
+import androidx.car.widget.ListItemAdapter;
+import androidx.car.widget.ListItemProvider;
+import androidx.car.widget.PagedListView;
+
+/**
+ * Demo activity for {@link ListItem}.
+ */
+public class ListItemActivity extends Activity {
+
+    private static int pixelToDip(Context context, int pixels) {
+        return (int) (pixels / context.getResources().getDisplayMetrics().density);
+    }
+
+    PagedListView mPagedListView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_paged_list_view);
+
+        mPagedListView = findViewById(R.id.paged_list_view);
+
+        ListItemAdapter adapter = new ListItemAdapter(this,
+                new SampleProvider(this));
+        mPagedListView.setAdapter(adapter);
+        mPagedListView.setMaxPages(PagedListView.UNLIMITED_PAGES);
+    }
+
+    private static class SampleProvider extends ListItemProvider {
+        private Context mContext;
+        private List<ListItem> mItems;
+
+        private View.OnClickListener mGetParentHeight = (v) -> {
+            int parentHeight = ((FrameLayout) v.getParent().getParent().getParent()).getHeight();
+            Toast.makeText(v.getContext(),
+                    "card height is " + pixelToDip(mContext, parentHeight) + " dp",
+                    Toast.LENGTH_SHORT).show();
+        };
+
+        private ListItemProvider.ListProvider mListProvider;
+
+        SampleProvider(Context context) {
+            mContext = context;
+            mItems = new ArrayList<>();
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true)
+                    .withTitle("single line with full icon and one action")
+                    .withAction("card height", true, mGetParentHeight)
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withTitle("primary action set by drawable")
+                    .withPrimaryActionIcon(mContext.getDrawable(R.drawable.pressed_icon), true)
+                    .withViewBinder(vh -> vh.getPrimaryIcon().setClickable(true))
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                    .withTitle("single line with small icon and clickable end icon")
+                    .withSupplementalIcon(android.R.drawable.sym_def_app_icon, true,
+                            mGetParentHeight)
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionEmptyIcon()
+                    .withTitle("single line with empty icon and end icon no divider")
+                    .withSupplementalIcon(android.R.drawable.sym_def_app_icon, false)
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withTitle("title is single line and ellipsizes. "
+                            + mContext.getString(R.string.long_text))
+                    .withSupplementalIcon(android.R.drawable.sym_def_app_icon, true)
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionNoIcon()
+                    .withTitle("single line with two actions and no divider")
+                    .withActions("action 1", false,
+                            (v) -> Toast.makeText(
+                                    v.getContext(), "action 1", Toast.LENGTH_SHORT).show(),
+                            "action 2", false,
+                            (v) -> Toast.makeText(
+                                    v.getContext(), "action 2", Toast.LENGTH_SHORT).show())
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionNoIcon()
+                    .withTitle("single line with two actions and action 2 divider")
+                    .withActions("action 1", false,
+                            (v) -> Toast.makeText(
+                                    v.getContext(), "action 1", Toast.LENGTH_SHORT).show(),
+                            "action 2", true,
+                            (v) -> Toast.makeText(
+                                    v.getContext(), "action 2", Toast.LENGTH_SHORT).show())
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionNoIcon()
+                    .withTitle("single line with divider between actions. "
+                            + mContext.getString(R.string.long_text))
+                    .withActions("action 1", true,
+                            (v) -> Toast.makeText(
+                                    v.getContext(), "action 1", Toast.LENGTH_SHORT).show(),
+                            "action 2", false,
+                            (v) -> Toast.makeText(
+                                    v.getContext(), "action 2", Toast.LENGTH_SHORT).show())
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true)
+                    .withTitle("double line with full icon and no end icon divider")
+                    .withBody("one line text")
+                    .withSupplementalIcon(android.R.drawable.sym_def_app_icon, false,
+                            mGetParentHeight)
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                    .withTitle("double line with small icon and one action")
+                    .withBody("one line text")
+                    .withAction("card height", true, mGetParentHeight)
+                    .build());
+
+            String tenChars = "Ten Chars.";
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                    .withTitle("Card with small icon and text longer than limit")
+                    .withBody("some chars")
+                    .withBody(TextUtils.join("", Collections.nCopies(20, tenChars)))
+                    .withSupplementalIcon(android.R.drawable.sym_def_app_icon, true,
+                            mGetParentHeight)
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionEmptyIcon()
+                    .withTitle("double line with empty primary icon."
+                            + mContext.getString(R.string.long_text))
+                    .withBody("one line text as primary", true)
+                    .withActions("screen size", false, (v) -> {
+                        Context c = v.getContext();
+                        Point size = new Point();
+                        c.getSystemService(WindowManager.class).getDefaultDisplay().getSize(size);
+
+                        Toast.makeText(v.getContext(),
+                                String.format("%s x %s dp", pixelToDip(c, size.x),
+                                        pixelToDip(c, size.y)), Toast.LENGTH_SHORT).show();
+                    }, "card height", true, mGetParentHeight)
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withTitle("double line with no primary action and one divider")
+                    .withBody("one line text as primary", true)
+                    .withActions("screen size", false, (v) -> {
+                        Context c = v.getContext();
+                        Point size = new Point();
+                        c.getSystemService(WindowManager.class).getDefaultDisplay().getSize(size);
+
+                        Toast.makeText(v.getContext(),
+                                String.format("%s x %s dp", pixelToDip(c, size.x),
+                                        pixelToDip(c, size.y)), Toast.LENGTH_SHORT).show();
+                    }, "card height", true, mGetParentHeight)
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true)
+                    .withBody("Only body - no title is set")
+                    .withAction("card height", true, mGetParentHeight)
+                    .build());
+
+            mItems.add(new ListItem.Builder(mContext)
+                    .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                    .withBody("Only body - no title. " + mContext.getString(R.string.long_text))
+                    .build());
+
+            mListProvider = new ListItemProvider.ListProvider(mItems);
+        }
+
+        @Override
+        public ListItem get(int position) {
+            return mListProvider.get(position);
+        }
+
+        @Override
+        public int size() {
+            return mListProvider.size();
+        }
+    }
+}
diff --git a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/PagedListViewActivity.java b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/PagedListViewActivity.java
new file mode 100644
index 0000000..2aa4e0c
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/PagedListViewActivity.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.androidx.car;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.car.widget.PagedListView;
+
+/**
+ * Demo activity for PagedListView.
+ */
+public class PagedListViewActivity extends Activity {
+
+    private static final int ITEM_COUNT = 80;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_paged_list_view);
+
+        PagedListView pagedListView = findViewById(R.id.paged_list_view);
+        pagedListView.setAdapter(new DemoAdapter(ITEM_COUNT));
+
+        getActionBar().setDisplayHomeAsUpEnabled(true);
+    }
+
+    /**
+     * Adapter that populates a number of items for demo purposes.
+     */
+    public static class DemoAdapter extends RecyclerView.Adapter<DemoAdapter.ViewHolder> {
+
+        private final List<String> mItems = new ArrayList<>();
+
+        /**
+         * Generates a string for item text.
+         */
+        public static String getItemText(int index) {
+            return "Item " + index;
+        }
+
+
+        public DemoAdapter(int itemCount) {
+            for (int i = 0; i < itemCount; i++) {
+                mItems.add(getItemText(i));
+            }
+        }
+
+        @Override
+        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+            View view = inflater.inflate(R.layout.paged_list_item, parent, false);
+            return new ViewHolder(view);
+        }
+
+        @Override
+        public void onBindViewHolder(ViewHolder holder, int position) {
+            holder.mTextView.setText(mItems.get(position));
+        }
+
+        @Override
+        public int getItemCount() {
+            return mItems.size();
+        }
+
+        /**
+         * ViewHolder for DemoAdapter.
+         */
+        public static class ViewHolder extends RecyclerView.ViewHolder {
+            private TextView mTextView;
+
+            public ViewHolder(View itemView) {
+                super(itemView);
+                mTextView = itemView.findViewById(R.id.text);
+            }
+        }
+    }
+}
+
diff --git a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/SupportCarDemoActivity.java b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/SupportCarDemoActivity.java
new file mode 100644
index 0000000..049c5c6
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/SupportCarDemoActivity.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.androidx.car;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Home activity for car support library samples.
+ */
+public class SupportCarDemoActivity extends ListActivity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setListAdapter(new SampleAdapter(querySampleActivities()));
+    }
+
+    @Override
+    protected void onListItemClick(ListView lv, View v, int pos, long id) {
+        SampleInfo info = (SampleInfo) getListAdapter().getItem(pos);
+        startActivity(info.mIntent);
+    }
+
+    protected List<SampleInfo> querySampleActivities() {
+        Intent intent = new Intent(Intent.ACTION_MAIN, null);
+        intent.setPackage(getPackageName());
+        intent.addCategory(Intent.CATEGORY_SAMPLE_CODE);
+
+        PackageManager pm = getPackageManager();
+        List<ResolveInfo> infos = pm.queryIntentActivities(intent, 0);
+
+        ArrayList<SampleInfo> samples = new ArrayList<>();
+
+        final int count = infos.size();
+        for (int i = 0; i < count; i++) {
+            final ResolveInfo info = infos.get(i);
+            final CharSequence labelSeq = info.loadLabel(pm);
+            String label = TextUtils.isEmpty(labelSeq)
+                    ? info.activityInfo.name
+                    : labelSeq.toString();
+
+            Intent target = new Intent();
+            target.setClassName(info.activityInfo.applicationInfo.packageName,
+                    info.activityInfo.name);
+            SampleInfo sample = new SampleInfo(label, target);
+            samples.add(sample);
+        }
+
+        return samples;
+    }
+
+    static class SampleInfo {
+        String mName;
+        Intent mIntent;
+
+        SampleInfo(String name, Intent intent) {
+            this.mName = name;
+            this.mIntent = intent;
+        }
+    }
+
+    class SampleAdapter extends BaseAdapter {
+        private List<SampleInfo> mItems;
+
+        SampleAdapter(List<SampleInfo> items) {
+            mItems = items;
+        }
+
+        @Override
+        public int getCount() {
+            return mItems.size();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return mItems.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = getLayoutInflater().inflate(android.R.layout.simple_list_item_1,
+                        parent, false);
+                convertView.setTag(convertView.findViewById(android.R.id.text1));
+            }
+            TextView tv = (TextView) convertView.getTag();
+            tv.setText(mItems.get(position).mName);
+            return convertView;
+        }
+
+    }
+}
diff --git a/samples/SupportCarDemos/src/main/res/drawable/app_sample_code.png b/samples/SupportCarDemos/src/main/res/drawable/app_sample_code.png
new file mode 100755
index 0000000..66a1984
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/drawable/app_sample_code.png
Binary files differ
diff --git a/samples/SupportCarDemos/src/main/res/drawable/pressed_icon.xml b/samples/SupportCarDemos/src/main/res/drawable/pressed_icon.xml
new file mode 100644
index 0000000..32a497f
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/drawable/pressed_icon.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:drawable="@android:drawable/btn_star_big_on"/>
+    <item android:drawable="@android:drawable/btn_star_big_off"/>
+</selector>
diff --git a/samples/SupportCarDemos/src/main/res/layout/activity_paged_list_view.xml b/samples/SupportCarDemos/src/main/res/layout/activity_paged_list_view.xml
new file mode 100644
index 0000000..5b9a1a5
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/layout/activity_paged_list_view.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <androidx.car.widget.PagedListView
+        android:id="@+id/paged_list_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:showPagedListViewDivider="true"
+        app:offsetScrollBar="true"/>
+</FrameLayout>
+
diff --git a/samples/SupportCarDemos/src/main/res/layout/paged_list_item.xml b/samples/SupportCarDemos/src/main/res/layout/paged_list_item.xml
new file mode 100644
index 0000000..26f9c5a
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/layout/paged_list_item.xml
@@ -0,0 +1,30 @@
+<?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.
+  -->
+<androidx.car.widget.ColumnCardView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="0dp"
+    android:layout_height="wrap_content"
+    app:cardBackgroundColor="@color/car_card">
+    <TextView
+        android:id="@+id/text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:textAppearance="@style/CarBody1"/>
+</androidx.car.widget.ColumnCardView>
\ No newline at end of file
diff --git a/samples/SupportCarDemos/src/main/res/values/strings.xml b/samples/SupportCarDemos/src/main/res/values/strings.xml
new file mode 100644
index 0000000..adffe89
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="activity_sample_code">Support Car Demos</string>
+    <string name="long_text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</string>
+</resources>
+
diff --git a/samples/SupportCarDemos/src/main/res/values/themes.xml b/samples/SupportCarDemos/src/main/res/values/themes.xml
new file mode 100644
index 0000000..4b82ecd
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/values/themes.xml
@@ -0,0 +1,31 @@
+<?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">
+    <!-- The main theme for all activities within the Car Demo. -->
+    <style name="CarTheme" parent="android:Theme.Material.Light">
+        <item name="android:windowBackground">@color/car_grey_50</item>
+        <item name="android:colorAccent">@color/car_yellow_500</item>
+        <item name="android:colorPrimary">@color/car_highlight</item>
+        <item name="android:colorPrimaryDark">@color/car_grey_300</item>
+        <item name="android:buttonStyle">@style/CarButton</item>
+        <item name="android:borderlessButtonStyle">@style/CarButton.Borderless</item>
+        <item name="android:progressBarStyleHorizontal">
+            @style/CarProgressBar.Horizontal
+        </item>
+        <item name="android:windowLightStatusBar">true</item>
+    </style>
+</resources>
diff --git a/samples/SupportContentDemos/build.gradle b/samples/SupportContentDemos/build.gradle
index 1ed1134..898774c 100644
--- a/samples/SupportContentDemos/build.gradle
+++ b/samples/SupportContentDemos/build.gradle
@@ -17,9 +17,9 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':design')
-    implementation project(':appcompat-v7')
-    implementation project(':support-content')
+    implementation(project(":design"))
+    implementation(project(":appcompat-v7"))
+    implementation(project(":support-content"))
 }
 
 android {
diff --git a/samples/SupportDesignDemos/build.gradle b/samples/SupportDesignDemos/build.gradle
index 7abaa0e..ed111f3 100644
--- a/samples/SupportDesignDemos/build.gradle
+++ b/samples/SupportDesignDemos/build.gradle
@@ -1,7 +1,7 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':design')
+    implementation(project(":design"))
 }
 
 android {
diff --git a/samples/SupportDesignDemos/src/main/res/layout/design_fab.xml b/samples/SupportDesignDemos/src/main/res/layout/design_fab.xml
index ad26d5b..f00dd96 100644
--- a/samples/SupportDesignDemos/src/main/res/layout/design_fab.xml
+++ b/samples/SupportDesignDemos/src/main/res/layout/design_fab.xml
@@ -66,6 +66,21 @@
                 android:clickable="true"
                 app:fabSize="mini" />
 
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_margin="16dp"
+            android:textAppearance="@style/TextAppearance.AppCompat.Title"
+            android:text="@string/fab_size_custom" />
+
+        <android.support.design.widget.FloatingActionButton
+            android:id="@+id/custom_fab"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_margin="16dp"
+            android:src="@drawable/ic_add"
+            android:clickable="true"
+            app:fabCustomSize="@dimen/custom_fab_size" />
     </LinearLayout>
 
 </FrameLayout>
\ No newline at end of file
diff --git a/samples/SupportDesignDemos/src/main/res/values/dimens.xml b/samples/SupportDesignDemos/src/main/res/values/dimens.xml
index c8a5ea9..68e4775 100644
--- a/samples/SupportDesignDemos/src/main/res/values/dimens.xml
+++ b/samples/SupportDesignDemos/src/main/res/values/dimens.xml
@@ -20,4 +20,6 @@
     <dimen name="bottom_sheet_peek_height">128dp</dimen>
 
     <dimen name="custom_snackbar_max_width">-1px</dimen>
+
+    <dimen name="custom_fab_size">45dp</dimen>
 </resources>
diff --git a/samples/SupportDesignDemos/src/main/res/values/strings.xml b/samples/SupportDesignDemos/src/main/res/values/strings.xml
index 6ebe24c..e1818af 100644
--- a/samples/SupportDesignDemos/src/main/res/values/strings.xml
+++ b/samples/SupportDesignDemos/src/main/res/values/strings.xml
@@ -37,6 +37,7 @@
 
     <string name="fab_size_normal">Normal size</string>
     <string name="fab_size_mini">Mini size</string>
+    <string name="fab_size_custom">Custom size</string>
 
     <string name="navigation_open">Open</string>
     <string name="navigation_close">Close</string>
diff --git a/samples/SupportEmojiDemos/build.gradle b/samples/SupportEmojiDemos/build.gradle
index abc8328..dea5bf4 100644
--- a/samples/SupportEmojiDemos/build.gradle
+++ b/samples/SupportEmojiDemos/build.gradle
@@ -21,9 +21,9 @@
 }
 
 dependencies {
-    implementation project(':support-emoji')
-    implementation project(':support-emoji-bundled')
-    implementation project(':support-emoji-appcompat')
+    implementation(project(":support-emoji"))
+    implementation(project(":support-emoji-bundled"))
+    implementation(project(":support-emoji-appcompat"))
 }
 
 android {
diff --git a/samples/SupportLeanbackDemos/build.gradle b/samples/SupportLeanbackDemos/build.gradle
index 61d0209..a00d435 100644
--- a/samples/SupportLeanbackDemos/build.gradle
+++ b/samples/SupportLeanbackDemos/build.gradle
@@ -1,8 +1,8 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':leanback-v17')
-    implementation project(':preference-leanback-v17')
+    implementation(project(":leanback-v17"))
+    implementation(project(":preference-leanback-v17"))
     implementation 'com.google.code.gson:gson:2.6.2'
 }
 
diff --git a/samples/SupportLeanbackJank/build.gradle b/samples/SupportLeanbackJank/build.gradle
index eef9986..3ba2d64 100644
--- a/samples/SupportLeanbackJank/build.gradle
+++ b/samples/SupportLeanbackJank/build.gradle
@@ -2,8 +2,8 @@
 
 dependencies {
     implementation 'com.github.bumptech.glide:glide:3.6.1'
-    implementation project(':leanback-v17')
-    implementation project(':preference-leanback-v17')
+    implementation(project(":leanback-v17"))
+    implementation(project(":preference-leanback-v17"))
 }
 
 android {
diff --git a/samples/SupportPercentDemos/build.gradle b/samples/SupportPercentDemos/build.gradle
index cec4b03..353e034 100644
--- a/samples/SupportPercentDemos/build.gradle
+++ b/samples/SupportPercentDemos/build.gradle
@@ -1,7 +1,7 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':percent')
+    implementation(project(":percent"))
 }
 
 android {
diff --git a/samples/SupportPreferenceDemos/build.gradle b/samples/SupportPreferenceDemos/build.gradle
index f720b92..742ceb7 100644
--- a/samples/SupportPreferenceDemos/build.gradle
+++ b/samples/SupportPreferenceDemos/build.gradle
@@ -1,12 +1,12 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':appcompat-v7')
-    implementation project(':recyclerview-v7')
-    implementation project(':preference-v7')
-    implementation project(':preference-v14')
-    implementation project(':leanback-v17')
-    implementation project(':preference-leanback-v17')
+    implementation(project(":appcompat-v7"))
+    implementation(project(":recyclerview-v7"))
+    implementation(project(":preference-v7"))
+    implementation(project(":preference-v14"))
+    implementation(project(":leanback-v17"))
+    implementation(project(":preference-leanback-v17"))
 }
 
 android {
diff --git a/samples/SupportTransitionDemos/build.gradle b/samples/SupportTransitionDemos/build.gradle
index 8719221..47c84ad 100644
--- a/samples/SupportTransitionDemos/build.gradle
+++ b/samples/SupportTransitionDemos/build.gradle
@@ -1,8 +1,8 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':transition')
-    implementation project(':appcompat-v7')
+    implementation(project(":transition"))
+    implementation(project(":appcompat-v7"))
 }
 
 android {
diff --git a/samples/SupportVectorDrawableDemos/build.gradle b/samples/SupportVectorDrawableDemos/build.gradle
index e9c9d2c..09bb2d5 100644
--- a/samples/SupportVectorDrawableDemos/build.gradle
+++ b/samples/SupportVectorDrawableDemos/build.gradle
@@ -17,9 +17,9 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':support-vector-drawable')
-    implementation project(':animated-vector-drawable')
-    implementation project(':appcompat-v7')
+    implementation(project(":support-vector-drawable"))
+    implementation(project(":animated-vector-drawable"))
+    implementation(project(":appcompat-v7"))
 }
 
 android {
diff --git a/samples/SupportWearDemos/build.gradle b/samples/SupportWearDemos/build.gradle
index ae0f195..96da969 100644
--- a/samples/SupportWearDemos/build.gradle
+++ b/samples/SupportWearDemos/build.gradle
@@ -17,7 +17,7 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    implementation project(':wear')
+    implementation(project(":wear"))
     implementation project(path: ':appcompat-v7')
 }
 
diff --git a/samples/SupportWearDemos/src/main/java/com/example/android/support/wear/app/AlertDialogDemo.java b/samples/SupportWearDemos/src/main/java/com/example/android/support/wear/app/AlertDialogDemo.java
index 4ea448a..35a32ce 100644
--- a/samples/SupportWearDemos/src/main/java/com/example/android/support/wear/app/AlertDialogDemo.java
+++ b/samples/SupportWearDemos/src/main/java/com/example/android/support/wear/app/AlertDialogDemo.java
@@ -17,6 +17,7 @@
 package com.example.android.support.wear.app;
 
 import android.app.Activity;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.v7.app.AlertDialog;
@@ -55,10 +56,12 @@
     }
 
     private AlertDialog createV7Dialog() {
+        Drawable drawable = getDrawable(R.drawable.app_sample_code);
         return new AlertDialog.Builder(this)
                 .setTitle("AppCompatDialog")
                 .setMessage("Lorem ipsum dolor...")
                 .setPositiveButton("Ok", null)
+                .setPositiveButtonIcon(drawable)
                 .setNegativeButton("Cancel", null)
                 .create();
     }
diff --git a/samples/SupportWearDemos/src/main/res/layout/alert_dialog_demo.xml b/samples/SupportWearDemos/src/main/res/layout/alert_dialog_demo.xml
index 833d489..5df4f4c 100644
--- a/samples/SupportWearDemos/src/main/res/layout/alert_dialog_demo.xml
+++ b/samples/SupportWearDemos/src/main/res/layout/alert_dialog_demo.xml
@@ -41,4 +41,4 @@
             android:text="Show Framework dialog"/>
     </LinearLayout>
 
-</android.support.wear.widget.BoxInsetLayout>
\ No newline at end of file
+</android.support.wear.widget.BoxInsetLayout>
diff --git a/settings.gradle b/settings.gradle
index 0544c91..1eccbcf 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -165,6 +165,8 @@
 include ':support-emoji-demos'
 project(':support-emoji-demos').projectDir = new File(samplesRoot, 'SupportEmojiDemos')
 
+include ':support-car-demos'
+project(':support-car-demos').projectDir = new File(samplesRoot, 'SupportCarDemos')
 /////////////////////////////
 //
 // Testing libraries
diff --git a/testutils/build.gradle b/testutils/build.gradle
index 6ecc012..074ab34 100644
--- a/testutils/build.gradle
+++ b/testutils/build.gradle
@@ -14,19 +14,21 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
+
 plugins {
     id("SupportAndroidLibraryPlugin")
 }
 
 dependencies {
-    api project(':support-fragment')
-    api project(':appcompat-v7')
+    api(project(":support-fragment"))
+    api(project(":appcompat-v7"))
 
-    compile libs.test_runner,      { exclude module: 'support-annotations' }
-    compile libs.espresso_core,    { exclude module: 'support-annotations' }
-    compile libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has its own MockMaker
-    compile libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has its own MockMaker
-    compile libs.junit
+    implementation(TEST_RUNNER)
+    implementation(ESPRESSO_CORE)
+    implementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    implementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    implementation(JUNIT)
 }
 
 android {
diff --git a/testutils/lint-baseline.xml b/testutils/lint-baseline.xml
deleted file mode 100644
index f50cc2a..0000000
--- a/testutils/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-beta2">
-
-</issues>
diff --git a/transition/api/current.txt b/transition/api/current.txt
index 805fcfc..b939299 100644
--- a/transition/api/current.txt
+++ b/transition/api/current.txt
@@ -118,7 +118,7 @@
     method public void setSlideEdge(int);
   }
 
-  public abstract class Transition {
+  public abstract class Transition implements java.lang.Cloneable {
     ctor public Transition();
     ctor public Transition(android.content.Context, android.util.AttributeSet);
     method public android.support.transition.Transition addListener(android.support.transition.Transition.TransitionListener);
diff --git a/transition/build.gradle b/transition/build.gradle
index cd2c237..dcf3a76 100644
--- a/transition/build.gradle
+++ b/transition/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,16 +7,16 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-compat')
+    api(project(":support-annotations"))
+    api(project(":support-compat"))
     compileOnly project(':support-fragment')
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation project(':support-v4')
-    androidTestImplementation project(':appcompat-v7')
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(project(":support-v4"))
+    androidTestImplementation(project(":appcompat-v7"))
 }
 
 android {
diff --git a/transition/lint-baseline.xml b/transition/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/transition/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/transition/src/main/java/android/support/transition/package.html b/transition/src/main/java/android/support/transition/package.html
index b09005f..d8394a5 100644
--- a/transition/src/main/java/android/support/transition/package.html
+++ b/transition/src/main/java/android/support/transition/package.html
@@ -1,6 +1,6 @@
 <body>
 
-Support android.transition classes to provide transition API back to android API level 14.
+Support android.transition classes to provide transition API back to Android API level 14.
 This library contains {@link android.support.transition.Transition},
 {@link android.support.transition.TransitionManager}, and other related classes
 back-ported from their platform versions introduced Android API level 19.
diff --git a/tv-provider/api/27.0.0.ignore b/tv-provider/api/27.0.0.ignore
new file mode 100644
index 0000000..3bd938a
--- /dev/null
+++ b/tv-provider/api/27.0.0.ignore
@@ -0,0 +1,7 @@
+122b8cc
+7a7f371
+906efec
+355dc8b
+1490eba
+e3d27cc
+cd7673a
diff --git a/tv-provider/api/current.txt b/tv-provider/api/current.txt
index 80421e9..ef10221 100644
--- a/tv-provider/api/current.txt
+++ b/tv-provider/api/current.txt
@@ -74,12 +74,10 @@
   }
 
   public final class PreviewProgram {
-    method public boolean equals(java.lang.Object);
     method public static android.support.media.tv.PreviewProgram fromCursor(android.database.Cursor);
     method public long getChannelId();
     method public int getWeight();
     method public android.content.ContentValues toContentValues();
-    method public java.lang.String toString();
   }
 
   public static final class PreviewProgram.Builder {
@@ -92,16 +90,13 @@
 
   public final class Program implements java.lang.Comparable {
     method public int compareTo(android.support.media.tv.Program);
-    method public boolean equals(java.lang.Object);
     method public static android.support.media.tv.Program fromCursor(android.database.Cursor);
     method public java.lang.String[] getBroadcastGenres();
     method public long getChannelId();
     method public long getEndTimeUtcMillis();
     method public long getStartTimeUtcMillis();
-    method public int hashCode();
     method public boolean isRecordingProhibited();
     method public android.content.ContentValues toContentValues();
-    method public java.lang.String toString();
   }
 
   public static class Program.Builder {
@@ -149,7 +144,7 @@
     field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
   }
 
-  public static abstract interface TvContractCompat.BaseTvColumns {
+  public static abstract interface TvContractCompat.BaseTvColumns implements android.provider.BaseColumns {
     field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
   }
 
@@ -525,12 +520,10 @@
   }
 
   public final class WatchNextProgram {
-    method public boolean equals(java.lang.Object);
     method public static android.support.media.tv.WatchNextProgram fromCursor(android.database.Cursor);
     method public long getLastEngagementTimeUtcMillis();
     method public int getWatchNextType();
     method public android.content.ContentValues toContentValues();
-    method public java.lang.String toString();
     field public static final int WATCH_NEXT_TYPE_UNKNOWN = -1; // 0xffffffff
   }
 
diff --git a/tv-provider/build.gradle b/tv-provider/build.gradle
index 60c2b2e..7090108 100644
--- a/tv-provider/build.gradle
+++ b/tv-provider/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,10 +7,10 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-compat')
+    api(project(":support-annotations"))
+    api(project(":support-compat"))
 
-    androidTestImplementation libs.test_runner, { exclude module: 'support-annotations' }
+    androidTestImplementation(TEST_RUNNER)
 }
 
 android {
diff --git a/v13/api/current.txt b/v13/api/current.txt
index 73871f6..1d9fdbf 100644
--- a/v13/api/current.txt
+++ b/v13/api/current.txt
@@ -5,44 +5,63 @@
     method public static android.support.v13.view.DragAndDropPermissionsCompat requestDragAndDropPermissions(android.app.Activity, android.view.DragEvent);
   }
 
-  public class FragmentCompat {
-    ctor public FragmentCompat();
-    method public static void requestPermissions(android.app.Fragment, java.lang.String[], int);
+  public deprecated class FragmentCompat {
+    ctor public deprecated FragmentCompat();
+    method public static deprecated void requestPermissions(android.app.Fragment, java.lang.String[], int);
     method public static deprecated void setMenuVisibility(android.app.Fragment, boolean);
-    method public static void setPermissionCompatDelegate(android.support.v13.app.FragmentCompat.PermissionCompatDelegate);
-    method public static void setUserVisibleHint(android.app.Fragment, boolean);
-    method public static boolean shouldShowRequestPermissionRationale(android.app.Fragment, java.lang.String);
+    method public static deprecated void setPermissionCompatDelegate(android.support.v13.app.FragmentCompat.PermissionCompatDelegate);
+    method public static deprecated void setUserVisibleHint(android.app.Fragment, boolean);
+    method public static deprecated boolean shouldShowRequestPermissionRationale(android.app.Fragment, java.lang.String);
   }
 
-  public static abstract interface FragmentCompat.OnRequestPermissionsResultCallback {
-    method public abstract void onRequestPermissionsResult(int, java.lang.String[], int[]);
+  public static abstract deprecated interface FragmentCompat.OnRequestPermissionsResultCallback {
+    method public abstract deprecated void onRequestPermissionsResult(int, java.lang.String[], int[]);
   }
 
-  public static abstract interface FragmentCompat.PermissionCompatDelegate {
-    method public abstract boolean requestPermissions(android.app.Fragment, java.lang.String[], int);
+  public static abstract deprecated interface FragmentCompat.PermissionCompatDelegate {
+    method public abstract deprecated boolean requestPermissions(android.app.Fragment, java.lang.String[], int);
   }
 
-  public abstract class FragmentPagerAdapter extends android.support.v4.view.PagerAdapter {
-    ctor public FragmentPagerAdapter(android.app.FragmentManager);
-    method public abstract android.app.Fragment getItem(int);
-    method public long getItemId(int);
-    method public boolean isViewFromObject(android.view.View, java.lang.Object);
+  public abstract deprecated class FragmentPagerAdapter extends android.support.v4.view.PagerAdapter {
+    ctor public deprecated FragmentPagerAdapter(android.app.FragmentManager);
+    method public deprecated void destroyItem(android.view.ViewGroup, int, java.lang.Object);
+    method public deprecated void finishUpdate(android.view.ViewGroup);
+    method public abstract deprecated android.app.Fragment getItem(int);
+    method public deprecated long getItemId(int);
+    method public deprecated java.lang.Object instantiateItem(android.view.ViewGroup, int);
+    method public deprecated boolean isViewFromObject(android.view.View, java.lang.Object);
+    method public deprecated void restoreState(android.os.Parcelable, java.lang.ClassLoader);
+    method public deprecated android.os.Parcelable saveState();
+    method public deprecated void setPrimaryItem(android.view.ViewGroup, int, java.lang.Object);
+    method public deprecated void startUpdate(android.view.ViewGroup);
   }
 
-  public abstract class FragmentStatePagerAdapter extends android.support.v4.view.PagerAdapter {
-    ctor public FragmentStatePagerAdapter(android.app.FragmentManager);
-    method public abstract android.app.Fragment getItem(int);
-    method public boolean isViewFromObject(android.view.View, java.lang.Object);
+  public abstract deprecated class FragmentStatePagerAdapter extends android.support.v4.view.PagerAdapter {
+    ctor public deprecated FragmentStatePagerAdapter(android.app.FragmentManager);
+    method public deprecated void destroyItem(android.view.ViewGroup, int, java.lang.Object);
+    method public deprecated void finishUpdate(android.view.ViewGroup);
+    method public abstract deprecated android.app.Fragment getItem(int);
+    method public deprecated java.lang.Object instantiateItem(android.view.ViewGroup, int);
+    method public deprecated boolean isViewFromObject(android.view.View, java.lang.Object);
+    method public deprecated void restoreState(android.os.Parcelable, java.lang.ClassLoader);
+    method public deprecated android.os.Parcelable saveState();
+    method public deprecated void setPrimaryItem(android.view.ViewGroup, int, java.lang.Object);
+    method public deprecated void startUpdate(android.view.ViewGroup);
   }
 
-  public class FragmentTabHost extends android.widget.TabHost implements android.widget.TabHost.OnTabChangeListener {
-    ctor public FragmentTabHost(android.content.Context);
-    ctor public FragmentTabHost(android.content.Context, android.util.AttributeSet);
-    method public void addTab(android.widget.TabHost.TabSpec, java.lang.Class<?>, android.os.Bundle);
-    method public void onTabChanged(java.lang.String);
+  public deprecated class FragmentTabHost extends android.widget.TabHost implements android.widget.TabHost.OnTabChangeListener {
+    ctor public deprecated FragmentTabHost(android.content.Context);
+    ctor public deprecated FragmentTabHost(android.content.Context, android.util.AttributeSet);
+    method public deprecated void addTab(android.widget.TabHost.TabSpec, java.lang.Class<?>, android.os.Bundle);
+    method protected deprecated void onAttachedToWindow();
+    method protected deprecated void onDetachedFromWindow();
+    method protected deprecated void onRestoreInstanceState(android.os.Parcelable);
+    method protected deprecated android.os.Parcelable onSaveInstanceState();
+    method public deprecated void onTabChanged(java.lang.String);
+    method public deprecated void setOnTabChangedListener(android.widget.TabHost.OnTabChangeListener);
     method public deprecated void setup();
-    method public void setup(android.content.Context, android.app.FragmentManager);
-    method public void setup(android.content.Context, android.app.FragmentManager, int);
+    method public deprecated void setup(android.content.Context, android.app.FragmentManager);
+    method public deprecated void setup(android.content.Context, android.app.FragmentManager, int);
   }
 
 }
diff --git a/v13/build.gradle b/v13/build.gradle
index bd01c55..425a31f 100644
--- a/v13/build.gradle
+++ b/v13/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,13 +7,13 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-v4')
+    api(project(":support-annotations"))
+    api(project(":support-v4"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
 }
 
 android {
diff --git a/v13/java/android/support/v13/app/FragmentCompat.java b/v13/java/android/support/v13/app/FragmentCompat.java
index 31c2343..e8915fb 100644
--- a/v13/java/android/support/v13/app/FragmentCompat.java
+++ b/v13/java/android/support/v13/app/FragmentCompat.java
@@ -30,8 +30,19 @@
 
 /**
  * Helper for accessing features in {@link Fragment} in a backwards compatible fashion.
+ *
+ * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework fragment.
  */
+@Deprecated
 public class FragmentCompat {
+
+    /**
+     * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework fragment.
+     */
+    @Deprecated
+    public FragmentCompat() {
+    }
+
     interface FragmentCompatImpl {
         void setUserVisibleHint(Fragment f, boolean deferStart);
         void requestPermissions(Fragment fragment, String[] permissions, int requestCode);
@@ -48,7 +59,11 @@
      *     to the compatibility methods in this class will first check whether the delegate can
      *     handle the method call, and invoke the corresponding method if it can.
      * </p>
+     *
+     * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework
+     * {@link Fragment}.
      */
+    @Deprecated
     public interface PermissionCompatDelegate {
 
         /**
@@ -66,7 +81,11 @@
          *
          * @return Whether the delegate has handled the permission request.
          * @see FragmentCompat#requestPermissions(Fragment, String[], int)
+         *
+         * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework
+         * {@link Fragment}.
          */
+        @Deprecated
         boolean requestPermissions(Fragment fragment, String[] permissions, int requestCode);
     }
 
@@ -157,22 +176,34 @@
      * delegate.
      *
      * @param delegate The delegate to be set. {@code null} to clear the set delegate.
+     *
+     * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework
+     * {@link Fragment}.
      */
+    @Deprecated
     public static void setPermissionCompatDelegate(PermissionCompatDelegate delegate) {
         sDelegate = delegate;
     }
 
     /**
      * @hide
+     *
+     * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework
+     * {@link Fragment}.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    @Deprecated
     public static PermissionCompatDelegate getPermissionCompatDelegate() {
         return sDelegate;
     }
 
     /**
      * This interface is the contract for receiving the results for permission requests.
+     *
+     * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework
+     * {@link Fragment}.
      */
+    @Deprecated
     public interface OnRequestPermissionsResultCallback {
 
         /**
@@ -188,7 +219,11 @@
          *     or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null.
          *
          * @see #requestPermissions(android.app.Fragment, String[], int)
+         *
+         * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework
+         * {@link Fragment}.
          */
+        @Deprecated
         public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                 @NonNull int[] grantResults);
     }
@@ -197,7 +232,8 @@
      * Call {@link Fragment#setMenuVisibility(boolean) Fragment.setMenuVisibility(boolean)}
      * if running on an appropriate version of the platform.
      *
-     * @deprecated Use {@link Fragment#setMenuVisibility(boolean)} directly.
+     * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework
+     * {@link Fragment}.
      */
     @Deprecated
     public static void setMenuVisibility(Fragment f, boolean visible) {
@@ -207,7 +243,11 @@
     /**
      * Call {@link Fragment#setUserVisibleHint(boolean) setUserVisibleHint(boolean)}
      * if running on an appropriate version of the platform.
+     *
+     * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework
+     * {@link Fragment}.
      */
+    @Deprecated
     public static void setUserVisibleHint(Fragment f, boolean deferStart) {
         IMPL.setUserVisibleHint(f, deferStart);
     }
@@ -262,7 +302,11 @@
      * @see android.support.v4.content.ContextCompat#checkSelfPermission(
      *     android.content.Context, String)
      * @see #shouldShowRequestPermissionRationale(android.app.Fragment, String)
+     *
+     * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework
+     * {@link Fragment}.
      */
+    @Deprecated
     public static void requestPermissions(@NonNull Fragment fragment,
             @NonNull String[] permissions, int requestCode) {
         if (sDelegate != null && sDelegate.requestPermissions(fragment, permissions, requestCode)) {
@@ -293,7 +337,11 @@
      * @see android.support.v4.content.ContextCompat#checkSelfPermission(
      *     android.content.Context, String)
      * @see #requestPermissions(android.app.Fragment, String[], int)
+     *
+     * @deprecated Use {@link android.support.v4.app.Fragment} instead of the framework
+     * {@link Fragment}.
      */
+    @Deprecated
     public static boolean shouldShowRequestPermissionRationale(@NonNull Fragment fragment,
             @NonNull String permission) {
         return IMPL.shouldShowRequestPermissionRationale(fragment, permission);
diff --git a/v13/java/android/support/v13/app/FragmentPagerAdapter.java b/v13/java/android/support/v13/app/FragmentPagerAdapter.java
index e0b788a..112ed02 100644
--- a/v13/java/android/support/v13/app/FragmentPagerAdapter.java
+++ b/v13/java/android/support/v13/app/FragmentPagerAdapter.java
@@ -61,7 +61,10 @@
  *
  * {@sample frameworks/support/samples/Support13Demos/src/main/res/layout/fragment_pager_list.xml
  *      complete}
+ *
+ * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
  */
+@Deprecated
 public abstract class FragmentPagerAdapter extends PagerAdapter {
     private static final String TAG = "FragmentPagerAdapter";
     private static final boolean DEBUG = false;
@@ -70,15 +73,26 @@
     private FragmentTransaction mCurTransaction = null;
     private Fragment mCurrentPrimaryItem = null;
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
+     */
+    @Deprecated
     public FragmentPagerAdapter(FragmentManager fm) {
         mFragmentManager = fm;
     }
 
     /**
      * Return the Fragment associated with a specified position.
+     *
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
      */
+    @Deprecated
     public abstract Fragment getItem(int position);
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public void startUpdate(ViewGroup container) {
         if (container.getId() == View.NO_ID) {
@@ -87,6 +101,10 @@
         }
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
+     */
+    @Deprecated
     @SuppressWarnings("ReferenceEquality")
     @Override
     public Object instantiateItem(ViewGroup container, int position) {
@@ -116,6 +134,10 @@
         return fragment;
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public void destroyItem(ViewGroup container, int position, Object object) {
         if (mCurTransaction == null) {
@@ -126,6 +148,10 @@
         mCurTransaction.detach((Fragment)object);
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
+     */
+    @Deprecated
     @SuppressWarnings("ReferenceEquality")
     @Override
     public void setPrimaryItem(ViewGroup container, int position, Object object) {
@@ -143,6 +169,10 @@
         }
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public void finishUpdate(ViewGroup container) {
         if (mCurTransaction != null) {
@@ -152,16 +182,28 @@
         }
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public boolean isViewFromObject(View view, Object object) {
         return ((Fragment)object).getView() == view;
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public Parcelable saveState() {
         return null;
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public void restoreState(Parcelable state, ClassLoader loader) {
     }
@@ -174,7 +216,10 @@
      *
      * @param position Position within this adapter
      * @return Unique identifier for the item at position
+     *
+     * @deprecated Use {@link android.support.v4.app.FragmentPagerAdapter} instead.
      */
+    @Deprecated
     public long getItemId(int position) {
         return position;
     }
diff --git a/v13/java/android/support/v13/app/FragmentStatePagerAdapter.java b/v13/java/android/support/v13/app/FragmentStatePagerAdapter.java
index 45a6bf5..76a3224 100644
--- a/v13/java/android/support/v13/app/FragmentStatePagerAdapter.java
+++ b/v13/java/android/support/v13/app/FragmentStatePagerAdapter.java
@@ -64,7 +64,10 @@
  *
  * {@sample frameworks/support/samples/Support4Demos/src/main/res/layout/fragment_pager_list.xml
  *      complete}
+ *
+ * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
  */
+@Deprecated
 public abstract class FragmentStatePagerAdapter extends PagerAdapter {
     private static final String TAG = "FragStatePagerAdapter";
     private static final boolean DEBUG = false;
@@ -76,15 +79,26 @@
     private ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
     private Fragment mCurrentPrimaryItem = null;
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
+     */
+    @Deprecated
     public FragmentStatePagerAdapter(FragmentManager fm) {
         mFragmentManager = fm;
     }
 
     /**
      * Return the Fragment associated with a specified position.
+     *
+     * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
      */
+    @Deprecated
     public abstract Fragment getItem(int position);
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public void startUpdate(ViewGroup container) {
         if (container.getId() == View.NO_ID) {
@@ -93,6 +107,10 @@
         }
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public Object instantiateItem(ViewGroup container, int position) {
         // If we already have this item instantiated, there is nothing
@@ -129,6 +147,10 @@
         return fragment;
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public void destroyItem(ViewGroup container, int position, Object object) {
         Fragment fragment = (Fragment) object;
@@ -148,6 +170,10 @@
         mCurTransaction.remove(fragment);
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
+     */
+    @Deprecated
     @SuppressWarnings("ReferenceEquality")
     @Override
     public void setPrimaryItem(ViewGroup container, int position, Object object) {
@@ -165,6 +191,10 @@
         }
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public void finishUpdate(ViewGroup container) {
         if (mCurTransaction != null) {
@@ -174,11 +204,19 @@
         }
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public boolean isViewFromObject(View view, Object object) {
         return ((Fragment)object).getView() == view;
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public Parcelable saveState() {
         Bundle state = null;
@@ -201,6 +239,10 @@
         return state;
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentStatePagerAdapter} instead.
+     */
+    @Deprecated
     @Override
     public void restoreState(Parcelable state, ClassLoader loader) {
         if (state != null) {
diff --git a/v13/java/android/support/v13/app/FragmentTabHost.java b/v13/java/android/support/v13/app/FragmentTabHost.java
index 2326ccb..5c34ab5 100644
--- a/v13/java/android/support/v13/app/FragmentTabHost.java
+++ b/v13/java/android/support/v13/app/FragmentTabHost.java
@@ -38,7 +38,10 @@
  * Version of {@link android.support.v4.app.FragmentTabHost} that can be
  * used with the platform {@link android.app.Fragment} APIs.  You will not
  * normally use this, instead using action bar tabs.
+ *
+ * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
  */
+@Deprecated
 public class FragmentTabHost extends TabHost implements TabHost.OnTabChangeListener {
     private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
     private FrameLayout mRealTabContent;
@@ -117,6 +120,10 @@
         };
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     public FragmentTabHost(Context context) {
         // Note that we call through to the version that takes an AttributeSet,
         // because the simple Context construct can result in a broken object!
@@ -124,6 +131,10 @@
         initFragmentTabHost(context, null);
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     public FragmentTabHost(Context context, AttributeSet attrs) {
         super(context, attrs);
         initFragmentTabHost(context, attrs);
@@ -167,9 +178,7 @@
     }
 
     /**
-     * @deprecated Don't call the original TabHost setup, you must instead
-     * call {@link #setup(Context, FragmentManager)} or
-     * {@link #setup(Context, FragmentManager, int)}.
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
      */
     @Override
     @Deprecated
@@ -178,6 +187,10 @@
                 "Must call setup() that takes a Context and FragmentManager");
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     public void setup(Context context, FragmentManager manager) {
         ensureHierarchy(context);  // Ensure views required by super.setup()
         super.setup();
@@ -186,6 +199,10 @@
         ensureContent();
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     public void setup(Context context, FragmentManager manager, int containerId) {
         ensureHierarchy(context);  // Ensure views required by super.setup()
         super.setup();
@@ -212,11 +229,19 @@
         }
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     @Override
     public void setOnTabChangedListener(OnTabChangeListener l) {
         mOnTabChangeListener = l;
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
         tabSpec.setContent(new DummyTabFactory(mContext));
         String tag = tabSpec.getTag();
@@ -239,6 +264,10 @@
         addTab(tabSpec);
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
@@ -278,12 +307,20 @@
         }
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         mAttached = false;
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     @Override
     protected Parcelable onSaveInstanceState() {
         Parcelable superState = super.onSaveInstanceState();
@@ -292,6 +329,10 @@
         return ss;
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     @Override
     protected void onRestoreInstanceState(Parcelable state) {
         if (!(state instanceof SavedState)) {
@@ -303,6 +344,10 @@
         setCurrentTabByTag(ss.curTab);
     }
 
+    /**
+     * @deprecated Use {@link android.support.v4.app.FragmentTabHost} instead.
+     */
+    @Deprecated
     @Override
     public void onTabChanged(String tabId) {
         if (mAttached) {
diff --git a/v13/java/android/support/v13/app/package.html b/v13/java/android/support/v13/app/package.html
deleted file mode 100755
index 3557ecb..0000000
--- a/v13/java/android/support/v13/app/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-Support classes to access some of the android.app package features introduced after API level 13 in a backwards compatible fashion.
-
-</body>
diff --git a/v13/lint-baseline.xml b/v13/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/v13/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/v14/preference/api/current.txt b/v14/preference/api/current.txt
index b92ccf9..af3db09 100644
--- a/v14/preference/api/current.txt
+++ b/v14/preference/api/current.txt
@@ -46,7 +46,7 @@
     field protected static final java.lang.String ARG_KEY = "key";
   }
 
-  public abstract class PreferenceFragment extends android.app.Fragment implements android.support.v7.preference.PreferenceManager.OnDisplayPreferenceDialogListener android.support.v7.preference.PreferenceManager.OnNavigateToScreenListener android.support.v7.preference.PreferenceManager.OnPreferenceTreeClickListener {
+  public abstract class PreferenceFragment extends android.app.Fragment implements android.support.v7.preference.DialogPreference.TargetFragment android.support.v7.preference.PreferenceManager.OnDisplayPreferenceDialogListener android.support.v7.preference.PreferenceManager.OnNavigateToScreenListener android.support.v7.preference.PreferenceManager.OnPreferenceTreeClickListener {
     ctor public PreferenceFragment();
     method public void addPreferencesFromResource(int);
     method public android.support.v7.preference.Preference findPreference(java.lang.CharSequence);
diff --git a/v14/preference/build.gradle b/v14/preference/build.gradle
index f68379a..c129cba 100644
--- a/v14/preference/build.gradle
+++ b/v14/preference/build.gradle
@@ -22,10 +22,10 @@
 }
 
 dependencies {
-    api project(':support-v4')
-    api project(':appcompat-v7')
-    api project(':recyclerview-v7')
-    api project(':preference-v7')
+    api(project(":support-v4"))
+    api(project(":appcompat-v7"))
+    api(project(":recyclerview-v7"))
+    api(project(":preference-v7"))
 }
 
 android {
diff --git a/v14/preference/res/layout-v17/preference_category_material.xml b/v14/preference/res/layout-v17/preference_category_material.xml
index 804da6a..db3abfe 100644
--- a/v14/preference/res/layout-v17/preference_category_material.xml
+++ b/v14/preference/res/layout-v17/preference_category_material.xml
@@ -15,49 +15,13 @@
   ~ limitations under the License
   -->
 
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/title"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginBottom="8dp"
-    android:layout_marginTop="8dp"
-    android:paddingStart="?android:attr/listPreferredItemPaddingStart">
-
-    <LinearLayout
-        android:id="@+id/icon_frame"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:gravity="start|center_vertical"
-        android:orientation="horizontal">
-        <android.support.v7.internal.widget.PreferenceImageView
-            android:id="@android:id/icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            app:maxHeight="18dp"
-            app:maxWidth="18dp"/>
-    </LinearLayout>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:paddingStart="56dp">
-        <TextView
-            android:id="@android:id/title"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="16dp"
-            android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-            android:textAlignment="viewStart"
-            android:textColor="@color/preference_fallback_accent_color"/>
-        <TextView
-            android:id="@android:id/summary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:singleLine="true"
-            android:textColor="?android:attr/textColorSecondary"/>
-    </LinearLayout>
-
-</FrameLayout>
+    android:layout_marginBottom="16dip"
+    android:textAppearance="@style/Preference_TextAppearanceMaterialBody2"
+    android:textColor="@color/preference_fallback_accent_color"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingTop="16dip" />
diff --git a/v14/preference/res/layout-v21/preference_category_material.xml b/v14/preference/res/layout-v21/preference_category_material.xml
index 1331268..dad9a5c 100644
--- a/v14/preference/res/layout-v21/preference_category_material.xml
+++ b/v14/preference/res/layout-v21/preference_category_material.xml
@@ -15,52 +15,13 @@
   ~ limitations under the License
   -->
 
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/title"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginBottom="8dp"
-    android:layout_marginTop="8dp"
-    android:paddingStart="?android:attr/listPreferredItemPaddingStart">
-
-    <LinearLayout
-        android:id="@+id/icon_frame"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:gravity="start|center_vertical"
-        android:orientation="horizontal">
-        <android.support.v7.internal.widget.PreferenceImageView
-            android:id="@android:id/icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            app:maxHeight="18dp"
-            app:maxWidth="18dp"
-            android:tint="?android:attr/textColorPrimary"/>
-    </LinearLayout>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:paddingStart="56dp">
-        <TextView
-            android:id="@android:id/title"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="16dp"
-            android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-            android:textAlignment="viewStart"
-            android:textAppearance="@android:style/TextAppearance.Material.Body2"
-            android:textColor="?android:attr/colorAccent"/>
-        <TextView
-            android:id="@android:id/summary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:singleLine="true"
-            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
-            android:textColor="?android:attr/textColorSecondary"/>
-    </LinearLayout>
-
-</FrameLayout>
+    android:layout_marginBottom="16dip"
+    android:textAppearance="@android:style/TextAppearance.Material.Body2"
+    android:textColor="?android:attr/colorAccent"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingTop="16dip" />
diff --git a/v14/preference/res/layout-v21/preference_dropdown_material.xml b/v14/preference/res/layout-v21/preference_dropdown_material.xml
index f886d88..a92095e 100644
--- a/v14/preference/res/layout-v21/preference_dropdown_material.xml
+++ b/v14/preference/res/layout-v21/preference_dropdown_material.xml
@@ -15,18 +15,74 @@
   ~ limitations under the License
   -->
 
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
+    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:background="?android:attr/selectableItemBackground"
+    android:clipToPadding="false"
+    android:focusable="true" >
 
     <Spinner
         android:id="@+id/spinner"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/preference_no_icon_padding_start"
         android:visibility="invisible" />
 
-    <include layout="@layout/preference_material"/>
+    <LinearLayout
+        android:id="@+id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="-4dp"
+        android:minWidth="60dp"
+        android:gravity="start|center_vertical"
+        android:orientation="horizontal"
+        android:paddingRight="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp">
+        <android.support.v7.internal.widget.PreferenceImageView
+            android:id="@android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            app:maxWidth="48dp"
+            app:maxHeight="48dp" />
+    </LinearLayout>
 
-</FrameLayout>
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp">
+
+        <TextView android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="@style/Preference_TextAppearanceMaterialSubhead"
+            android:ellipsize="marquee" />
+
+        <TextView android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="10" />
+
+    </RelativeLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="end|center_vertical"
+        android:paddingLeft="16dp"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v14/preference/res/layout-v21/preference_material.xml b/v14/preference/res/layout-v21/preference_material.xml
index da6b69f..c3000f9 100644
--- a/v14/preference/res/layout-v21/preference_material.xml
+++ b/v14/preference/res/layout-v21/preference_material.xml
@@ -31,11 +31,10 @@
         android:id="@+id/icon_frame"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginStart="-4dp"
-        android:minWidth="60dp"
+        android:minWidth="56dp"
         android:gravity="start|center_vertical"
         android:orientation="horizontal"
-        android:paddingEnd="12dp"
+        android:paddingEnd="8dp"
         android:paddingTop="4dp"
         android:paddingBottom="4dp">
         <android.support.v7.internal.widget.PreferenceImageView
@@ -66,6 +65,7 @@
             android:layout_below="@android:id/title"
             android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+            android:textAlignment="viewStart"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="10" />
 
diff --git a/v14/preference/res/layout/preference_category_material.xml b/v14/preference/res/layout/preference_category_material.xml
index 8eb2137..e366e7a 100644
--- a/v14/preference/res/layout/preference_category_material.xml
+++ b/v14/preference/res/layout/preference_category_material.xml
@@ -15,49 +15,13 @@
   ~ limitations under the License
   -->
 
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/title"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginBottom="8dp"
-    android:layout_marginTop="8dp"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft">
-
-    <LinearLayout
-        android:id="@+id/icon_frame"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:gravity="start|center_vertical"
-        android:orientation="horizontal">
-        <android.support.v7.internal.widget.PreferenceImageView
-            android:id="@android:id/icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            app:maxHeight="18dp"
-            app:maxWidth="18dp"/>
-    </LinearLayout>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:paddingLeft="56dp">
-        <TextView
-            android:id="@android:id/title"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="16dp"
-            android:paddingRight="?android:attr/listPreferredItemPaddingRight"
-            android:textAlignment="viewStart"
-            android:textColor="@color/preference_fallback_accent_color"/>
-        <TextView
-            android:id="@android:id/summary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:singleLine="true"
-            android:textColor="?android:attr/textColorSecondary"/>
-    </LinearLayout>
-
-</FrameLayout>
+    android:layout_marginBottom="16dip"
+    android:textAppearance="@style/Preference_TextAppearanceMaterialBody2"
+    android:textColor="@color/preference_fallback_accent_color"
+    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
+    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingTop="16dip" />
diff --git a/v14/preference/res/values/styles.xml b/v14/preference/res/values/styles.xml
index edd5285..26b1544 100644
--- a/v14/preference/res/values/styles.xml
+++ b/v14/preference/res/values/styles.xml
@@ -24,10 +24,6 @@
 
     <style name="Preference.Material">
         <item name="android:layout">@layout/preference_material</item>
-        <item name="allowDividerAbove">false</item>
-        <item name="allowDividerBelow">true</item>
-        <item name="singleLineTitle">false</item>
-        <item name="iconSpaceReserved">true</item>
     </style>
 
     <style name="Preference.Information.Material">
@@ -38,16 +34,10 @@
 
     <style name="Preference.Category.Material">
         <item name="android:layout">@layout/preference_category_material</item>
-        <item name="allowDividerAbove">true</item>
-        <item name="allowDividerBelow">true</item>
-        <item name="iconSpaceReserved">true</item>
     </style>
 
     <style name="Preference.CheckBoxPreference.Material">
         <item name="android:layout">@layout/preference_material</item>
-        <item name="allowDividerAbove">false</item>
-        <item name="allowDividerBelow">true</item>
-        <item name="iconSpaceReserved">true</item>
     </style>
 
     <style name="Preference.SwitchPreferenceCompat.Material">
@@ -56,10 +46,6 @@
 
     <style name="Preference.SwitchPreference.Material">
         <item name="android:layout">@layout/preference_material</item>
-        <item name="allowDividerAbove">false</item>
-        <item name="allowDividerBelow">true</item>
-        <item name="singleLineTitle">false</item>
-        <item name="iconSpaceReserved">true</item>
     </style>
 
     <style name="Preference.SeekBarPreference.Material">
@@ -70,31 +56,18 @@
 
     <style name="Preference.PreferenceScreen.Material">
         <item name="android:layout">@layout/preference_material</item>
-        <item name="allowDividerAbove">false</item>
-        <item name="allowDividerBelow">true</item>
-        <item name="iconSpaceReserved">true</item>
     </style>
 
     <style name="Preference.DialogPreference.Material">
         <item name="android:layout">@layout/preference_material</item>
-        <item name="allowDividerAbove">false</item>
-        <item name="allowDividerBelow">true</item>
-        <item name="iconSpaceReserved">true</item>
     </style>
 
     <style name="Preference.DialogPreference.EditTextPreference.Material">
         <item name="android:layout">@layout/preference_material</item>
-        <item name="allowDividerAbove">false</item>
-        <item name="allowDividerBelow">true</item>
-        <item name="singleLineTitle">false</item>
-        <item name="iconSpaceReserved">true</item>
     </style>
 
     <style name="Preference.DropDown.Material">
         <item name="android:layout">@layout/preference_dropdown_material</item>
-        <item name="allowDividerAbove">false</item>
-        <item name="allowDividerBelow">true</item>
-        <item name="iconSpaceReserved">true</item>
     </style>
 
     <style name="Preference_TextAppearanceMaterialBody2">
@@ -113,7 +86,6 @@
 
     <style name="PreferenceFragment.Material">
         <item name="android:divider">@drawable/preference_list_divider_material</item>
-        <item name="allowDividerAfterLastItem">false</item>
     </style>
 
     <style name="PreferenceFragmentList.Material">
diff --git a/v14/preference/res/values/themes.xml b/v14/preference/res/values/themes.xml
index 919873e..a69126f 100644
--- a/v14/preference/res/values/themes.xml
+++ b/v14/preference/res/values/themes.xml
@@ -36,6 +36,5 @@
         <item name="editTextPreferenceStyle">@style/Preference.DialogPreference.EditTextPreference.Material</item>
         <item name="dropdownPreferenceStyle">@style/Preference.DropDown.Material</item>
         <item name="preferenceFragmentListStyle">@style/PreferenceFragmentList.Material</item>
-        <item name="android:scrollbars">vertical</item>
     </style>
 </resources>
diff --git a/v4/build.gradle b/v4/build.gradle
index 0a17101..ac5a9f5 100644
--- a/v4/build.gradle
+++ b/v4/build.gradle
@@ -6,11 +6,11 @@
 }
 
 dependencies {
-    api project(':support-compat')
-    api project(':support-media-compat')
-    api project(':support-core-utils')
-    api project(':support-core-ui')
-    api project(':support-fragment')
+    api(project(":support-compat"))
+    api(project(":support-media-compat"))
+    api(project(":support-core-utils"))
+    api(project(":support-core-ui"))
+    api(project(":support-fragment"))
 }
 
 android {
diff --git a/v4/lint-baseline.xml b/v4/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/v4/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/v7/appcompat/api/27.0.0.ignore b/v7/appcompat/api/27.0.0.ignore
new file mode 100644
index 0000000..97cc753
--- /dev/null
+++ b/v7/appcompat/api/27.0.0.ignore
@@ -0,0 +1,2 @@
+b0b1638
+dfaf9f5
diff --git a/v7/appcompat/api/current.txt b/v7/appcompat/api/current.txt
index d39b109..5d4fa6e 100644
--- a/v7/appcompat/api/current.txt
+++ b/v7/appcompat/api/current.txt
@@ -161,6 +161,7 @@
     method public android.widget.ListView getListView();
     method public void setButton(int, java.lang.CharSequence, android.os.Message);
     method public void setButton(int, java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public void setButton(int, java.lang.CharSequence, android.graphics.drawable.Drawable, android.content.DialogInterface.OnClickListener);
     method public void setCustomTitle(android.view.View);
     method public void setIcon(int);
     method public void setIcon(android.graphics.drawable.Drawable);
@@ -192,14 +193,17 @@
     method public android.support.v7.app.AlertDialog.Builder setMultiChoiceItems(android.database.Cursor, java.lang.String, java.lang.String, android.content.DialogInterface.OnMultiChoiceClickListener);
     method public android.support.v7.app.AlertDialog.Builder setNegativeButton(int, android.content.DialogInterface.OnClickListener);
     method public android.support.v7.app.AlertDialog.Builder setNegativeButton(java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public android.support.v7.app.AlertDialog.Builder setNegativeButtonIcon(android.graphics.drawable.Drawable);
     method public android.support.v7.app.AlertDialog.Builder setNeutralButton(int, android.content.DialogInterface.OnClickListener);
     method public android.support.v7.app.AlertDialog.Builder setNeutralButton(java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public android.support.v7.app.AlertDialog.Builder setNeutralButtonIcon(android.graphics.drawable.Drawable);
     method public android.support.v7.app.AlertDialog.Builder setOnCancelListener(android.content.DialogInterface.OnCancelListener);
     method public android.support.v7.app.AlertDialog.Builder setOnDismissListener(android.content.DialogInterface.OnDismissListener);
     method public android.support.v7.app.AlertDialog.Builder setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener);
     method public android.support.v7.app.AlertDialog.Builder setOnKeyListener(android.content.DialogInterface.OnKeyListener);
     method public android.support.v7.app.AlertDialog.Builder setPositiveButton(int, android.content.DialogInterface.OnClickListener);
     method public android.support.v7.app.AlertDialog.Builder setPositiveButton(java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public android.support.v7.app.AlertDialog.Builder setPositiveButtonIcon(android.graphics.drawable.Drawable);
     method public android.support.v7.app.AlertDialog.Builder setSingleChoiceItems(int, int, android.content.DialogInterface.OnClickListener);
     method public android.support.v7.app.AlertDialog.Builder setSingleChoiceItems(android.database.Cursor, int, java.lang.String, android.content.DialogInterface.OnClickListener);
     method public android.support.v7.app.AlertDialog.Builder setSingleChoiceItems(java.lang.CharSequence[], int, android.content.DialogInterface.OnClickListener);
@@ -211,7 +215,7 @@
     method public android.support.v7.app.AlertDialog show();
   }
 
-  public class AppCompatActivity extends android.support.v4.app.FragmentActivity implements android.support.v7.app.ActionBarDrawerToggle.DelegateProvider android.support.v7.app.AppCompatCallback {
+  public class AppCompatActivity extends android.support.v4.app.FragmentActivity implements android.support.v7.app.ActionBarDrawerToggle.DelegateProvider android.support.v7.app.AppCompatCallback android.support.v4.app.TaskStackBuilder.SupportParentable {
     ctor public AppCompatActivity();
     method public android.support.v7.app.AppCompatDelegate getDelegate();
     method public android.support.v7.app.ActionBarDrawerToggle.Delegate getDrawerToggleDelegate();
@@ -403,6 +407,15 @@
     method public abstract void onActionViewExpanded();
   }
 
+  public class ContextThemeWrapper extends android.content.ContextWrapper {
+    ctor public ContextThemeWrapper();
+    ctor public ContextThemeWrapper(android.content.Context, int);
+    ctor public ContextThemeWrapper(android.content.Context, android.content.res.Resources.Theme);
+    method public void applyOverrideConfiguration(android.content.res.Configuration);
+    method public int getThemeResId();
+    method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean);
+  }
+
 }
 
 package android.support.v7.widget {
@@ -443,27 +456,41 @@
     method public abstract boolean onMenuItemClick(android.view.MenuItem);
   }
 
-  public class AppCompatAutoCompleteTextView extends android.widget.AutoCompleteTextView {
+  public class AppCompatAutoCompleteTextView extends android.widget.AutoCompleteTextView implements android.support.v4.view.TintableBackgroundView {
     ctor public AppCompatAutoCompleteTextView(android.content.Context);
     ctor public AppCompatAutoCompleteTextView(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatAutoCompleteTextView(android.content.Context, android.util.AttributeSet, int);
+    method public android.content.res.ColorStateList getSupportBackgroundTintList();
+    method public android.graphics.PorterDuff.Mode getSupportBackgroundTintMode();
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setSupportBackgroundTintList(android.content.res.ColorStateList);
+    method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode);
     method public void setTextAppearance(android.content.Context, int);
   }
 
-  public class AppCompatButton extends android.widget.Button {
+  public class AppCompatButton extends android.widget.Button implements android.support.v4.widget.AutoSizeableTextView android.support.v4.view.TintableBackgroundView {
     ctor public AppCompatButton(android.content.Context);
     ctor public AppCompatButton(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatButton(android.content.Context, android.util.AttributeSet, int);
+    method public android.content.res.ColorStateList getSupportBackgroundTintList();
+    method public android.graphics.PorterDuff.Mode getSupportBackgroundTintMode();
+    method public void setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int) throws java.lang.IllegalArgumentException;
+    method public void setAutoSizeTextTypeUniformWithPresetSizes(int[], int) throws java.lang.IllegalArgumentException;
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
     method public void setSupportAllCaps(boolean);
+    method public void setSupportBackgroundTintList(android.content.res.ColorStateList);
+    method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode);
     method public void setTextAppearance(android.content.Context, int);
   }
 
-  public class AppCompatCheckBox extends android.widget.CheckBox {
+  public class AppCompatCheckBox extends android.widget.CheckBox implements android.support.v4.widget.TintableCompoundButton {
     ctor public AppCompatCheckBox(android.content.Context);
     ctor public AppCompatCheckBox(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatCheckBox(android.content.Context, android.util.AttributeSet, int);
+    method public android.content.res.ColorStateList getSupportButtonTintList();
+    method public android.graphics.PorterDuff.Mode getSupportButtonTintMode();
+    method public void setSupportButtonTintList(android.content.res.ColorStateList);
+    method public void setSupportButtonTintMode(android.graphics.PorterDuff.Mode);
   }
 
   public class AppCompatCheckedTextView extends android.widget.CheckedTextView {
@@ -473,40 +500,68 @@
     method public void setTextAppearance(android.content.Context, int);
   }
 
-  public class AppCompatEditText extends android.widget.EditText {
+  public class AppCompatEditText extends android.widget.EditText implements android.support.v4.view.TintableBackgroundView {
     ctor public AppCompatEditText(android.content.Context);
     ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet, int);
+    method public android.content.res.ColorStateList getSupportBackgroundTintList();
+    method public android.graphics.PorterDuff.Mode getSupportBackgroundTintMode();
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setSupportBackgroundTintList(android.content.res.ColorStateList);
+    method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode);
     method public void setTextAppearance(android.content.Context, int);
   }
 
-  public class AppCompatImageButton extends android.widget.ImageButton {
+  public class AppCompatImageButton extends android.widget.ImageButton implements android.support.v4.view.TintableBackgroundView android.support.v4.widget.TintableImageSourceView {
     ctor public AppCompatImageButton(android.content.Context);
     ctor public AppCompatImageButton(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatImageButton(android.content.Context, android.util.AttributeSet, int);
+    method public android.content.res.ColorStateList getSupportBackgroundTintList();
+    method public android.graphics.PorterDuff.Mode getSupportBackgroundTintMode();
+    method public android.content.res.ColorStateList getSupportImageTintList();
+    method public android.graphics.PorterDuff.Mode getSupportImageTintMode();
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setSupportBackgroundTintList(android.content.res.ColorStateList);
+    method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode);
+    method public void setSupportImageTintList(android.content.res.ColorStateList);
+    method public void setSupportImageTintMode(android.graphics.PorterDuff.Mode);
   }
 
-  public class AppCompatImageView extends android.widget.ImageView {
+  public class AppCompatImageView extends android.widget.ImageView implements android.support.v4.view.TintableBackgroundView android.support.v4.widget.TintableImageSourceView {
     ctor public AppCompatImageView(android.content.Context);
     ctor public AppCompatImageView(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatImageView(android.content.Context, android.util.AttributeSet, int);
+    method public android.content.res.ColorStateList getSupportBackgroundTintList();
+    method public android.graphics.PorterDuff.Mode getSupportBackgroundTintMode();
+    method public android.content.res.ColorStateList getSupportImageTintList();
+    method public android.graphics.PorterDuff.Mode getSupportImageTintMode();
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setSupportBackgroundTintList(android.content.res.ColorStateList);
+    method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode);
+    method public void setSupportImageTintList(android.content.res.ColorStateList);
+    method public void setSupportImageTintMode(android.graphics.PorterDuff.Mode);
   }
 
-  public class AppCompatMultiAutoCompleteTextView extends android.widget.MultiAutoCompleteTextView {
+  public class AppCompatMultiAutoCompleteTextView extends android.widget.MultiAutoCompleteTextView implements android.support.v4.view.TintableBackgroundView {
     ctor public AppCompatMultiAutoCompleteTextView(android.content.Context);
     ctor public AppCompatMultiAutoCompleteTextView(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatMultiAutoCompleteTextView(android.content.Context, android.util.AttributeSet, int);
+    method public android.content.res.ColorStateList getSupportBackgroundTintList();
+    method public android.graphics.PorterDuff.Mode getSupportBackgroundTintMode();
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setSupportBackgroundTintList(android.content.res.ColorStateList);
+    method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode);
     method public void setTextAppearance(android.content.Context, int);
   }
 
-  public class AppCompatRadioButton extends android.widget.RadioButton {
+  public class AppCompatRadioButton extends android.widget.RadioButton implements android.support.v4.widget.TintableCompoundButton {
     ctor public AppCompatRadioButton(android.content.Context);
     ctor public AppCompatRadioButton(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatRadioButton(android.content.Context, android.util.AttributeSet, int);
+    method public android.content.res.ColorStateList getSupportButtonTintList();
+    method public android.graphics.PorterDuff.Mode getSupportButtonTintMode();
+    method public void setSupportButtonTintList(android.content.res.ColorStateList);
+    method public void setSupportButtonTintMode(android.graphics.PorterDuff.Mode);
   }
 
   public class AppCompatRatingBar extends android.widget.RatingBar {
@@ -521,21 +576,31 @@
     ctor public AppCompatSeekBar(android.content.Context, android.util.AttributeSet, int);
   }
 
-  public class AppCompatSpinner extends android.widget.Spinner {
+  public class AppCompatSpinner extends android.widget.Spinner implements android.support.v4.view.TintableBackgroundView {
     ctor public AppCompatSpinner(android.content.Context);
     ctor public AppCompatSpinner(android.content.Context, int);
     ctor public AppCompatSpinner(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatSpinner(android.content.Context, android.util.AttributeSet, int);
     ctor public AppCompatSpinner(android.content.Context, android.util.AttributeSet, int, int);
     ctor public AppCompatSpinner(android.content.Context, android.util.AttributeSet, int, int, android.content.res.Resources.Theme);
+    method public android.content.res.ColorStateList getSupportBackgroundTintList();
+    method public android.graphics.PorterDuff.Mode getSupportBackgroundTintMode();
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setSupportBackgroundTintList(android.content.res.ColorStateList);
+    method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode);
   }
 
-  public class AppCompatTextView extends android.widget.TextView {
+  public class AppCompatTextView extends android.widget.TextView implements android.support.v4.widget.AutoSizeableTextView android.support.v4.view.TintableBackgroundView {
     ctor public AppCompatTextView(android.content.Context);
     ctor public AppCompatTextView(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatTextView(android.content.Context, android.util.AttributeSet, int);
+    method public android.content.res.ColorStateList getSupportBackgroundTintList();
+    method public android.graphics.PorterDuff.Mode getSupportBackgroundTintMode();
+    method public void setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int) throws java.lang.IllegalArgumentException;
+    method public void setAutoSizeTextTypeUniformWithPresetSizes(int[], int) throws java.lang.IllegalArgumentException;
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setSupportBackgroundTintList(android.content.res.ColorStateList);
+    method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode);
     method public void setTextAppearance(android.content.Context, int);
   }
 
@@ -555,7 +620,6 @@
     method public float getWeightSum();
     method public boolean isBaselineAligned();
     method public boolean isMeasureWithLargestChildEnabled();
-    method protected void onLayout(boolean, int, int, int, int);
     method public void setBaselineAligned(boolean);
     method public void setBaselineAlignedChildIndex(int);
     method public void setDividerDrawable(android.graphics.drawable.Drawable);
@@ -819,7 +883,6 @@
     method public boolean hideOverflowMenu();
     method public void inflateMenu(int);
     method public boolean isOverflowMenuShowing();
-    method protected void onLayout(boolean, int, int, int, int);
     method public void setContentInsetEndWithActions(int);
     method public void setContentInsetStartWithNavigation(int);
     method public void setContentInsetsAbsolute(int, int);
diff --git a/v7/appcompat/build.gradle b/v7/appcompat/build.gradle
index 8e242cc..a3b80a8 100644
--- a/v7/appcompat/build.gradle
+++ b/v7/appcompat/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,16 +7,16 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-core-utils')
-    api project(':support-fragment')
-    api project(':support-vector-drawable')
-    api project(':animated-vector-drawable')
+    api(project(":support-annotations"))
+    api(project(":support-core-utils"))
+    api(project(":support-fragment"))
+    api(project(":support-vector-drawable"))
+    api(project(":animated-vector-drawable"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
     androidTestImplementation project(':support-testutils'), {
         exclude group: 'com.android.support', module: 'appcompat-v7'
     }
@@ -23,7 +24,7 @@
 
 android {
     defaultConfig {
-        minSdkVersion 14
+        minSdkVersion(14)
         // This disables the builds tools automatic vector -> PNG generation
         generatedDensities = []
     }
diff --git a/v7/appcompat/lint-baseline.xml b/v7/appcompat/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/v7/appcompat/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/v7/appcompat/res/values/attrs.xml b/v7/appcompat/res/values/attrs.xml
index 2012a3a..c48b7ba 100644
--- a/v7/appcompat/res/values/attrs.xml
+++ b/v7/appcompat/res/values/attrs.xml
@@ -1140,6 +1140,7 @@
         <attr name="singleChoiceItemLayout" format="reference" />
         <attr name="listItemLayout" format="reference" />
         <attr name="showTitle" format="boolean" />
+        <attr name="buttonIconDimen" format="dimension" />
     </declare-styleable>
 
     <!-- @hide -->
diff --git a/v7/appcompat/res/values/dimens.xml b/v7/appcompat/res/values/dimens.xml
index a02b7c0..5bcd4b4 100644
--- a/v7/appcompat/res/values/dimens.xml
+++ b/v7/appcompat/res/values/dimens.xml
@@ -95,6 +95,9 @@
     <!-- Minimum "smallest width" of the display for cascading menus to be enabled. -->
     <dimen name="abc_cascading_menus_min_smallest_width">720dp</dimen>
 
+    <!-- Dimension of the AlertDialog button icon -->
+    <dimen name="abc_alert_dialog_button_dimen">48dp</dimen>
+
     <!-- Tooltip dimensions. -->
     <!-- Vertical offset from the edge of the anchor view for a touch-triggered tooltip. -->
     <dimen name="tooltip_y_offset_touch">16dp</dimen>
diff --git a/v7/appcompat/res/values/styles_base.xml b/v7/appcompat/res/values/styles_base.xml
index adaaae0..c1aa3a7 100644
--- a/v7/appcompat/res/values/styles_base.xml
+++ b/v7/appcompat/res/values/styles_base.xml
@@ -520,6 +520,7 @@
         <item name="listItemLayout">@layout/select_dialog_item_material</item>
         <item name="multiChoiceItemLayout">@layout/select_dialog_multichoice_material</item>
         <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_material</item>
+        <item name="buttonIconDimen">@dimen/abc_alert_dialog_button_dimen</item>
     </style>
 
     <style name="Base.AlertDialog.AppCompat.Light" parent="Base.AlertDialog.AppCompat" />
diff --git a/v7/appcompat/src/main/java/android/support/v7/app/AlertController.java b/v7/appcompat/src/main/java/android/support/v7/app/AlertController.java
index 5ff4537..01bc449 100644
--- a/v7/appcompat/src/main/java/android/support/v7/app/AlertController.java
+++ b/v7/appcompat/src/main/java/android/support/v7/app/AlertController.java
@@ -65,6 +65,7 @@
     private final Context mContext;
     final AppCompatDialog mDialog;
     private final Window mWindow;
+    private final int mButtonIconDimen;
 
     private CharSequence mTitle;
     private CharSequence mMessage;
@@ -82,14 +83,17 @@
     Button mButtonPositive;
     private CharSequence mButtonPositiveText;
     Message mButtonPositiveMessage;
+    private Drawable mButtonPositiveIcon;
 
     Button mButtonNegative;
     private CharSequence mButtonNegativeText;
     Message mButtonNegativeMessage;
+    private Drawable mButtonNegativeIcon;
 
     Button mButtonNeutral;
     private CharSequence mButtonNeutralText;
     Message mButtonNeutralMessage;
+    private Drawable mButtonNeutralIcon;
 
     NestedScrollView mScrollView;
 
@@ -192,6 +196,7 @@
                 .getResourceId(R.styleable.AlertDialog_singleChoiceItemLayout, 0);
         mListItemLayout = a.getResourceId(R.styleable.AlertDialog_listItemLayout, 0);
         mShowTitle = a.getBoolean(R.styleable.AlertDialog_showTitle, true);
+        mButtonIconDimen = a.getDimensionPixelSize(R.styleable.AlertDialog_buttonIconDimen, 0);
 
         a.recycle();
 
@@ -298,8 +303,8 @@
     }
 
     /**
-     * Sets a click listener or a message to be sent when the button is clicked.
-     * You only need to pass one of {@code listener} or {@code msg}.
+     * Sets an icon, a click listener or a message to be sent when the button is clicked.
+     * You only need to pass one of {@code icon}, {@code listener} or {@code msg}.
      *
      * @param whichButton Which button, can be one of
      *                    {@link DialogInterface#BUTTON_POSITIVE},
@@ -308,9 +313,11 @@
      * @param text        The text to display in positive button.
      * @param listener    The {@link DialogInterface.OnClickListener} to use.
      * @param msg         The {@link Message} to be sent when clicked.
+     * @param icon        The (@link Drawable) to be used as an icon for the button.
+     *
      */
     public void setButton(int whichButton, CharSequence text,
-            DialogInterface.OnClickListener listener, Message msg) {
+            DialogInterface.OnClickListener listener, Message msg, Drawable icon) {
 
         if (msg == null && listener != null) {
             msg = mHandler.obtainMessage(whichButton, listener);
@@ -321,16 +328,19 @@
             case DialogInterface.BUTTON_POSITIVE:
                 mButtonPositiveText = text;
                 mButtonPositiveMessage = msg;
+                mButtonPositiveIcon = icon;
                 break;
 
             case DialogInterface.BUTTON_NEGATIVE:
                 mButtonNegativeText = text;
                 mButtonNegativeMessage = msg;
+                mButtonNegativeIcon = icon;
                 break;
 
             case DialogInterface.BUTTON_NEUTRAL:
                 mButtonNeutralText = text;
                 mButtonNeutralMessage = msg;
+                mButtonNeutralIcon = icon;
                 break;
 
             default:
@@ -752,35 +762,45 @@
         mButtonPositive = (Button) buttonPanel.findViewById(android.R.id.button1);
         mButtonPositive.setOnClickListener(mButtonHandler);
 
-        if (TextUtils.isEmpty(mButtonPositiveText)) {
+        if (TextUtils.isEmpty(mButtonPositiveText) && mButtonPositiveIcon == null) {
             mButtonPositive.setVisibility(View.GONE);
         } else {
             mButtonPositive.setText(mButtonPositiveText);
+            if (mButtonPositiveIcon != null) {
+                mButtonPositiveIcon.setBounds(0, 0, mButtonIconDimen, mButtonIconDimen);
+                mButtonPositive.setCompoundDrawables(mButtonPositiveIcon, null, null, null);
+            }
             mButtonPositive.setVisibility(View.VISIBLE);
             whichButtons = whichButtons | BIT_BUTTON_POSITIVE;
         }
 
-        mButtonNegative = (Button) buttonPanel.findViewById(android.R.id.button2);
+        mButtonNegative = buttonPanel.findViewById(android.R.id.button2);
         mButtonNegative.setOnClickListener(mButtonHandler);
 
-        if (TextUtils.isEmpty(mButtonNegativeText)) {
+        if (TextUtils.isEmpty(mButtonNegativeText) && mButtonNegativeIcon == null) {
             mButtonNegative.setVisibility(View.GONE);
         } else {
             mButtonNegative.setText(mButtonNegativeText);
+            if (mButtonNegativeIcon != null) {
+                mButtonNegativeIcon.setBounds(0, 0, mButtonIconDimen, mButtonIconDimen);
+                mButtonNegative.setCompoundDrawables(mButtonNegativeIcon, null, null, null);
+            }
             mButtonNegative.setVisibility(View.VISIBLE);
-
             whichButtons = whichButtons | BIT_BUTTON_NEGATIVE;
         }
 
         mButtonNeutral = (Button) buttonPanel.findViewById(android.R.id.button3);
         mButtonNeutral.setOnClickListener(mButtonHandler);
 
-        if (TextUtils.isEmpty(mButtonNeutralText)) {
+        if (TextUtils.isEmpty(mButtonNeutralText) && mButtonNeutralIcon == null) {
             mButtonNeutral.setVisibility(View.GONE);
         } else {
             mButtonNeutral.setText(mButtonNeutralText);
+            if (mButtonPositiveIcon != null) {
+                mButtonPositiveIcon.setBounds(0, 0, mButtonIconDimen, mButtonIconDimen);
+                mButtonPositive.setCompoundDrawables(mButtonPositiveIcon, null, null, null);
+            }
             mButtonNeutral.setVisibility(View.VISIBLE);
-
             whichButtons = whichButtons | BIT_BUTTON_NEUTRAL;
         }
 
@@ -852,10 +872,13 @@
         public View mCustomTitleView;
         public CharSequence mMessage;
         public CharSequence mPositiveButtonText;
+        public Drawable mPositiveButtonIcon;
         public DialogInterface.OnClickListener mPositiveButtonListener;
         public CharSequence mNegativeButtonText;
+        public Drawable mNegativeButtonIcon;
         public DialogInterface.OnClickListener mNegativeButtonListener;
         public CharSequence mNeutralButtonText;
+        public Drawable mNeutralButtonIcon;
         public DialogInterface.OnClickListener mNeutralButtonListener;
         public boolean mCancelable;
         public DialogInterface.OnCancelListener mOnCancelListener;
@@ -923,17 +946,17 @@
             if (mMessage != null) {
                 dialog.setMessage(mMessage);
             }
-            if (mPositiveButtonText != null) {
+            if (mPositiveButtonText != null || mPositiveButtonIcon != null) {
                 dialog.setButton(DialogInterface.BUTTON_POSITIVE, mPositiveButtonText,
-                        mPositiveButtonListener, null);
+                        mPositiveButtonListener, null, mPositiveButtonIcon);
             }
-            if (mNegativeButtonText != null) {
+            if (mNegativeButtonText != null || mNegativeButtonIcon != null) {
                 dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mNegativeButtonText,
-                        mNegativeButtonListener, null);
+                        mNegativeButtonListener, null, mNegativeButtonIcon);
             }
-            if (mNeutralButtonText != null) {
+            if (mNeutralButtonText != null || mNeutralButtonIcon != null) {
                 dialog.setButton(DialogInterface.BUTTON_NEUTRAL, mNeutralButtonText,
-                        mNeutralButtonListener, null);
+                        mNeutralButtonListener, null, mNeutralButtonIcon);
             }
             // For a list, the client can either supply an array of items or an
             // adapter or a cursor
diff --git a/v7/appcompat/src/main/java/android/support/v7/app/AlertDialog.java b/v7/appcompat/src/main/java/android/support/v7/app/AlertDialog.java
index 4b87dcc..1712f20 100644
--- a/v7/appcompat/src/main/java/android/support/v7/app/AlertDialog.java
+++ b/v7/appcompat/src/main/java/android/support/v7/app/AlertDialog.java
@@ -207,7 +207,7 @@
      * @param msg         The {@link Message} to be sent when clicked.
      */
     public void setButton(int whichButton, CharSequence text, Message msg) {
-        mAlert.setButton(whichButton, text, null, msg);
+        mAlert.setButton(whichButton, text, null, msg, null);
     }
 
     /**
@@ -222,7 +222,25 @@
      * @param listener    The {@link DialogInterface.OnClickListener} to use.
      */
     public void setButton(int whichButton, CharSequence text, OnClickListener listener) {
-        mAlert.setButton(whichButton, text, listener, null);
+        mAlert.setButton(whichButton, text, listener, null, null);
+    }
+
+    /**
+     * Sets an icon to be displayed along with the button text and a listener to be invoked when
+     * the positive button of the dialog is pressed. This method has no effect if called after
+     * {@link #show()}.
+     *
+     * @param whichButton Which button to set the listener on, can be one of
+     *                    {@link DialogInterface#BUTTON_POSITIVE},
+     *                    {@link DialogInterface#BUTTON_NEGATIVE}, or
+     *                    {@link DialogInterface#BUTTON_NEUTRAL}
+     * @param text        The text to display in positive button.
+     * @param listener    The {@link DialogInterface.OnClickListener} to use.
+     * @param icon        The {@link Drawable} to be set as an icon for the button.
+     */
+    public void setButton(int whichButton, CharSequence text, Drawable icon,
+            OnClickListener listener) {
+        mAlert.setButton(whichButton, text, listener, null,  icon);
     }
 
     /**
@@ -470,6 +488,16 @@
         }
 
         /**
+         * Set an icon to be displayed for the positive button.
+         * @param icon The icon to be displayed
+         * @return This Builder object to allow for chaining of calls to set methods
+         */
+        public Builder setPositiveButtonIcon(Drawable icon) {
+            P.mPositiveButtonIcon = icon;
+            return this;
+        }
+
+        /**
          * Set a listener to be invoked when the negative button of the dialog is pressed.
          * @param textId The resource id of the text to display in the negative button
          * @param listener The {@link DialogInterface.OnClickListener} to use.
@@ -496,6 +524,16 @@
         }
 
         /**
+         * Set an icon to be displayed for the negative button.
+         * @param icon The icon to be displayed
+         * @return This Builder object to allow for chaining of calls to set methods
+         */
+        public Builder setNegativeButtonIcon(Drawable icon) {
+            P.mNegativeButtonIcon = icon;
+            return this;
+        }
+
+        /**
          * Set a listener to be invoked when the neutral button of the dialog is pressed.
          * @param textId The resource id of the text to display in the neutral button
          * @param listener The {@link DialogInterface.OnClickListener} to use.
@@ -522,6 +560,16 @@
         }
 
         /**
+         * Set an icon to be displayed for the neutral button.
+         * @param icon The icon to be displayed
+         * @return This Builder object to allow for chaining of calls to set methods
+         */
+        public Builder setNeutralButtonIcon(Drawable icon) {
+            P.mNeutralButtonIcon = icon;
+            return this;
+        }
+
+        /**
          * Sets whether the dialog is cancelable or not.  Default is true.
          *
          * @return This Builder object to allow for chaining of calls to set methods
diff --git a/v7/appcompat/src/main/java/android/support/v7/view/ContextThemeWrapper.java b/v7/appcompat/src/main/java/android/support/v7/view/ContextThemeWrapper.java
index aa5b36e..cc63480 100644
--- a/v7/appcompat/src/main/java/android/support/v7/view/ContextThemeWrapper.java
+++ b/v7/appcompat/src/main/java/android/support/v7/view/ContextThemeWrapper.java
@@ -16,26 +16,19 @@
 
 package android.support.v7.view;
 
-import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.res.AssetManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.Build;
-import android.support.annotation.RestrictTo;
 import android.support.annotation.StyleRes;
 import android.support.v7.appcompat.R;
 import android.view.LayoutInflater;
 
 /**
- * A ContextWrapper that allows you to modify the theme from what is in the
- * wrapped context.
- *
- * @hide
+ * A context wrapper that allows you to modify or replace the theme of the wrapped context.
  */
-@RestrictTo(LIBRARY_GROUP)
 public class ContextThemeWrapper extends ContextWrapper {
     private int mThemeResource;
     private Resources.Theme mTheme;
@@ -110,15 +103,6 @@
         mOverrideConfiguration = new Configuration(overrideConfiguration);
     }
 
-    /**
-     * Used by ActivityThread to apply the overridden configuration to onConfigurationChange
-     * callbacks.
-     * @hide
-     */
-    public Configuration getOverrideConfiguration() {
-        return mOverrideConfiguration;
-    }
-
     @Override
     public Resources getResources() {
         return getResourcesInternal();
@@ -144,6 +128,10 @@
         }
     }
 
+    /**
+     * Returns the resource ID of the theme that is to be applied on top of the base context's
+     * theme.
+     */
     public int getThemeResId() {
         return mThemeResource;
     }
diff --git a/v7/appcompat/src/main/java/android/support/v7/view/menu/CascadingMenuPopup.java b/v7/appcompat/src/main/java/android/support/v7/view/menu/CascadingMenuPopup.java
index 564bbfc..834f854 100644
--- a/v7/appcompat/src/main/java/android/support/v7/view/menu/CascadingMenuPopup.java
+++ b/v7/appcompat/src/main/java/android/support/v7/view/menu/CascadingMenuPopup.java
@@ -54,7 +54,6 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
-import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -85,7 +84,7 @@
     final Handler mSubMenuHoverHandler;
 
     /** List of menus that were added before this popup was shown. */
-    private final List<MenuBuilder> mPendingMenus = new LinkedList<>();
+    private final List<MenuBuilder> mPendingMenus = new ArrayList<>();
 
     /**
      * List of open menus. The first item is the root menu and each
diff --git a/v7/appcompat/src/main/java/android/support/v7/widget/ActionMenuView.java b/v7/appcompat/src/main/java/android/support/v7/widget/ActionMenuView.java
index 76e06da..14723a0 100644
--- a/v7/appcompat/src/main/java/android/support/v7/widget/ActionMenuView.java
+++ b/v7/appcompat/src/main/java/android/support/v7/widget/ActionMenuView.java
@@ -268,10 +268,10 @@
                 // Mark indices of children that can receive an extra cell.
                 if (lp.cellsUsed < minCells) {
                     minCells = lp.cellsUsed;
-                    minCellsAt = 1 << i;
+                    minCellsAt = 1L << i;
                     minCellsItemCount = 1;
                 } else if (lp.cellsUsed == minCells) {
-                    minCellsAt |= 1 << i;
+                    minCellsAt |= 1L << i;
                     minCellsItemCount++;
                 }
             }
diff --git a/v7/appcompat/src/main/java/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java b/v7/appcompat/src/main/java/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java
index e82e469..7e98494 100644
--- a/v7/appcompat/src/main/java/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java
+++ b/v7/appcompat/src/main/java/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java
@@ -45,8 +45,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Hashtable;
 import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Utility class which encapsulates the logic for the TextView auto-size text feature added to
@@ -66,7 +66,8 @@
     private static final int DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX = 1;
     // Cache of TextView methods used via reflection; the key is the method name and the value is
     // the method itself or null if it can not be found.
-    private static Hashtable<String, Method> sTextViewMethodByNameCache = new Hashtable<>();
+    private static ConcurrentHashMap<String, Method> sTextViewMethodByNameCache =
+            new ConcurrentHashMap<>();
     // Use this to specify that any of the auto-size configuration int values have not been set.
     static final float UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE = -1f;
     // Ported from TextView#VERY_WIDE. Represents a maximum width in pixels the TextView takes when
diff --git a/v7/appcompat/src/main/java/android/support/v7/widget/ListPopupWindow.java b/v7/appcompat/src/main/java/android/support/v7/widget/ListPopupWindow.java
index edc9781..b98197c 100644
--- a/v7/appcompat/src/main/java/android/support/v7/widget/ListPopupWindow.java
+++ b/v7/appcompat/src/main/java/android/support/v7/widget/ListPopupWindow.java
@@ -283,7 +283,7 @@
             mAdapter.unregisterDataSetObserver(mObserver);
         }
         mAdapter = adapter;
-        if (mAdapter != null) {
+        if (adapter != null) {
             adapter.registerDataSetObserver(mObserver);
         }
 
diff --git a/v7/appcompat/src/main/java/android/support/v7/widget/TooltipPopup.java b/v7/appcompat/src/main/java/android/support/v7/widget/TooltipPopup.java
index dc20aa1..396fe05 100644
--- a/v7/appcompat/src/main/java/android/support/v7/widget/TooltipPopup.java
+++ b/v7/appcompat/src/main/java/android/support/v7/widget/TooltipPopup.java
@@ -31,6 +31,7 @@
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.widget.TextView;
 
@@ -99,6 +100,7 @@
 
     private void computePosition(View anchorView, int anchorX, int anchorY, boolean fromTouch,
             WindowManager.LayoutParams outParams) {
+        outParams.token = anchorView.getApplicationWindowToken();
         final int tooltipPreciseAnchorThreshold = mContext.getResources().getDimensionPixelOffset(
                 R.dimen.tooltip_precise_anchor_threshold);
 
@@ -157,7 +159,7 @@
         mTmpAnchorPos[1] -= mTmpAppPos[1];
         // mTmpAnchorPos is now relative to the main app window.
 
-        outParams.x = mTmpAnchorPos[0] + offsetX - mTmpDisplayFrame.width() / 2;
+        outParams.x = mTmpAnchorPos[0] + offsetX - appView.getWidth() / 2;
 
         final int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
         mContentView.measure(spec, spec);
@@ -181,6 +183,16 @@
     }
 
     private static View getAppRootView(View anchorView) {
+        View rootView = anchorView.getRootView();
+        ViewGroup.LayoutParams lp = rootView.getLayoutParams();
+        if (lp instanceof WindowManager.LayoutParams
+                && (((WindowManager.LayoutParams) lp).type
+                    == WindowManager.LayoutParams.TYPE_APPLICATION)) {
+            // This covers regular app windows and Dialog windows.
+            return rootView;
+        }
+        // For non-application window types (such as popup windows) try to find the main app window
+        // through the context.
         Context context = anchorView.getContext();
         while (context instanceof ContextWrapper) {
             if (context instanceof Activity) {
@@ -189,6 +201,8 @@
                 context = ((ContextWrapper) context).getBaseContext();
             }
         }
-        return anchorView.getRootView();
+        // Main app window not found, fall back to the anchor's root view. There is no guarantee
+        // that the tooltip position will be computed correctly.
+        return rootView;
     }
 }
diff --git a/v7/appcompat/tests/res/values/styles.xml b/v7/appcompat/tests/res/values/styles.xml
index b9fa921..9693b3a 100644
--- a/v7/appcompat/tests/res/values/styles.xml
+++ b/v7/appcompat/tests/res/values/styles.xml
@@ -98,4 +98,6 @@
     <style name="TextView_Typeface_Monospace">
         <item name="android:typeface">monospace</item>
     </style>
+
+    <style name="TextAppearance" parent="TextAppearance.AppCompat" />
 </resources>
diff --git a/v7/appcompat/tests/src/android/support/v7/view/ContextThemeWrapperTest.java b/v7/appcompat/tests/src/android/support/v7/view/ContextThemeWrapperTest.java
new file mode 100644
index 0000000..ab6b1da
--- /dev/null
+++ b/v7/appcompat/tests/src/android/support/v7/view/ContextThemeWrapperTest.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v7.view;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.appcompat.test.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ContextThemeWrapperTest {
+    private static final int SYSTEM_DEFAULT_THEME = 0;
+
+    private Context mContext;
+
+    private static class MockContextThemeWrapper extends ContextThemeWrapper {
+        boolean mIsOnApplyThemeResourceCalled;
+        MockContextThemeWrapper(Context base, int themeres) {
+            super(base, themeres);
+        }
+
+        @Override
+        protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
+            mIsOnApplyThemeResourceCalled = true;
+            super.onApplyThemeResource(theme, resid, first);
+        }
+    }
+
+    @Before
+    public void setup() {
+        mContext = InstrumentationRegistry.getTargetContext();
+    }
+
+    @Test
+    public void testConstructor() {
+        new ContextThemeWrapper();
+
+        new ContextThemeWrapper(mContext, R.style.TextAppearance);
+
+        new ContextThemeWrapper(mContext, mContext.getTheme());
+    }
+
+    @Test
+    public void testAccessTheme() {
+        ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(
+                mContext, SYSTEM_DEFAULT_THEME);
+        // set Theme to TextAppearance
+        contextThemeWrapper.setTheme(R.style.TextAppearance);
+        TypedArray ta = contextThemeWrapper.getTheme().obtainStyledAttributes(
+                R.styleable.TextAppearance);
+
+        // assert theme style of TextAppearance
+        verifyIdenticalTextAppearanceStyle(ta);
+    }
+
+    @Test
+    public void testGetSystemService() {
+        // Note that we can't use Mockito since ContextThemeWrapper.onApplyThemeResource is
+        // protected
+        final MockContextThemeWrapper contextThemeWrapper =
+                new MockContextThemeWrapper(mContext, R.style.TextAppearance);
+        contextThemeWrapper.getTheme();
+        assertTrue(contextThemeWrapper.mIsOnApplyThemeResourceCalled);
+
+        // All service get from contextThemeWrapper just the same as this context get,
+        // except Context.LAYOUT_INFLATER_SERVICE.
+        assertEquals(mContext.getSystemService(Context.ACTIVITY_SERVICE),
+                contextThemeWrapper.getSystemService(Context.ACTIVITY_SERVICE));
+        assertNotSame(mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE),
+                contextThemeWrapper.getSystemService(Context.LAYOUT_INFLATER_SERVICE));
+    }
+
+    @Test
+    public void testAttachBaseContext() {
+        assertTrue((new ContextThemeWrapper() {
+            public boolean test() {
+                // Set two different context to ContextThemeWrapper
+                // it should throw a exception when set it at second time.
+                // As ContextThemeWrapper is a context, we will attachBaseContext to
+                // two different ContextThemeWrapper instances.
+                try {
+                    attachBaseContext(new ContextThemeWrapper(mContext,
+                            R.style.TextAppearance));
+                } catch (IllegalStateException e) {
+                    fail("test attachBaseContext fail");
+                }
+
+                try {
+                    attachBaseContext(new ContextThemeWrapper());
+                    fail("test attachBaseContext fail");
+                } catch (IllegalStateException e) {
+                    // expected
+                }
+                return true;
+            }
+        }).test());
+    }
+
+    @Test
+    public void testApplyOverrideConfiguration() {
+        // Configuration.densityApi is only available on API 17 and above
+        if (Build.VERSION.SDK_INT >= 17) {
+            final int realDensity = mContext.getResources().getConfiguration().densityDpi;
+            final int expectedDensity = realDensity + 1;
+
+            ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(
+                    mContext, SYSTEM_DEFAULT_THEME);
+
+            Configuration overrideConfig = new Configuration();
+            overrideConfig.densityDpi = expectedDensity;
+            contextThemeWrapper.applyOverrideConfiguration(overrideConfig);
+
+            Configuration actualConfiguration =
+                    contextThemeWrapper.getResources().getConfiguration();
+            assertEquals(expectedDensity, actualConfiguration.densityDpi);
+        }
+    }
+
+    private void verifyIdenticalTextAppearanceStyle(TypedArray ta) {
+        final int defValue = -1;
+        // get Theme and assert
+        Resources.Theme expected = mContext.getResources().newTheme();
+        expected.setTo(mContext.getTheme());
+        expected.applyStyle(R.style.TextAppearance, true);
+        TypedArray expectedTa = expected.obtainStyledAttributes(R.styleable.TextAppearance);
+        assertEquals(expectedTa.getIndexCount(), ta.getIndexCount());
+        assertEquals(expectedTa.getColor(
+                android.support.v7.appcompat.R.styleable.TextAppearance_android_textColor,
+                defValue),
+                ta.getColor(
+                        android.support.v7.appcompat.R.styleable.TextAppearance_android_textColor,
+                        defValue));
+        assertEquals(expectedTa.getColor(
+                android.support.v7.appcompat.R.styleable.TextAppearance_android_textColorHint,
+                defValue),
+                ta.getColor(
+                        android.support.v7.appcompat.R.styleable
+                                .TextAppearance_android_textColorHint,
+                        defValue));
+        assertEquals(expectedTa.getColor(
+                android.support.v7.appcompat.R.styleable.TextAppearance_android_textColorLink,
+                defValue),
+                ta.getColor(
+                        android.support.v7.appcompat.R.styleable
+                                .TextAppearance_android_textColorLink,
+                        defValue));
+        assertEquals(expectedTa.getDimension(
+                android.support.v7.appcompat.R.styleable.TextAppearance_android_textSize,
+                defValue),
+                ta.getDimension(
+                        android.support.v7.appcompat.R.styleable.TextAppearance_android_textSize,
+                        defValue), 0.0f);
+        assertEquals(expectedTa.getInt(
+                android.support.v7.appcompat.R.styleable.TextAppearance_android_textStyle,
+                defValue),
+                ta.getInt(android.support.v7.appcompat.R.styleable
+                                .TextAppearance_android_textStyle,
+                        defValue));
+    }
+}
diff --git a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java
index cbc3176..eb52653 100644
--- a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java
@@ -35,6 +35,7 @@
 import android.support.annotation.ColorInt;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.MediumTest;
+import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.support.v4.content.ContextCompat;
 import android.support.v4.content.res.ResourcesCompat;
@@ -353,10 +354,11 @@
         assertEquals(Typeface.SERIF, textView.getTypeface());
     }
 
+    @SdkSuppress(minSdkVersion = 16)
     @Test
     @UiThreadTest
     public void testfontFamilyNamespaceHierarchy() {
-        // This view has fontFamilyset in both the app and android namespace. App should be used.
+        // This view has fontFamily set in both the app and android namespace. App should be used.
         TextView textView = mContainer.findViewById(R.id.textview_app_and_android_fontfamily);
 
         assertEquals(Typeface.MONOSPACE, textView.getTypeface());
diff --git a/v7/cardview/build.gradle b/v7/cardview/build.gradle
index 23d8076..a6f98e1 100644
--- a/v7/cardview/build.gradle
+++ b/v7/cardview/build.gradle
@@ -6,16 +6,16 @@
 }
 
 dependencies {
-    api project(':support-annotations')
+    api(project(":support-annotations"))
 }
 
 android {
     defaultConfig {
-        minSdkVersion 14
+        minSdkVersion(14)
     }
 
     sourceSets {
-        main.res.srcDir 'res'
+        main.res.srcDir("res")
     }
 }
 
diff --git a/v7/cardview/lint-baseline.xml b/v7/cardview/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/v7/cardview/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/v7/cardview/res/values/attrs.xml b/v7/cardview/res/values/attrs.xml
index deed51b..8bac9cc 100644
--- a/v7/cardview/res/values/attrs.xml
+++ b/v7/cardview/res/values/attrs.xml
@@ -15,6 +15,9 @@
 -->
 
 <resources>
+    <!-- Default CardView style -->
+    <attr name="cardViewStyle" format="reference" />
+
     <declare-styleable name="CardView">
         <!-- Background color for CardView. -->
         <attr name="cardBackgroundColor" format="color" />
diff --git a/v7/cardview/src/main/java/android/support/v7/widget/CardView.java b/v7/cardview/src/main/java/android/support/v7/widget/CardView.java
index 58a04f0..a45ee98 100644
--- a/v7/cardview/src/main/java/android/support/v7/widget/CardView.java
+++ b/v7/cardview/src/main/java/android/support/v7/widget/CardView.java
@@ -108,18 +108,57 @@
     final Rect mShadowBounds = new Rect();
 
     public CardView(@NonNull Context context) {
-        super(context);
-        initialize(context, null, 0);
+        this(context, null);
     }
 
     public CardView(@NonNull Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
-        initialize(context, attrs, 0);
+        this(context, attrs, R.attr.cardViewStyle);
     }
 
     public CardView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        initialize(context, attrs, defStyleAttr);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CardView, defStyleAttr,
+                R.style.CardView);
+        ColorStateList backgroundColor;
+        if (a.hasValue(R.styleable.CardView_cardBackgroundColor)) {
+            backgroundColor = a.getColorStateList(R.styleable.CardView_cardBackgroundColor);
+        } else {
+            // There isn't one set, so we'll compute one based on the theme
+            final TypedArray aa = getContext().obtainStyledAttributes(COLOR_BACKGROUND_ATTR);
+            final int themeColorBackground = aa.getColor(0, 0);
+            aa.recycle();
+
+            // If the theme colorBackground is light, use our own light color, otherwise dark
+            final float[] hsv = new float[3];
+            Color.colorToHSV(themeColorBackground, hsv);
+            backgroundColor = ColorStateList.valueOf(hsv[2] > 0.5f
+                    ? getResources().getColor(R.color.cardview_light_background)
+                    : getResources().getColor(R.color.cardview_dark_background));
+        }
+        float radius = a.getDimension(R.styleable.CardView_cardCornerRadius, 0);
+        float elevation = a.getDimension(R.styleable.CardView_cardElevation, 0);
+        float maxElevation = a.getDimension(R.styleable.CardView_cardMaxElevation, 0);
+        mCompatPadding = a.getBoolean(R.styleable.CardView_cardUseCompatPadding, false);
+        mPreventCornerOverlap = a.getBoolean(R.styleable.CardView_cardPreventCornerOverlap, true);
+        int defaultPadding = a.getDimensionPixelSize(R.styleable.CardView_contentPadding, 0);
+        mContentPadding.left = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingLeft,
+                defaultPadding);
+        mContentPadding.top = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingTop,
+                defaultPadding);
+        mContentPadding.right = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingRight,
+                defaultPadding);
+        mContentPadding.bottom = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingBottom,
+                defaultPadding);
+        if (elevation > maxElevation) {
+            maxElevation = elevation;
+        }
+        mUserSetMinWidth = a.getDimensionPixelSize(R.styleable.CardView_android_minWidth, 0);
+        mUserSetMinHeight = a.getDimensionPixelSize(R.styleable.CardView_android_minHeight, 0);
+        a.recycle();
+
+        IMPL.initialize(mCardViewDelegate, context, backgroundColor, radius,
+                elevation, maxElevation);
     }
 
     @Override
@@ -220,50 +259,6 @@
         }
     }
 
-    private void initialize(Context context, AttributeSet attrs, int defStyleAttr) {
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CardView, defStyleAttr,
-                R.style.CardView);
-        ColorStateList backgroundColor;
-        if (a.hasValue(R.styleable.CardView_cardBackgroundColor)) {
-            backgroundColor = a.getColorStateList(R.styleable.CardView_cardBackgroundColor);
-        } else {
-            // There isn't one set, so we'll compute one based on the theme
-            final TypedArray aa = getContext().obtainStyledAttributes(COLOR_BACKGROUND_ATTR);
-            final int themeColorBackground = aa.getColor(0, 0);
-            aa.recycle();
-
-            // If the theme colorBackground is light, use our own light color, otherwise dark
-            final float[] hsv = new float[3];
-            Color.colorToHSV(themeColorBackground, hsv);
-            backgroundColor = ColorStateList.valueOf(hsv[2] > 0.5f
-                    ? getResources().getColor(R.color.cardview_light_background)
-                    : getResources().getColor(R.color.cardview_dark_background));
-        }
-        float radius = a.getDimension(R.styleable.CardView_cardCornerRadius, 0);
-        float elevation = a.getDimension(R.styleable.CardView_cardElevation, 0);
-        float maxElevation = a.getDimension(R.styleable.CardView_cardMaxElevation, 0);
-        mCompatPadding = a.getBoolean(R.styleable.CardView_cardUseCompatPadding, false);
-        mPreventCornerOverlap = a.getBoolean(R.styleable.CardView_cardPreventCornerOverlap, true);
-        int defaultPadding = a.getDimensionPixelSize(R.styleable.CardView_contentPadding, 0);
-        mContentPadding.left = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingLeft,
-                defaultPadding);
-        mContentPadding.top = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingTop,
-                defaultPadding);
-        mContentPadding.right = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingRight,
-                defaultPadding);
-        mContentPadding.bottom = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingBottom,
-                defaultPadding);
-        if (elevation > maxElevation) {
-            maxElevation = elevation;
-        }
-        mUserSetMinWidth = a.getDimensionPixelSize(R.styleable.CardView_android_minWidth, 0);
-        mUserSetMinHeight = a.getDimensionPixelSize(R.styleable.CardView_android_minHeight, 0);
-        a.recycle();
-
-        IMPL.initialize(mCardViewDelegate, context, backgroundColor, radius,
-                elevation, maxElevation);
-    }
-
     @Override
     public void setMinimumWidth(int minWidth) {
         mUserSetMinWidth = minWidth;
diff --git a/v7/gridlayout/api/27.0.0.ignore b/v7/gridlayout/api/27.0.0.ignore
new file mode 100644
index 0000000..938da3f
--- /dev/null
+++ b/v7/gridlayout/api/27.0.0.ignore
@@ -0,0 +1 @@
+7420ef1
diff --git a/v7/gridlayout/api/current.txt b/v7/gridlayout/api/current.txt
index 1fc6e1d..9f12b89 100644
--- a/v7/gridlayout/api/current.txt
+++ b/v7/gridlayout/api/current.txt
@@ -15,7 +15,6 @@
     method public boolean getUseDefaultMargins();
     method public boolean isColumnOrderPreserved();
     method public boolean isRowOrderPreserved();
-    method protected void onLayout(boolean, int, int, int, int);
     method public void setAlignmentMode(int);
     method public void setColumnCount(int);
     method public void setColumnOrderPreserved(boolean);
diff --git a/v7/gridlayout/build.gradle b/v7/gridlayout/build.gradle
index 052b9db..7df5397 100644
--- a/v7/gridlayout/build.gradle
+++ b/v7/gridlayout/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,11 +7,11 @@
 }
 
 dependencies {
-    api project(':support-compat')
-    api project(':support-core-ui')
+    api(project(":support-compat"))
+    api(project(":support-core-ui"))
 
-    androidTestImplementation libs.test_runner,   { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core, { exclude module: 'support-annotations' }
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
 }
 
 android {
diff --git a/v7/gridlayout/lint-baseline.xml b/v7/gridlayout/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/v7/gridlayout/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/v7/mediarouter/build.gradle b/v7/mediarouter/build.gradle
index 09e48df..dbf3da5 100644
--- a/v7/mediarouter/build.gradle
+++ b/v7/mediarouter/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,13 +7,13 @@
 }
 
 dependencies {
-    api project(":support-media-compat")
-    api project(":appcompat-v7")
-    api project(":palette-v7")
+    api(project(":support-media-compat"))
+    api(project(":appcompat-v7"))
+    api(project(":palette-v7"))
 
-    androidTestImplementation libs.test_runner,   { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core, { exclude module: 'support-annotations' }
-    androidTestImplementation libs.test_rules
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(TEST_RULES)
 }
 
 android {
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
index cf6fc1f..cc372ec 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
@@ -2560,12 +2560,16 @@
             // TODO: Remove the following logging when no longer needed.
             if (sGlobal == null || (mBluetoothRoute != null && route.isDefault())) {
                 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
-                StringBuffer sb = new StringBuffer();
+                StringBuilder sb = new StringBuilder();
                 // callStack[3] is the caller of this method.
                 for (int i = 3; i < callStack.length; i++) {
                     StackTraceElement caller = callStack[i];
-                    sb.append(caller.getClassName() + "." + caller.getMethodName()
-                            + ":" + caller.getLineNumber()).append("  ");
+                    sb.append(caller.getClassName())
+                            .append(".")
+                            .append(caller.getMethodName())
+                            .append(":")
+                            .append(caller.getLineNumber())
+                            .append("  ");
                 }
                 if (sGlobal == null) {
                     Log.w(TAG, "setSelectedRouteInternal is called while sGlobal is null: pkgName="
diff --git a/v7/mediarouter/src/android/support/v7/media/package.html b/v7/mediarouter/src/android/support/v7/media/package.html
index 0866a42..be2aaf2 100644
--- a/v7/mediarouter/src/android/support/v7/media/package.html
+++ b/v7/mediarouter/src/android/support/v7/media/package.html
@@ -4,7 +4,6 @@
 
 <p>Contains APIs that control the routing of media channels and streams from the current device
   to external speakers and destination devices.</p>
-<p>Compatible with API level 7 and higher.</p>
 
 </body>
 </html>
diff --git a/v7/palette/build.gradle b/v7/palette/build.gradle
index 2703f2c..a1b1fc9 100644
--- a/v7/palette/build.gradle
+++ b/v7/palette/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,10 +7,10 @@
 }
 
 dependencies {
-    api project(':support-compat')
-    api project(':support-core-utils')
+    api(project(":support-compat"))
+    api(project(":support-core-utils"))
 
-    androidTestImplementation libs.test_runner, { exclude module: 'support-annotations' }
+    androidTestImplementation(TEST_RUNNER)
 }
 
 android {
diff --git a/v7/palette/lint-baseline.xml b/v7/palette/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/v7/palette/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/v7/preference/build.gradle b/v7/preference/build.gradle
index f5bc372..698afb6 100644
--- a/v7/preference/build.gradle
+++ b/v7/preference/build.gradle
@@ -14,6 +14,7 @@
  * limitations under the License
  */
 
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -22,14 +23,14 @@
 }
 
 dependencies {
-    api project(':support-v4')
-    api project(':appcompat-v7')
-    api project(':recyclerview-v7')
+    api(project(":support-v4"))
+    api(project(":appcompat-v7"))
+    api(project(":recyclerview-v7"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
 }
 
 android {
diff --git a/v7/preference/src/main/java/android/support/v7/preference/CollapsiblePreferenceGroupController.java b/v7/preference/src/main/java/android/support/v7/preference/CollapsiblePreferenceGroupController.java
index e15ca18..b63ff75 100644
--- a/v7/preference/src/main/java/android/support/v7/preference/CollapsiblePreferenceGroupController.java
+++ b/v7/preference/src/main/java/android/support/v7/preference/CollapsiblePreferenceGroupController.java
@@ -166,7 +166,7 @@
             CharSequence summary = null;
             for (int i = collapsedIndex; i < flattenedPreferenceList.size(); i++) {
                 final Preference preference = flattenedPreferenceList.get(i);
-                if (preference instanceof PreferenceGroup) {
+                if (preference instanceof PreferenceGroup || !preference.isVisible()) {
                     continue;
                 }
                 final CharSequence title = preference.getTitle();
diff --git a/v7/preference/tests/src/android/support/v7/preference/PreferenceGroupInitialExpandedChildrenCountTest.java b/v7/preference/tests/src/android/support/v7/preference/PreferenceGroupInitialExpandedChildrenCountTest.java
index 4f53b9a..499e2c1 100644
--- a/v7/preference/tests/src/android/support/v7/preference/PreferenceGroupInitialExpandedChildrenCountTest.java
+++ b/v7/preference/tests/src/android/support/v7/preference/PreferenceGroupInitialExpandedChildrenCountTest.java
@@ -188,6 +188,26 @@
     }
 
     /**
+     * Verifies that summary for the expand button only lists visible preferences.
+     */
+    @Test
+    @UiThreadTest
+    public void createPreferenceGroupAdapter_expandButtonSummaryShouldListVisiblePreferencesOnly() {
+        mScreen.setInitialExpandedChildrenCount(INITIAL_EXPANDED_COUNT);
+        mPreferenceList.get(INITIAL_EXPANDED_COUNT + 1).setVisible(false);
+        mPreferenceList.get(INITIAL_EXPANDED_COUNT + 4).setVisible(false);
+        PreferenceGroupAdapter preferenceGroupAdapter = new PreferenceGroupAdapter(mScreen);
+        // Preference 5 to Preference 9 are collapsed, only preferences 5, 7, 8 are visible
+        CharSequence summary = mPreferenceList.get(INITIAL_EXPANDED_COUNT).getTitle();
+        summary = mContext.getString(R.string.summary_collapsed_preference_list,
+                summary, mPreferenceList.get(INITIAL_EXPANDED_COUNT + 2).getTitle());
+        summary = mContext.getString(R.string.summary_collapsed_preference_list,
+                summary, mPreferenceList.get(INITIAL_EXPANDED_COUNT + 3).getTitle());
+        final Preference expandButton = preferenceGroupAdapter.getItem(INITIAL_EXPANDED_COUNT);
+        assertEquals(summary, expandButton.getSummary());
+    }
+
+    /**
      * Verifies that clicking the expand button will show all preferences.
      */
     @Test
diff --git a/v7/recyclerview/api/27.0.0.ignore b/v7/recyclerview/api/27.0.0.ignore
new file mode 100644
index 0000000..357c296
--- /dev/null
+++ b/v7/recyclerview/api/27.0.0.ignore
@@ -0,0 +1 @@
+d69e9e2
diff --git a/v7/recyclerview/api/current.txt b/v7/recyclerview/api/current.txt
index 17cd472..0909d7d 100644
--- a/v7/recyclerview/api/current.txt
+++ b/v7/recyclerview/api/current.txt
@@ -84,6 +84,9 @@
     method public void recalculatePositionOfItemAt(int);
     method public boolean remove(T);
     method public T removeItemAt(int);
+    method public void replaceAll(T[], boolean);
+    method public void replaceAll(T...);
+    method public void replaceAll(java.util.Collection<T>);
     method public int size();
     method public void updateItemAt(int, T);
     field public static final int INVALID_POSITION = -1; // 0xffffffff
@@ -190,6 +193,7 @@
     method public boolean getStackFromEnd();
     method protected boolean isLayoutRTL();
     method public boolean isSmoothScrollbarEnabled();
+    method public void prepareForDrop(android.view.View, android.view.View, int, int);
     method public void scrollToPositionWithOffset(int, int);
     method public void setInitialPrefetchItemCount(int);
     method public void setOrientation(int);
@@ -277,7 +281,7 @@
     method public int findTargetSnapPosition(android.support.v7.widget.RecyclerView.LayoutManager, int, int);
   }
 
-  public class RecyclerView extends android.view.ViewGroup {
+  public class RecyclerView extends android.view.ViewGroup implements android.support.v4.view.NestedScrollingChild2 android.support.v4.view.ScrollingView {
     ctor public RecyclerView(android.content.Context);
     ctor public RecyclerView(android.content.Context, android.util.AttributeSet);
     ctor public RecyclerView(android.content.Context, android.util.AttributeSet, int);
@@ -336,7 +340,6 @@
     method public void onChildAttachedToWindow(android.view.View);
     method public void onChildDetachedFromWindow(android.view.View);
     method public void onDraw(android.graphics.Canvas);
-    method protected void onLayout(boolean, int, int, int, int);
     method public void onScrollStateChanged(int);
     method public void onScrolled(int, int);
     method public void removeItemDecoration(android.support.v7.widget.RecyclerView.ItemDecoration);
diff --git a/v7/recyclerview/build.gradle b/v7/recyclerview/build.gradle
index daac4ab..0a83989 100644
--- a/v7/recyclerview/build.gradle
+++ b/v7/recyclerview/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,33 +7,33 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-compat')
-    api project(':support-core-ui')
+    api(project(":support-annotations"))
+    api(project(":support-compat"))
+    api(project(":support-core-ui"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.junit
-    androidTestImplementation project(':support-testutils')
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(JUNIT)
+    androidTestImplementation(project(":support-testutils"))
 
-    testImplementation libs.junit
-    testImplementation libs.mockito_core
-    testImplementation libs.test_runner, { exclude module: 'support-annotations' }
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
+    testImplementation(TEST_RUNNER)
 }
 
 android {
     defaultConfig {
-        minSdkVersion 14
+        minSdkVersion(14)
     }
 
     sourceSets {
-        main.res.srcDirs 'res', 'res-public'
+        main.res.srcDirs "res", "res-public"
     }
 
     buildTypes.all {
-        consumerProguardFiles 'proguard-rules.pro'
+        consumerProguardFiles("proguard-rules.pro")
     }
 }
 
diff --git a/v7/recyclerview/lint-baseline.xml b/v7/recyclerview/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/v7/recyclerview/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/v7/recyclerview/src/main/java/android/support/v7/util/SortedList.java b/v7/recyclerview/src/main/java/android/support/v7/util/SortedList.java
index af000a1..bd07b01 100644
--- a/v7/recyclerview/src/main/java/android/support/v7/util/SortedList.java
+++ b/v7/recyclerview/src/main/java/android/support/v7/util/SortedList.java
@@ -16,6 +16,7 @@
 
 package android.support.v7.util;
 
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
 import java.lang.reflect.Array;
@@ -51,17 +52,23 @@
     T[] mData;
 
     /**
-     * A copy of the previous list contents used during the merge phase of addAll.
+     * A reference to the previous set of data that is kept during a mutation operation (addAll or
+     * replaceAll).
      */
     private T[] mOldData;
+
+    /**
+     * The current index into mOldData that has not yet been processed during a mutation operation
+     * (addAll or replaceAll).
+     */
     private int mOldDataStart;
     private int mOldDataSize;
 
     /**
-     * The size of the valid portion of mData during the merge phase of addAll.
+     * The current index into the new data that has not yet been processed during a mutation
+     * operation (addAll or replaceAll).
      */
-    private int mMergedSize;
-
+    private int mNewDataStart;
 
     /**
      * The callback instance that controls the behavior of the SortedList and get notified when
@@ -133,7 +140,7 @@
      * @see Callback#areContentsTheSame(Object, Object)}
      */
     public int add(T item) {
-        throwIfMerging();
+        throwIfInMutationOperation();
         return add(item, true);
     }
 
@@ -142,30 +149,30 @@
      * except the callback events may be in a different order/granularity since addAll can batch
      * them for better performance.
      * <p>
-     * If allowed, may modify the input array and even take the ownership over it in order
-     * to avoid extra memory allocation during sorting and deduplication.
-     * </p>
+     * If allowed, will reference the input array during, and possibly after, the operation to avoid
+     * extra memory allocation, in which case you should not continue to reference or modify the
+     * array yourself.
+     * <p>
      * @param items Array of items to be added into the list.
-     * @param mayModifyInput If true, SortedList is allowed to modify the input.
-     * @see SortedList#addAll(Object[] items)
+     * @param mayModifyInput If true, SortedList is allowed to modify and permanently reference the
+     *                       input array.
+     * @see SortedList#addAll(T[] items)
      */
     public void addAll(T[] items, boolean mayModifyInput) {
-        throwIfMerging();
+        throwIfInMutationOperation();
         if (items.length == 0) {
             return;
         }
+
         if (mayModifyInput) {
             addAllInternal(items);
         } else {
-            T[] copy = (T[]) Array.newInstance(mTClass, items.length);
-            System.arraycopy(items, 0, copy, 0, items.length);
-            addAllInternal(copy);
+            addAllInternal(copyArray(items));
         }
-
     }
 
     /**
-     * Adds the given items to the list. Does not modify the input.
+     * Adds the given items to the list. Does not modify or retain the input.
      *
      * @see SortedList#addAll(T[] items, boolean mayModifyInput)
      *
@@ -176,7 +183,7 @@
     }
 
     /**
-     * Adds the given items to the list. Does not modify the input.
+     * Adds the given items to the list. Does not modify or retain the input.
      *
      * @see SortedList#addAll(T[] items, boolean mayModifyInput)
      *
@@ -187,26 +194,133 @@
         addAll(items.toArray(copy), true);
     }
 
+    /**
+     * Replaces the current items with the new items, dispatching {@link ListUpdateCallback} events
+     * for each change detected as appropriate.
+     * <p>
+     * If allowed, will reference the input array during, and possibly after, the operation to avoid
+     * extra memory allocation, in which case you should not continue to reference or modify the
+     * array yourself.
+     * <p>
+     * Note: this method does not detect moves or dispatch
+     * {@link ListUpdateCallback#onMoved(int, int)} events. It instead treats moves as a remove
+     * followed by an add and therefore dispatches {@link ListUpdateCallback#onRemoved(int, int)}
+     * and {@link ListUpdateCallback#onRemoved(int, int)} events.  See {@link DiffUtil} if you want
+     * your implementation to dispatch move events.
+     * <p>
+     * @param items Array of items to replace current items.
+     * @param mayModifyInput If true, SortedList is allowed to modify and permanently reference the
+     *                       input array.
+     * @see #replaceAll(T[])
+     */
+    public void replaceAll(@NonNull T[] items, boolean mayModifyInput) {
+        throwIfInMutationOperation();
+
+        if (mayModifyInput) {
+            replaceAllInternal(items);
+        } else {
+            replaceAllInternal(copyArray(items));
+        }
+    }
+
+    /**
+     * Replaces the current items with the new items, dispatching {@link ListUpdateCallback} events
+     * for each change detected as appropriate.  Does not modify or retain the input.
+     *
+     * @see #replaceAll(T[], boolean)
+     *
+     * @param items Array of items to replace current items.
+     */
+    public void replaceAll(@NonNull T... items) {
+        replaceAll(items, false);
+    }
+
+    /**
+     * Replaces the current items with the new items, dispatching {@link ListUpdateCallback} events
+     * for each change detected as appropriate. Does not modify or retain the input.
+     *
+     * @see #replaceAll(T[], boolean)
+     *
+     * @param items Array of items to replace current items.
+     */
+    public void replaceAll(@NonNull Collection<T> items) {
+        T[] copy = (T[]) Array.newInstance(mTClass, items.size());
+        replaceAll(items.toArray(copy), true);
+    }
+
     private void addAllInternal(T[] newItems) {
+        if (newItems.length < 1) {
+            return;
+        }
+
+        final int newSize = sortAndDedup(newItems);
+
+        if (mSize == 0) {
+            mData = newItems;
+            mSize = newSize;
+            mCallback.onInserted(0, newSize);
+        } else {
+            merge(newItems, newSize);
+        }
+    }
+
+    private void replaceAllInternal(@NonNull T[] newData) {
         final boolean forceBatchedUpdates = !(mCallback instanceof BatchedCallback);
         if (forceBatchedUpdates) {
             beginBatchedUpdates();
         }
 
-        mOldData = mData;
         mOldDataStart = 0;
         mOldDataSize = mSize;
+        mOldData = mData;
 
-        Arrays.sort(newItems, mCallback);  // Arrays.sort is stable.
+        mNewDataStart = 0;
+        int newSize = sortAndDedup(newData);
+        mData = (T[]) Array.newInstance(mTClass, newSize);
 
-        final int newSize = deduplicate(newItems);
-        if (mSize == 0) {
-            mData = newItems;
-            mSize = newSize;
-            mMergedSize = newSize;
-            mCallback.onInserted(0, newSize);
-        } else {
-            merge(newItems, newSize);
+        while (mNewDataStart < newSize || mOldDataStart < mOldDataSize) {
+            if (mOldDataStart >= mOldDataSize) {
+                int insertIndex = mNewDataStart;
+                int itemCount = newSize - mNewDataStart;
+                System.arraycopy(newData, insertIndex, mData, insertIndex, itemCount);
+                mNewDataStart += itemCount;
+                mSize += itemCount;
+                mCallback.onInserted(insertIndex, itemCount);
+                break;
+            }
+            if (mNewDataStart >= newSize) {
+                int itemCount = mOldDataSize - mOldDataStart;
+                mSize -= itemCount;
+                mCallback.onRemoved(mNewDataStart, itemCount);
+                break;
+            }
+
+            T oldItem = mOldData[mOldDataStart];
+            T newItem = newData[mNewDataStart];
+
+            int result = mCallback.compare(oldItem, newItem);
+            if (result < 0) {
+                replaceAllRemove();
+            } else if (result > 0) {
+                replaceAllInsert(newItem);
+            } else {
+                if (!mCallback.areItemsTheSame(oldItem, newItem)) {
+                    // The items aren't the same even though they were supposed to occupy the same
+                    // place, so both notify to remove and add an item in the current location.
+                    replaceAllRemove();
+                    replaceAllInsert(newItem);
+                } else {
+                    mData[mNewDataStart] = newItem;
+                    mOldDataStart++;
+                    mNewDataStart++;
+                    if (!mCallback.areContentsTheSame(oldItem, newItem)) {
+                        // The item is the same but the contents have changed, so notify that an
+                        // onChanged event has occurred.
+                        mCallback.onChanged(mNewDataStart - 1, 1,
+                                mCallback.getChangePayload(oldItem, newItem));
+                    }
+                }
+            }
         }
 
         mOldData = null;
@@ -216,17 +330,33 @@
         }
     }
 
+    private void replaceAllInsert(T newItem) {
+        mData[mNewDataStart] = newItem;
+        mNewDataStart++;
+        mSize++;
+        mCallback.onInserted(mNewDataStart - 1, 1);
+    }
+
+    private void replaceAllRemove() {
+        mSize--;
+        mOldDataStart++;
+        mCallback.onRemoved(mNewDataStart, 1);
+    }
+
     /**
-     * Remove duplicate items, leaving only the last item from each group of "same" items.
-     * Move the remaining items to the beginning of the array.
+     * Sorts and removes duplicate items, leaving only the last item from each group of "same"
+     * items. Move the remaining items to the beginning of the array.
      *
      * @return Number of deduplicated items at the beginning of the array.
      */
-    private int deduplicate(T[] items) {
+    private int sortAndDedup(@NonNull T[] items) {
         if (items.length == 0) {
-            throw new IllegalArgumentException("Input array must be non-empty");
+            return 0;
         }
 
+        // Arrays.sort is stable.
+        Arrays.sort(items, mCallback);
+
         // Keep track of the range of equal items at the end of the output.
         // Start with the range containing just the first item.
         int rangeStart = 0;
@@ -236,9 +366,6 @@
             T currentItem = items[i];
 
             int compare = mCallback.compare(items[rangeStart], currentItem);
-            if (compare > 0) {
-                throw new IllegalArgumentException("Input must be sorted in ascending order.");
-            }
 
             if (compare == 0) {
                 // The range of equal items continues, update it.
@@ -278,27 +405,36 @@
      * This method assumes that newItems are sorted and deduplicated.
      */
     private void merge(T[] newData, int newDataSize) {
+        final boolean forceBatchedUpdates = !(mCallback instanceof BatchedCallback);
+        if (forceBatchedUpdates) {
+            beginBatchedUpdates();
+        }
+
+        mOldData = mData;
+        mOldDataStart = 0;
+        mOldDataSize = mSize;
+
         final int mergedCapacity = mSize + newDataSize + CAPACITY_GROWTH;
         mData = (T[]) Array.newInstance(mTClass, mergedCapacity);
-        mMergedSize = 0;
+        mNewDataStart = 0;
 
         int newDataStart = 0;
         while (mOldDataStart < mOldDataSize || newDataStart < newDataSize) {
             if (mOldDataStart == mOldDataSize) {
                 // No more old items, copy the remaining new items.
                 int itemCount = newDataSize - newDataStart;
-                System.arraycopy(newData, newDataStart, mData, mMergedSize, itemCount);
-                mMergedSize += itemCount;
+                System.arraycopy(newData, newDataStart, mData, mNewDataStart, itemCount);
+                mNewDataStart += itemCount;
                 mSize += itemCount;
-                mCallback.onInserted(mMergedSize - itemCount, itemCount);
+                mCallback.onInserted(mNewDataStart - itemCount, itemCount);
                 break;
             }
 
             if (newDataStart == newDataSize) {
                 // No more new items, copy the remaining old items.
                 int itemCount = mOldDataSize - mOldDataStart;
-                System.arraycopy(mOldData, mOldDataStart, mData, mMergedSize, itemCount);
-                mMergedSize += itemCount;
+                System.arraycopy(mOldData, mOldDataStart, mData, mNewDataStart, itemCount);
+                mNewDataStart += itemCount;
                 break;
             }
 
@@ -307,36 +443,47 @@
             int compare = mCallback.compare(oldItem, newItem);
             if (compare > 0) {
                 // New item is lower, output it.
-                mData[mMergedSize++] = newItem;
+                mData[mNewDataStart++] = newItem;
                 mSize++;
                 newDataStart++;
-                mCallback.onInserted(mMergedSize - 1, 1);
+                mCallback.onInserted(mNewDataStart - 1, 1);
             } else if (compare == 0 && mCallback.areItemsTheSame(oldItem, newItem)) {
                 // Items are the same. Output the new item, but consume both.
-                mData[mMergedSize++] = newItem;
+                mData[mNewDataStart++] = newItem;
                 newDataStart++;
                 mOldDataStart++;
                 if (!mCallback.areContentsTheSame(oldItem, newItem)) {
-                    mCallback.onChanged(mMergedSize - 1, 1,
+                    mCallback.onChanged(mNewDataStart - 1, 1,
                             mCallback.getChangePayload(oldItem, newItem));
                 }
             } else {
                 // Old item is lower than or equal to (but not the same as the new). Output it.
                 // New item with the same sort order will be inserted later.
-                mData[mMergedSize++] = oldItem;
+                mData[mNewDataStart++] = oldItem;
                 mOldDataStart++;
             }
         }
-    }
 
-    private void throwIfMerging() {
-        if (mOldData != null) {
-            throw new IllegalStateException("Cannot call this method from within addAll");
+        mOldData = null;
+
+        if (forceBatchedUpdates) {
+            endBatchedUpdates();
         }
     }
 
     /**
-     * Batches adapter updates that happen between calling this method until calling
+     * Throws an exception if called while we are in the middle of a mutation operation (addAll or
+     * replaceAll).
+     */
+    private void throwIfInMutationOperation() {
+        if (mOldData != null) {
+            throw new IllegalStateException("Data cannot be mutated in the middle of a batch "
+                    + "update operation such as addAll or replaceAll.");
+        }
+    }
+
+    /**
+     * Batches adapter updates that happen after calling this method and before calling
      * {@link #endBatchedUpdates()}. For example, if you add multiple items in a loop
      * and they are placed into consecutive indices, SortedList calls
      * {@link Callback#onInserted(int, int)} only once with the proper item count. If an event
@@ -368,7 +515,7 @@
      * has no effect.
      */
     public void beginBatchedUpdates() {
-        throwIfMerging();
+        throwIfInMutationOperation();
         if (mCallback instanceof BatchedCallback) {
             return;
         }
@@ -382,7 +529,7 @@
      * Ends the update transaction and dispatches any remaining event to the callback.
      */
     public void endBatchedUpdates() {
-        throwIfMerging();
+        throwIfInMutationOperation();
         if (mCallback instanceof BatchedCallback) {
             ((BatchedCallback) mCallback).dispatchLastEvent();
         }
@@ -424,7 +571,7 @@
      * @return True if item is removed, false if item cannot be found in the list.
      */
     public boolean remove(T item) {
-        throwIfMerging();
+        throwIfInMutationOperation();
         return remove(item, true);
     }
 
@@ -436,7 +583,7 @@
      * @return The removed item.
      */
     public T removeItemAt(int index) {
-        throwIfMerging();
+        throwIfInMutationOperation();
         T item = get(index);
         removeItemAtIndex(index, true);
         return item;
@@ -481,7 +628,7 @@
      * @see #add(Object)
      */
     public void updateItemAt(int index, T item) {
-        throwIfMerging();
+        throwIfInMutationOperation();
         final T existing = get(index);
         // assume changed if the same object is given back
         boolean contentsChanged = existing == item || !mCallback.areContentsTheSame(existing, item);
@@ -535,7 +682,7 @@
      * @see #add(Object)
      */
     public void recalculatePositionOfItemAt(int index) {
-        throwIfMerging();
+        throwIfInMutationOperation();
         // TODO can be improved
         final T item = get(index);
         removeItemAtIndex(index, false);
@@ -562,8 +709,8 @@
         if (mOldData != null) {
             // The call is made from a callback during addAll execution. The data is split
             // between mData and mOldData.
-            if (index >= mMergedSize) {
-                return mOldData[index - mMergedSize + mOldDataStart];
+            if (index >= mNewDataStart) {
+                return mOldData[index - mNewDataStart + mOldDataStart];
             }
         }
         return mData[index];
@@ -579,13 +726,13 @@
      */
     public int indexOf(T item) {
         if (mOldData != null) {
-            int index = findIndexOf(item, mData, 0, mMergedSize, LOOKUP);
+            int index = findIndexOf(item, mData, 0, mNewDataStart, LOOKUP);
             if (index != INVALID_POSITION) {
                 return index;
             }
             index = findIndexOf(item, mOldData, mOldDataStart, mOldDataSize, LOOKUP);
             if (index != INVALID_POSITION) {
-                return index - mOldDataStart + mMergedSize;
+                return index - mOldDataStart + mNewDataStart;
             }
             return INVALID_POSITION;
         }
@@ -662,11 +809,17 @@
         mSize++;
     }
 
+    private T[] copyArray(T[] items) {
+        T[] copy = (T[]) Array.newInstance(mTClass, items.length);
+        System.arraycopy(items, 0, copy, 0, items.length);
+        return copy;
+    }
+
     /**
      * Removes all items from the SortedList.
      */
     public void clear() {
-        throwIfMerging();
+        throwIfInMutationOperation();
         if (mSize == 0) {
             return;
         }
@@ -722,8 +875,8 @@
          * so
          * that you can change its behavior depending on your UI.
          * <p>
-         * For example, if you are using SortedList with a {@link android.support.v7.widget.RecyclerView.Adapter
-         * RecyclerView.Adapter}, you should
+         * For example, if you are using SortedList with a
+         * {@link android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}, you should
          * return whether the items' visual representations are the same or not.
          *
          * @param oldItem The previous representation of the object.
@@ -734,7 +887,7 @@
         abstract public boolean areContentsTheSame(T2 oldItem, T2 newItem);
 
         /**
-         * Called by the SortedList to decide whether two object represent the same Item or not.
+         * Called by the SortedList to decide whether two objects represent the same Item or not.
          * <p>
          * For example, if your items have unique ids, this method should check their equality.
          *
diff --git a/v7/recyclerview/src/main/java/android/support/v7/widget/RecyclerView.java b/v7/recyclerview/src/main/java/android/support/v7/widget/RecyclerView.java
index c8b51a4..4a65553 100644
--- a/v7/recyclerview/src/main/java/android/support/v7/widget/RecyclerView.java
+++ b/v7/recyclerview/src/main/java/android/support/v7/widget/RecyclerView.java
@@ -2001,7 +2001,7 @@
             }
             mEatRequestLayout = 1;
         }
-        if (!performLayoutChildren) {
+        if (!performLayoutChildren && !mLayoutFrozen) {
             // Reset the layout request eaten counter.
             // This is necessary since eatRequest calls can be nested in which case the other
             // call will override the inner one.
@@ -2520,9 +2520,17 @@
         if (next == null || next == this) {
             return false;
         }
+        // panic, result view is not a child anymore, maybe workaround b/37864393
+        if (findContainingItemView(next) == null) {
+            return false;
+        }
         if (focused == null) {
             return true;
         }
+        // panic, focused view is not a child anymore, maybe workaround b/37864393
+        if (findContainingItemView(focused) == null) {
+            return true;
+        }
 
         mTempRect.set(0, 0, focused.getWidth(), focused.getHeight());
         mTempRect2.set(0, 0, next.getWidth(), next.getHeight());
@@ -3232,7 +3240,8 @@
     }
 
     /**
-     * Used when onMeasure is called before layout manager is set
+     * An implementation of {@link View#onMeasure(int, int)} to fall back to in various scenarios
+     * where this RecyclerView is otherwise lacking better information.
      */
     void defaultOnMeasure(int widthSpec, int heightSpec) {
         // calling LayoutManager here is not pretty but that API is already public and it is better
@@ -6536,7 +6545,8 @@
          * @see #getItemViewType(int)
          * @see #onBindViewHolder(ViewHolder, int)
          */
-        public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
+        @NonNull
+        public abstract VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType);
 
         /**
          * Called by RecyclerView to display the data at the specified position. This method should
@@ -6558,7 +6568,7 @@
          *        item at the given position in the data set.
          * @param position The position of the item within the adapter's data set.
          */
-        public abstract void onBindViewHolder(VH holder, int position);
+        public abstract void onBindViewHolder(@NonNull VH holder, int position);
 
         /**
          * Called by RecyclerView to display the data at the specified position. This method
@@ -6589,7 +6599,8 @@
          * @param payloads A non-null list of merged payloads. Can be empty list if requires full
          *                 update.
          */
-        public void onBindViewHolder(VH holder, int position, List<Object> payloads) {
+        public void onBindViewHolder(@NonNull VH holder, int position,
+                @NonNull List<Object> payloads) {
             onBindViewHolder(holder, position);
         }
 
@@ -6599,7 +6610,7 @@
          *
          * @see #onCreateViewHolder(ViewGroup, int)
          */
-        public final VH createViewHolder(ViewGroup parent, int viewType) {
+        public final VH createViewHolder(@NonNull ViewGroup parent, int viewType) {
             TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG);
             final VH holder = onCreateViewHolder(parent, viewType);
             holder.mItemViewType = viewType;
@@ -6614,7 +6625,7 @@
          *
          * @see #onBindViewHolder(ViewHolder, int)
          */
-        public final void bindViewHolder(VH holder, int position) {
+        public final void bindViewHolder(@NonNull VH holder, int position) {
             holder.mPosition = position;
             if (hasStableIds()) {
                 holder.mItemId = getItemId(position);
@@ -6711,7 +6722,7 @@
          *
          * @param holder The ViewHolder for the view being recycled
          */
-        public void onViewRecycled(VH holder) {
+        public void onViewRecycled(@NonNull VH holder) {
         }
 
         /**
@@ -6748,7 +6759,7 @@
          * RecyclerView will check the View's transient state again before giving a final decision.
          * Default implementation returns false.
          */
-        public boolean onFailedToRecycleView(VH holder) {
+        public boolean onFailedToRecycleView(@NonNull VH holder) {
             return false;
         }
 
@@ -6762,7 +6773,7 @@
          *
          * @param holder Holder of the view being attached
          */
-        public void onViewAttachedToWindow(VH holder) {
+        public void onViewAttachedToWindow(@NonNull VH holder) {
         }
 
         /**
@@ -6774,7 +6785,7 @@
          *
          * @param holder Holder of the view being detached
          */
-        public void onViewDetachedFromWindow(VH holder) {
+        public void onViewDetachedFromWindow(@NonNull VH holder) {
         }
 
         /**
@@ -6802,7 +6813,7 @@
          *
          * @see #unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver)
          */
-        public void registerAdapterDataObserver(AdapterDataObserver observer) {
+        public void registerAdapterDataObserver(@NonNull AdapterDataObserver observer) {
             mObservable.registerObserver(observer);
         }
 
@@ -6816,7 +6827,7 @@
          *
          * @see #registerAdapterDataObserver(RecyclerView.AdapterDataObserver)
          */
-        public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
+        public void unregisterAdapterDataObserver(@NonNull AdapterDataObserver observer) {
             mObservable.unregisterObserver(observer);
         }
 
@@ -6828,7 +6839,7 @@
          * @param recyclerView The RecyclerView instance which started observing this adapter.
          * @see #onDetachedFromRecyclerView(RecyclerView)
          */
-        public void onAttachedToRecyclerView(RecyclerView recyclerView) {
+        public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
         }
 
         /**
@@ -6837,7 +6848,7 @@
          * @param recyclerView The RecyclerView instance which stopped observing this adapter.
          * @see #onAttachedToRecyclerView(RecyclerView)
          */
-        public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
+        public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
         }
 
         /**
@@ -6913,7 +6924,7 @@
          *
          * @see #notifyItemRangeChanged(int, int)
          */
-        public final void notifyItemChanged(int position, Object payload) {
+        public final void notifyItemChanged(int position, @Nullable Object payload) {
             mObservable.notifyItemRangeChanged(position, 1, payload);
         }
 
@@ -6961,7 +6972,8 @@
          *
          * @see #notifyItemChanged(int)
          */
-        public final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {
+        public final void notifyItemRangeChanged(int positionStart, int itemCount,
+                @Nullable Object payload) {
             mObservable.notifyItemRangeChanged(positionStart, itemCount, payload);
         }
 
@@ -7435,9 +7447,10 @@
          * wants to handle the layout measurements itself.
          * <p>
          * This method is usually called by the LayoutManager with value {@code true} if it wants
-         * to support WRAP_CONTENT. If you are using a public LayoutManager but want to customize
-         * the measurement logic, you can call this method with {@code false} and override
-         * {@link LayoutManager#onMeasure(int, int)} to implement your custom measurement logic.
+         * to support {@link ViewGroup.LayoutParams#WRAP_CONTENT}. If you are using a public
+         * LayoutManager but want to customize the measurement logic, you can call this method with
+         * {@code false} and override {@link LayoutManager#onMeasure(Recycler, State, int, int)} to
+         * implement your custom measurement logic.
          * <p>
          * AutoMeasure is a convenience mechanism for LayoutManagers to easily wrap their content or
          * handle various specs provided by the RecyclerView's parent.
@@ -7511,24 +7524,26 @@
         }
 
         /**
-         * Returns whether this LayoutManager supports automatic item animations.
-         * A LayoutManager wishing to support item animations should obey certain
-         * rules as outlined in {@link #onLayoutChildren(Recycler, State)}.
-         * The default return value is <code>false</code>, so subclasses of LayoutManager
-         * will not get predictive item animations by default.
-         *
-         * <p>Whether item animations are enabled in a RecyclerView is determined both
-         * by the return value from this method and the
+         * Returns whether this LayoutManager supports "predictive item animations".
+         * <p>
+         * "Predictive item animations" are automatically created animations that show
+         * where items came from, and where they are going to, as items are added, removed,
+         * or moved within a layout.
+         * <p>
+         * A LayoutManager wishing to support predictive item animations must override this
+         * method to return true (the default implementation returns false) and must obey certain
+         * behavioral contracts outlined in {@link #onLayoutChildren(Recycler, State)}.
+         * <p>
+         * Whether item animations actually occur in a RecyclerView is actually determined by both
+         * the return value from this method and the
          * {@link RecyclerView#setItemAnimator(ItemAnimator) ItemAnimator} set on the
          * RecyclerView itself. If the RecyclerView has a non-null ItemAnimator but this
-         * method returns false, then simple item animations will be enabled, in which
-         * views that are moving onto or off of the screen are simply faded in/out. If
-         * the RecyclerView has a non-null ItemAnimator and this method returns true,
-         * then there will be two calls to {@link #onLayoutChildren(Recycler, State)} to
-         * setup up the information needed to more intelligently predict where appearing
-         * and disappearing views should be animated from/to.</p>
+         * method returns false, then only "simple item animations" will be enabled in the
+         * RecyclerView, in which views whose position are changing are simply faded in/out. If the
+         * RecyclerView has a non-null ItemAnimator and this method returns true, then predictive
+         * item animations will be enabled in the RecyclerView.
          *
-         * @return true if predictive item animations should be enabled, false otherwise
+         * @return true if this LayoutManager supports predictive item animations, false otherwise.
          */
         public boolean supportsPredictiveItemAnimations() {
             return false;
@@ -10822,8 +10837,12 @@
          */
         private void onEnteredHiddenState(RecyclerView parent) {
             // While the view item is in hidden state, make it invisible for the accessibility.
-            mWasImportantForAccessibilityBeforeHidden =
-                    ViewCompat.getImportantForAccessibility(itemView);
+            if (mPendingAccessibilityState != PENDING_ACCESSIBILITY_STATE_NOT_SET) {
+                mWasImportantForAccessibilityBeforeHidden = mPendingAccessibilityState;
+            } else {
+                mWasImportantForAccessibilityBeforeHidden =
+                        ViewCompat.getImportantForAccessibility(itemView);
+            }
             parent.setChildImportantForAccessibilityInternal(this,
                     ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
         }
@@ -11182,7 +11201,7 @@
             // do nothing
         }
 
-        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
+        public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
             // fallback to onItemRangeChanged(positionStart, itemCount) if app
             // does not override this method.
             onItemRangeChanged(positionStart, itemCount);
@@ -11659,7 +11678,8 @@
             notifyItemRangeChanged(positionStart, itemCount, null);
         }
 
-        public void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {
+        public void notifyItemRangeChanged(int positionStart, int itemCount,
+                @Nullable Object payload) {
             // since onItemRangeChanged() is implemented by the app, it could do anything, including
             // removing itself from {@link mObservers} - and that could cause problems if
             // an iterator is used on the ArrayList {@link mObservers}.
@@ -11813,6 +11833,11 @@
 
         boolean mStructureChanged = false;
 
+        /**
+         * True if the associated {@link RecyclerView} is in the pre-layout step where it is having
+         * its {@link LayoutManager} layout items where they will be at the beginning of a set of
+         * predictive item animations.
+         */
         boolean mInPreLayout = false;
 
         boolean mTrackOldChangeHolders = false;
@@ -11888,8 +11913,9 @@
         }
 
         /**
-         * Returns true if
-         * @return
+         * Returns true if the {@link RecyclerView} is in the pre-layout step where it is having its
+         * {@link LayoutManager} layout items where they will be at the beginning of a set of
+         * predictive item animations.
          */
         public boolean isPreLayout() {
             return mInPreLayout;
@@ -12046,6 +12072,7 @@
                     + "mTargetPosition=" + mTargetPosition
                     + ", mData=" + mData
                     + ", mItemCount=" + mItemCount
+                    + ", mIsMeasuring=" + mIsMeasuring
                     + ", mPreviousLayoutItemCount=" + mPreviousLayoutItemCount
                     + ", mDeletedInvisibleItemCountSincePreviousLayout="
                     + mDeletedInvisibleItemCountSincePreviousLayout
diff --git a/v7/recyclerview/src/main/java/android/support/v7/widget/helper/ItemTouchHelper.java b/v7/recyclerview/src/main/java/android/support/v7/widget/helper/ItemTouchHelper.java
index aee48df..d2b6a20 100644
--- a/v7/recyclerview/src/main/java/android/support/v7/widget/helper/ItemTouchHelper.java
+++ b/v7/recyclerview/src/main/java/android/support/v7/widget/helper/ItemTouchHelper.java
@@ -457,7 +457,7 @@
             destroyCallbacks();
         }
         mRecyclerView = recyclerView;
-        if (mRecyclerView != null) {
+        if (recyclerView != null) {
             final Resources resources = recyclerView.getResources();
             mSwipeEscapeVelocity = resources
                     .getDimension(R.dimen.item_touch_helper_swipe_escape_velocity);
diff --git a/v7/recyclerview/src/test/java/android/support/v7/util/SortedListTest.java b/v7/recyclerview/src/test/java/android/support/v7/util/SortedListTest.java
index 47d2ac0..f8bc496 100644
--- a/v7/recyclerview/src/test/java/android/support/v7/util/SortedListTest.java
+++ b/v7/recyclerview/src/test/java/android/support/v7/util/SortedListTest.java
@@ -27,11 +27,15 @@
 import org.junit.runners.JUnit4;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Queue;
 import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
 
 @RunWith(JUnit4.class)
 @SmallTest
@@ -44,6 +48,8 @@
     List<Pair> mUpdates = new ArrayList<Pair>();
     private boolean mPayloadChanges = false;
     List<PayloadChange> mPayloadUpdates = new ArrayList<>();
+    Queue<AssertListStateRunnable> mCallbackRunnables;
+    List<Event> mEvents = new ArrayList<>();
     private SortedList.Callback<Item> mCallback;
     InsertedCallback<Item> mInsertedCallback;
     ChangedCallback<Item> mChangedCallback;
@@ -67,6 +73,7 @@
     @Before
     public void setUp() throws Exception {
         super.setUp();
+
         mCallback = new SortedList.Callback<Item>() {
             @Override
             public int compare(Item o1, Item o2) {
@@ -75,28 +82,35 @@
 
             @Override
             public void onInserted(int position, int count) {
+                mEvents.add(new Event(TYPE.ADD, position, count));
                 mAdditions.add(new Pair(position, count));
                 if (mInsertedCallback != null) {
                     mInsertedCallback.onInserted(position, count);
                 }
+                pollAndRun(mCallbackRunnables);
             }
 
             @Override
             public void onRemoved(int position, int count) {
+                mEvents.add(new Event(TYPE.REMOVE, position, count));
                 mRemovals.add(new Pair(position, count));
+                pollAndRun(mCallbackRunnables);
             }
 
             @Override
             public void onMoved(int fromPosition, int toPosition) {
+                mEvents.add(new Event(TYPE.MOVE, fromPosition, toPosition));
                 mMoves.add(new Pair(fromPosition, toPosition));
             }
 
             @Override
             public void onChanged(int position, int count) {
+                mEvents.add(new Event(TYPE.CHANGE, position, count));
                 mUpdates.add(new Pair(position, count));
                 if (mChangedCallback != null) {
                     mChangedCallback.onChanged(position, count);
                 }
+                pollAndRun(mCallbackRunnables);
             }
 
             @Override
@@ -110,7 +124,7 @@
 
             @Override
             public boolean areContentsTheSame(Item oldItem, Item newItem) {
-                return oldItem.cmpField == newItem.cmpField && oldItem.data == newItem.data;
+                return oldItem.data == newItem.data;
             }
 
             @Override
@@ -127,11 +141,41 @@
                 return null;
             }
         };
-        mInsertedCallback = null;
-        mChangedCallback = null;
         mList = new SortedList<Item>(Item.class, mCallback);
     }
 
+    private void pollAndRun(Queue<AssertListStateRunnable> queue) {
+        if (queue != null) {
+            Runnable runnable = queue.poll();
+            assertNotNull(runnable);
+            runnable.run();
+        }
+    }
+
+    @Test
+    public void testValidMethodsDuringOnInsertedCallbackFromEmptyList() {
+
+        final Item[] items =
+                new Item[] {new Item(0), new Item(1), new Item(2)};
+
+        final AtomicInteger atomicInteger = new AtomicInteger(0);
+        mInsertedCallback = new InsertedCallback<Item>() {
+            @Override
+            public void onInserted(int position, int count) {
+                for (int i = 0; i < count; i++) {
+                    assertEquals(mList.get(i), items[i]);
+                    assertEquals(mList.indexOf(items[i]), i);
+                    atomicInteger.incrementAndGet();
+                }
+            }
+        };
+
+        mList.add(items[0]);
+        mList.clear();
+        mList.addAll(items, false);
+        assertEquals(4, atomicInteger.get());
+    }
+
     @Test
     public void testEmpty() {
         assertEquals("empty", mList.size(), 0);
@@ -139,16 +183,16 @@
 
     @Test
     public void testAdd() {
-        Item item = new Item();
+        Item item = new Item(1);
         assertEquals(insert(item), 0);
         assertEquals(size(), 1);
         assertTrue(mAdditions.contains(new Pair(0, 1)));
-        Item item2 = new Item();
+        Item item2 = new Item(2);
         item2.cmpField = item.cmpField + 1;
         assertEquals(insert(item2), 1);
         assertEquals(size(), 2);
         assertTrue(mAdditions.contains(new Pair(1, 1)));
-        Item item3 = new Item();
+        Item item3 = new Item(3);
         item3.cmpField = item.cmpField - 1;
         mAdditions.clear();
         assertEquals(insert(item3), 0);
@@ -158,9 +202,8 @@
 
     @Test
     public void testAddDuplicate() {
-        Item item = new Item();
-        Item item2 = new Item(item.id, item.cmpField);
-        item2.data = item.data;
+        Item item = new Item(1);
+        Item item2 = new Item(item.id);
         insert(item);
         assertEquals(0, insert(item2));
         assertEquals(1, size());
@@ -170,7 +213,7 @@
 
     @Test
     public void testRemove() {
-        Item item = new Item();
+        Item item = new Item(1);
         assertFalse(remove(item));
         assertEquals(0, mRemovals.size());
         insert(item);
@@ -184,8 +227,8 @@
 
     @Test
     public void testRemove2() {
-        Item item = new Item();
-        Item item2 = new Item(item.cmpField);
+        Item item = new Item(1);
+        Item item2 = new Item(2, 1, 1);
         insert(item);
         assertFalse(remove(item2));
         assertEquals(0, mRemovals.size());
@@ -218,11 +261,12 @@
         Random random = new Random(System.nanoTime());
         List<Item> copy = new ArrayList<Item>();
         StringBuilder log = new StringBuilder();
+        int id = 1;
         try {
             for (int i = 0; i < 10000; i++) {
                 switch (random.nextInt(3)) {
                     case 0://ADD
-                        Item item = new Item();
+                        Item item = new Item(id++);
                         copy.add(item);
                         insert(item);
                         log.append("add ").append(item).append("\n");
@@ -241,12 +285,13 @@
                             int index = random.nextInt(mList.size());
                             item = mList.get(index);
                             // TODO this cannot work
-                            Item newItem = new Item(item.id, item.cmpField);
-                            log.append("update ").append(item).append(" to ").append(newItem)
-                                    .append("\n");
+                            Item newItem =
+                                    new Item(item.id, item.cmpField, random.nextInt(1000));
                             while (newItem.data == item.data) {
                                 newItem.data = random.nextInt(1000);
                             }
+                            log.append("update ").append(item).append(" to ").append(newItem)
+                                    .append("\n");
                             int itemIndex = mList.add(newItem);
                             copy.remove(item);
                             copy.add(newItem);
@@ -258,10 +303,12 @@
                         if (copy.size() > 0) {
                             int index = random.nextInt(mList.size());
                             item = mList.get(index);
-                            Item newItem = new Item(item.id, random.nextInt());
+                            Item newItem = new Item(item.id, random.nextInt(), random.nextInt());
                             mList.updateItemAt(index, newItem);
                             copy.remove(item);
                             copy.add(newItem);
+                            log.append("update at ").append(index).append(" ").append(item)
+                                    .append(" to ").append(newItem).append("\n");
                         }
                 }
                 int lastCmp = Integer.MIN_VALUE;
@@ -299,14 +346,21 @@
         Item[] items = new Item[count];
         int id = idFrom;
         for (int i = 0; i < count; i++) {
-            Item item = new Item(id, id);
-            item.data = id;
+            Item item = new Item(id);
             items[i] = item;
             id += idStep;
         }
         return items;
     }
 
+    private static Item[] createItemsFromInts(int ... ints) {
+        Item[] items = new Item[ints.length];
+        for (int i = ints.length - 1; i >= 0; i--) {
+            items[i] = new Item(ints[i]);
+        }
+        return items;
+    }
+
     private static Item[] shuffle(Item[] items) {
         Random random = new Random(System.nanoTime());
         final int count = items.length;
@@ -493,8 +547,7 @@
             int uniqueId = 0;
             for (int cmpField = 0; cmpField < maxCmpField; cmpField++) {
                 for (int id = 0; id < idsPerCmpField; id++) {
-                    Item item = new Item(uniqueId++, cmpField);
-                    item.data = generation;
+                    Item item = new Item(uniqueId++, cmpField, generation);
                     items[index++] = item;
                 }
             }
@@ -548,13 +601,13 @@
     @Test
     public void testAddAllStableSort() {
         int id = 0;
-        Item item = new Item(id++, 0);
+        Item item = new Item(id++, 0, 0);
         mList.add(item);
 
         // Create a few items with the same sort order.
         Item[] items = new Item[3];
         for (int i = 0; i < 3; i++) {
-            items[i] = new Item(id++, item.cmpField);
+            items[i] = new Item(id++, item.cmpField, 0);
             assertEquals(0, mCallback.compare(item, items[i]));
         }
 
@@ -576,6 +629,7 @@
             item.data = 1;
         }
 
+
         mInsertedCallback = new InsertedCallback<Item>() {
             @Override
             public void onInserted(int position, int count) {
@@ -585,6 +639,7 @@
                     assertEquals(i * 2, mList.get(i).id);
                 }
                 assertIntegrity(5, "onInserted(" + position + ", " + count + ")");
+
             }
         };
 
@@ -639,7 +694,7 @@
             @Override
             public void onInserted(int position, int count) {
                 try {
-                    mList.add(new Item());
+                    mList.add(new Item(1));
                     fail("add must throw from within a callback");
                 } catch (IllegalStateException e) {
                 }
@@ -729,14 +784,14 @@
     @Test
     public void testAddExistingItemCallsChangeWithPayload() {
         mList.addAll(
-                new Item(1, 10),
-                new Item(2, 20),
-                new Item(3, 30)
+                new Item(1),
+                new Item(2),
+                new Item(3)
         );
         mPayloadChanges = true;
 
         // add an item with the same id but a new data field i.e. send an update
-        final Item twoUpdate = new Item(2, 20);
+        final Item twoUpdate = new Item(2);
         twoUpdate.data = 1337;
         mList.add(twoUpdate);
         assertEquals(1, mPayloadUpdates.size());
@@ -750,14 +805,14 @@
     @Test
     public void testUpdateItemCallsChangeWithPayload() {
         mList.addAll(
-                new Item(1, 10),
-                new Item(2, 20),
-                new Item(3, 30)
+                new Item(1),
+                new Item(2),
+                new Item(3)
         );
         mPayloadChanges = true;
 
         // add an item with the same id but a new data field i.e. send an update
-        final Item twoUpdate = new Item(2, 20);
+        final Item twoUpdate = new Item(2);
         twoUpdate.data = 1337;
         mList.updateItemAt(1, twoUpdate);
         assertEquals(1, mPayloadUpdates.size());
@@ -772,16 +827,16 @@
     @Test
     public void testAddMultipleExistingItemCallsChangeWithPayload() {
         mList.addAll(
-                new Item(1, 10),
-                new Item(2, 20),
-                new Item(3, 30)
+                new Item(1),
+                new Item(2),
+                new Item(3)
         );
         mPayloadChanges = true;
 
         // add two items with the same ids but a new data fields i.e. send two updates
-        final Item twoUpdate = new Item(2, 20);
+        final Item twoUpdate = new Item(2);
         twoUpdate.data = 222;
-        final Item threeUpdate = new Item(3, 30);
+        final Item threeUpdate = new Item(3);
         threeUpdate.data = 333;
         mList.addAll(twoUpdate, threeUpdate);
         assertEquals(2, mPayloadUpdates.size());
@@ -796,6 +851,648 @@
         assertEquals(3, size());
     }
 
+    @Test
+    public void replaceAll_mayModifyInputFalse_doesNotModify() {
+        mList.addAll(
+                new Item(1),
+                new Item(2)
+        );
+        Item replacement0 = new Item(4);
+        Item replacement1 = new Item(3);
+        Item[] replacements = new Item[]{
+                replacement0,
+                replacement1
+        };
+
+        mList.replaceAll(replacements, false);
+
+        assertSame(replacement0, replacements[0]);
+        assertSame(replacement1, replacements[1]);
+    }
+
+    @Test
+    public void replaceAll_varArgs_isEquivalentToDefault() {
+        mList.addAll(
+                new Item(1),
+                new Item(2)
+        );
+        Item replacement0 = new Item(3);
+        Item replacement1 = new Item(4);
+
+        mList.replaceAll(replacement0, replacement1);
+
+        assertEquals(mList.get(0), replacement0);
+        assertEquals(mList.get(1), replacement1);
+        assertEquals(2, mList.size());
+    }
+
+    @Test
+    public void replaceAll_collection_isEquivalentToDefaultWithMayModifyInputFalse() {
+        mList.addAll(
+                new Item(1),
+                new Item(2)
+        );
+        Item replacement0 = new Item(4);
+        Item replacement1 = new Item(3);
+        List<Item> replacements = new ArrayList<>();
+        replacements.add(replacement0);
+        replacements.add(replacement1);
+
+        mList.replaceAll(replacements);
+
+        assertEquals(mList.get(0), replacement1);
+        assertEquals(mList.get(1), replacement0);
+        assertSame(replacements.get(0), replacement0);
+        assertSame(replacements.get(1), replacement1);
+        assertEquals(2, mList.size());
+    }
+
+    @Test
+    public void replaceAll_callsChangeWithPayload() {
+        mList.addAll(
+                new Item(1),
+                new Item(2),
+                new Item(3)
+        );
+        mPayloadChanges = true;
+        final Item twoUpdate = new Item(2);
+        twoUpdate.data = 222;
+        final Item threeUpdate = new Item(3);
+        threeUpdate.data = 333;
+
+        mList.replaceAll(twoUpdate, threeUpdate);
+
+        assertEquals(2, mPayloadUpdates.size());
+        final PayloadChange update1 = mPayloadUpdates.get(0);
+        assertEquals(0, update1.position);
+        assertEquals(1, update1.count);
+        assertEquals(222, update1.payload);
+        final PayloadChange update2 = mPayloadUpdates.get(1);
+        assertEquals(1, update2.position);
+        assertEquals(1, update2.count);
+        assertEquals(333, update2.payload);
+    }
+
+    @Test
+    public void replaceAll_totallyEquivalentData_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 2, 3);
+        Item[] items2 = createItemsFromInts(1, 2, 3);
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mList.replaceAll(items2);
+
+        assertEquals(0, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+    }
+
+    @Test
+    public void replaceAll_removalsAndAdds1_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 3, 5);
+        Item[] items2 = createItemsFromInts(2, 4);
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(2, 3, 5)));
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(2, 5)));
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(2, 4, 5)));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.REMOVE, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.ADD, 0, 1), mEvents.get(1));
+        assertEquals(new Event(TYPE.REMOVE, 1, 1), mEvents.get(2));
+        assertEquals(new Event(TYPE.ADD, 1, 1), mEvents.get(3));
+        assertEquals(new Event(TYPE.REMOVE, 2, 1), mEvents.get(4));
+        assertEquals(5, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_removalsAndAdds2_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(2, 4);
+        Item[] items2 = createItemsFromInts(1, 3, 5);
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(1, 4)));
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(1, 3, 4)));
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(1, 3)));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.ADD, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.REMOVE, 1, 1), mEvents.get(1));
+        assertEquals(new Event(TYPE.ADD, 1, 1), mEvents.get(2));
+        assertEquals(new Event(TYPE.REMOVE, 2, 1), mEvents.get(3));
+        assertEquals(new Event(TYPE.ADD, 2, 1), mEvents.get(4));
+        assertEquals(5, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_removalsAndAdds3_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 3, 5);
+        Item[] items2 = createItemsFromInts(2, 3, 4);
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(2, 3, 5)));
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(2, 3, 4, 5)));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.REMOVE, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.ADD, 0, 1), mEvents.get(1));
+        assertEquals(new Event(TYPE.ADD, 2, 1), mEvents.get(2));
+        assertEquals(new Event(TYPE.REMOVE, 3, 1), mEvents.get(3));
+        assertEquals(4, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_removalsAndAdds4_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(2, 3, 4);
+        Item[] items2 = createItemsFromInts(1, 3, 5);
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(1, 3, 4)));
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(1, 3)));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.ADD, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.REMOVE, 1, 1), mEvents.get(1));
+        assertEquals(new Event(TYPE.REMOVE, 2, 1), mEvents.get(2));
+        assertEquals(new Event(TYPE.ADD, 2, 1), mEvents.get(3));
+        assertEquals(4, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_removalsAndAdds5_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 2, 3);
+        Item[] items2 = createItemsFromInts(3, 4, 5);
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.REMOVE, 0, 2), mEvents.get(0));
+        assertEquals(new Event(TYPE.ADD, 1, 2), mEvents.get(1));
+        assertEquals(2, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_removalsAndAdds6_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(3, 4, 5);
+        Item[] items2 = createItemsFromInts(1, 2, 3);
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.ADD, 0, 2), mEvents.get(0));
+        assertEquals(new Event(TYPE.REMOVE, 3, 2), mEvents.get(1));
+        assertEquals(2, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_move1_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 2, 3);
+        Item[] items2 = new Item[]{
+                new Item(2),
+                new Item(3),
+                new Item(1, 4, 1)};
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.REMOVE, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.ADD, 2, 1), mEvents.get(1));
+        assertEquals(2, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_move2_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 2, 3);
+        Item[] items2 = new Item[]{
+                new Item(3, 0, 3),
+                new Item(1),
+                new Item(2)};
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.ADD, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.REMOVE, 3, 1), mEvents.get(1));
+        assertEquals(2, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_move3_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 3, 5, 7, 9);
+        Item[] items2 = new Item[]{
+                new Item(3, 0, 3),
+                new Item(1),
+                new Item(5),
+                new Item(9),
+                new Item(7, 10, 7),
+        };
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(3, 0, 3),
+                new Item(1),
+                new Item(5),
+                new Item(7),
+                new Item(9)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(3, 0, 3),
+                new Item(1),
+                new Item(5),
+                new Item(9)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.ADD, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.REMOVE, 2, 1), mEvents.get(1));
+        assertEquals(new Event(TYPE.REMOVE, 3, 1), mEvents.get(2));
+        assertEquals(new Event(TYPE.ADD, 4, 1), mEvents.get(3));
+        assertEquals(4, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_move4_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 3, 5, 7, 9);
+        Item[] items2 = new Item[]{
+                new Item(3),
+                new Item(1, 4, 1),
+                new Item(5),
+                new Item(9, 6, 9),
+                new Item(7),
+        };
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(3),
+                new Item(1, 4, 1),
+                new Item(5),
+                new Item(7),
+                new Item(9)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(3),
+                new Item(1, 4, 1),
+                new Item(5),
+                new Item(9, 6, 9),
+                new Item(7),
+                new Item(9)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.REMOVE, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.ADD, 1, 1), mEvents.get(1));
+        assertEquals(new Event(TYPE.ADD, 3, 1), mEvents.get(2));
+        assertEquals(new Event(TYPE.REMOVE, 5, 1), mEvents.get(3));
+        assertEquals(4, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_move5_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 3, 5, 7, 9);
+        Item[] items2 = new Item[]{
+                new Item(9, 1, 9),
+                new Item(7, 3, 7),
+                new Item(5),
+                new Item(3, 7, 3),
+                new Item(1, 9, 1),
+        };
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(9, 1, 9),
+                new Item(3),
+                new Item(5),
+                new Item(7),
+                new Item(9)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(9, 1, 9),
+                new Item(5),
+                new Item(7),
+                new Item(9)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(9, 1, 9),
+                new Item(7, 3, 7),
+                new Item(5),
+                new Item(7),
+                new Item(9)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(9, 1, 9),
+                new Item(7, 3, 7),
+                new Item(5),
+                new Item(9)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(9, 1, 9),
+                new Item(7, 3, 7),
+                new Item(5),
+                new Item(3, 7, 3),
+                new Item(9)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(9, 1, 9),
+                new Item(7, 3, 7),
+                new Item(5),
+                new Item(3, 7, 3)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.REMOVE, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.ADD, 0, 1), mEvents.get(1));
+        assertEquals(new Event(TYPE.REMOVE, 1, 1), mEvents.get(2));
+        assertEquals(new Event(TYPE.ADD, 1, 1), mEvents.get(3));
+        assertEquals(new Event(TYPE.REMOVE, 3, 1), mEvents.get(4));
+        assertEquals(new Event(TYPE.ADD, 3, 1), mEvents.get(5));
+        assertEquals(new Event(TYPE.REMOVE, 4, 1), mEvents.get(6));
+        assertEquals(new Event(TYPE.ADD, 4, 1), mEvents.get(7));
+        assertEquals(8, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_orderSameItemDifferent_worksCorrectly() {
+        Item[] items1 = new Item[]{
+                new Item(1),
+                new Item(2, 3, 2),
+                new Item(5)
+        };
+        Item[] items2 = new Item[]{
+                new Item(1),
+                new Item(4, 3, 4),
+                new Item(5)
+        };
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.REMOVE, 1, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.ADD, 1, 1), mEvents.get(1));
+        assertEquals(2, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_orderSameItemSameContentsDifferent_worksCorrectly() {
+        Item[] items1 = new Item[]{
+                new Item(1),
+                new Item(3, 3, 2),
+                new Item(5)
+        };
+        Item[] items2 = new Item[]{
+                new Item(1),
+                new Item(3, 3, 4),
+                new Item(5)
+        };
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.CHANGE, 1, 1), mEvents.get(0));
+        assertEquals(1, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_allTypesOfChanges1_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(2, 5, 6);
+        Item[] items2 = new Item[]{
+                new Item(1),
+                new Item(3, 2, 3),
+                new Item(6, 6, 7)
+        };
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(createItemsFromInts(1, 5, 6)));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(1),
+                new Item(3, 2, 3),
+                new Item(5),
+                new Item(6)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(1),
+                new Item(3, 2, 3),
+                new Item(6)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.ADD, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.REMOVE, 1, 1), mEvents.get(1));
+        assertEquals(new Event(TYPE.ADD, 1, 1), mEvents.get(2));
+        assertEquals(new Event(TYPE.REMOVE, 2, 1), mEvents.get(3));
+        assertEquals(new Event(TYPE.CHANGE, 2, 1), mEvents.get(4));
+        assertEquals(5, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_allTypesOfChanges2_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 4, 6);
+        Item[] items2 = new Item[]{
+                new Item(1, 1, 2),
+                new Item(3),
+                new Item(5, 4, 5)
+        };
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(1, 1, 2),
+                new Item(3),
+                new Item(4),
+                new Item(6)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(1, 1, 2),
+                new Item(3),
+                new Item(6)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(1, 1, 2),
+                new Item(3),
+                new Item(5, 4, 5),
+                new Item(6)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.CHANGE, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.ADD, 1, 1), mEvents.get(1));
+        assertEquals(new Event(TYPE.REMOVE, 2, 1), mEvents.get(2));
+        assertEquals(new Event(TYPE.ADD, 2, 1), mEvents.get(3));
+        assertEquals(new Event(TYPE.REMOVE, 3, 1), mEvents.get(4));
+        assertEquals(5, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_allTypesOfChanges3_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 2);
+        Item[] items2 = new Item[]{
+                new Item(2, 2, 3),
+                new Item(3, 2, 4),
+                new Item(5)
+        };
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(
+                new Item(2, 2, 3)
+        ));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.replaceAll(items2);
+
+        assertEquals(new Event(TYPE.REMOVE, 0, 1), mEvents.get(0));
+        assertEquals(new Event(TYPE.CHANGE, 0, 1), mEvents.get(1));
+        assertEquals(new Event(TYPE.ADD, 1, 2), mEvents.get(2));
+        assertEquals(3, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
+    @Test
+    public void replaceAll_newItemsAreIdentical_resultIsDeduped() {
+        Item[] items = createItemsFromInts(1, 1);
+        mList.replaceAll(items);
+
+        assertEquals(new Item(1), mList.get(0));
+        assertEquals(1, mList.size());
+    }
+
+    @Test
+    public void replaceAll_newItemsUnsorted_resultIsSorted() {
+        Item[] items = createItemsFromInts(2, 1);
+        mList.replaceAll(items);
+
+        assertEquals(new Item(1), mList.get(0));
+        assertEquals(new Item(2), mList.get(1));
+        assertEquals(2, mList.size());
+    }
+
+    @Test
+    public void replaceAll_calledAfterBeginBatchedUpdates_worksCorrectly() {
+        Item[] items1 = createItemsFromInts(1, 2, 3);
+        Item[] items2 = createItemsFromInts(4, 5, 6);
+        mList.addAll(items1);
+        mEvents.clear();
+
+        mCallbackRunnables = new LinkedList<>();
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+        mCallbackRunnables.add(new AssertListStateRunnable(items2));
+
+        mList.beginBatchedUpdates();
+        mList.replaceAll(items2);
+        mList.endBatchedUpdates();
+
+        assertEquals(new Event(TYPE.REMOVE, 0, 3), mEvents.get(0));
+        assertEquals(new Event(TYPE.ADD, 0, 3), mEvents.get(1));
+        assertEquals(2, mEvents.size());
+        assertTrue(sortedListEquals(mList, items2));
+        assertTrue(mCallbackRunnables.isEmpty());
+    }
+
     private int size() {
         return mList.size();
     }
@@ -810,63 +1507,33 @@
 
     static class Item {
 
-        static int idCounter = 0;
         final int id;
-
         int cmpField;
+        int data;
 
-        int data = (int) (Math.random() * 1000);//used for comparison
-
-        public Item() {
-            id = idCounter++;
-            cmpField = (int) (Math.random() * 1000);
+        Item(int allFields) {
+            this(allFields, allFields, allFields);
         }
 
-        public Item(int cmpField) {
-            id = idCounter++;
-            this.cmpField = cmpField;
-        }
-
-        public Item(int id, int cmpField) {
+        Item(int id, int compField, int data) {
             this.id = id;
-            this.cmpField = cmpField;
+            this.cmpField = compField;
+            this.data = data;
         }
 
         @Override
         public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
 
             Item item = (Item) o;
 
-            if (cmpField != item.cmpField) {
-                return false;
-            }
-            if (id != item.id) {
-                return false;
-            }
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = id;
-            result = 31 * result + cmpField;
-            return result;
+            return id == item.id && cmpField == item.cmpField && data == item.data;
         }
 
         @Override
         public String toString() {
-            return "Item{" +
-                    "id=" + id +
-                    ", cmpField=" + cmpField +
-                    ", data=" + data +
-                    '}';
+            return "Item(id=" + id + ", cmpField=" + cmpField + ", data=" + data + ')';
         }
     }
 
@@ -913,6 +1580,85 @@
         }
     }
 
+    private enum TYPE {
+        ADD, REMOVE, MOVE, CHANGE
+    }
+
+    private final class AssertListStateRunnable implements Runnable {
+
+        private Item[] mExpectedItems;
+
+        AssertListStateRunnable(Item... expectedItems) {
+            this.mExpectedItems = expectedItems;
+        }
+
+        @Override
+        public void run() {
+            try {
+                assertEquals(mExpectedItems.length, mList.size());
+                for (int i = mExpectedItems.length - 1; i >= 0; i--) {
+                    assertEquals(mExpectedItems[i], mList.get(i));
+                    assertEquals(i, mList.indexOf(mExpectedItems[i]));
+                }
+            } catch (AssertionError assertionError) {
+                throw new AssertionError(
+                        assertionError.getMessage()
+                        + "\nExpected: "
+                        + Arrays.toString(mExpectedItems)
+                        + "\nActual: "
+                        + sortedListToString(mList));
+            }
+        }
+    }
+
+    private static final class Event {
+        private final TYPE mType;
+        private final int mVal1;
+        private final int mVal2;
+
+        Event(TYPE type, int val1, int val2) {
+            this.mType = type;
+            this.mVal1 = val1;
+            this.mVal2 = val2;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            Event that = (Event) o;
+            return mType == that.mType && mVal1 == that.mVal1 && mVal2 == that.mVal2;
+        }
+
+        @Override
+        public String toString() {
+            return "Event(" + mType + ", " + mVal1 + ", " + mVal2 + ")";
+        }
+    }
+
+    private <T> boolean sortedListEquals(SortedList<T> sortedList, T[] array) {
+        if (sortedList.size() != array.length) {
+            return false;
+        }
+        for (int i = sortedList.size() - 1; i >= 0; i--) {
+            if (!sortedList.get(i).equals(array[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static String sortedListToString(SortedList sortedList) {
+        StringBuilder stringBuilder = new StringBuilder("[");
+        int size = sortedList.size();
+        for (int i = 0; i < size; i++) {
+            stringBuilder.append(sortedList.get(i).toString() + ", ");
+        }
+        stringBuilder.delete(stringBuilder.length() - 2, stringBuilder.length());
+        stringBuilder.append("]");
+        return stringBuilder.toString();
+    }
+
     private static final class PayloadChange {
         public final int position;
         public final int count;
diff --git a/v7/recyclerview/tests/src/android/support/v7/util/ImeCleanUpTestRule.java b/v7/recyclerview/tests/src/android/support/v7/util/ImeCleanUpTestRule.java
deleted file mode 100644
index f4caad3..0000000
--- a/v7/recyclerview/tests/src/android/support/v7/util/ImeCleanUpTestRule.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v7.util;
-
-import android.graphics.Rect;
-import android.support.testutils.PollingCheck;
-import android.view.View;
-
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-/**
- * A JUnit rule that ensures that IME is closed after a test is finished (or exception thrown).
- * A test that triggers IME open/close should call setContainerView with the activity's container
- * view in order to trigger this cleanup at the end of the test. Otherwise, no cleanup happens.
- */
-public class ImeCleanUpTestRule implements TestRule {
-
-    private View mContainerView;
-
-    @Override
-    public Statement apply(final Statement base, Description description) {
-        return new Statement() {
-            @Override
-            public void evaluate() throws Throwable {
-                try {
-                    base.evaluate();
-                } finally {
-                    closeImeIfOpen();
-                }
-            }
-        };
-    }
-
-    /**
-     * Sets the container view used to calculate the total screen height and the height available
-     * to the test activity.
-     */
-    public void setContainerView(View containerView) {
-        mContainerView = containerView;
-    }
-
-    private void closeImeIfOpen() {
-        if (mContainerView == null) {
-            return;
-        }
-        // Ensuring that IME is closed after starting each test.
-        final Rect r = new Rect();
-        mContainerView.getWindowVisibleDisplayFrame(r);
-        // This is the entire height of the screen available to both the view and IME
-        final int screenHeight = mContainerView.getRootView().getHeight();
-
-        // r.bottom is the position above IME if it's open or device button.
-        // if IME is shown, r.bottom is smaller than screenHeight.
-        int imeHeight = screenHeight - r.bottom;
-
-        // Picking a threshold to detect when IME is open
-        if (imeHeight > screenHeight * 0.15) {
-            // Soft keyboard is shown, will wait for it to close after running the test. Note that
-            // we don't press back button here as the IME should close by itself when a test
-            // finishes. If the wait isn't done here, the IME can mess up with the layout of the
-            // next test.
-            PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
-                @Override
-                public boolean canProceed() {
-                    mContainerView.getWindowVisibleDisplayFrame(r);
-                    int imeHeight = screenHeight - r.bottom;
-                    return imeHeight < screenHeight * 0.15;
-                }
-            });
-        }
-    }
-}
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/BaseGridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/BaseGridLayoutManagerTest.java
index 13dd1e4..f4a8e37 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/BaseGridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/BaseGridLayoutManagerTest.java
@@ -325,16 +325,16 @@
         }
     }
 
-    class GridEditTextAdapter extends EditTextAdapter {
+    class GridFocusableAdapter extends FocusableAdapter {
 
         Set<Integer> mFullSpanItems = new HashSet<Integer>();
         int mSpanPerItem = 1;
 
-        GridEditTextAdapter(int count) {
+        GridFocusableAdapter(int count) {
             this(count, 1);
         }
 
-        GridEditTextAdapter(int count, int spanPerItem) {
+        GridFocusableAdapter(int count, int spanPerItem) {
             super(count);
             mSpanPerItem = spanPerItem;
         }
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
index 157fb12..eed7d20 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
@@ -35,14 +35,13 @@
 import android.support.annotation.Nullable;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
+import android.support.testutils.PollingCheck;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.recyclerview.test.R;
-import android.text.Editable;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.EditText;
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
@@ -325,6 +324,12 @@
                 result[0] = view.requestFocus();
             }
         });
+        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
+            @Override
+            public boolean canProceed() {
+                return view.hasFocus();
+            }
+        });
         if (waitForScroll && result[0]) {
             waitForIdleScroll(mRecyclerView);
         }
@@ -789,34 +794,32 @@
         }
     }
 
-    public class EditTextAdapter extends RecyclerView.Adapter<TestViewHolder> {
+    public class FocusableAdapter extends RecyclerView.Adapter<TestViewHolder> {
 
-        final ArrayList<Editable> mEditables;
-        public EditTextAdapter(int count) {
-            mEditables = new ArrayList<>();
-            for (int i = 0; i < count; ++i) {
-                mEditables.add(Editable.Factory.getInstance().newEditable("Sample Text " + i));
-            }
+        private int mCount;
+
+        FocusableAdapter(int count) {
+            mCount = count;
         }
 
         @Override
         public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-            final EditText editText = new EditText(parent.getContext());
-            editText.setLayoutParams(new ViewGroup.LayoutParams(
+            final TextView textView = new TextView(parent.getContext());
+            textView.setLayoutParams(new ViewGroup.LayoutParams(
                     ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
-            final TestViewHolder viewHolder = new TestViewHolder(editText);
-            return viewHolder;
+            textView.setFocusable(true);
+            textView.setBackgroundResource(R.drawable.item_bg);
+            return new TestViewHolder(textView);
         }
 
         @Override
         public void onBindViewHolder(TestViewHolder holder, int position) {
-            ((EditText) holder.itemView).setText(Editable.Factory.getInstance().newEditable(
-                    mEditables.get(position)));
+            ((TextView) holder.itemView).setText("Item " + position);
         }
 
         @Override
         public int getItemCount() {
-            return mEditables.size();
+            return mCount;
         }
     }
 
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/DummyItemAnimator.java b/v7/recyclerview/tests/src/android/support/v7/widget/DummyItemAnimator.java
new file mode 100644
index 0000000..a1491fa
--- /dev/null
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/DummyItemAnimator.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v7.widget;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This is a dummy ItemAnimator class that does not depends on Duration, Tests would use this class
+ * to control whenever they want the Animator to finish.
+ * 1. Test MUST call endAnimation(ViewHolder) on UI thread to finish animation of a given ViewHolder
+ *    Or Test calls endAnimations() on UI thread to end animations for all.
+ * 2. Test can call getAddAnimations() etc. to get ViewHolders that currently running animation.
+ * 3. Test can call {@link #expect(int, int)} and {@link #waitFor(int)} to wait given
+ *    Events are fired.
+ */
+public class DummyItemAnimator extends SimpleItemAnimator {
+
+    static final long TIMEOUT_SECOND = 10;
+
+    ArrayList<RecyclerView.ViewHolder> mAdds = new ArrayList();
+    ArrayList<RecyclerView.ViewHolder> mRemoves = new ArrayList();
+    ArrayList<RecyclerView.ViewHolder> mMoves = new ArrayList();
+    ArrayList<RecyclerView.ViewHolder> mChangesOld = new ArrayList();
+    ArrayList<RecyclerView.ViewHolder> mChangesNew = new ArrayList();
+
+    @Retention(CLASS)
+    @Target({PARAMETER, METHOD, LOCAL_VARIABLE, FIELD})
+    public @interface CountDownLatchIndex {
+    }
+
+    @CountDownLatchIndex
+    public static final int ADD_START = 0;
+
+    @CountDownLatchIndex
+    public static final int ADD_FINISHED = 1;
+
+    @CountDownLatchIndex
+    public static final int REMOVE_START = 2;
+
+    @CountDownLatchIndex
+    public static final int REMOVE_FINISHED = 3;
+
+    @CountDownLatchIndex
+    public static final int MOVE_START = 4;
+
+    @CountDownLatchIndex
+    public static final int MOVE_FINISHED = 5;
+
+    @CountDownLatchIndex
+    public static final int CHANGE_OLD_START = 6;
+
+    @CountDownLatchIndex
+    public static final int CHANGE_OLD_FINISHED = 7;
+
+    @CountDownLatchIndex
+    public static final int CHANGE_NEW_START = 8;
+
+    @CountDownLatchIndex
+    public static final int CHANGE_NEW_FINISHED = 9;
+
+    static final int NUM_COUNT_DOWN_LATCH = 10;
+
+    CountDownLatch[] mCountDownLatches = new CountDownLatch[NUM_COUNT_DOWN_LATCH];
+
+
+    public List<RecyclerView.ViewHolder> getAddAnimations() {
+        return mAdds;
+    }
+
+    public List<RecyclerView.ViewHolder> getRemoveAnimations() {
+        return mRemoves;
+    }
+
+    public List<RecyclerView.ViewHolder> getMovesAnimations() {
+        return mMoves;
+    }
+
+    public List<RecyclerView.ViewHolder> getChangesOldAnimations() {
+        return mChangesOld;
+    }
+
+    public List<RecyclerView.ViewHolder> getChangesNewAnimations() {
+        return mChangesNew;
+    }
+
+    @Override
+    public boolean animateRemove(RecyclerView.ViewHolder holder) {
+        mRemoves.add(holder);
+        dispatchRemoveStarting(holder);
+        return false;
+    }
+
+    @Override
+    public boolean animateAdd(RecyclerView.ViewHolder holder) {
+        mAdds.add(holder);
+        dispatchAddStarting(holder);
+        return false;
+    }
+
+    @Override
+    public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX,
+            int toY) {
+        mMoves.add(holder);
+        dispatchMoveStarting(holder);
+        return false;
+    }
+
+    @Override
+    public boolean animateChange(RecyclerView.ViewHolder oldHolder,
+            RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop) {
+        mChangesOld.add(oldHolder);
+        mChangesNew.add(newHolder);
+        dispatchChangeStarting(oldHolder, true);
+        dispatchChangeStarting(newHolder, false);
+        return false;
+    }
+
+    public void expect(@CountDownLatchIndex int index, int count) {
+        mCountDownLatches[index] = new CountDownLatch(count);
+    }
+
+    public void waitFor(@CountDownLatchIndex int index)
+            throws InterruptedException {
+        mCountDownLatches[index].await(TIMEOUT_SECOND, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public void onChangeStarting(RecyclerView.ViewHolder item, boolean oldItem) {
+        CountDownLatch latch = mCountDownLatches[oldItem ? CHANGE_OLD_START : CHANGE_NEW_START];
+        if (latch != null) {
+            latch.countDown();
+        }
+    }
+
+    @Override
+    public void onMoveStarting(RecyclerView.ViewHolder item) {
+        CountDownLatch latch = mCountDownLatches[MOVE_START];
+        if (latch != null) {
+            latch.countDown();
+        }
+    }
+
+    @Override
+    public void onAddStarting(RecyclerView.ViewHolder item) {
+        CountDownLatch latch = mCountDownLatches[ADD_START];
+        if (latch != null) {
+            latch.countDown();
+        }
+    }
+
+    @Override
+    public void onRemoveStarting(RecyclerView.ViewHolder item) {
+        CountDownLatch latch = mCountDownLatches[REMOVE_START];
+        if (latch != null) {
+            latch.countDown();
+        }
+    }
+
+    @Override
+    public void onChangeFinished(RecyclerView.ViewHolder item, boolean oldItem) {
+        CountDownLatch latch = mCountDownLatches[oldItem
+                ? CHANGE_OLD_FINISHED : CHANGE_NEW_FINISHED];
+        if (latch != null) {
+            latch.countDown();
+        }
+    }
+
+    @Override
+    public void onMoveFinished(RecyclerView.ViewHolder item) {
+        CountDownLatch latch = mCountDownLatches[MOVE_FINISHED];
+        if (latch != null) {
+            latch.countDown();
+        }
+    }
+
+    @Override
+    public void onAddFinished(RecyclerView.ViewHolder item) {
+        CountDownLatch latch = mCountDownLatches[ADD_FINISHED];
+        if (latch != null) {
+            latch.countDown();
+        }
+    }
+
+    @Override
+    public void onRemoveFinished(RecyclerView.ViewHolder item) {
+        CountDownLatch latch = mCountDownLatches[REMOVE_FINISHED];
+        if (latch != null) {
+            latch.countDown();
+        }
+    }
+
+    @Override
+    public void runPendingAnimations() {
+    }
+
+    @Override
+    public void endAnimation(RecyclerView.ViewHolder item) {
+        if (mAdds.remove(item)) {
+            dispatchAddFinished(item);
+        } else if (mRemoves.remove(item)) {
+            dispatchRemoveFinished(item);
+        } else if (mMoves.remove(item)) {
+            dispatchMoveFinished(item);
+        } else if (mChangesOld.remove(item)) {
+            dispatchChangeFinished(item, true);
+        } else if (mChangesNew.remove(item)) {
+            dispatchChangeFinished(item, false);
+        }
+    }
+
+    @Override
+    public void endAnimations() {
+        for (int i = mAdds.size() - 1; i >= 0; i--) {
+            endAnimation(mAdds.get(i));
+        }
+        for (int i = mRemoves.size() - 1; i >= 0; i--) {
+            endAnimation(mRemoves.get(i));
+        }
+        for (int i = mMoves.size() - 1; i >= 0; i--) {
+            endAnimation(mMoves.get(i));
+        }
+        for (int i = mChangesOld.size() - 1; i >= 0; i--) {
+            endAnimation(mChangesOld.get(i));
+        }
+        for (int i = mChangesNew.size() - 1; i >= 0; i--) {
+            endAnimation(mChangesNew.get(i));
+        }
+    }
+
+    @Override
+    public boolean isRunning() {
+        return mAdds.size() != 0
+                || mRemoves.size() != 0
+                || mMoves.size() != 0
+                || mChangesOld.size() != 0
+                || mChangesNew.size() != 0;
+    }
+}
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
index 23eaf52..1a5892d 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
@@ -20,7 +20,6 @@
 import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertEquals;
@@ -37,20 +36,15 @@
 import android.support.test.filters.LargeTest;
 import android.support.test.filters.SdkSuppress;
 import android.support.test.runner.AndroidJUnit4;
-import android.support.testutils.PollingCheck;
 import android.support.v4.view.AccessibilityDelegateCompat;
 import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
-import android.support.v7.util.ImeCleanUpTestRule;
-import android.support.v7.util.TouchUtils;
 import android.test.UiThreadTest;
 import android.util.SparseIntArray;
 import android.util.StateSet;
-import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
 
 import org.hamcrest.CoreMatchers;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -64,9 +58,6 @@
 @RunWith(AndroidJUnit4.class)
 public class GridLayoutManagerTest extends BaseGridLayoutManagerTest {
 
-    @Rule
-    public final ImeCleanUpTestRule imeCleanUp = new ImeCleanUpTestRule();
-
     @Test
     public void focusSearchFailureUp() throws Throwable {
         focusSearchFailure(false);
@@ -179,100 +170,140 @@
         }
     }
 
+    /**
+     * Tests that the GridLayoutManager retains the focused element after multiple measure
+     * calls to the RecyclerView.  There was a bug where the focused view was lost when the soft
+     * keyboard opened.  This test simulates the measure/layout events triggered by the opening
+     * of the soft keyboard by making two calls to measure.  A simulation was done because using
+     * the soft keyboard in the test caused many issues on API levels 15, 17 and 19.
+     */
     @Test
-    public void editTextVisibility() throws Throwable {
+    public void focusedChildStaysInViewWhenRecyclerViewShrinks() throws Throwable {
+
+        // Arrange.
+
         final int spanCount = 3;
         final int itemCount = 100;
 
-        imeCleanUp.setContainerView(getActivity().getContainer());
-        RecyclerView recyclerView = new WrappedRecyclerView(getActivity());
-        GridEditTextAdapter editTextAdapter = new GridEditTextAdapter(itemCount) {
-            @Override
-            public TestViewHolder onCreateViewHolder(ViewGroup parent,
-                    int viewType) {
-                TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
-                // Good to have colors for debugging
-                StateListDrawable stl = new StateListDrawable();
-                stl.addState(new int[]{android.R.attr.state_focused},
-                        new ColorDrawable(Color.RED));
-                stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
-                //noinspection deprecation using this for kitkat tests
-                testViewHolder.itemView.setBackgroundDrawable(stl);
-                return testViewHolder;
-            }
-        };
-        mActivityRule.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mActivityRule.getActivity().getWindow().setSoftInputMode(SOFT_INPUT_ADJUST_RESIZE);
-            }
-        });
-
-        recyclerView.setLayoutParams(
-                new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
+        final RecyclerView recyclerView = inflateWrappedRV();
+        ViewGroup.LayoutParams lp = recyclerView.getLayoutParams();
+        lp.height = WRAP_CONTENT;
+        lp.width = MATCH_PARENT;
 
         Config config = new Config(spanCount, itemCount);
         mGlm = new WrappedGridLayoutManager(getActivity(), config.mSpanCount, config.mOrientation,
                 config.mReverseLayout);
-        editTextAdapter.assignSpanSizeLookup(mGlm);
-        recyclerView.setAdapter(editTextAdapter);
         recyclerView.setLayoutManager(mGlm);
-        waitForFirstLayout(recyclerView);
 
-        // First focus on the last fully visible EditText located at span index #1.
-        View toFocus = findLastFullyVisibleChild(mRecyclerView);
-        int focusIndex = mRecyclerView.getChildAdapterPosition(toFocus);
-        focusIndex = (focusIndex / spanCount) * spanCount + 1;
-        toFocus = mRecyclerView.findViewHolderForAdapterPosition(focusIndex).itemView;
-        assertTrue(focusIndex >= 1 && focusIndex < itemCount);
+        GridFocusableAdapter gridFocusableAdapter = new GridFocusableAdapter(itemCount);
+        gridFocusableAdapter.assignSpanSizeLookup(mGlm);
+        recyclerView.setAdapter(gridFocusableAdapter);
 
-        final int heightBeforeImeOpen = mRecyclerView.getHeight();
-        TouchUtils.tapView(getInstrumentation(), mRecyclerView, toFocus);
-        getInstrumentation().waitForIdleSync();
-        // Wait for IME to pop up.
-        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
+        mGlm.expectLayout(1);
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
-            public boolean canProceed() {
-                return mRecyclerView.getHeight() < heightBeforeImeOpen;
+            public void run() {
+                getActivity().getContainer().addView(recyclerView);
             }
         });
+        mGlm.waitForLayout(3);
+
+        int width = recyclerView.getWidth();
+        int height = recyclerView.getHeight();
+        final int widthMeasureSpec =
+                View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
+        final int fullHeightMeasureSpec =
+                View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
+        // "MinusOne" so that a measure call will appropriately trigger onMeasure after RecyclerView
+        // was previously laid out with the full height version.
+        final int fullHeightMinusOneMeasureSpec =
+                View.MeasureSpec.makeMeasureSpec(height - 1, View.MeasureSpec.AT_MOST);
+        final int halfHeightMeasureSpec =
+                View.MeasureSpec.makeMeasureSpec(height / 2, View.MeasureSpec.AT_MOST);
+
+        // Act 1.
+
+        // First focus on the last fully visible child located at span index #1.
+        View toFocus = findLastFullyVisibleChild(recyclerView);
+        int focusIndex = recyclerView.getChildAdapterPosition(toFocus);
+        focusIndex = (focusIndex / spanCount) * spanCount + 1;
+        toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex).itemView;
+        assertTrue(focusIndex >= 1 && focusIndex < itemCount);
+
+        requestFocus(toFocus, false);
+
+        mGlm.expectLayout(1);
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                recyclerView.measure(widthMeasureSpec, fullHeightMinusOneMeasureSpec);
+                recyclerView.measure(widthMeasureSpec, halfHeightMeasureSpec);
+                recyclerView.layout(
+                        0,
+                        0,
+                        recyclerView.getMeasuredWidth(),
+                        recyclerView.getMeasuredHeight());
+            }
+        });
+        mGlm.waitForLayout(3);
+
+        // Assert 1.
 
         assertThat("Child at position " + focusIndex + " should be focused",
                 toFocus.hasFocus(), is(true));
         assertTrue("Child view at adapter pos " + focusIndex + " should be fully visible.",
-                isViewPartiallyInBound(mRecyclerView, toFocus));
+                isViewPartiallyInBound(recyclerView, toFocus));
 
-        // Close IME
-        final int heightBeforeImeClose = mRecyclerView.getHeight();
-        getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
-        getInstrumentation().waitForIdleSync();
-        // Wait for IME to close
-        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
+        // Act 2.
+
+        mGlm.expectLayout(1);
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
-            public boolean canProceed() {
-                return mRecyclerView.getHeight() > heightBeforeImeClose;
+            public void run() {
+                recyclerView.measure(widthMeasureSpec, fullHeightMeasureSpec);
+                recyclerView.layout(
+                        0,
+                        0,
+                        recyclerView.getMeasuredWidth(),
+                        recyclerView.getMeasuredHeight());
             }
         });
+        mGlm.waitForLayout(3);
+
+        // Assert 2.
+
         assertTrue("Child view at adapter pos " + focusIndex + " should be fully visible.",
-                isViewPartiallyInBound(mRecyclerView, toFocus));
+                isViewPartiallyInBound(recyclerView, toFocus));
+
+        // Act 3.
 
         // Now focus on the first fully visible EditText located at the last span index.
-        toFocus = findFirstFullyVisibleChild(mRecyclerView);
-        focusIndex = mRecyclerView.getChildAdapterPosition(toFocus);
+        toFocus = findFirstFullyVisibleChild(recyclerView);
+        focusIndex = recyclerView.getChildAdapterPosition(toFocus);
         focusIndex = (focusIndex / spanCount) * spanCount + (spanCount - 1);
-        toFocus = mRecyclerView.findViewHolderForAdapterPosition(focusIndex).itemView;
-        final int heightBeforeImeOpen2 = mRecyclerView.getHeight();
-        TouchUtils.tapView(getInstrumentation(), mRecyclerView, toFocus);
-        getInstrumentation().waitForIdleSync();
-        // Wait for IME to pop up
-        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
+        toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex).itemView;
+
+        requestFocus(toFocus, false);
+
+        mGlm.expectLayout(1);
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
-            public boolean canProceed() {
-                return mRecyclerView.getHeight() < heightBeforeImeOpen2;
+            public void run() {
+                recyclerView.measure(widthMeasureSpec, fullHeightMinusOneMeasureSpec);
+                recyclerView.measure(widthMeasureSpec, halfHeightMeasureSpec);
+                recyclerView.layout(
+                        0,
+                        0,
+                        recyclerView.getMeasuredWidth(),
+                        recyclerView.getMeasuredHeight());
             }
         });
+        mGlm.waitForLayout(3);
+
+        // Assert 3.
+
         assertTrue("Child view at adapter pos " + focusIndex + " should be fully visible.",
-                isViewPartiallyInBound(mRecyclerView, toFocus));
+                isViewPartiallyInBound(recyclerView, toFocus));
     }
 
     @Test
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
index 91d0dbf..de23213 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
@@ -20,7 +20,6 @@
 import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertEquals;
@@ -37,19 +36,14 @@
 import android.os.Build;
 import android.support.test.filters.LargeTest;
 import android.support.test.filters.SdkSuppress;
-import android.support.testutils.PollingCheck;
 import android.support.v4.view.AccessibilityDelegateCompat;
-import android.support.v7.util.ImeCleanUpTestRule;
-import android.support.v7.util.TouchUtils;
+import android.support.v4.view.ViewCompat;
 import android.util.Log;
 import android.util.StateSet;
-import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
-import android.widget.LinearLayout;
 
-import org.junit.Rule;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -69,68 +63,76 @@
 @LargeTest
 public class LinearLayoutManagerTest extends BaseLinearLayoutManagerTest {
 
-    @Rule
-    public final ImeCleanUpTestRule imeCleanUp = new ImeCleanUpTestRule();
-
+    /**
+     * Tests that the LinearLayoutManager retains the focused element after multiple measure
+     * calls to the RecyclerView.  There was a bug where the focused view was lost when the soft
+     * keyboard opened.  This test simulates the measure/layout events triggered by the opening
+     * of the soft keyboard by making two calls to measure.  A simulation was done because using
+     * the soft keyboard in the test caused many issues on API levels 15, 17 and 19.
+     */
     @Test
-    public void editTextVisibility() throws Throwable {
+    public void focusedChildStaysInViewWhenRecyclerViewShrinks() throws Throwable {
 
-        // Simulating a scenario where an EditText is tapped (which will receive focus).
-        // The soft keyboard that's opened overlaps the focused EditText which will shrink RV's
-        // padded bounded area. LLM should still lay out the focused EditText so that it becomes
-        // visible above the soft keyboard.
-        // The condition for this test is setting RV's height to a non-exact height, so that measure
-        // is called twice (once with the larger height and another time with smaller height when
-        // the keyboard shows up). To ensure this resizing of RV, SOFT_INPUT_ADJUST_RESIZE is set.
-        imeCleanUp.setContainerView(getActivity().getContainer());
-        final LinearLayout container = new LinearLayout(getActivity());
-        container.setOrientation(LinearLayout.VERTICAL);
-        container.setLayoutParams(
-                new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup
-                        .LayoutParams.MATCH_PARENT));
+        // Arrange.
 
-        final EditTextAdapter editTextAdapter = new EditTextAdapter(50);
-
-        mRecyclerView = inflateWrappedRV();
-        ViewGroup.LayoutParams lp = mRecyclerView.getLayoutParams();
+        final RecyclerView recyclerView = inflateWrappedRV();
+        ViewGroup.LayoutParams lp = recyclerView.getLayoutParams();
         lp.height = WRAP_CONTENT;
         lp.width = MATCH_PARENT;
+        recyclerView.setHasFixedSize(true);
 
-        mRecyclerView.setHasFixedSize(true);
-        mRecyclerView.setAdapter(editTextAdapter);
+        final FocusableAdapter focusableAdapter =
+                new FocusableAdapter(50);
+        recyclerView.setAdapter(focusableAdapter);
+
         mLayoutManager = new WrappedLinearLayoutManager(getActivity(), VERTICAL, false);
-        mRecyclerView.setLayoutManager(mLayoutManager);
-
-        container.addView(mRecyclerView);
+        recyclerView.setLayoutManager(mLayoutManager);
 
         mLayoutManager.expectLayouts(1);
         mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                getActivity().getContainer().addView(container);
+                getActivity().getContainer().addView(recyclerView);
             }
         });
+        mLayoutManager.waitForLayout(3);
+
+        int width = recyclerView.getWidth();
+        int height = recyclerView.getHeight();
+        final int widthMeasureSpec =
+                View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
+        final int fullHeightMeasureSpec =
+                View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
+        // "MinusOne" so that a measure call will appropriately trigger onMeasure after RecyclerView
+        // was previously laid out with the full height version.
+        final int fullHeightMinusOneMeasureSpec =
+                View.MeasureSpec.makeMeasureSpec(height - 1, View.MeasureSpec.AT_MOST);
+        final int halfHeightMeasureSpec =
+                View.MeasureSpec.makeMeasureSpec(height / 2, View.MeasureSpec.AT_MOST);
+
+        // Act 1.
+
+        View toFocus = findLastFullyVisibleChild(recyclerView);
+        int focusIndex = recyclerView.getChildAdapterPosition(toFocus);
+
+        requestFocus(toFocus, false);
+
+        mLayoutManager.expectLayouts(1);
         mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mActivityRule.getActivity().getWindow().setSoftInputMode(SOFT_INPUT_ADJUST_RESIZE);
+                recyclerView.measure(widthMeasureSpec, fullHeightMinusOneMeasureSpec);
+                recyclerView.measure(widthMeasureSpec, halfHeightMeasureSpec);
+                recyclerView.layout(
+                        0,
+                        0,
+                        recyclerView.getMeasuredWidth(),
+                        recyclerView.getMeasuredHeight());
             }
         });
+        mLayoutManager.waitForLayout(3);
 
-        // First focus on the last fully visible EditText.
-        View toFocus = findLastFullyVisibleChild(mRecyclerView);
-        int focusIndex = mRecyclerView.getChildAdapterPosition(toFocus);
-
-        final int heightBeforeImeOpen = mRecyclerView.getHeight();
-        TouchUtils.tapView(getInstrumentation(), mRecyclerView, toFocus);
-        getInstrumentation().waitForIdleSync();
-       // Wait for IME to pop up.
-        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
-            @Override
-            public boolean canProceed() {
-                return mRecyclerView.getHeight() < heightBeforeImeOpen;
-            }
-        });
+        // Verify 1.
 
         assertThat("Child at position " + focusIndex + " should be focused",
                 toFocus.hasFocus(), is(true));
@@ -138,40 +140,59 @@
         // requestRectangleOnScreen (inside bringPointIntoView) for the focused view with a rect
         // containing the content area. This rect is guaranteed to be fully visible whereas a
         // portion of TextView could be out of bounds.
-        assertTrue("Child view at adapter pos " + focusIndex + " should be fully visible.",
-                isViewPartiallyInBound(mRecyclerView, toFocus));
+        assertThat("Child view at adapter pos " + focusIndex + " should be fully visible.",
+                isViewPartiallyInBound(recyclerView, toFocus), is(true));
 
-        // Close IME
-        final int heightBeforeImeClose = mRecyclerView.getHeight();
-        getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
-        getInstrumentation().waitForIdleSync();
-        // Wait for IME to close
-        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
+        // Act 2.
+
+        mLayoutManager.expectLayouts(1);
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
-            public boolean canProceed() {
-                return mRecyclerView.getHeight() > heightBeforeImeClose;
+            public void run() {
+                recyclerView.measure(widthMeasureSpec, fullHeightMeasureSpec);
+                recyclerView.layout(
+                        0,
+                        0,
+                        recyclerView.getMeasuredWidth(),
+                        recyclerView.getMeasuredHeight());
             }
         });
+        mLayoutManager.waitForLayout(3);
+
+        // Verify 2.
+
         assertThat("Child at position " + focusIndex + " should be focused",
                 toFocus.hasFocus(), is(true));
         assertTrue("Child view at adapter pos " + focusIndex + " should be fully visible.",
-                isViewPartiallyInBound(mRecyclerView, toFocus));
+                isViewPartiallyInBound(recyclerView, toFocus));
+
+        // Act 3.
 
         // Now focus on the first fully visible EditText.
-        toFocus = findFirstFullyVisibleChild(mRecyclerView);
-        focusIndex = mRecyclerView.getChildAdapterPosition(toFocus);
-        final int heightBeforeImeOpen2 = mRecyclerView.getHeight();
-        TouchUtils.tapView(getInstrumentation(), mRecyclerView, toFocus);
-        getInstrumentation().waitForIdleSync();
-        // Wait for IME to pop up
-        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
+        toFocus = findFirstFullyVisibleChild(recyclerView);
+        focusIndex = recyclerView.getChildAdapterPosition(toFocus);
+
+        requestFocus(toFocus, false);
+
+        mLayoutManager.expectLayouts(1);
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
-            public boolean canProceed() {
-                return mRecyclerView.getHeight() < heightBeforeImeOpen2;
+            public void run() {
+                recyclerView.measure(widthMeasureSpec, fullHeightMinusOneMeasureSpec);
+                recyclerView.measure(widthMeasureSpec, halfHeightMeasureSpec);
+                recyclerView.layout(
+                        0,
+                        0,
+                        recyclerView.getMeasuredWidth(),
+                        recyclerView.getMeasuredHeight());
             }
         });
+        mLayoutManager.waitForLayout(3);
+
+        // Assert 3.
+
         assertTrue("Child view at adapter pos " + focusIndex + " should be fully visible.",
-                isViewPartiallyInBound(mRecyclerView, toFocus));
+                isViewPartiallyInBound(recyclerView, toFocus));
     }
 
     @Test
@@ -592,7 +613,7 @@
                     @Override
                     public void onFocusChange(View v, boolean hasFocus) {
                         assertNull("Focus just got cleared and no children should be holding"
-                                        + " focus now.", mRecyclerView.getFocusedChild());
+                                + " focus now.", mRecyclerView.getFocusedChild());
                         try {
                             // Calling focusSearch should be a no-op here since even though there
                             // are unfocusable views down to scroll to, none of RV's children hold
@@ -771,6 +792,170 @@
                 mRecyclerView.getChildCount() <= childCount + 3 /*1 for removed view, 2 for its size*/);
     }
 
+    void waitOneCycle() throws Throwable {
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+            }
+        });
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
+    @Test
+    public void hiddenNoneRemoveViewAccessibility() throws Throwable {
+        final Config config = new Config();
+        int adapterSize = 1000;
+        final boolean[] firstItemSpecialSize = new boolean[] {false};
+        TestAdapter adapter = new TestAdapter(adapterSize) {
+            @Override
+            public void onBindViewHolder(TestViewHolder holder,
+                    int position) {
+                super.onBindViewHolder(holder, position);
+                ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
+                if (!(lp instanceof ViewGroup.MarginLayoutParams)) {
+                    lp = new ViewGroup.MarginLayoutParams(0, 0);
+                    holder.itemView.setLayoutParams(lp);
+                }
+                ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) lp;
+                final int maxSize;
+                if (config.mOrientation == HORIZONTAL) {
+                    maxSize = mRecyclerView.getWidth();
+                    mlp.height = ViewGroup.MarginLayoutParams.MATCH_PARENT;
+                } else {
+                    maxSize = mRecyclerView.getHeight();
+                    mlp.width = ViewGroup.MarginLayoutParams.MATCH_PARENT;
+                }
+
+                final int desiredSize;
+                if (position == 0 && firstItemSpecialSize[0]) {
+                    desiredSize = maxSize / 3;
+                } else {
+                    desiredSize = maxSize / 8;
+                }
+                if (config.mOrientation == HORIZONTAL) {
+                    mlp.width = desiredSize;
+                } else {
+                    mlp.height = desiredSize;
+                }
+            }
+
+            @Override
+            public void onBindViewHolder(TestViewHolder holder,
+                    int position, List<Object> payloads) {
+                onBindViewHolder(holder, position);
+            }
+        };
+        adapter.setHasStableIds(false);
+        config.adapter(adapter);
+        setupByConfig(config, true);
+        final DummyItemAnimator itemAnimator = new DummyItemAnimator();
+        mRecyclerView.setItemAnimator(itemAnimator);
+
+        // push last item out by increasing first item's size
+        final int childBeingPushOut = mLayoutManager.getChildCount() - 1;
+        RecyclerView.ViewHolder itemViewHolder = mRecyclerView
+                .findViewHolderForAdapterPosition(childBeingPushOut);
+        final int originalAccessibility = ViewCompat.getImportantForAccessibility(
+                itemViewHolder.itemView);
+        assertTrue(ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO == originalAccessibility
+                || ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES == originalAccessibility);
+
+        itemAnimator.expect(DummyItemAnimator.MOVE_START, 1);
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                firstItemSpecialSize[0] = true;
+                mTestAdapter.notifyItemChanged(0, "XXX");
+            }
+        });
+        // wait till itemAnimator starts which will block itemView's accessibility
+        itemAnimator.waitFor(DummyItemAnimator.MOVE_START);
+        // RV Changes accessiblity after onMoveStart, so wait one more cycle.
+        waitOneCycle();
+        assertTrue(itemAnimator.getMovesAnimations().contains(itemViewHolder));
+        assertEquals(ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
+                ViewCompat.getImportantForAccessibility(itemViewHolder.itemView));
+
+        // notify Change again to run predictive animation.
+        mLayoutManager.expectLayouts(2);
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mTestAdapter.notifyItemChanged(0, "XXX");
+            }
+        });
+        mLayoutManager.waitForLayout(1);
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                itemAnimator.endAnimations();
+            }
+        });
+        // scroll to the view being pushed out, it should get same view from cache as the item
+        // in adapter does not change.
+        smoothScrollToPosition(childBeingPushOut);
+        RecyclerView.ViewHolder itemViewHolder2 = mRecyclerView
+                .findViewHolderForAdapterPosition(childBeingPushOut);
+        assertSame(itemViewHolder, itemViewHolder2);
+        // the important for accessibility should be reset to YES/AUTO:
+        final int newAccessibility = ViewCompat.getImportantForAccessibility(
+                itemViewHolder.itemView);
+        assertTrue(ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO == newAccessibility
+                || ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES == newAccessibility);
+    }
+
+    @Test
+    public void layoutFrozenBug70402422() throws Throwable {
+        final Config config = new Config();
+        TestAdapter adapter = new TestAdapter(2);
+        adapter.setHasStableIds(false);
+        config.adapter(adapter);
+        setupByConfig(config, true);
+        final DummyItemAnimator itemAnimator = new DummyItemAnimator();
+        mRecyclerView.setItemAnimator(itemAnimator);
+
+        final View firstItemView = mRecyclerView
+                .findViewHolderForAdapterPosition(0).itemView;
+
+        itemAnimator.expect(DummyItemAnimator.REMOVE_START, 1);
+        mTestAdapter.deleteAndNotify(1, 1);
+        itemAnimator.waitFor(DummyItemAnimator.REMOVE_START);
+
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mRecyclerView.setLayoutFrozen(true);
+            }
+        });
+        // requestLayout during item animation, which should be eaten by setLayoutFrozen(true)
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                firstItemView.requestLayout();
+            }
+        });
+        assertTrue(firstItemView.isLayoutRequested());
+        assertFalse(mRecyclerView.isLayoutRequested());
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                itemAnimator.endAnimations();
+            }
+        });
+        // When setLayoutFrozen(false), the firstItemView should run a layout pass and clear
+        // isLayoutRequested() flag.
+        mLayoutManager.expectLayouts(1);
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mRecyclerView.setLayoutFrozen(false);
+            }
+        });
+        mLayoutManager.waitForLayout(1);
+        assertFalse(firstItemView.isLayoutRequested());
+        assertFalse(mRecyclerView.isLayoutRequested());
+    }
+
     @Test
     public void keepFocusOnRelayout() throws Throwable {
         setupByConfig(new Config(VERTICAL, false, false).itemCount(500), true);
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
index 1c03c0f..dbad400 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
@@ -46,6 +46,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -1532,7 +1533,33 @@
 
     @Test
     public void scrollToPositionCallback() throws Throwable {
-        RecyclerView recyclerView = new RecyclerView(getActivity());
+
+        class TestRecyclerView extends RecyclerView {
+
+            private CountDownLatch mDrawLatch;
+
+            TestRecyclerView(Context context) {
+                super(context);
+            }
+
+            public void expectDraws(int count) {
+                mDrawLatch = new CountDownLatch(count);
+            }
+
+            public void waitForDraw(int seconds) throws InterruptedException {
+                mDrawLatch.await(seconds, TimeUnit.SECONDS);
+            }
+
+            @Override
+            public void onDraw(Canvas c) {
+                super.onDraw(c);
+                if (mDrawLatch != null) {
+                    mDrawLatch.countDown();
+                }
+            }
+        }
+
+        TestRecyclerView recyclerView = new TestRecyclerView(getActivity());
         TestLayoutManager tlm = new TestLayoutManager() {
             int scrollPos = RecyclerView.NO_POSITION;
 
@@ -1562,7 +1589,6 @@
             @Override
             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                 rvCounter.incrementAndGet();
-                super.onScrolled(recyclerView, dx, dy);
             }
         });
 
@@ -1574,13 +1600,16 @@
                     }
                 });
 
+        recyclerView.expectDraws(1);
         tlm.expectLayouts(1);
         setRecyclerView(recyclerView);
         tlm.waitForLayout(2);
-
+        recyclerView.waitForDraw(2);
         assertEquals("RV on scroll should be called for initialization", 1, rvCounter.get());
         assertEquals("VTO on scroll should be called for initialization", 1,
                 viewGroupCounter.get());
+
+        recyclerView.expectDraws(1);
         tlm.expectLayouts(1);
         freezeLayout(true);
         scrollToPosition(3);
@@ -1588,13 +1617,15 @@
         freezeLayout(false);
         scrollToPosition(3);
         tlm.waitForLayout(2);
+        recyclerView.waitForDraw(2);
         assertEquals("RV on scroll should be called", 2, rvCounter.get());
         assertEquals("VTO on scroll should be called", 2, viewGroupCounter.get());
+
+        recyclerView.expectDraws(1);
         tlm.expectLayouts(1);
         requestLayoutOnUIThread(recyclerView);
         tlm.waitForLayout(2);
-        // wait for draw :/
-        Thread.sleep(1000);
+        recyclerView.waitForDraw(2);
         assertEquals("on scroll should NOT be called", 2, rvCounter.get());
         assertEquals("on scroll should NOT be called", 2, viewGroupCounter.get());
     }
diff --git a/wear/Android.mk b/wear/Android.mk
index fe9b8d3..96934f7 100644
--- a/wear/Android.mk
+++ b/wear/Android.mk
@@ -32,9 +32,11 @@
 
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
+LOCAL_AAPT2_ONLY := true
 LOCAL_MODULE := android-support-wear
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under,src/main/java)
+LOCAL_MANIFEST_FILE := src/main/AndroidManifest.xml
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 LOCAL_SHARED_ANDROID_LIBRARIES := \
         android-support-core-ui \
diff --git a/wear/api/27.0.0.ignore b/wear/api/27.0.0.ignore
new file mode 100644
index 0000000..ebc6632
--- /dev/null
+++ b/wear/api/27.0.0.ignore
@@ -0,0 +1 @@
+a55e0de
diff --git a/wear/api/current.txt b/wear/api/current.txt
index e9b7d86..3fd2465 100644
--- a/wear/api/current.txt
+++ b/wear/api/current.txt
@@ -2,7 +2,7 @@
 
   public final class AmbientMode extends android.app.Fragment {
     ctor public AmbientMode();
-    method public static <T extends android.app.Activity & android.support.wear.ambient.AmbientMode.AmbientCallbackProvider> android.support.wear.ambient.AmbientMode.AmbientController attachAmbientSupport(T);
+    method public static <T extends android.app.Activity> android.support.wear.ambient.AmbientMode.AmbientController attachAmbientSupport(T);
     field public static final java.lang.String EXTRA_BURN_IN_PROTECTION = "com.google.android.wearable.compat.extra.BURN_IN_PROTECTION";
     field public static final java.lang.String EXTRA_LOWBIT_AMBIENT = "com.google.android.wearable.compat.extra.LOWBIT_AMBIENT";
     field public static final java.lang.String FRAGMENT_TAG = "android.support.wearable.ambient.AmbientMode";
@@ -48,7 +48,6 @@
     ctor public BoxInsetLayout(android.content.Context, android.util.AttributeSet);
     ctor public BoxInsetLayout(android.content.Context, android.util.AttributeSet, int);
     method public android.support.wear.widget.BoxInsetLayout.LayoutParams generateLayoutParams(android.util.AttributeSet);
-    method protected void onLayout(boolean, int, int, int, int);
   }
 
   public static class BoxInsetLayout.LayoutParams extends android.widget.FrameLayout.LayoutParams {
@@ -182,7 +181,7 @@
     method public void peekDrawer();
   }
 
-  public class WearableDrawerLayout extends android.widget.FrameLayout implements android.view.View.OnLayoutChangeListener {
+  public class WearableDrawerLayout extends android.widget.FrameLayout implements android.support.v4.view.NestedScrollingParent android.view.View.OnLayoutChangeListener {
     ctor public WearableDrawerLayout(android.content.Context);
     ctor public WearableDrawerLayout(android.content.Context, android.util.AttributeSet);
     ctor public WearableDrawerLayout(android.content.Context, android.util.AttributeSet, int);
diff --git a/wear/build.gradle b/wear/build.gradle
index 458f722..79c69ee 100644
--- a/wear/build.gradle
+++ b/wear/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,18 +7,18 @@
 }
 
 dependencies {
-    api project(':support-annotations')
-    api project(':support-core-ui')
-    api project(':support-fragment')
-    api project(':percent')
-    api project(':recyclerview-v7')
+    api(project(":support-annotations"))
+    api(project(":support-core-ui"))
+    api(project(":support-fragment"))
+    api(project(":percent"))
+    api(project(":recyclerview-v7"))
 
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
-    androidTestImplementation libs.mockito_core,     { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
+    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
 
-    provided fileTree(dir: 'wear_stubs', include: ['com.google.android.wearable-stubs.jar'])
+    compileOnly fileTree(dir: 'wear_stubs', include: ['com.google.android.wearable-stubs.jar'])
 }
 
 android {
@@ -44,5 +45,4 @@
     mavenGroup = LibraryGroups.SUPPORT
     inceptionYear = "2016"
     description = "Android Wear Support UI"
-    legacySourceLocation = true
 }
diff --git a/wear/lint-baseline.xml b/wear/lint-baseline.xml
deleted file mode 100644
index 8bc6f6f..0000000
--- a/wear/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="4" by="lint 3.0.0-alpha9">
-
-</issues>
diff --git a/wear/tests/AndroidManifest.xml b/wear/src/androidTest/AndroidManifest.xml
similarity index 90%
rename from wear/tests/AndroidManifest.xml
rename to wear/src/androidTest/AndroidManifest.xml
index ce78477..67ccd91 100644
--- a/wear/tests/AndroidManifest.xml
+++ b/wear/src/androidTest/AndroidManifest.xml
@@ -55,6 +55,13 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
+
+        <activity android:name="android.support.wear.ambient.AmbientModeResumeTestActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
         <!-- Test app is iOS compatible. -->
         <meta-data
             android:name="com.google.android.wearable.standalone"
diff --git a/wear/tests/NO_DOCS b/wear/src/androidTest/NO_DOCS
similarity index 100%
rename from wear/tests/NO_DOCS
rename to wear/src/androidTest/NO_DOCS
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientDelegateTest.java b/wear/src/androidTest/java/android/support/wear/ambient/AmbientDelegateTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/ambient/AmbientDelegateTest.java
rename to wear/src/androidTest/java/android/support/wear/ambient/AmbientDelegateTest.java
diff --git a/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeResumeTest.java b/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeResumeTest.java
new file mode 100644
index 0000000..32de769
--- /dev/null
+++ b/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeResumeTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.wear.ambient;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.wear.widget.util.WakeLockRule;
+
+import com.google.android.wearable.compat.WearableActivityController;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class AmbientModeResumeTest {
+    @Rule
+    public final WakeLockRule mWakeLock = new WakeLockRule();
+
+    @Rule
+    public final ActivityTestRule<AmbientModeResumeTestActivity> mActivityRule =
+            new ActivityTestRule<>(AmbientModeResumeTestActivity.class);
+
+    @Test
+    public void testActivityDefaults() throws Throwable {
+        assertTrue(WearableActivityController.getLastInstance().isAutoResumeEnabled());
+        assertFalse(WearableActivityController.getLastInstance().isAmbientEnabled());
+    }
+}
diff --git a/car/tests/src/android/support/car/widget/ColumnCardViewTestActivity.java b/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeResumeTestActivity.java
similarity index 67%
copy from car/tests/src/android/support/car/widget/ColumnCardViewTestActivity.java
copy to wear/src/androidTest/java/android/support/wear/ambient/AmbientModeResumeTestActivity.java
index 693e4a1..0ca3c15 100644
--- a/car/tests/src/android/support/car/widget/ColumnCardViewTestActivity.java
+++ b/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeResumeTestActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -13,17 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package android.support.car.widget;
+package android.support.wear.ambient;
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.support.car.test.R;
 
-public class ColumnCardViewTestActivity extends Activity {
+public class AmbientModeResumeTestActivity extends Activity {
+    AmbientMode.AmbientController mAmbientController;
+
     @Override
-    public void onCreate(Bundle savedInstanceState) {
+    protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_column_card_view);
+        mAmbientController = AmbientMode.attachAmbientSupport(this);
     }
 }
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientModeTest.java b/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/ambient/AmbientModeTest.java
rename to wear/src/androidTest/java/android/support/wear/ambient/AmbientModeTest.java
diff --git a/wear/tests/src/android/support/wear/ambient/AmbientModeTestActivity.java b/wear/src/androidTest/java/android/support/wear/ambient/AmbientModeTestActivity.java
similarity index 100%
rename from wear/tests/src/android/support/wear/ambient/AmbientModeTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/ambient/AmbientModeTestActivity.java
diff --git a/wear/tests/src/android/support/wear/utils/MetadataTestActivity.java b/wear/src/androidTest/java/android/support/wear/utils/MetadataTestActivity.java
similarity index 99%
rename from wear/tests/src/android/support/wear/utils/MetadataTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/utils/MetadataTestActivity.java
index 86d92ab..b934b5b 100644
--- a/wear/tests/src/android/support/wear/utils/MetadataTestActivity.java
+++ b/wear/src/androidTest/java/android/support/wear/utils/MetadataTestActivity.java
@@ -34,4 +34,4 @@
         assertEquals(R.drawable.preview_face_circular,
                 MetadataConstants.getPreviewDrawableResourceId(this, true));
     }
-}
\ No newline at end of file
+}
diff --git a/wear/tests/src/android/support/wear/widget/BoxInsetLayoutTest.java b/wear/src/androidTest/java/android/support/wear/widget/BoxInsetLayoutTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/BoxInsetLayoutTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/BoxInsetLayoutTest.java
diff --git a/wear/tests/src/android/support/wear/widget/CircularProgressLayoutControllerTest.java b/wear/src/androidTest/java/android/support/wear/widget/CircularProgressLayoutControllerTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/CircularProgressLayoutControllerTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/CircularProgressLayoutControllerTest.java
diff --git a/wear/tests/src/android/support/wear/widget/CircularProgressLayoutTest.java b/wear/src/androidTest/java/android/support/wear/widget/CircularProgressLayoutTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/CircularProgressLayoutTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/CircularProgressLayoutTest.java
diff --git a/wear/tests/src/android/support/wear/widget/LayoutTestActivity.java b/wear/src/androidTest/java/android/support/wear/widget/LayoutTestActivity.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/LayoutTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/widget/LayoutTestActivity.java
diff --git a/wear/tests/src/android/support/wear/widget/RoundedDrawableTest.java b/wear/src/androidTest/java/android/support/wear/widget/RoundedDrawableTest.java
similarity index 99%
rename from wear/tests/src/android/support/wear/widget/RoundedDrawableTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/RoundedDrawableTest.java
index 21aee7b..b01b3fa 100644
--- a/wear/tests/src/android/support/wear/widget/RoundedDrawableTest.java
+++ b/wear/src/androidTest/java/android/support/wear/widget/RoundedDrawableTest.java
@@ -33,11 +33,11 @@
 import android.graphics.RectF;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.Build;
+import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.wear.test.R;
-import android.support.test.filters.SdkSuppress;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/wear/tests/src/android/support/wear/widget/ScrollManagerTest.java b/wear/src/androidTest/java/android/support/wear/widget/ScrollManagerTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/ScrollManagerTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/ScrollManagerTest.java
diff --git a/wear/tests/src/android/support/wear/widget/SwipeDismissFrameLayoutTest.java b/wear/src/androidTest/java/android/support/wear/widget/SwipeDismissFrameLayoutTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/SwipeDismissFrameLayoutTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/SwipeDismissFrameLayoutTest.java
diff --git a/wear/tests/src/android/support/wear/widget/SwipeDismissFrameLayoutTestActivity.java b/wear/src/androidTest/java/android/support/wear/widget/SwipeDismissFrameLayoutTestActivity.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/SwipeDismissFrameLayoutTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/widget/SwipeDismissFrameLayoutTestActivity.java
diff --git a/wear/tests/src/android/support/wear/widget/SwipeDismissPreferenceFragment.java b/wear/src/androidTest/java/android/support/wear/widget/SwipeDismissPreferenceFragment.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/SwipeDismissPreferenceFragment.java
rename to wear/src/androidTest/java/android/support/wear/widget/SwipeDismissPreferenceFragment.java
diff --git a/wear/tests/src/android/support/wear/widget/WearableLinearLayoutManagerTest.java b/wear/src/androidTest/java/android/support/wear/widget/WearableLinearLayoutManagerTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/WearableLinearLayoutManagerTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/WearableLinearLayoutManagerTest.java
diff --git a/wear/tests/src/android/support/wear/widget/WearableRecyclerViewTest.java b/wear/src/androidTest/java/android/support/wear/widget/WearableRecyclerViewTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/WearableRecyclerViewTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/WearableRecyclerViewTest.java
diff --git a/wear/tests/src/android/support/wear/widget/WearableRecyclerViewTestActivity.java b/wear/src/androidTest/java/android/support/wear/widget/WearableRecyclerViewTestActivity.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/WearableRecyclerViewTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/widget/WearableRecyclerViewTestActivity.java
diff --git a/wear/tests/src/android/support/wear/widget/drawer/DrawerTestActivity.java b/wear/src/androidTest/java/android/support/wear/widget/drawer/DrawerTestActivity.java
similarity index 97%
rename from wear/tests/src/android/support/wear/widget/drawer/DrawerTestActivity.java
rename to wear/src/androidTest/java/android/support/wear/widget/drawer/DrawerTestActivity.java
index 14af0e1..414b97b 100644
--- a/wear/tests/src/android/support/wear/widget/drawer/DrawerTestActivity.java
+++ b/wear/src/androidTest/java/android/support/wear/widget/drawer/DrawerTestActivity.java
@@ -152,9 +152,9 @@
             DrawerStyle.ONLY_ACTION_DRAWER_WITH_TITLE
     })
     public @interface DrawerStyle {
-    int BOTH_DRAWER_NAV_SINGLE_PAGE = 0;
-    int BOTH_DRAWER_NAV_MULTI_PAGE = 1;
-    int ONLY_ACTION_DRAWER_WITH_TITLE = 2;
+        int BOTH_DRAWER_NAV_SINGLE_PAGE = 0;
+        int BOTH_DRAWER_NAV_MULTI_PAGE = 1;
+        int ONLY_ACTION_DRAWER_WITH_TITLE = 2;
     }
 
     /**
diff --git a/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java b/wear/src/androidTest/java/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
diff --git a/wear/tests/src/android/support/wear/widget/util/ArcSwipe.java b/wear/src/androidTest/java/android/support/wear/widget/util/ArcSwipe.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/util/ArcSwipe.java
rename to wear/src/androidTest/java/android/support/wear/widget/util/ArcSwipe.java
diff --git a/wear/tests/src/android/support/wear/widget/util/ArcSwipeTest.java b/wear/src/androidTest/java/android/support/wear/widget/util/ArcSwipeTest.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/util/ArcSwipeTest.java
rename to wear/src/androidTest/java/android/support/wear/widget/util/ArcSwipeTest.java
diff --git a/wear/tests/src/android/support/wear/widget/util/AsyncViewActions.java b/wear/src/androidTest/java/android/support/wear/widget/util/AsyncViewActions.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/util/AsyncViewActions.java
rename to wear/src/androidTest/java/android/support/wear/widget/util/AsyncViewActions.java
diff --git a/wear/tests/src/android/support/wear/widget/util/MoreViewAssertions.java b/wear/src/androidTest/java/android/support/wear/widget/util/MoreViewAssertions.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/util/MoreViewAssertions.java
rename to wear/src/androidTest/java/android/support/wear/widget/util/MoreViewAssertions.java
diff --git a/wear/tests/src/android/support/wear/widget/util/WakeLockRule.java b/wear/src/androidTest/java/android/support/wear/widget/util/WakeLockRule.java
similarity index 100%
rename from wear/tests/src/android/support/wear/widget/util/WakeLockRule.java
rename to wear/src/androidTest/java/android/support/wear/widget/util/WakeLockRule.java
diff --git a/wear/tests/src/com/google/android/wearable/compat/WearableActivityController.java b/wear/src/androidTest/java/com/google/android/wearable/compat/WearableActivityController.java
similarity index 97%
rename from wear/tests/src/com/google/android/wearable/compat/WearableActivityController.java
rename to wear/src/androidTest/java/com/google/android/wearable/compat/WearableActivityController.java
index 7823f23..0a76af0 100644
--- a/wear/tests/src/com/google/android/wearable/compat/WearableActivityController.java
+++ b/wear/src/androidTest/java/com/google/android/wearable/compat/WearableActivityController.java
@@ -33,7 +33,7 @@
 
     private AmbientCallback mCallback;
     private boolean mAmbientEnabled = false;
-    private boolean mAutoResumeEnabled = false;
+    private boolean mAutoResumeEnabled = true;
     private boolean mAmbient = false;
 
     public WearableActivityController(String tag, Activity activity, AmbientCallback callback) {
diff --git a/wear/tests/res/drawable/preview_face.png b/wear/src/androidTest/res/drawable/preview_face.png
similarity index 100%
rename from wear/tests/res/drawable/preview_face.png
rename to wear/src/androidTest/res/drawable/preview_face.png
Binary files differ
diff --git a/wear/tests/res/drawable/preview_face_circular.png b/wear/src/androidTest/res/drawable/preview_face_circular.png
similarity index 100%
rename from wear/tests/res/drawable/preview_face_circular.png
rename to wear/src/androidTest/res/drawable/preview_face_circular.png
Binary files differ
diff --git a/wear/tests/res/drawable/rounded_drawable.xml b/wear/src/androidTest/res/drawable/rounded_drawable.xml
similarity index 100%
rename from wear/tests/res/drawable/rounded_drawable.xml
rename to wear/src/androidTest/res/drawable/rounded_drawable.xml
diff --git a/wear/tests/res/drawable/test_drawable.xml b/wear/src/androidTest/res/drawable/test_drawable.xml
similarity index 100%
rename from wear/tests/res/drawable/test_drawable.xml
rename to wear/src/androidTest/res/drawable/test_drawable.xml
diff --git a/wear/tests/res/layout/box_inset_layout_testcase_1.xml b/wear/src/androidTest/res/layout/box_inset_layout_testcase_1.xml
similarity index 100%
rename from wear/tests/res/layout/box_inset_layout_testcase_1.xml
rename to wear/src/androidTest/res/layout/box_inset_layout_testcase_1.xml
diff --git a/wear/tests/res/layout/box_inset_layout_testcase_2.xml b/wear/src/androidTest/res/layout/box_inset_layout_testcase_2.xml
similarity index 100%
rename from wear/tests/res/layout/box_inset_layout_testcase_2.xml
rename to wear/src/androidTest/res/layout/box_inset_layout_testcase_2.xml
diff --git a/wear/tests/res/layout/box_inset_layout_testcase_3.xml b/wear/src/androidTest/res/layout/box_inset_layout_testcase_3.xml
similarity index 100%
rename from wear/tests/res/layout/box_inset_layout_testcase_3.xml
rename to wear/src/androidTest/res/layout/box_inset_layout_testcase_3.xml
diff --git a/wear/tests/res/layout/box_inset_layout_testcase_4.xml b/wear/src/androidTest/res/layout/box_inset_layout_testcase_4.xml
similarity index 100%
rename from wear/tests/res/layout/box_inset_layout_testcase_4.xml
rename to wear/src/androidTest/res/layout/box_inset_layout_testcase_4.xml
diff --git a/wear/tests/res/layout/circular_progress_layout.xml b/wear/src/androidTest/res/layout/circular_progress_layout.xml
similarity index 100%
rename from wear/tests/res/layout/circular_progress_layout.xml
rename to wear/src/androidTest/res/layout/circular_progress_layout.xml
diff --git a/wear/tests/res/layout/curved_offsetting_helper_child.xml b/wear/src/androidTest/res/layout/curved_offsetting_helper_child.xml
similarity index 100%
rename from wear/tests/res/layout/curved_offsetting_helper_child.xml
rename to wear/src/androidTest/res/layout/curved_offsetting_helper_child.xml
diff --git a/wear/tests/res/layout/rounded_drawable_layout.xml b/wear/src/androidTest/res/layout/rounded_drawable_layout.xml
similarity index 100%
rename from wear/tests/res/layout/rounded_drawable_layout.xml
rename to wear/src/androidTest/res/layout/rounded_drawable_layout.xml
diff --git a/wear/tests/res/layout/swipe_dismiss_layout_testcase_1.xml b/wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_1.xml
similarity index 100%
rename from wear/tests/res/layout/swipe_dismiss_layout_testcase_1.xml
rename to wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_1.xml
diff --git a/wear/tests/res/layout/swipe_dismiss_layout_testcase_2.xml b/wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_2.xml
similarity index 100%
rename from wear/tests/res/layout/swipe_dismiss_layout_testcase_2.xml
rename to wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_2.xml
diff --git a/wear/tests/res/layout/swipe_dismiss_layout_testcase_3.xml b/wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_3.xml
similarity index 100%
rename from wear/tests/res/layout/swipe_dismiss_layout_testcase_3.xml
rename to wear/src/androidTest/res/layout/swipe_dismiss_layout_testcase_3.xml
diff --git a/wear/tests/res/layout/test_multi_page_nav_drawer_layout.xml b/wear/src/androidTest/res/layout/test_multi_page_nav_drawer_layout.xml
similarity index 100%
rename from wear/tests/res/layout/test_multi_page_nav_drawer_layout.xml
rename to wear/src/androidTest/res/layout/test_multi_page_nav_drawer_layout.xml
diff --git a/wear/tests/res/layout/test_only_action_drawer_with_title_layout.xml b/wear/src/androidTest/res/layout/test_only_action_drawer_with_title_layout.xml
similarity index 100%
rename from wear/tests/res/layout/test_only_action_drawer_with_title_layout.xml
rename to wear/src/androidTest/res/layout/test_only_action_drawer_with_title_layout.xml
diff --git a/wear/tests/res/layout/test_single_page_nav_drawer_layout.xml b/wear/src/androidTest/res/layout/test_single_page_nav_drawer_layout.xml
similarity index 100%
rename from wear/tests/res/layout/test_single_page_nav_drawer_layout.xml
rename to wear/src/androidTest/res/layout/test_single_page_nav_drawer_layout.xml
diff --git a/wear/tests/res/layout/wearable_recycler_view_basic.xml b/wear/src/androidTest/res/layout/wearable_recycler_view_basic.xml
similarity index 100%
rename from wear/tests/res/layout/wearable_recycler_view_basic.xml
rename to wear/src/androidTest/res/layout/wearable_recycler_view_basic.xml
diff --git a/wear/tests/res/menu/action_drawer.xml b/wear/src/androidTest/res/menu/action_drawer.xml
similarity index 100%
rename from wear/tests/res/menu/action_drawer.xml
rename to wear/src/androidTest/res/menu/action_drawer.xml
diff --git a/wear/tests/res/values-sw213dp/styles.xml b/wear/src/androidTest/res/values-sw213dp/styles.xml
similarity index 100%
rename from wear/tests/res/values-sw213dp/styles.xml
rename to wear/src/androidTest/res/values-sw213dp/styles.xml
diff --git a/wear/tests/res/values/colors.xml b/wear/src/androidTest/res/values/colors.xml
similarity index 100%
rename from wear/tests/res/values/colors.xml
rename to wear/src/androidTest/res/values/colors.xml
diff --git a/wear/tests/res/values/dimens.xml b/wear/src/androidTest/res/values/dimens.xml
similarity index 100%
rename from wear/tests/res/values/dimens.xml
rename to wear/src/androidTest/res/values/dimens.xml
diff --git a/wear/tests/res/values/styles.xml b/wear/src/androidTest/res/values/styles.xml
similarity index 100%
rename from wear/tests/res/values/styles.xml
rename to wear/src/androidTest/res/values/styles.xml
diff --git a/wear/AndroidManifest.xml b/wear/src/main/AndroidManifest.xml
similarity index 100%
rename from wear/AndroidManifest.xml
rename to wear/src/main/AndroidManifest.xml
diff --git a/wear/src/main/java/android/support/wear/ambient/AmbientMode.java b/wear/src/main/java/android/support/wear/ambient/AmbientMode.java
index 5db9383..0077a5b 100644
--- a/wear/src/main/java/android/support/wear/ambient/AmbientMode.java
+++ b/wear/src/main/java/android/support/wear/ambient/AmbientMode.java
@@ -21,7 +21,9 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.support.annotation.CallSuper;
+import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
+import android.util.Log;
 
 import com.google.android.wearable.compat.WearableActivityController;
 
@@ -48,6 +50,7 @@
  * }</pre>
  */
 public final class AmbientMode extends Fragment {
+    private static final String TAG = "AmbientMode";
 
     /**
      * Property in bundle passed to {@code AmbientCallback#onEnterAmbient(Bundle)} to indicate
@@ -104,9 +107,6 @@
          * running (after onResume, before onPause). All drawing should complete by the conclusion
          * of this method. Note that {@code invalidate()} calls will be executed before resuming
          * lower-power mode.
-         * <p>
-         * <p><em>Derived classes must call through to the super class's implementation of this
-         * method. If they do not, an exception will be thrown.</em>
          *
          * @param ambientDetails bundle containing information about the display being used.
          *                      It includes information about low-bit color and burn-in protection.
@@ -122,9 +122,6 @@
         /**
          * Called when an activity should exit ambient mode. This event is sent while an activity is
          * running (after onResume, before onPause).
-         * <p>
-         * <p><em>Derived classes must call through to the super class's implementation of this
-         * method. If they do not, an exception will be thrown.</em>
          */
         public void onExitAmbient() {}
     }
@@ -133,20 +130,27 @@
             new AmbientDelegate.AmbientCallback() {
                 @Override
                 public void onEnterAmbient(Bundle ambientDetails) {
-                    mSuppliedCallback.onEnterAmbient(ambientDetails);
+                    if (mSuppliedCallback != null) {
+                        mSuppliedCallback.onEnterAmbient(ambientDetails);
+                    }
                 }
 
                 @Override
                 public void onExitAmbient() {
-                    mSuppliedCallback.onExitAmbient();
+                    if (mSuppliedCallback != null) {
+                        mSuppliedCallback.onExitAmbient();
+                    }
                 }
 
                 @Override
                 public void onUpdateAmbient() {
-                    mSuppliedCallback.onUpdateAmbient();
+                    if (mSuppliedCallback != null) {
+                        mSuppliedCallback.onUpdateAmbient();
+                    }
                 }
             };
     private AmbientDelegate mDelegate;
+    @Nullable
     private AmbientCallback mSuppliedCallback;
     private AmbientController mController;
 
@@ -166,8 +170,7 @@
         if (context instanceof AmbientCallbackProvider) {
             mSuppliedCallback = ((AmbientCallbackProvider) context).getAmbientCallback();
         } else {
-            throw new IllegalArgumentException(
-                    "fragment should attach to an activity that implements AmbientCallback");
+            Log.w(TAG, "No callback provided - enabling only smart resume");
         }
     }
 
@@ -176,7 +179,9 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mDelegate.onCreate();
-        mDelegate.setAmbientEnabled();
+        if (mSuppliedCallback != null) {
+            mDelegate.setAmbientEnabled();
+        }
     }
 
     @Override
@@ -215,15 +220,19 @@
     }
 
     /**
-     * Attach ambient support to the given activity.
+     * Attach ambient support to the given activity. Calling this method with an Activity
+     * implementing the {@link AmbientCallbackProvider} interface will provide you with an
+     * opportunity to react to ambient events such as {@code onEnterAmbient}. Alternatively,
+     * you can call this method with an Activity which does not implement
+     * the {@link AmbientCallbackProvider} interface and that will only enable the auto-resume
+     * functionality. This is equivalent to providing (@code null} from
+     * the {@link AmbientCallbackProvider}.
      *
-     * @param activity the activity to attach ambient support to. This activity has to also
-     *                implement {@link AmbientCallbackProvider}
+     * @param activity the activity to attach ambient support to.
      * @return the associated {@link AmbientController} which can be used to query the state of
      * ambient mode.
      */
-    public static <T extends Activity & AmbientCallbackProvider> AmbientController
-            attachAmbientSupport(T activity) {
+    public static <T extends Activity> AmbientController attachAmbientSupport(T activity) {
         FragmentManager fragmentManager = activity.getFragmentManager();
         AmbientMode ambientFragment = (AmbientMode) fragmentManager.findFragmentByTag(FRAGMENT_TAG);
         if (ambientFragment == null) {