Clean up references to project directory structure

Use canonicalPath instead of absolutePath since it is absolute and
canonical.

Bug: 152627091
Test: ./gradlew bOS
Change-Id: Ibe63e5588524c9f6674fc222f5a1bfeb22c88d25
diff --git a/build.gradle b/build.gradle
index bc3d3d4..8b77da6 100644
--- a/build.gradle
+++ b/build.gradle
@@ -19,11 +19,13 @@
 import static androidx.build.dependencies.DependenciesKt.*
 
 buildscript {
-    ext.supportRootFolder = project.projectDir
+    SdkHelperKt.setSupportRootFolder(project, project.projectDir)
+
     apply from: 'buildSrc/repos.gradle'
     apply from: 'buildSrc/build_dependencies.gradle'
     repos.addMavenRepositories(repositories)
-    SdkHelperKt.setSdkInLocalPropertiesFile(ext.supportRootFolder)
+
+    SdkHelperKt.writeSdkPathToLocalPropertiesFile(project)
 
     dependencies {
         classpath build_libs.agp
diff --git a/buildSrc/repos.gradle b/buildSrc/repos.gradle
index 3433878..3ef5f7e 100644
--- a/buildSrc/repos.gradle
+++ b/buildSrc/repos.gradle
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
-def supportRoot = ext.supportRootFolder
-if (supportRoot == null) {
-    throw new RuntimeException("variable supportRootFolder is not set. you must set it before" +
-            " including this script")
+def supportRootFolder = ext.supportRootFolder
+if (supportRootFolder == null) {
+    throw new RuntimeException("Canonical root project directory is not set. You must specify " +
+            "ext.supportRootFolder before including this script")
 }
+// Makes strong assumptions about the project structure.
+def checkoutRoot = supportRootFolder.parentFile.parentFile
 
-def checkoutRoot = "${ext.supportRootFolder}/../.."
 ext.repos = new Properties()
-ext.repos.checkoutRoot = checkoutRoot
-ext.repos.prebuiltsRoot = "${checkoutRoot}/prebuilts"
+ext.repos.checkoutRoot = checkoutRoot.absolutePath
+ext.repos.prebuiltsRoot = new File(checkoutRoot, "prebuilts").absolutePath
 
 /**
  * Adds maven repositories to the given repository handler.
diff --git a/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
index b7cbe3c..685f30b 100644
--- a/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
@@ -251,8 +251,7 @@
             }
             task.systemProperty("robolectric.offline", "true")
             val robolectricDependencies =
-                File(SupportConfig.getPrebuiltsRootPath(project) +
-                        "/androidx/external/org/robolectric/android-all")
+                File(project.getPrebuiltsRoot(), "androidx/external/org/robolectric/android-all")
             task.systemProperty(
                 "robolectric.dependency.dir",
                 robolectricDependencies.absolutePath
@@ -331,8 +330,7 @@
         buildOnServerTask.dependsOn(createCoverageJarTask)
         buildOnServerTask.dependsOn(Jacoco.createZipEcFilesTask(this))
 
-        val rootProjectDir = SupportConfig.getSupportRoot(rootProject).canonicalFile
-        val allDocsTask = DiffAndDocs.configureDiffAndDocs(this, rootProjectDir,
+        val allDocsTask = DiffAndDocs.configureDiffAndDocs(this,
                 DacOptions("androidx", "ANDROIDX_DATA"),
                 listOf(RELEASE_RULE))
         buildOnServerTask.dependsOn(allDocsTask)
@@ -372,7 +370,7 @@
 
         project.tasks.register("listTaskOutputs", ListTaskOutputsTask::class.java) { task ->
             task.setOutput(File(project.getDistributionDirectory(), "task_outputs.txt"))
-            task.removePrefix(File(rootProjectDir, "../../").canonicalFile.path)
+            task.removePrefix(project.getCheckoutRoot().path)
         }
         publishInspectionArtifacts()
     }
@@ -431,7 +429,7 @@
 
         val debugSigningConfig = signingConfigs.getByName("debug")
         // Use a local debug keystore to avoid build server issues.
-        debugSigningConfig.storeFile = SupportConfig.getKeystore(project)
+        debugSigningConfig.storeFile = project.getKeystore()
         buildTypes.all { buildType ->
             // Sign all the builds (including release) with debug key
             buildType.signingConfig = debugSigningConfig
diff --git a/buildSrc/src/main/kotlin/androidx/build/BuildServerConfiguration.kt b/buildSrc/src/main/kotlin/androidx/build/BuildServerConfiguration.kt
index 8a29918..e0fef7e 100644
--- a/buildSrc/src/main/kotlin/androidx/build/BuildServerConfiguration.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/BuildServerConfiguration.kt
@@ -78,11 +78,6 @@
 fun Project.getHostTestCoverageDirectory(): File =
     File(getDistributionDirectory(), "host-test-coverage")
 
-private fun getRootDirectory(project: Project): File {
-    val actualRootProject = if (project.isRoot) project else project.rootProject
-    return actualRootProject.extensions.extraProperties.get("supportRootFolder") as File
-}
-
 /**
  * Whether the build should force all versions to be snapshots.
  */
diff --git a/buildSrc/src/main/kotlin/androidx/build/CreateLibraryBuildInfoFileTask.kt b/buildSrc/src/main/kotlin/androidx/build/CreateLibraryBuildInfoFileTask.kt
index 51710ea..aed9362 100644
--- a/buildSrc/src/main/kotlin/androidx/build/CreateLibraryBuildInfoFileTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/CreateLibraryBuildInfoFileTask.kt
@@ -16,7 +16,6 @@
 
 package androidx.build
 
-import androidx.build.SupportConfig.getSupportRoot
 import androidx.build.gitclient.Commit
 import androidx.build.gitclient.GitClientImpl
 import androidx.build.gitclient.GitCommitRange
@@ -46,25 +45,23 @@
     @OutputFile
     val outputFile: Property<File> = project.objects.property(File::class.java)
 
-    private fun getLibraryBuildInfoFilename(): String {
-        return "${project.group}_${project.name}_build_info.txt"
-    }
-
-    /* Returns the local project directory without the full framework/support root directory path
-    * Note: `project.projectDir.toString().removePrefix(project.rootDir.toString())` does not work
-    * because the project rootDir is not guaranteed to be a substring of the projectDir
-    */
+    /**
+     * Returns the local project directory without the full framework/support root directory path
+     * <p>
+     * Note: `project.projectDir.toString().removePrefix(project.rootDir.toString())` does not work
+     * because the project rootDir is not guaranteed to be a substring of the projectDir
+     */
     private fun getProjectSpecificDirectory(): String {
-        return project.projectDir.toString().removePrefix(
-            getSupportRoot(project).toString())
+        return project.projectDir.absolutePath.removePrefix(
+            project.getSupportRootFolder().absolutePath)
     }
 
-    /* Returns whether or not the groupId of the project requires the same version for all
+    /**
+     * Returns whether or not the groupId of the project requires the same version for all
      * artifactIds.
      */
     private fun requiresSameVersion(): Boolean {
-        val library =
-            project.extensions.findByType(AndroidXExtension::class.java)
+        val library = project.extensions.findByType(AndroidXExtension::class.java)
         return library?.mavenGroup?.requireSameVersion ?: false
     }
 
@@ -72,17 +69,17 @@
      * of the build that is released.  Thus, we use frameworks/support to get the sha
      */
     private fun getFrameworksSupportCommitShaAtHead(): String {
-        val supportRoot = getSupportRoot(project)
-        val commitList: List<Commit> = GitClientImpl(supportRoot, logger).getGitLog(
-            GitCommitRange(
-                fromExclusive = "",
-                untilInclusive = "HEAD",
-                n = 1
-            ),
-            keepMerges = true,
-            fullProjectDir = supportRoot
-        )
-        if (commitList.size < 1) {
+        val commitList: List<Commit> = GitClientImpl(project.getSupportRootFolder(), logger)
+            .getGitLog(
+                GitCommitRange(
+                    fromExclusive = "",
+                    untilInclusive = "HEAD",
+                    n = 1
+                ),
+                keepMerges = true,
+                fullProjectDir = project.getSupportRootFolder()
+            )
+        if (commitList.isEmpty()) {
             throw RuntimeException("Failed to find git commit for HEAD!")
         }
         return commitList.first().sha
diff --git a/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt b/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
index e6d61a9..3ad6d54 100644
--- a/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
@@ -36,7 +36,6 @@
 import org.gradle.api.artifacts.ResolveException
 import org.gradle.api.file.FileCollection
 import org.gradle.api.file.FileTree
-import org.gradle.api.plugins.ExtraPropertiesExtension
 import org.gradle.api.plugins.JavaBasePlugin
 import org.gradle.api.tasks.TaskContainer
 import org.gradle.api.tasks.TaskProvider
@@ -55,14 +54,12 @@
  * Object used to manage configuration of documentation generation tasks.
  *
  * @property root the top-level AndroidX project.
- * @property supportRootFolder the directory in which the top-level AndroidX project lives.
  * @property dacOptions additional options for generating output compatible with d.android.com.
  * @property additionalRules optional list of rule sets used to generate documentation.
  * @constructor Creates a DiffAndDocs object and immediately creates related documentation tasks.
  */
 class DiffAndDocs private constructor(
     root: Project,
-    supportRootFolder: File,
     dacOptions: DacOptions,
     additionalRules: List<PublishDocsRules> = emptyList()
 ) {
@@ -113,9 +110,10 @@
             }
 
             val generateDocsTask = createGenerateDocsTask(
-                project = root, generateSdkApiTask = generateSdkApiTask,
+                project = root,
+                generateSdkApiTask = generateSdkApiTask,
                 doclavaConfig = doclavaConfiguration,
-                supportRootFolder = supportRootFolder, dacOptions = dacOptions,
+                dacOptions = dacOptions,
                 destDir = File(root.docsDir(), rule.name),
                 taskName = "${rule.name}DocsTask",
                 offline = offline)
@@ -150,7 +148,6 @@
          * This should happen only once (and on the root project).
          *
          * @property root the top-level AndroidX project.
-         * @property supportRootFolder the directory in which the top-level AndroidX project lives.
          * @property dacOptions additional options for generating output compatible with
          *           d.android.com.
          * @property additionalRules optional list of rule sets used to generate documentation.
@@ -158,7 +155,6 @@
          */
         fun configureDiffAndDocs(
             root: Project,
-            supportRootFolder: File,
             dacOptions: DacOptions,
             additionalRules: List<PublishDocsRules> = emptyList()
         ): TaskProvider<Task> {
@@ -167,7 +163,6 @@
                 "Cannot initialize DiffAndDocs twice")
             val instance = DiffAndDocs(
                 root = root,
-                supportRootFolder = supportRootFolder,
                 dacOptions = dacOptions,
                 additionalRules = additionalRules
             )
@@ -503,7 +498,6 @@
  * @param project the project from which source files and JARs will be used to generate docs.
  * @param generateSdkApiTask the task that provides the Android SDK's API txt file.
  * @param doclavaConfig command-line options to pass to the Doclava javadoc tool.
- * @param supportRootFolder the directory in which the top-level AndroidX project lives.
  * @param dacOptions additional options for generating output compatible with d.android.com.
  * @param destDir the directory into which generated documentation should be output.
  * @param taskName the name to give the resulting task.
@@ -513,7 +507,6 @@
     project: Project,
     generateSdkApiTask: TaskProvider<DoclavaTask>,
     doclavaConfig: Configuration,
-    supportRootFolder: File,
     dacOptions: DacOptions,
     destDir: File,
     taskName: String = "generateDocs",
@@ -539,8 +532,10 @@
 
                 coreJavadocOptions {
                     addStringOption("templatedir",
-                        "$supportRootFolder/../../external/doclava/res/assets/templates-sdk")
-                    addStringOption("samplesdir", "$supportRootFolder/samples")
+                        "${project.getCheckoutRoot()}/external/doclava/res/assets/templates-sdk")
+                    // Note this is using the project's real root directory, e.g. `fw/support/ui`.
+                    addStringOption("samplesdir",
+                        "${project.rootDir}/samples")
                     addMultilineMultiValueOption("federate").value = listOf(
                         listOf("Android", "https://developer.android.com")
                     )
@@ -585,13 +580,13 @@
  * @return the project's Android SDK stub JAR as a File.
  */
 fun androidJarFile(project: Project): FileCollection =
-        project.files(arrayOf(File(project.sdkPath(),
+        project.files(arrayOf(File(project.getSdkPath(),
                 "platforms/${SupportConfig.COMPILE_SDK_VERSION}/android.jar")))
 
 /**
  * @return the project's Android SDK stub source JAR as a File.
  */
-private fun androidSrcJarFile(project: Project): File = File(project.sdkPath(),
+private fun androidSrcJarFile(project: Project): File = File(project.getSdkPath(),
         "platforms/${SupportConfig.COMPILE_SDK_VERSION}/android-stubs-src.jar")
 
 /**
@@ -608,15 +603,6 @@
 }
 
 /**
- * @return the root project's SDK path as a File.
- */
-private fun Project.sdkPath(): File {
-    val supportRoot = (project.rootProject.property("ext") as ExtraPropertiesExtension)
-        .get("supportRootFolder") as File
-    return getSdkPath(supportRoot)
-}
-
-/**
  * Extension for accessing Strings in Project.properties by [name].
  */
 fun Project.processProperty(name: String) =
diff --git a/buildSrc/src/main/kotlin/androidx/build/SdkHelper.kt b/buildSrc/src/main/kotlin/androidx/build/SdkHelper.kt
index c872b84..e0473ec 100644
--- a/buildSrc/src/main/kotlin/androidx/build/SdkHelper.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/SdkHelper.kt
@@ -16,24 +16,21 @@
 
 package androidx.build
 
+import org.gradle.api.Project
+import org.gradle.api.plugins.ExtraPropertiesExtension
 import java.io.File
-
-/**
- * Writes the appropriate SDK path to local.properties file.
- */
-fun setSdkInLocalPropertiesFile(supportRoot: File) {
-    setSdkInLocalPropertiesFile(supportRoot, supportRoot)
-}
+import java.util.Locale
 
 /**
  * Writes the appropriate SDK path to local.properties file in specified location.
  */
-fun setSdkInLocalPropertiesFile(supportRoot: File, propertiesFile: File) {
-    val sdkPath = getSdkPath(supportRoot)
+fun Project.writeSdkPathToLocalPropertiesFile() {
+    val sdkPath = project.getSdkPath()
     if (sdkPath.exists()) {
-        val props = File(propertiesFile, "local.properties")
-        // gradle always deliminate directories with '/' regardless of the OS.
-        // So convert deliminator here.
+        // This must be the project's real root directory (ex. fw/support/ui) rather than the
+        // canonical root obtained via getSupportRootFolder().
+        val props = File(project.rootDir, "local.properties")
+        // Gradle always separates directories with '/' regardless of the OS, so convert here.
         val gradlePath = sdkPath.absolutePath.replace(File.separator, "/")
         var expectedContents = "sdk.dir=$gradlePath"
         expectedContents += "\ncmake.dir=$gradlePath/cmake"
@@ -45,19 +42,48 @@
             println("updated local.properties")
         }
     } else {
-        throw Exception("You are using non androidx-master-dev checkout. You need to check out " +
-                "androidx-master-dev to work on support library. See go/androidx for details.")
+        throw Exception("Unable to find SDK prebuilts at $sdkPath. If you are not using a " +
+                "standard repo-based checkout, please follow the checkout instructions at " +
+                "go/androidx-onboarding.")
     }
 }
 
 /**
- * Returns the appropriate SDK path.
+ * Returns the root project's platform-specific SDK path as a file.
  */
-fun getSdkPath(supportRoot: File): File {
-    val osName = System.getProperty("os.name").toLowerCase()
-    val isMacOsX = osName.contains("mac os x") || osName.contains("darwin") ||
+fun Project.getSdkPath(): File {
+    val osName = System.getProperty("os.name").toLowerCase(Locale.US)
+    val isMacOsX = osName.contains("mac os x") ||
+            osName.contains("darwin") ||
             osName.contains("osx")
     val platform = if (isMacOsX) "darwin" else "linux"
-    // Making an assumption that prebuilts directory is in $supportRoot/../../prebuilts/
-    return File(supportRoot.parentFile.parentFile, "prebuilts/fullsdk-$platform")
-}
\ No newline at end of file
+
+    // By convention, the SDK prebuilts live under the root checkout directory.
+    return File(project.getCheckoutRoot(), "prebuilts/fullsdk-$platform")
+}
+
+/**
+ * Sets the path to the canonical root project directory, e.g. {@code frameworks/support}.
+ */
+fun Project.setSupportRootFolder(rootDir: File) {
+    val extension = project.rootProject.property("ext") as ExtraPropertiesExtension
+    return extension.set("supportRootFolder", rootDir)
+}
+
+/**
+ * Returns the path to the canonical root project directory, e.g. {@code frameworks/support}.
+ */
+fun Project.getSupportRootFolder(): File {
+    // When the `ui` project is merged, this can be simplified to `project.rootDir`.
+    val extension = project.rootProject.property("ext") as ExtraPropertiesExtension
+    return extension.get("supportRootFolder") as File
+}
+
+/**
+ * Returns the path to the checkout's root directory, e.g. where {@code repo init} was run.
+ * <p>
+ * This method assumes that the canonical root project directory is {@code frameworks/support}.
+ */
+fun Project.getCheckoutRoot(): File {
+    return project.getSupportRootFolder().parentFile.parentFile
+}
diff --git a/buildSrc/src/main/kotlin/androidx/build/SdkResourceGenerator.kt b/buildSrc/src/main/kotlin/androidx/build/SdkResourceGenerator.kt
index c2ebd63..f312785 100644
--- a/buildSrc/src/main/kotlin/androidx/build/SdkResourceGenerator.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/SdkResourceGenerator.kt
@@ -92,9 +92,9 @@
                 "generateSdkResource",
                 SdkResourceGenerator::class.java
             ) {
-                it.prebuiltsRoot = (File(SupportConfig.getPrebuiltsRootPath(project))).canonicalPath
-                it.debugKeystore.set(SupportConfig.getKeystore(project))
-                it.localSupportRepo = SupportConfig.getSupportRepoPath(project)
+                it.prebuiltsRoot = project.getPrebuiltsRoot().canonicalPath
+                it.debugKeystore.set(project.getKeystore())
+                it.localSupportRepo = project.getRepositoryDirectory().canonicalPath
                 it.gradleVersion = project.gradle.gradleVersion
                 it.outputFile.set(File(generatedDirectory, "sdk.prop"))
             }
diff --git a/buildSrc/src/main/kotlin/androidx/build/SupportConfig.kt b/buildSrc/src/main/kotlin/androidx/build/SupportConfig.kt
index 05bfc78..92b340b 100644
--- a/buildSrc/src/main/kotlin/androidx/build/SupportConfig.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/SupportConfig.kt
@@ -47,40 +47,22 @@
     const val TARGET_SDK_VERSION = 29
 
     @JvmStatic
-    fun getKeystore(project: Project): File {
-        val supportRoot = (project.rootProject.property("ext") as ExtraPropertiesExtension)
-                .get("supportRootFolder") as File
-        return File(supportRoot, "development/keystore/debug.keystore")
-    }
-
-    @JvmStatic
-    fun getSupportRoot(project: Project): File {
-        val extension = (project.rootProject.property("ext") as ExtraPropertiesExtension)
-        return extension.get("supportRootFolder") as File
-    }
-
-    @JvmStatic
-    fun getExternalProjectPath(project: Project): File {
-        val extension = (project.rootProject.property("ext") as ExtraPropertiesExtension)
-        val file = extension.get("supportRootFolder") as File
-        return File(file.parentFile.parentFile, "external")
-    }
-
-    @JvmStatic
-    fun getPrebuiltsRootPath(project: Project): String {
-        val reposProperties = (project.rootProject.property("ext") as ExtraPropertiesExtension)
-            .get("repos") as Map<*, *>
-        return reposProperties["prebuiltsRoot"].toString()
-    }
-
-    @JvmStatic
-    fun getSupportRepoPath(project: Project): String {
-        return project.getRepositoryDirectory().absolutePath
-    }
-
-    @JvmStatic
     fun isUiProject() = System.getenv("DIST_SUBDIR") == "/ui"
 
     @JvmStatic
     fun getJavaToolsJarPath() = System.getenv("JAVA_TOOLS_JAR")
 }
+
+fun Project.getExternalProjectPath(): File {
+    return File(project.getCheckoutRoot(), "external")
+}
+
+fun Project.getKeystore(): File {
+    return File(project.getSupportRootFolder(), "development/keystore/debug.keystore")
+}
+
+fun Project.getPrebuiltsRoot(): File {
+    val ext = project.rootProject.property("ext") as ExtraPropertiesExtension
+    val reposProperties = ext.get("repos") as Map<*, *>
+    return File(reposProperties["prebuiltsRoot"].toString())
+}
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/ProjectGraph.kt b/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/ProjectGraph.kt
index 049a1de..da0d591 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/ProjectGraph.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/ProjectGraph.kt
@@ -16,7 +16,7 @@
 
 package androidx.build.dependencyTracker
 
-import androidx.build.SupportConfig
+import androidx.build.getSupportRootFolder
 import org.gradle.api.Project
 import java.io.File
 
@@ -25,15 +25,15 @@
 /**
  * Creates a project graph for fast lookup by file path
  */
-class ProjectGraph(rootProject: Project, val logger: Logger? = null) {
+class ProjectGraph(project: Project, val logger: Logger? = null) {
     private val rootNode: Node
 
     init {
         // always use cannonical file: b/112205561
         logger?.info("initializing ProjectGraph")
         rootNode = Node(logger)
-        val rootProjectDir = SupportConfig.getSupportRoot(rootProject).canonicalFile
-        rootProject.subprojects.forEach {
+        val rootProjectDir = project.getSupportRootFolder().canonicalFile
+        project.subprojects.forEach {
             logger?.info("creating node for ${it.path}")
             val relativePath = it.projectDir.canonicalFile.toRelativeString(rootProjectDir)
             val sections = relativePath.split(File.separatorChar)
diff --git a/buildSrc/src/main/kotlin/androidx/build/license/CheckExternalDependencyLicensesTask.kt b/buildSrc/src/main/kotlin/androidx/build/license/CheckExternalDependencyLicensesTask.kt
index 8c3a4e1..acbdf79 100644
--- a/buildSrc/src/main/kotlin/androidx/build/license/CheckExternalDependencyLicensesTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/license/CheckExternalDependencyLicensesTask.kt
@@ -15,12 +15,12 @@
  */
 package androidx.build.license
 
+import androidx.build.getCheckoutRoot
 import androidx.build.gradle.isRoot
 import org.gradle.api.DefaultTask
 import org.gradle.api.GradleException
 import org.gradle.api.Project
 import org.gradle.api.artifacts.ExternalDependency
-import org.gradle.api.plugins.ExtraPropertiesExtension
 import org.gradle.api.tasks.TaskAction
 import java.io.File
 
@@ -33,10 +33,7 @@
 open class CheckExternalDependencyLicensesTask : DefaultTask() {
     @TaskAction
     fun checkDependencies() {
-        val supportRoot = (project.rootProject.property("ext") as ExtraPropertiesExtension)
-                .get("supportRootFolder") as File
-        val prebuiltsRoot = File(supportRoot, "../../prebuilts").canonicalFile
-
+        val prebuiltsRoot = File(project.getCheckoutRoot(), "prebuilts")
         val checkerConfig = project.configurations.getByName(CONFIGURATION_NAME)
 
         project
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
index f132f7b..b844f81 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
@@ -16,8 +16,8 @@
 
 package androidx.build.metalava
 
-import androidx.build.checkapi.ApiLocation
 import androidx.build.checkapi.ApiBaselinesLocation
+import androidx.build.checkapi.ApiLocation
 import org.gradle.api.provider.Property
 import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.InputFiles
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt
index c971b5a..c2c9afe 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt
@@ -16,8 +16,8 @@
 
 package androidx.build.metalava
 
-import androidx.build.checkapi.ApiLocation
 import androidx.build.checkapi.ApiBaselinesLocation
+import androidx.build.checkapi.ApiLocation
 import androidx.build.java.JavaCompileInputs
 import org.gradle.api.provider.Property
 import org.gradle.api.tasks.Input
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt
index bb9b3a1..563cd55 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt
@@ -16,11 +16,11 @@
 
 package androidx.build.metalava
 
-import androidx.build.SupportConfig
 import androidx.build.Version
 import androidx.build.checkapi.getApiFileVersion
 import androidx.build.checkapi.getVersionedApiLocation
 import androidx.build.checkapi.isValidArtifactVersion
+import androidx.build.getCheckoutRoot
 import androidx.build.java.JavaCompileInputs
 import org.gradle.api.DefaultTask
 import org.gradle.api.Project
@@ -45,8 +45,7 @@
     fun exec() {
         val groupId = project.group.toString()
         val artifactId = project.name
-        val internalPrebuiltsDir =
-            File(SupportConfig.getSupportRoot(project), "../../prebuilts/androidx/internal")
+        val internalPrebuiltsDir = File(project.getCheckoutRoot(), "prebuilts/androidx/internal")
         val projectPrebuiltsDir =
             File(internalPrebuiltsDir, groupId.replace(".", "/") + "/" + artifactId)
 
diff --git a/buildSrc/src/main/kotlin/androidx/build/studio/StudioArchiveCreator.kt b/buildSrc/src/main/kotlin/androidx/build/studio/StudioArchiveCreator.kt
index ae6a0f9..17ab837 100644
--- a/buildSrc/src/main/kotlin/androidx/build/studio/StudioArchiveCreator.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/studio/StudioArchiveCreator.kt
@@ -16,7 +16,7 @@
 
 package androidx.build.studio
 
-import androidx.build.SupportConfig
+import androidx.build.getPrebuiltsRoot
 import org.gradle.api.Project
 import java.io.File
 import java.nio.file.Files
@@ -68,8 +68,8 @@
     filename: String,
     destinationPath: String
 ) {
-    val prebuiltsDir = SupportConfig.getPrebuiltsRootPath(project)
-    val prebuiltsFile = File("$prebuiltsDir/androidx/studio/$filename")
+    val prebuiltsRoot = project.getPrebuiltsRoot()
+    val prebuiltsFile = File(prebuiltsRoot, "androidx/studio/$filename")
 
     // Copy archive from prebuilts to the parent directory of the install directory
     println("Copying prebuilt studio archive to $destinationPath")
diff --git a/buildSrc/src/main/kotlin/androidx/build/studio/StudioTask.kt b/buildSrc/src/main/kotlin/androidx/build/studio/StudioTask.kt
index 4f9aff3..201f3b8 100644
--- a/buildSrc/src/main/kotlin/androidx/build/studio/StudioTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/studio/StudioTask.kt
@@ -17,6 +17,7 @@
 package androidx.build.studio
 
 import androidx.build.SupportConfig
+import androidx.build.getSupportRootFolder
 import org.gradle.api.DefaultTask
 import org.gradle.api.Project
 import org.gradle.api.internal.tasks.userinput.UserInputHandler
@@ -121,8 +122,7 @@
     }
 
     private fun launchStudio() {
-        val supportRootDir = SupportConfig.getSupportRoot(project)
-        val vmOptions = File(supportRootDir, "development/studio/studio.vmoptions")
+        val vmOptions = File(project.getSupportRootFolder(), "development/studio/studio.vmoptions")
 
         ProcessBuilder().apply {
             inheritIO()
diff --git a/navigation/navigation-safe-args-generator/build.gradle b/navigation/navigation-safe-args-generator/build.gradle
index ee82964..6d7022a 100644
--- a/navigation/navigation-safe-args-generator/build.gradle
+++ b/navigation/navigation-safe-args-generator/build.gradle
@@ -37,10 +37,14 @@
 
     testImplementation(JUNIT)
     testImplementation(GOOGLE_COMPILE_TESTING)
-    testImplementation fileTree(dir: "${SdkHelperKt.getSdkPath(project.rootDir)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
-            include : "android.jar")
-    testImplementation fileTree(dir: "${new File(project(":navigation:navigation-common").buildDir, "libJar")}",
-            include : "*.jar")
+    testImplementation fileTree(
+            dir: "${SdkHelperKt.getSdkPath(project)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
+            include : "android.jar"
+    )
+    testImplementation fileTree(
+            dir: "${new File(project(":navigation:navigation-common").buildDir, "libJar")}",
+            include : "*.jar"
+    )
 }
 
 tasks.findByName("test").doFirst {
diff --git a/room/compiler/build.gradle b/room/compiler/build.gradle
index 0bc38b7..ac9052a0 100644
--- a/room/compiler/build.gradle
+++ b/room/compiler/build.gradle
@@ -117,12 +117,18 @@
     testImplementation(JUNIT)
     testImplementation(JSR250)
     testImplementation(MOCKITO_CORE)
-    testImplementation fileTree(dir: "${SdkHelperKt.getSdkPath(project.rootDir)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
-            include : "android.jar")
-    testImplementation fileTree(dir: "${new File(project(":room:room-runtime").buildDir, "libJar")}",
-            include : "*.jar")
-    testImplementation fileTree(dir: "${new File(project(":sqlite:sqlite").buildDir, "libJar")}",
-            include : "*.jar")
+    testImplementation fileTree(
+            dir: "${SdkHelperKt.getSdkPath(project)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
+            include : "android.jar"
+    )
+    testImplementation fileTree(
+            dir: "${new File(project(":room:room-runtime").buildDir, "libJar")}",
+            include : "*.jar"
+    )
+    testImplementation fileTree(
+            dir: "${new File(project(":sqlite:sqlite").buildDir, "libJar")}",
+            include : "*.jar"
+    )
 }
 
 def generateAntlrTask = task('generateAntlrGrammar', type: JavaExec) {
diff --git a/ui/build.gradle b/ui/build.gradle
index 398aa6c..8bc08ff 100644
--- a/ui/build.gradle
+++ b/ui/build.gradle
@@ -2,11 +2,15 @@
 import androidx.build.SdkHelperKt
 
 buildscript {
-    ext.supportRootFolder = file(project.projectDir.parent)
+    // Note this is different from the root project's `build.gradle`. We call this method to
+    // establish the "canonical" root project directory, e.g. `frameworks/support`.
+    SdkHelperKt.setSupportRootFolder(project, project.projectDir.parentFile)
+
     apply from: 'buildSrc/repos.gradle'
     apply from: 'buildSrc/build_dependencies.gradle'
     repos.addMavenRepositories(repositories)
-    SdkHelperKt.setSdkInLocalPropertiesFile(ext.supportRootFolder, project.projectDir)
+
+    SdkHelperKt.writeSdkPathToLocalPropertiesFile(project)
 
     dependencies {
         classpath build_libs.agp
diff --git a/webkit/webkit/build.gradle b/webkit/webkit/build.gradle
index 145f657..79c930c 100644
--- a/webkit/webkit/build.gradle
+++ b/webkit/webkit/build.gradle
@@ -16,9 +16,8 @@
 
 import static androidx.build.dependencies.DependenciesKt.*
 import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
 import androidx.build.Publish
-import androidx.build.SupportConfig
+import androidx.build.SupportConfigKt
 
 plugins {
     id("AndroidXPlugin")
@@ -41,7 +40,7 @@
 }
 
 ext {
-    webviewBoundaryInterfacesDir = new File(SupportConfig.getExternalProjectPath(project),
+    webviewBoundaryInterfacesDir = new File(SupportConfigKt.getExternalProjectPath(project),
             "webview_support_interfaces")
 }
 
@@ -51,11 +50,14 @@
     }
     sourceSets {
         // Allow compiling the WebView support library boundary interfaces from this project.
-        main.java.srcDirs += new File(webviewBoundaryInterfacesDir, "src").getAbsolutePath()
+        main.java.srcDirs += new File(webviewBoundaryInterfacesDir, "src").getCanonicalPath()
     }
 
     buildTypes.all {
-        consumerProguardFiles new File(webviewBoundaryInterfacesDir, "proguard.flags") , 'proguard-rules.pro'
+        consumerProguardFiles(
+                new File(webviewBoundaryInterfacesDir, 'proguard.flags'),
+                'proguard-rules.pro'
+        )
     }
 }