Merge "Further split DataSource callbacks, so any method available is valid" into oc-mr1-support-27.0-dev
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
index 8abdf5a..8c113a2 100644
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -92,7 +92,11 @@
         <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>
@@ -317,4 +321,4 @@
     <option name="USE_PER_PROJECT_SETTINGS" value="true" />
     <option name="PREFERRED_PROJECT_CODE_STYLE" value="AndroidStyle" />
   </component>
-</project>
\ No newline at end of file
+</project>
diff --git a/app-toolkit/common/build.gradle b/app-toolkit/common/build.gradle
index d5583d9..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,8 +26,8 @@
 dependencies {
     compile libs.support.annotations
 
-    testCompile libs.junit
-    testCompile libs.mockito_core
+    testCompile(JUNIT)
+    testCompile(MOCKITO_CORE)
 }
 
 supportLibrary {
diff --git a/app-toolkit/core-testing/build.gradle b/app-toolkit/core-testing/build.gradle
index cf2d6c7..3ee9584 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,17 +30,17 @@
 }
 
 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(JUNIT)
     testImplementation libs.support.annotations
 
-    androidTestImplementation libs.junit
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
+    androidTestImplementation(JUNIT)
+    androidTestImplementation(TEST_RUNNER, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
 }
 
 supportLibrary {
diff --git a/app-toolkit/init.gradle b/app-toolkit/init.gradle
index af4190d..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()
diff --git a/app-toolkit/runtime/build.gradle b/app-toolkit/runtime/build.gradle
index 8d2c370..83d4293 100644
--- a/app-toolkit/runtime/build.gradle
+++ b/app-toolkit/runtime/build.gradle
@@ -30,7 +30,7 @@
 
 dependencies {
     api libs.support.annotations
-    api project(":arch:common")
+    api(project(":arch:common"))
 }
 
 supportLibrary {
diff --git a/buildSrc/build_dependencies.gradle b/buildSrc/build_dependencies.gradle
index dc41841..ffbc5a8 100644
--- a/buildSrc/build_dependencies.gradle
+++ b/buildSrc/build_dependencies.gradle
@@ -27,7 +27,7 @@
 
 // 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"]
 
diff --git a/buildSrc/dependencies.gradle b/buildSrc/dependencies.gradle
index b61cfc6..470551b 100644
--- a/buildSrc/dependencies.gradle
+++ b/buildSrc/dependencies.gradle
@@ -16,14 +16,17 @@
 // 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_annotations = {
+    exclude module: 'support-annotations'
+}
+
+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 6b613d0..18c3114 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() {
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..9f0e402
--- /dev/null
+++ b/buildSrc/src/main/kotlin/android/support/DiffAndDocs.kt
@@ -0,0 +1,660 @@
+/*
+ * 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 ->
+            if (project.hasProperty("noDocs") && (project.properties["noDocs"] as Boolean)) {
+                project.logger.warn("Project $project.name specified noDocs, ignoring API tasks.")
+                return@afterEvaluate
+            }
+            if (project.hasProperty("supportLibrary")
+                    && !(project.properties["supportLibrary"] as SupportLibraryExtension).publish) {
+                project.logger.warn("Project ${project.name} is not published, 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.warn("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.warn("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 9ca21ff..c83d740 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
@@ -55,11 +55,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 {
@@ -111,7 +111,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,6 +119,7 @@
                         "-XDcompilePolicy=simple", // Workaround for b/36098770
 
                         // Enforce the following checks.
+                        "-Xep:RestrictTo:OFF",
                         "-Xep:MissingOverride:ERROR",
                         "-Xep:NarrowingCompoundAssignment:ERROR",
                         "-Xep:ClassNewInstance:ERROR",
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..6748b50
--- /dev/null
+++ b/buildSrc/src/main/kotlin/android/support/dependencies/Dependencies.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.dependencies
+
+const val MOCKITO_CORE = "org.mockito:mockito-core:2.7.6"
+const val DEXMAKER_MOCKITO = "com.linkedin.dexmaker:dexmaker-mockito:2.2.0"
+const val JUNIT = "junit:junit:4.12"
+const val TEST_RUNNER = "com.android.support.test:runner:1.0.1"
+const val TEST_RULES = "com.android.support.test:rules:1.0.1"
+const val ESPRESSO_CORE = "com.android.support.test.espresso:espresso-core:3.0.1"
+const val ESPRESSO_CONTRIB = "com.android.support.test.espresso:espresso-contrib:3.0.1"
\ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/android/support/doclava/DoclavaTask.kt b/buildSrc/src/main/kotlin/android/support/doclava/DoclavaTask.kt
index 1007535..48a98f9 100644
--- a/buildSrc/src/main/kotlin/android/support/doclava/DoclavaTask.kt
+++ b/buildSrc/src/main/kotlin/android/support/doclava/DoclavaTask.kt
@@ -202,6 +202,9 @@
         addOption(DoclavaJavadocOptionFileOption("android"))
     }
 
+    fun coreJavadocOptions(configure: CoreJavadocOptions.() -> Unit) =
+            (options as CoreJavadocOptions).configure()
+
     override fun generate() {
         configureDoclava()
         super.generate()
diff --git a/compat/build.gradle b/compat/build.gradle
index 82d503c..56d0a98 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/content/build.gradle b/content/build.gradle
index 3639301..15f96c4 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
 }
 
 android {
diff --git a/core-ui/build.gradle b/core-ui/build.gradle
index cd70447..6c17d40 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,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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/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/tests/AndroidManifest.xml b/core-ui/tests/AndroidManifest.xml
index c1b1a75..0185f72 100644
--- a/core-ui/tests/AndroidManifest.xml
+++ b/core-ui/tests/AndroidManifest.xml
@@ -36,6 +36,8 @@
 
         <activity android:name="android.support.v4.view.ViewPagerWithTabStripActivity"/>
 
+        <activity android:name="android.support.v4.view.ViewPagerTest$ViewPagerActivity"/>
+
     </application>
 
 </manifest>
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-utils/build.gradle b/core-utils/build.gradle
index b384a37..c0482d0 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/customtabs/build.gradle b/customtabs/build.gradle
index 28b5f99..0bbd03d 100644
--- a/customtabs/build.gradle
+++ b/customtabs/build.gradle
@@ -1,3 +1,5 @@
+import static android.support.dependencies.DependenciesKt.ESPRESSO_CORE
+import static android.support.dependencies.DependenciesKt.TEST_RUNNER
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -6,21 +8,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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/design/build.gradle b/design/build.gradle
index 3af966d..30bd21a 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,22 +7,20 @@
 }
 
 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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')
 
-    testImplementation libs.junit
-    testImplementation (libs.test_runner) {
-        exclude module: 'support-annotations'
-    }
+    testImplementation(JUNIT)
+    testImplementation(TEST_RUNNER, libs.exclude_annotations)
 }
 
 android {
diff --git a/dynamic-animation/build.gradle b/dynamic-animation/build.gradle
index 5069a73..21dbfb3 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/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/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/core/build.gradle b/emoji/core/build.gradle
index f07c277..67d7530 100644
--- a/emoji/core/build.gradle
+++ b/emoji/core/build.gradle
@@ -1,3 +1,4 @@
+import static android.support.dependencies.DependenciesKt.*
 import android.support.LibraryGroups
 import android.support.LibraryVersions
 
@@ -19,12 +20,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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/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/MetadataListReader.java b/emoji/core/src/main/java/android/support/text/emoji/MetadataListReader.java
index 6034726..1008c17 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
@@ -275,7 +275,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/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..f5e63f6 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, libs.exclude_annotations)
 }
 
 android {
diff --git a/fragment/build.gradle b/fragment/build.gradle
index dfb6ca9..0b80b62 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 it"s own MockMaker
-    androidTestImplementation libs.dexmaker_mockito, { exclude group: 'net.bytebuddy' } // DexMaker has it"s own MockMaker
+    androidTestImplementation(TEST_RUNNER, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/graphics/drawable/animated/build.gradle b/graphics/drawable/animated/build.gradle
index bfe405f..ffa850f 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
 }
 
 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/build.gradle b/graphics/drawable/static/build.gradle
index b8ab699..8e498fe 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, libs.exclude_annotations)
 }
 
 android {
diff --git a/lifecycle/common-java8/build.gradle b/lifecycle/common-java8/build.gradle
index e96e7ae..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,9 +24,9 @@
 }
 
 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
 }
 
diff --git a/lifecycle/common/build.gradle b/lifecycle/common/build.gradle
index 33d8235..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,8 +24,8 @@
 }
 
 dependencies {
-    testCompile libs.junit
-    testCompile libs.mockito_core
+    testCompile(JUNIT)
+    testCompile(MOCKITO_CORE)
     compile libs.support.annotations
 }
 
diff --git a/lifecycle/compiler/build.gradle b/lifecycle/compiler/build.gradle
index 6d6fd66..cbed742 100644
--- a/lifecycle/compiler/build.gradle
+++ b/lifecycle/compiler/build.gradle
@@ -15,7 +15,7 @@
 }
 
 dependencies {
-    compile project(":lifecycle:common")
+    compile(project(":lifecycle:common"))
     compile libs.kotlin.stdlib
     compile libs.auto_common
     compile libs.javapoet
diff --git a/lifecycle/extensions/build.gradle b/lifecycle/extensions/build.gradle
index f74fd40..b7166ea 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,18 +34,18 @@
 }
 
 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
     androidTestImplementation libs.support.app_compat, libs.support_exclude_config
 }
 
diff --git a/lifecycle/integration-tests/testapp/build.gradle b/lifecycle/integration-tests/testapp/build.gradle
index d733c32..c640eeb 100644
--- a/lifecycle/integration-tests/testapp/build.gradle
+++ b/lifecycle/integration-tests/testapp/build.gradle
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
+
 apply plugin: 'com.android.application'
 
 project.ext.noDocs = true
@@ -60,22 +62,18 @@
 
 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
 
-    testImplementation libs.junit
-    testImplementation libs.mockito_core
-    testAnnotationProcessor project(":lifecycle:compiler")
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
+    testAnnotationProcessor(project(":lifecycle:compiler"))
 }
 
 tasks['check'].dependsOn(tasks['connectedCheck'])
diff --git a/lifecycle/reactivestreams/build.gradle b/lifecycle/reactivestreams/build.gradle
index 6d77bb7..af7b430 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
@@ -30,19 +31,17 @@
 
 allprojects {
     dependencies {
-        api project(":arch:common")
-        api project(":lifecycle:common")
-        api project(":lifecycle:extensions")
-        api project(":lifecycle:runtime")
+        api(project(":arch:common"))
+        api(project(":lifecycle:common"))
+        api(project(":lifecycle:extensions"))
+        api(project(":lifecycle:runtime"))
         api libs.support.annotations
         api libs.reactive_streams
 
-        testImplementation libs.junit
+        testImplementation(JUNIT)
         testImplementation libs.rx_java
+        testImplementation(TEST_RUNNER, libs.exclude_annotations)
 
-        testImplementation(libs.test_runner) {
-            exclude module: 'support-annotations'
-        }
         androidTestImplementation libs.support.app_compat, libs.support_exclude_config
     }
 }
diff --git a/lifecycle/runtime/build.gradle b/lifecycle/runtime/build.gradle
index cf0e4d3..96f9a6f 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,16 +18,16 @@
 }
 
 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, libs.exclude_annotations)
 }
 
 supportLibrary {
diff --git a/media-compat-test-client/build.gradle b/media-compat-test-client/build.gradle
index 47141db..5441793 100644
--- a/media-compat-test-client/build.gradle
+++ b/media-compat-test-client/build.gradle
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
+
 plugins {
     id("SupportAndroidLibraryPlugin")
 }
 
 dependencies {
-    androidTestImplementation project(':support-annotations')
-    androidTestImplementation project(':support-media-compat')
-    androidTestImplementation project(':support-media-compat-test-lib')
-    androidTestImplementation project(':support-testutils')
+    androidTestImplementation(project(":support-annotations"))
+    androidTestImplementation(project(":support-media-compat"))
+    androidTestImplementation(project(":support-media-compat-test-lib"))
+    androidTestImplementation(project(":support-testutils"))
 
-    androidTestImplementation(libs.test_runner) {
-        exclude module: 'support-annotations'
-    }
+    androidTestImplementation(TEST_RUNNER, libs.exclude_annotations)
 }
 
 android {
diff --git a/media-compat-test-service/build.gradle b/media-compat-test-service/build.gradle
index 946d48b..aaf120f 100644
--- a/media-compat-test-service/build.gradle
+++ b/media-compat-test-service/build.gradle
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
+
 plugins {
     id("SupportAndroidLibraryPlugin")
 }
 
 dependencies {
-    androidTestImplementation project(':support-annotations')
-    androidTestImplementation project(':support-media-compat')
-    androidTestImplementation project(':support-media-compat-test-lib')
+    androidTestImplementation(project(":support-annotations"))
+    androidTestImplementation(project(":support-media-compat"))
+    androidTestImplementation(project(":support-media-compat-test-lib"))
 
-    androidTestImplementation(libs.test_runner) {
-        exclude module: 'support-annotations'
-    }
+    androidTestImplementation(TEST_RUNNER, libs.exclude_annotations)
 }
 
 android {
diff --git a/media-compat/build.gradle b/media-compat/build.gradle
index ec4504e..b832de6 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/paging/common/build.gradle b/paging/common/build.gradle
index 6bebc5e..c4f949b 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,12 +26,11 @@
 
 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(JUNIT)
+    testCompile(MOCKITO_CORE)
+
     testCompile libs.kotlin.stdlib
 }
 
diff --git a/paging/integration-tests/testapp/build.gradle b/paging/integration-tests/testapp/build.gradle
index 76ef98b..91312a3 100644
--- a/paging/integration-tests/testapp/build.gradle
+++ b/paging/integration-tests/testapp/build.gradle
@@ -45,13 +45,13 @@
 }
 
 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
diff --git a/paging/runtime/build.gradle b/paging/runtime/build.gradle
index ce2d722..e075c6b 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,18 +31,18 @@
 }
 
 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(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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
     androidTestImplementation libs.kotlin.stdlib
 }
 
diff --git a/percent/build.gradle b/percent/build.gradle
index ccee3d2..da5ccc9 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
 }
 
 android {
diff --git a/persistence/db-framework/build.gradle b/persistence/db-framework/build.gradle
index 3ef00c1..6ce2b94 100644
--- a/persistence/db-framework/build.gradle
+++ b/persistence/db-framework/build.gradle
@@ -30,7 +30,7 @@
 
 dependencies {
     api libs.support.annotations
-    api project(":persistence:db")
+    api(project(":persistence:db"))
 }
 
 supportLibrary {
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/room/common/build.gradle b/room/common/build.gradle
index dea4b9a..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,8 +25,8 @@
 
 dependencies {
     compile libs.support.annotations
-    testCompile libs.junit
-    testCompile libs.mockito_core
+    testCompile(JUNIT)
+    testCompile(MOCKITO_CORE)
 }
 
 supportLibrary {
diff --git a/room/compiler/build.gradle b/room/compiler/build.gradle
index 56a0c27..60b2cfc 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
@@ -39,8 +40,8 @@
     // 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(project(":room:common"))
+    compile(project(":room:migration"))
     compile libs.kotlin.stdlib
     compile libs.auto_common
     compile libs.javapoet
@@ -49,10 +50,10 @@
     compile libs.apache.commons.codec
     testCompile libs.google_compile_testing
     testCompile project(":paging:common")
-    testCompile libs.junit
+    testCompile(JUNIT)
     testCompile libs.ij_annotations
     testCompile libs.jsr250
-    testCompile libs.mockito_core
+    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")}",
diff --git a/room/integration-tests/kotlintestapp/build.gradle b/room/integration-tests/kotlintestapp/build.gradle
index 4545c07..63759a7 100644
--- a/room/integration-tests/kotlintestapp/build.gradle
+++ b/room/integration-tests/kotlintestapp/build.gradle
@@ -13,6 +13,9 @@
  * 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'
@@ -57,21 +60,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"
     })
@@ -83,7 +86,7 @@
     androidTestImplementation project(':room:rxjava2')
     androidTestImplementation project(':arch:core-testing')
     androidTestImplementation libs.rx_java
-    testImplementation libs.mockito_core
+    testImplementation(MOCKITO_CORE)
 }
 
 tasks['check'].dependsOn(tasks['connectedCheck'])
diff --git a/room/integration-tests/testapp/build.gradle b/room/integration-tests/testapp/build.gradle
index 53ed69a..78dd295 100644
--- a/room/integration-tests/testapp/build.gradle
+++ b/room/integration-tests/testapp/build.gradle
@@ -13,6 +13,9 @@
  * 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'
 
 project.ext.noDocs = true
@@ -55,18 +58,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,23 +77,19 @@
     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(libs.rx_java)
+    androidTestImplementation(TEST_RUNNER, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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)
 }
 
 tasks['check'].dependsOn(tasks['connectedCheck'])
diff --git a/room/migration/build.gradle b/room/migration/build.gradle
index 086aac7..f2a8aed 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(project(":room:common"))
     compile libs.kotlin.stdlib
     compile libs.gson
-    testCompile libs.junit
+    testCompile(JUNIT)
     testCompile libs.ij_annotations
-    testCompile libs.mockito_core
+    testCompile(MOCKITO_CORE)
 }
 
 supportLibrary {
diff --git a/room/runtime/build.gradle b/room/runtime/build.gradle
index 85bcc40..ecbd0b3 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,23 +34,23 @@
 }
 
 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(project(":arch:core-testing"))
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
     testImplementation libs.support.annotations
 
-    androidTestImplementation libs.junit
-    androidTestImplementation libs.test_runner,      { exclude module: 'support-annotations' }
-    androidTestImplementation libs.espresso_core,    { exclude module: 'support-annotations' }
+    androidTestImplementation(JUNIT)
+    androidTestImplementation(TEST_RUNNER, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
 }
 
 // Used by testCompile in room-compiler
diff --git a/room/rxjava2/build.gradle b/room/rxjava2/build.gradle
index 1b6daba..6e95051 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,14 +30,14 @@
 }
 
 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")
+    testImplementation(JUNIT)
+    testImplementation(MOCKITO_CORE)
+    testImplementation(project(":arch:core-testing"))
 }
 
 supportLibrary {
diff --git a/room/testing/build.gradle b/room/testing/build.gradle
index 3556541..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,14 +30,14 @@
 }
 
 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)
 }
 
 supportLibrary {
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 0b562c8..841bcd9 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"))
 }
 
 android {
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/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/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 99223f9..4c2b471 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"))
 }
 
 android {
diff --git a/testutils/build.gradle b/testutils/build.gradle
index 15eabaf..7aafa96 100644
--- a/testutils/build.gradle
+++ b/testutils/build.gradle
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
+import static android.support.dependencies.DependenciesKt.*
+
 plugins {
     id("SupportAndroidLibraryPlugin")
 }
 
 dependencies {
-    compile libs.junit
+    api(JUNIT)
 }
 
 android {
diff --git a/transition/build.gradle b/transition/build.gradle
index 326a681..d9f2452 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/tv-provider/build.gradle b/tv-provider/build.gradle
index 60c2b2e..eb5d297 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, libs.exclude_annotations)
 }
 
 android {
diff --git a/v13/build.gradle b/v13/build.gradle
index bd01c55..0f5c9b6 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/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/v17/leanback/build.gradle b/v17/leanback/build.gradle
index 4ebec71..c07bc76 100644
--- a/v17/leanback/build.gradle
+++ b/v17/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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/v17/preference-leanback/build.gradle b/v17/preference-leanback/build.gradle
index 85d2577..f4d2fd6 100644
--- a/v17/preference-leanback/build.gradle
+++ b/v17/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/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/v7/appcompat/build.gradle b/v7/appcompat/build.gradle
index 308a122..ddf11f2 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,22 +7,22 @@
 }
 
 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 project(':support-testutils')
+    androidTestImplementation(TEST_RUNNER, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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"))
 }
 
 android {
     defaultConfig {
-        minSdkVersion 14
+        minSdkVersion(14)
         // This disables the builds tools automatic vector -> PNG generation
         generatedDensities = []
     }
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/gridlayout/build.gradle b/v7/gridlayout/build.gradle
index 052b9db..dc3a494 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
 }
 
 android {
diff --git a/v7/mediarouter/build.gradle b/v7/mediarouter/build.gradle
index 09e48df..0c94194 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    androidTestImplementation(TEST_RULES)
 }
 
 android {
diff --git a/v7/palette/build.gradle b/v7/palette/build.gradle
index 2703f2c..95c0799 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, libs.exclude_annotations)
 }
 
 android {
diff --git a/v7/preference/build.gradle b/v7/preference/build.gradle
index f5bc372..16af11e 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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/recyclerview/build.gradle b/v7/recyclerview/build.gradle
index daac4ab..b98e7f7 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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, libs.exclude_annotations)
 }
 
 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/wear/build.gradle b/wear/build.gradle
index 458f722..55320b9 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,16 +7,16 @@
 }
 
 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, libs.exclude_annotations)
+    androidTestImplementation(ESPRESSO_CORE, libs.exclude_annotations)
+    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'])
 }