Merge "Fixed problem of methodBinder nullability in DaoWriter.kt" into androidx-main
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/ToolbarMenuHostTest.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/ToolbarMenuHostTest.kt
index 09d44b2..317fcc3 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/ToolbarMenuHostTest.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/ToolbarMenuHostTest.kt
@@ -96,7 +96,7 @@
     @Test
     fun providedOnPrepareMenu() {
         with(ActivityScenario.launch(ToolbarTestActivity::class.java)) {
-            var menuPrepared: Boolean
+            var menuPrepared = false
             val toolbar: Toolbar = withActivity {
                 findViewById(androidx.appcompat.test.R.id.toolbar)
             }
@@ -117,8 +117,11 @@
                 })
             }
 
-            menuPrepared = false
-            withActivity { toolbar.invalidateMenu() }
+            assertThat(menuPrepared).isFalse()
+
+            toolbar.showOverflowMenu()
+            PollingCheck.waitFor { toolbar.isOverflowMenuShowing }
+
             assertThat(menuPrepared).isTrue()
         }
     }
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/Toolbar.java b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/Toolbar.java
index 205bfd6..9993998 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/Toolbar.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/Toolbar.java
@@ -158,7 +158,7 @@
 public class Toolbar extends ViewGroup implements MenuHost {
     private static final String TAG = "Toolbar";
 
-    private ActionMenuView mMenuView;
+    ActionMenuView mMenuView;
     private TextView mTitleTextView;
     private TextView mSubtitleTextView;
     private ImageButton mNavButtonView;
@@ -232,7 +232,7 @@
     private ActionMenuPresenter mOuterActionMenuPresenter;
     private ExpandedActionViewMenuPresenter mExpandedMenuPresenter;
     private MenuPresenter.Callback mActionMenuPresenterCallback;
-    private MenuBuilder.Callback mMenuBuilderCallback;
+    MenuBuilder.Callback mMenuBuilderCallback;
 
     private boolean mCollapsible;
 
@@ -1253,7 +1253,34 @@
             mMenuView = new ActionMenuView(getContext());
             mMenuView.setPopupTheme(mPopupTheme);
             mMenuView.setOnMenuItemClickListener(mMenuViewItemClickListener);
-            mMenuView.setMenuCallbacks(mActionMenuPresenterCallback, mMenuBuilderCallback);
+            mMenuView.setMenuCallbacks(mActionMenuPresenterCallback,
+                    // Have Toolbar insert a Callback to ensure onPrepareMenu is called properly
+                    new MenuBuilder.Callback() {
+                    // The mMenuView item does not call into the mMenuBuilderCallback when
+                    // menuItems are selected, so this should not get called, but we implement it
+                    // anyway
+                    @Override
+                    public boolean onMenuItemSelected(@NonNull MenuBuilder menu,
+                            @NonNull MenuItem item) {
+                        // Check if there is a mMenuBuilderCallback and if so, forward the call.
+                        return mMenuBuilderCallback != null
+                                && mMenuBuilderCallback.onMenuItemSelected(menu, item);
+                    }
+
+                    @Override
+                    public void onMenuModeChange(@NonNull MenuBuilder menu) {
+                        // If the menu is not showing, we are about to show it, so we need to
+                        // make the prepare call.
+                        if (!mMenuView.isOverflowMenuShowing()) {
+                            mMenuHostHelper.onPrepareMenu(menu);
+                        }
+                        // If there is a mMenuBuilderCallback, forward the onMenuModeChanged call.
+                        if (mMenuBuilderCallback != null) {
+                            mMenuBuilderCallback.onMenuModeChange(menu);
+                        }
+                    }
+                }
+            );
             final LayoutParams lp = generateDefaultLayoutParams();
             lp.gravity = GravityCompat.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
             mMenuView.setLayoutParams(lp);
@@ -2445,8 +2472,6 @@
         ArrayList<MenuItem> newMenuItemList = getCurrentMenuItems();
         newMenuItemList.removeAll(oldMenuItemList);
         mProvidedMenuItems = newMenuItemList;
-
-        mMenuHostHelper.onPrepareMenu(menu);
     }
 
     @Override
diff --git a/benchmark/benchmark-macro/api/current.txt b/benchmark/benchmark-macro/api/current.txt
index 4a1e12c..68a4a8c 100644
--- a/benchmark/benchmark-macro/api/current.txt
+++ b/benchmark/benchmark-macro/api/current.txt
@@ -64,6 +64,7 @@
     method public androidx.test.uiautomator.UiDevice getDevice();
     method public Integer? getIteration();
     method public String getPackageName();
+    method public void killProcess(optional boolean useKillAll);
     method public void killProcess();
     method public void pressHome(optional long delayDurationMs);
     method public void pressHome();
diff --git a/benchmark/benchmark-macro/api/public_plus_experimental_current.txt b/benchmark/benchmark-macro/api/public_plus_experimental_current.txt
index eb7d8a1..f2aa08e 100644
--- a/benchmark/benchmark-macro/api/public_plus_experimental_current.txt
+++ b/benchmark/benchmark-macro/api/public_plus_experimental_current.txt
@@ -81,6 +81,7 @@
     method public androidx.test.uiautomator.UiDevice getDevice();
     method public Integer? getIteration();
     method public String getPackageName();
+    method public void killProcess(optional boolean useKillAll);
     method public void killProcess();
     method public void pressHome(optional long delayDurationMs);
     method public void pressHome();
diff --git a/benchmark/benchmark-macro/api/restricted_current.txt b/benchmark/benchmark-macro/api/restricted_current.txt
index 53fcd5a..c548035 100644
--- a/benchmark/benchmark-macro/api/restricted_current.txt
+++ b/benchmark/benchmark-macro/api/restricted_current.txt
@@ -79,6 +79,7 @@
     method public androidx.test.uiautomator.UiDevice getDevice();
     method public Integer? getIteration();
     method public String getPackageName();
+    method public void killProcess(optional boolean useKillAll);
     method public void killProcess();
     method public void pressHome(optional long delayDurationMs);
     method public void pressHome();
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
index e11d2c8..697fc15 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
@@ -59,7 +59,7 @@
     )
 
     // always kill the process at beginning of a collection.
-    scope.killProcess()
+    scope.killProcess(useKillAll = Shell.isSessionRooted())
     try {
         userspaceTrace("compile $packageName") {
             compilationMode.resetAndCompile(
@@ -114,7 +114,7 @@
             Log.d(TAG, "Total Run Time Ns: $totalRunTime")
         }
     } finally {
-        scope.killProcess()
+        scope.killProcess(useKillAll = Shell.isSessionRooted())
     }
 }
 
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkScope.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkScope.kt
index a78f45e..f0d8b34 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkScope.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkScope.kt
@@ -215,10 +215,13 @@
 
     /**
      * Force-stop the process being measured.
+     *
+     *@param useKillAll should be set to `true` for System apps or pre-installed apps.
      */
-    public fun killProcess() {
+    @JvmOverloads
+    public fun killProcess(useKillAll: Boolean = false) {
         Log.d(TAG, "Killing process $packageName")
-        if (Shell.isSessionRooted()) {
+        if (useKillAll) {
             device.executeShellCommand("killall $packageName")
         } else {
             device.executeShellCommand("am force-stop $packageName")
diff --git a/buildSrc-tests/build.gradle b/buildSrc-tests/build.gradle
index ff35c32..30c2a30 100644
--- a/buildSrc-tests/build.gradle
+++ b/buildSrc-tests/build.gradle
@@ -25,10 +25,22 @@
     id("kotlin")
 }
 
+apply from: "../buildSrc/kotlin-dsl-dependency.gradle"
+
+def buildSrcJar(jarName) {
+    return project.files(
+            new File(
+                    BuildServerConfigurationKt.getRootOutDirectory(project),
+                    "buildSrc/$jarName/build/libs/${jarName}.jar"
+            )
+    )
+}
+
 dependencies {
     implementation(gradleApi())
-    implementation(project.files(new File(BuildServerConfigurationKt.getRootOutDirectory(project), "buildSrc/private/build/libs/private.jar")))
-    implementation(project.files(new File(BuildServerConfigurationKt.getRootOutDirectory(project), "buildSrc/public/build/libs/public.jar")))
+    implementation(buildSrcJar("private"))
+    implementation(buildSrcJar("public"))
+    implementation(buildSrcJar("jetpad-integration"))
     implementation("com.googlecode.json-simple:json-simple:1.1")
     implementation(libs.gson)
     implementation(libs.dom4j) {
@@ -43,6 +55,9 @@
     testImplementation(project(":internal-testutils-gradle-plugin"))
     testImplementation(gradleTestKit())
     testImplementation(libs.checkmark)
+    testImplementation(libs.kotlinGradlePluginz)
+    testImplementation(libs.toml)
+    testImplementation(findGradleKotlinDsl())
 }
 
 SdkResourceGenerator.generateForHostTest(project)
diff --git a/buildSrc-tests/src/test/kotlin/androidx/build/AndroidXSelfTestProject.kt b/buildSrc-tests/src/test/kotlin/androidx/build/AndroidXSelfTestProject.kt
index d29af2c..1a243cc 100644
--- a/buildSrc-tests/src/test/kotlin/androidx/build/AndroidXSelfTestProject.kt
+++ b/buildSrc-tests/src/test/kotlin/androidx/build/AndroidXSelfTestProject.kt
@@ -29,7 +29,8 @@
     companion object {
         fun cubaneBuildGradleText(
             plugins: List<String> = listOf("java-library", "kotlin", "AndroidXPlugin"),
-            version: String? = "1.2.3"
+            version: String? = "1.2.3",
+            moreConfig: String = ""
         ): String {
             val mavenVersionLine = if (version != null) {
                 "  mavenVersion = new Version(\"$version\")"
@@ -48,6 +49,8 @@
                       |  api(libs.kotlinStdlib)
                       |}
                       |
+                      |$moreConfig
+                      |
                       |androidx {
                       |  publish = Publish.SNAPSHOT_AND_RELEASE
                       |$mavenVersionLine
diff --git a/buildSrc-tests/src/test/kotlin/androidx/build/SdkResourceGeneratorTest.kt b/buildSrc-tests/src/test/kotlin/androidx/build/SdkResourceGeneratorTest.kt
index c58d39f..a571f1a 100644
--- a/buildSrc-tests/src/test/kotlin/androidx/build/SdkResourceGeneratorTest.kt
+++ b/buildSrc-tests/src/test/kotlin/androidx/build/SdkResourceGeneratorTest.kt
@@ -31,8 +31,8 @@
 
         val project = ProjectBuilder.builder().build()
 
+        project.setSupportRootFolder(File("files/support"))
         val extension = project.rootProject.property("ext") as ExtraPropertiesExtension
-        extension.set("supportRootFolder", File("files/support"))
         extension.set("buildSrcOut", project.projectDir.resolve("relative/path"))
 
         SdkResourceGenerator.registerSdkResourceGeneratorTask(project)
diff --git a/buildSrc-tests/src/test/kotlin/androidx/build/buildFiles.kt b/buildSrc-tests/src/test/kotlin/androidx/build/buildFiles.kt
index f2adaf6..df67b65 100644
--- a/buildSrc-tests/src/test/kotlin/androidx/build/buildFiles.kt
+++ b/buildSrc-tests/src/test/kotlin/androidx/build/buildFiles.kt
@@ -22,38 +22,47 @@
     writeBuildFiles(projects.toList())
 }
 
-fun AndroidXPluginTestContext.writeBuildFiles(projects: List<AndroidXSelfTestProject>) {
+fun AndroidXPluginTestContext.writeBuildFiles(
+    projects: List<AndroidXSelfTestProject>,
+    groupLines: List<String> = listOf()
+) {
     writeRootSettingsFile(projects.map { it.gradlePath })
     writeRootBuildFile()
-    writeApplyPluginScript()
+    writeApplyPluginScripts()
 
-    File(supportRoot, "libraryversions.toml").writeText(
-        """|[groups]
-               |[versions]
-               |""".trimMargin()
-    )
+    writeLibraryVersionsFile(supportRoot, groupLines)
 
     // Matches behavior of root properties
     File(supportRoot, "gradle.properties").writeText(
         """|# Do not automatically include stdlib
-               |kotlin.stdlib.default.dependency=false
-               |
-               |# Avoid OOM in subgradle
-               |# (https://github.com/gradle/gradle/issues/10527#issuecomment-887704062)
-               |org.gradle.jvmargs=-Xmx3g -XX:MaxMetaspaceSize=1g
-               |""".trimMargin()
+           |kotlin.stdlib.default.dependency=false
+           |
+           |# Avoid OOM in subgradle
+           |# (https://github.com/gradle/gradle/issues/10527#issuecomment-887704062)
+           |org.gradle.jvmargs=-Xmx3g -XX:MaxMetaspaceSize=1g
+           |""".trimMargin()
     )
 
     projects.forEach { it.writeFiles() }
 }
 
+fun writeLibraryVersionsFile(supportFolder: File, groupLines: List<String>) {
+    File(supportFolder, "libraryversions.toml").writeText(
+        buildString {
+            appendLine("[groups]")
+            groupLines.forEach { appendLine(it) }
+            appendLine("[versions]")
+        }
+    )
+}
+
 fun AndroidXPluginTestContext.writeRootSettingsFile(projectPaths: List<String>) {
     val settingsString = buildString {
         append(
             """|pluginManagement {
-                   |  ${setup.repositories}
-                   |}
-                   |""".trimMargin()
+               |  ${setup.repositories}
+               |}
+               |""".trimMargin()
         )
         appendLine()
         projectPaths.forEach {
@@ -63,15 +72,20 @@
     File(setup.rootDir, "settings.gradle").writeText(settingsString)
 }
 
-fun AndroidXPluginTestContext.writeApplyPluginScript() {
-    setup.rootDir.resolve("buildSrc/apply").also { it.mkdirs() }
-        .resolve("applyAndroidXImplPlugin.gradle").writeText(
-        """|import androidx.build.AndroidXImplPlugin
-           |buildscript {
-           |  ${setup.repositories}
-           |  $buildScriptDependencies
-           |}
-           |apply plugin: AndroidXImplPlugin
-           |""".trimMargin()
-    )
+fun AndroidXPluginTestContext.writeApplyPluginScripts() {
+    setup.rootDir.resolve("buildSrc/apply").also {
+        it.mkdirs()
+
+        listOf("AndroidXImplPlugin", "AndroidXComposeImplPlugin").forEach { pluginName ->
+            it.resolve("apply$pluginName.gradle").writeText(
+                """|import androidx.build.$pluginName
+                   |buildscript {
+                   |  ${setup.repositories}
+                   |  $buildScriptDependencies
+                   |}
+                   |apply plugin: $pluginName
+                   |""".trimMargin()
+            )
+        }
+    }
 }
\ No newline at end of file
diff --git a/buildSrc-tests/src/test/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTaskTest.kt b/buildSrc-tests/src/test/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTaskTest.kt
new file mode 100644
index 0000000..4035dac
--- /dev/null
+++ b/buildSrc-tests/src/test/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTaskTest.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.build.buildInfo
+
+import org.gradle.api.artifacts.ModuleDependency
+import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
+import org.junit.Test
+import androidx.build.buildInfo.CreateLibraryBuildInfoFileTask.Companion.asBuildInfoDependencies
+import net.saff.checkmark.Checkmark.Companion.check
+
+class CreateLibraryBuildInfoFileTaskTest {
+    @Test
+    fun buildInfoDependencies() {
+        val deps: List<ModuleDependency> =
+            listOf(DefaultExternalModuleDependency("androidx.group", "artifact", "version"))
+        deps.asBuildInfoDependencies().single().check { it.groupId == "androidx.group" }
+            .check { it.artifactId == "artifact" }.check { it.version == "version" }
+            .check { !it.isTipOfTree }
+    }
+
+    @Test
+    fun suffix() {
+        computeTaskSuffix("cubane").check { it == "" }
+        computeTaskSuffix("cubane-jvm").check { it == "Jvm" }
+        computeTaskSuffix("cubane-jvm-linux-x64").check { it == "JvmLinuxX64" }
+    }
+}
\ No newline at end of file
diff --git a/buildSrc-tests/src/test/kotlin/androidx/build/integrationtests/BuildInfoTest.kt b/buildSrc-tests/src/test/kotlin/androidx/build/integrationtests/BuildInfoTest.kt
index d7fae0d..e4a83e6 100644
--- a/buildSrc-tests/src/test/kotlin/androidx/build/integrationtests/BuildInfoTest.kt
+++ b/buildSrc-tests/src/test/kotlin/androidx/build/integrationtests/BuildInfoTest.kt
@@ -26,6 +26,32 @@
 
 class BuildInfoTest {
     @Test
+    fun kmpBuildInfoTasks() = pluginTest {
+        val env = environmentForExplicitChangeInfo()
+
+        writeBuildFiles(
+            AndroidXSelfTestProject.cubaneKmpProject.copy(
+                buildGradleText = AndroidXSelfTestProject.buildGradleForKmp(
+                    withJava = true,
+                    addJvmDependency = true
+                )
+            )
+        )
+
+        // Run to generate build_info file to examine.
+        runGradle(":cubane:cubanekmp:createLibraryBuildInfoFilesJvm", "--stacktrace", env = env)
+
+        // Generated by command above.  See CreateLibraryBuildInfoFileTask doc for derivation
+        // of filename
+        val buildInfoPath = "dist/build-info/cubane_cubanekmp-jvm_build_info.txt"
+        outDir.resolve(buildInfoPath).readText().check {
+            it.contains("\"artifactId\": \"cubanekmp-jvm\"")
+        }.check {
+            it.contains("jvmdep")
+        }
+    }
+
+    @Test
     fun androidLibraryBuildInfoTasks() = pluginTest {
         val env = environmentForExplicitChangeInfo()
 
@@ -48,6 +74,91 @@
         }
     }
 
+    @Test
+    fun androidLibraryMppBuildInfoTasks() = pluginTest {
+        val env = environmentForExplicitChangeInfo()
+
+        writeBuildFiles(
+            AndroidXSelfTestProject.cubaneProject.copy(
+                buildGradleText = AndroidXSelfTestProject.cubaneBuildGradleText(
+                    plugins = listOf(
+                        "AndroidXPlugin",
+                        "com.android.library",
+                        "AndroidXComposePlugin"
+                    ),
+                    moreConfig =
+                    """|import androidx.build.AndroidXComposePlugin
+                       |AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project)
+                       |
+                       |android {
+                       |  namespace "androidx.compose.animation"
+                       |}
+                       |
+                       |androidXComposeMultiplatform {
+                       |  android()
+                       |  desktop()
+                       |}
+                       |""".trimMargin()
+                )
+            ),
+
+            AndroidXSelfTestProject(
+                groupId = "compose",
+                artifactId = "compiler:compiler",
+                version = null,
+                buildGradleText = ""
+            )
+        )
+
+        // Run to generate build_info file to examine.
+        runGradle(
+            "-Pandroidx.compose.multiplatformEnabled=true",
+            ":cubane:cubane:createLibraryBuildInfoFilesAndroid",
+            "--stacktrace",
+            env = env
+        )
+
+        // Generated by command above.  See CreateLibraryBuildInfoFileTask doc for derivation
+        // of filename
+        val buildInfoPath = "dist/build-info/cubane_cubane-android_build_info.txt"
+        outDir.resolve(buildInfoPath).assertExists().readText().check {
+            it.contains("\"artifactId\": \"cubane-android\"")
+        }
+    }
+
+    @Test
+    fun pluginBuildInfoTasks() = pluginTest {
+        val env = environmentForExplicitChangeInfo()
+
+        writeBuildFiles(
+            AndroidXSelfTestProject.cubaneProject.copy(
+                buildGradleText = AndroidXSelfTestProject.cubaneBuildGradleText(
+                    plugins = listOf("AndroidXPlugin", "kotlin", "java-gradle-plugin"),
+                    moreConfig =
+                    """|gradlePlugin {
+                       |  plugins {
+                       |    benchmark {
+                       |      id = "androidx.benchmark"
+                       |      implementationClass = "androidx.benchmark.gradle.BenchmarkPlugin"
+                       |    }
+                       |  }
+                       |}
+                       |""".trimMargin()
+                )
+            )
+        )
+
+        // Run to generate build_info file to examine.
+        runGradle(":cubane:cubane:createLibraryBuildInfoFiles", "--stacktrace", env = env)
+
+        // Generated by command above.  See CreateLibraryBuildInfoFileTask doc for derivation
+        // of filename
+        val buildInfoPath = "dist/build-info/cubane_cubane_build_info.txt"
+        outDir.resolve(buildInfoPath).assertExists().readText().check {
+            it.contains("\"artifactId\": \"cubane\"")
+        }
+    }
+
     /**
      * Avoid calling git in tests by taking advantage of environment variables with changelist info
      * and manifest of changed files.  (These are usually set by busytown and detected in our
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
index 46f55a3..376419d 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
@@ -194,17 +194,19 @@
                 }
             }
 
-            // TODO: figure out how to apply this to multiplatform modules
-            dependencies.add(
-                "lintChecks",
-                project.dependencies.project(
-                    mapOf(
-                        "path" to ":compose:lint:internal-lint-checks",
-                        // TODO(b/206617878) remove this shadow configuration
-                        "configuration" to "shadow"
+            if (!allowMissingLintProject()) {
+                // TODO: figure out how to apply this to multiplatform modules
+                dependencies.add(
+                    "lintChecks",
+                    project.dependencies.project(
+                        mapOf(
+                            "path" to ":compose:lint:internal-lint-checks",
+                            // TODO(b/206617878) remove this shadow configuration
+                            "configuration" to "shadow"
+                        )
                     )
                 )
-            )
+            }
         }
 
         private fun Project.configureManifests() {
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt
index ac01224..c12c696 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt
@@ -17,6 +17,7 @@
 package androidx.build
 
 import androidx.build.checkapi.shouldConfigureApiTasks
+import com.android.build.gradle.internal.crash.afterEvaluate
 import groovy.lang.Closure
 import org.gradle.api.GradleException
 import org.gradle.api.Project
@@ -185,6 +186,14 @@
             false
         }
 
+    internal fun ifReleasing(action: () -> Unit) {
+        project.afterEvaluate {
+            if (shouldRelease()) {
+                action()
+            }
+        }
+    }
+
     internal fun isPublishConfigured(): Boolean = (
             publish != Publish.UNSET ||
             type.publish != Publish.UNSET
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
index f1067803..373b053 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
@@ -25,7 +25,7 @@
 import androidx.build.SupportConfig.DEFAULT_MIN_SDK_VERSION
 import androidx.build.SupportConfig.INSTRUMENTATION_RUNNER
 import androidx.build.SupportConfig.TARGET_SDK_VERSION
-import androidx.build.buildInfo.addCreateLibraryBuildInfoFileTask
+import androidx.build.buildInfo.addCreateLibraryBuildInfoFileTasks
 import androidx.build.checkapi.JavaApiTaskConfig
 import androidx.build.checkapi.KmpApiTaskConfig
 import androidx.build.checkapi.LibraryApiTaskConfig
@@ -418,7 +418,7 @@
         project.configurePublicResourcesStub(libraryExtension)
         project.configureSourceJarForAndroid(libraryExtension)
         project.configureVersionFileWriter(libraryExtension, androidXExtension)
-        project.addCreateLibraryBuildInfoFileTask(androidXExtension)
+        project.addCreateLibraryBuildInfoFileTasks(androidXExtension)
         project.configureJavaCompilationWarnings(androidXExtension)
 
         project.configureDependencyVerification(androidXExtension) { taskProvider ->
@@ -482,7 +482,7 @@
             }
         }
 
-        project.addCreateLibraryBuildInfoFileTask(extension)
+        project.addCreateLibraryBuildInfoFileTasks(extension)
 
         // Standard lint, docs, and Metalava configuration for AndroidX projects.
         project.configureNonAndroidProjectForLint(extension)
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
index aad479ab..b298c5b 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
@@ -16,6 +16,7 @@
 
 package androidx.build
 
+import androidx.build.AndroidXImplPlugin.Companion.CREATE_LIBRARY_BUILD_INFO_FILES_TASK
 import androidx.build.AndroidXImplPlugin.Companion.ZIP_CONSTRAINED_TEST_CONFIGS_WITH_APKS_TASK
 import androidx.build.AndroidXImplPlugin.Companion.ZIP_TEST_CONFIGS_WITH_APKS_TASK
 import androidx.build.buildInfo.CreateAggregateLibraryBuildInfoFileTask
@@ -26,8 +27,8 @@
 import androidx.build.playground.VerifyPlaygroundGradleConfigurationTask
 import androidx.build.studio.StudioTask.Companion.registerStudioTask
 import androidx.build.testConfiguration.registerOwnersServiceTasks
-import androidx.build.uptodatedness.cacheEvenIfNoOutputs
 import androidx.build.uptodatedness.TaskUpToDateValidator
+import androidx.build.uptodatedness.cacheEvenIfNoOutputs
 import com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
 import com.android.build.gradle.AppPlugin
 import com.android.build.gradle.LibraryPlugin
@@ -94,7 +95,7 @@
             )
         )
         buildOnServerTask.dependsOn(
-            tasks.register(AndroidXImplPlugin.CREATE_LIBRARY_BUILD_INFO_FILES_TASK)
+            tasks.register(CREATE_LIBRARY_BUILD_INFO_FILES_TASK)
         )
 
         VerifyPlaygroundGradleConfigurationTask.createIfNecessary(project)?.let {
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/MavenUploadHelper.kt b/buildSrc/private/src/main/kotlin/androidx/build/MavenUploadHelper.kt
index 6774607..8702293 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/MavenUploadHelper.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/MavenUploadHelper.kt
@@ -46,6 +46,7 @@
 import org.gradle.api.publish.PublishingExtension
 import org.gradle.api.publish.maven.MavenPom
 import org.gradle.api.publish.maven.MavenPublication
+import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
 import org.gradle.api.publish.maven.tasks.GenerateMavenPom
 import org.gradle.api.publish.tasks.GenerateModuleMetadata
 import org.gradle.kotlin.dsl.configure
@@ -350,6 +351,12 @@
                         }
                     })
                 }
+
+                // mark original publication as an alias, so we do not try to publish it.
+                pubs.named("kotlinMultiplatform").configure {
+                    it as MavenPublicationInternal
+                    it.isAlias = true
+                }
             }
         }
 
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateAggregateLibraryBuildInfoFileTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateAggregateLibraryBuildInfoFileTask.kt
index 7e7ac69..d4ebdb8 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateAggregateLibraryBuildInfoFileTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateAggregateLibraryBuildInfoFileTask.kt
@@ -24,10 +24,10 @@
 import org.gradle.api.DefaultTask
 import org.gradle.api.Project
 import org.gradle.api.provider.ListProperty
+import org.gradle.api.provider.Provider
 import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
-import org.gradle.api.tasks.TaskProvider
 import org.gradle.work.DisableCachingByDefault
 
 /**
@@ -114,7 +114,7 @@
 }
 
 fun Project.addTaskToAggregateBuildInfoFileTask(
-    task: TaskProvider<CreateLibraryBuildInfoFileTask>
+    task: Provider<CreateLibraryBuildInfoFileTask>
 ) {
     rootProject.tasks.named(CREATE_AGGREGATE_BUILD_INFO_FILES_TASK).configure {
         val aggregateLibraryBuildInfoFileTask = it as CreateAggregateLibraryBuildInfoFileTask
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
index fc1f69c..486ee23 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
@@ -27,20 +27,25 @@
 import androidx.build.gitclient.GitClient
 import androidx.build.gitclient.GitCommitRange
 import androidx.build.jetpad.LibraryBuildInfoFile
+import com.google.common.annotations.VisibleForTesting
 import com.google.gson.GsonBuilder
 import java.io.File
 import org.gradle.api.DefaultTask
 import org.gradle.api.Project
 import org.gradle.api.artifacts.Dependency
 import org.gradle.api.artifacts.ProjectDependency
+import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectComponentPublication
 import org.gradle.api.provider.ListProperty
 import org.gradle.api.provider.Property
 import org.gradle.api.provider.Provider
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
 import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.Optional
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
 import org.gradle.api.tasks.TaskProvider
+import org.gradle.kotlin.dsl.configure
 import org.gradle.work.DisableCachingByDefault
 import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
 
@@ -253,29 +258,55 @@
     }
 }
 
-// Task that creates a json file of a project's dependencies
-fun Project.addCreateLibraryBuildInfoFileTask(extension: AndroidXExtension) {
-    afterEvaluate {
-        if (extension.shouldRelease()) {
-            // Only generate build info files for published libraries.
-            val task = CreateLibraryBuildInfoFileTask.setup(
-                project,
-                extension.mavenGroup,
-                VariantPublishPlan(
-                    artifactId = project.name.toString(),
-                    dependencies = project.provider {
-                        val config = project.configurations.findByName("releaseRuntimeElements")
-                        config?.allDependencies.orEmpty().toList()
-                    }),
-                project.provider {
-                    project.getFrameworksSupportCommitShaAtHead()
+// Tasks that create a json files of a project's variant's dependencies
+fun Project.addCreateLibraryBuildInfoFileTasks(extension: AndroidXExtension) {
+    extension.ifReleasing {
+        configure<PublishingExtension> {
+            // Unfortunately, dependency information is only available through internal API
+            // (See https://github.com/gradle/gradle/issues/21345).
+            publications.withType(MavenPublicationInternal::class.java).configureEach { mavenPub ->
+                // Ideally we would be able to inspect each publication after initial configuration
+                // without using afterEvaluate, but there is not a clean gradle API for doing
+                // that (see https://github.com/gradle/gradle/issues/21424)
+                afterEvaluate {
+                    // java-gradle-plugin creates marker publications that are aliases of the
+                    // main publication.  We do not track these aliases.
+                    if (!mavenPub.isAlias) {
+                        createTaskForComponent(mavenPub, extension.mavenGroup, mavenPub.artifactId)
+                    }
                 }
-            )
-
-            rootProject.tasks.named(CreateLibraryBuildInfoFileTask.TASK_NAME).configure {
-                it.dependsOn(task)
             }
-            addTaskToAggregateBuildInfoFileTask(task)
         }
     }
 }
+
+private fun Project.createTaskForComponent(
+    pub: ProjectComponentPublication,
+    libraryGroup: LibraryGroup?,
+    artifactId: String
+) {
+    val task: TaskProvider<CreateLibraryBuildInfoFileTask> =
+        CreateLibraryBuildInfoFileTask.setup(
+            project = project,
+            mavenGroup = libraryGroup,
+            variant = VariantPublishPlan(
+                artifactId = artifactId,
+                taskSuffix = computeTaskSuffix(artifactId),
+                dependencies = project.provider {
+                    pub.component?.usages?.flatMap { it.dependencies }.orEmpty()
+                }
+            ),
+            shaProvider = project.provider {
+                project.getFrameworksSupportCommitShaAtHead()
+            }
+        )
+
+    rootProject.tasks.named(CreateLibraryBuildInfoFileTask.TASK_NAME)
+        .configure { it.dependsOn(task) }
+    addTaskToAggregateBuildInfoFileTask(task)
+}
+
+// For examples, see CreateLibraryBuildInfoFileTaskTest
+@VisibleForTesting
+fun computeTaskSuffix(artifactId: String) = artifactId.split("-").drop(1)
+    .joinToString("") { word -> word.replaceFirstChar { it.uppercase() } }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
index 5e62e91..760e4e8 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
@@ -18,6 +18,9 @@
 import androidx.camera.camera2.pipe.graph.GraphListener
 import kotlinx.coroutines.Deferred
 
+/**
+ * This is used to uniquely identify a specific backend implementation.
+ */
 @JvmInline
 value class CameraBackendId(public val value: String)
 
@@ -94,7 +97,7 @@
  * returned instances is managed by [CameraPipe] unless the application asks [CameraPipe] to close
  * and release previously created [CameraBackend]s.
  */
-interface CameraBackendFactory {
+fun interface CameraBackendFactory {
     /**
      * Create a new [CameraBackend] instance based on the provided [CameraContext].
      */
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
index 3b83c1f..6c03ad4 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
@@ -90,6 +90,12 @@
      * @param defaultListeners A default set of listeners that will be added to every [Request].
      * @param requiredParameters Will override any other configured parameter, and can be used
      *   to enforce that specific keys are always set to specific value for every [CaptureRequest].
+     * @param cameraBackendId If defined, this tells the [CameraGraph] to use a specific
+     *   [CameraBackend] to open and operate the camera. The defined [camera] parameter must be a
+     *   camera that can be opened by this [CameraBackend]. If this value is null it will use the
+     *   default backend that has been configured by [CameraPipe].
+     * @param customCameraBackend If defined, this [customCameraBackend] will be created an used for
+     *   _only_ this [CameraGraph]. This cannot be defined if [cameraBackendId] is defined.
      */
     public data class Config(
         val camera: CameraId,
@@ -104,10 +110,18 @@
         val defaultListeners: List<Request.Listener> = listOf(),
         val requiredParameters: Map<*, Any?> = emptyMap<Any, Any?>(),
 
+        val cameraBackendId: CameraBackendId? = null,
+        val customCameraBackend: CameraBackendFactory? = null,
         val metadataTransform: MetadataTransform = MetadataTransform(),
         val flags: Flags = Flags()
         // TODO: Internal error handling. May be better at the CameraPipe level.
-    )
+    ) {
+        init {
+            check(cameraBackendId == null || customCameraBackend == null) {
+                "Setting both cameraBackendId and customCameraBackend is not supported."
+            }
+        }
+    }
 
     /**
      * Flags define boolean values that are used to adjust the behavior and interactions with
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraPipe.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraPipe.kt
index 0f41232..2348cf6 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraPipe.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraPipe.kt
@@ -117,17 +117,17 @@
     /**
      * Configure the default and available [CameraBackend] instances that are available.
      *
-     * @param camera2Backend will override the internal camera2 backend defined by [CameraPipe].
+     * @param internalBackend will override the default camera backend defined by [CameraPipe].
      *   This may be used to mock and replace all interactions with camera2.
      * @param defaultBackend defines which camera backend instance should be used by default. If
      *   this value is specified, it must appear in the list of [cameraBackends]. If no value is
-     *   specified, the [camera2Backend] instance OR the internal camera2 backend will be used as
-     *   the default camera backend.
-     * @param cameraBackends defines a map of unique camera backend factories that may be used via
-     *   [CameraPipe].
+     *   specified, the [internalBackend] instance will be used. If [internalBackend] is null, the
+     *   default backend will use the pre-defined [CameraPipe] internal backend.
+     * @param cameraBackends defines a map of unique [CameraBackendFactory] that may be used to
+     *   create, query, and operate cameras via [CameraPipe].
      */
     class CameraBackendConfig(
-        val camera2Backend: CameraBackend? = null,
+        val internalBackend: CameraBackend? = null,
         val defaultBackend: CameraBackendId? = null,
         val cameraBackends: Map<CameraBackendId, CameraBackendFactory> = emptyMap()
     ) {
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
new file mode 100644
index 0000000..f2a53d3
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.compat
+
+import android.hardware.camera2.CameraAccessException
+import android.hardware.camera2.CameraManager
+import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraBackend
+import androidx.camera.camera2.pipe.CameraBackendId
+import androidx.camera.camera2.pipe.CameraContext
+import androidx.camera.camera2.pipe.CameraController
+import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.CameraMetadata
+import androidx.camera.camera2.pipe.StreamGraph
+import androidx.camera.camera2.pipe.config.Camera2ControllerComponent
+import androidx.camera.camera2.pipe.config.Camera2ControllerConfig
+import androidx.camera.camera2.pipe.core.Log
+import androidx.camera.camera2.pipe.graph.GraphListener
+import androidx.camera.camera2.pipe.graph.StreamGraphImpl
+import javax.inject.Inject
+import javax.inject.Provider
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.Deferred
+
+/**
+ * This is the default [CameraBackend] implementation for CameraPipe based on Camera2.
+ */
+@RequiresApi(21)
+internal class Camera2Backend @Inject constructor(
+    private val cameraManager: Provider<CameraManager>,
+    private val camera2MetadataCache: Camera2MetadataCache,
+    private val virtualCameraManager: VirtualCameraManager,
+    private val camera2CameraControllerComponent: Camera2ControllerComponent.Builder,
+) : CameraBackend {
+    override val id: CameraBackendId
+        get() = CameraBackendId("CXCP-Camera2")
+
+    override fun readCameraIdList(): List<CameraId> {
+        val cameraManager = cameraManager.get()
+        val cameraIdArray = try {
+            // WARNING: This method can, at times, return an empty list of cameras on devices that
+            //  will normally return a valid list of cameras (b/159052778)
+            cameraManager.cameraIdList
+        } catch (e: CameraAccessException) {
+            Log.warn(e) { "Failed to query CameraManager#getCameraIdList!" }
+            null
+        }
+        if (cameraIdArray?.isEmpty() == true) {
+            Log.warn { "Failed to query CameraManager#getCameraIdList: No values returned." }
+        }
+
+        return cameraIdArray?.map { CameraId(it) } ?: listOf()
+    }
+
+    override fun readCameraMetadata(cameraId: CameraId): CameraMetadata =
+        camera2MetadataCache.readCameraMetadata(cameraId)
+
+    override fun disconnectAllAsync(): Deferred<Unit> {
+        // TODO: VirtualCameraManager needs to be extended to support a suspendable future that can
+        //   be used to wait until close has been called on all camera devices.
+        virtualCameraManager.closeAll()
+        return CompletableDeferred(Unit)
+    }
+
+    override fun shutdownAsync(): Deferred<Unit> {
+        // TODO: VirtualCameraManager needs to be extended to support a suspendable future that can
+        //   be used to wait until close has been called on all camera devices.
+        virtualCameraManager.closeAll()
+        return CompletableDeferred(Unit)
+    }
+
+    override fun createCameraController(
+        cameraContext: CameraContext,
+        graphConfig: CameraGraph.Config,
+        graphListener: GraphListener,
+        streamGraph: StreamGraph
+    ): CameraController {
+        // Use Dagger to create the camera2 controller component, then create the CameraController.
+        val cameraControllerComponent = camera2CameraControllerComponent.camera2ControllerConfig(
+            Camera2ControllerConfig(
+                this,
+                graphConfig,
+                graphListener,
+                streamGraph as StreamGraphImpl
+            )
+        ).build()
+
+        // Create and return a Camera2 CameraController object.
+        return cameraControllerComponent.cameraController()
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Camera2Controller.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt
similarity index 71%
rename from camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Camera2Controller.kt
rename to camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt
index b726377..5c58947 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Camera2Controller.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt
@@ -16,18 +16,19 @@
 
 package androidx.camera.camera2.pipe.compat
 
+import android.view.Surface
 import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraController
 import androidx.camera.camera2.pipe.CameraGraph
-import androidx.camera.camera2.pipe.config.CameraGraphScope
-import androidx.camera.camera2.pipe.config.ForCameraGraph
+import androidx.camera.camera2.pipe.StreamId
+import androidx.camera.camera2.pipe.config.Camera2ControllerScope
 import androidx.camera.camera2.pipe.graph.GraphListener
-import androidx.camera.camera2.pipe.graph.StreamGraphImpl
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 
 /**
- * This represents the core state loop for a Camera Graph instance.
+ * This represents the core state loop for a CameraGraph instance.
  *
  * A camera graph will receive start / stop signals from the application. When started, it will do
  * everything possible to bring up and maintain an active camera instance with the given
@@ -36,18 +37,18 @@
  * TODO: Reorganize these constructor parameters.
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-@CameraGraphScope
-internal class Camera2Camera2Controller @Inject constructor(
-    @ForCameraGraph private val scope: CoroutineScope,
+@Camera2ControllerScope
+internal class Camera2CameraController @Inject constructor(
+    private val scope: CoroutineScope,
     private val config: CameraGraph.Config,
     private val graphListener: GraphListener,
     private val captureSessionFactory: CaptureSessionFactory,
     private val requestProcessorFactory: Camera2RequestProcessorFactory,
-    private val virtualCameraManager: VirtualCameraManager,
-    private val streamGraph: StreamGraphImpl
-) : Camera2Controller {
+    private val virtualCameraManager: VirtualCameraManager
+) : CameraController {
     private var currentCamera: VirtualCamera? = null
     private var currentSession: VirtualSessionState? = null
+    private var surfaceMap: Map<StreamId, Surface>? = null
 
     override fun start() {
         val camera = virtualCameraManager.open(
@@ -59,14 +60,20 @@
             check(currentSession == null)
 
             currentCamera = camera
-            currentSession = VirtualSessionState(
+            val session = VirtualSessionState(
                 graphListener,
                 captureSessionFactory,
                 requestProcessorFactory,
                 scope
             )
+            currentSession = session
+
+            val surfaces: Map<StreamId, Surface>? = surfaceMap
+            if (surfaces != null) {
+                session.onSurfaceMapUpdated(surfaces)
+            }
         }
-        scope.launch { configure() }
+        scope.launch { bindSessionToCamera() }
     }
 
     override fun stop() {
@@ -86,30 +93,20 @@
         }
     }
 
-    override fun restart() {
-        val oldSession: VirtualSessionState?
-        val newSession: VirtualSessionState?
+    override fun close() {
+        // TODO: Consider changing the behavior so that start / stop are not invokable after calling
+        //   close.
+        stop()
+    }
 
+    override fun updateSurfaceMap(surfaceMap: Map<StreamId, Surface>) {
         synchronized(this) {
-            check(currentCamera != null) { "Cannot invoke reconfigure while stopped." }
-
-            oldSession = currentSession
-            newSession = VirtualSessionState(
-                graphListener,
-                captureSessionFactory,
-                requestProcessorFactory,
-                scope
-            )
-            currentSession = newSession
-        }
-
-        scope.launch {
-            oldSession?.disconnect()
-            configure()
+            this.surfaceMap = surfaceMap
+            currentSession?.onSurfaceMapUpdated(surfaceMap)
         }
     }
 
-    private suspend fun configure() {
+    private suspend fun bindSessionToCamera() {
         val camera: VirtualCamera?
         val session: VirtualSessionState?
 
@@ -119,7 +116,6 @@
         }
 
         if (camera != null && session != null) {
-            streamGraph.listener = session
             camera.state.collect {
                 if (it is CameraStateOpen) {
                     session.cameraDevice = it.cameraDevice
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Controller.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Controller.kt
deleted file mode 100644
index 32a9395..0000000
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Controller.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.camera2.pipe.compat
-
-import androidx.annotation.RequiresApi
-import androidx.camera.camera2.pipe.RequestProcessor
-
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-internal interface Camera2Controller {
-    /**
-     * Tell the graph to start and initialize a [RequestProcessor] instances.
-     */
-    fun start()
-
-    /**
-     * Tell the [Camera2Controller] to stop initialization and to tear down any existing
-     * [RequestProcessor] instance.
-     */
-    fun stop()
-
-    /**
-     * Signals the [Camera2Controller] that a [RequestProcessor] may need to be recreated.
-     */
-    fun restart()
-}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataCache.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataCache.kt
index c781ed2..40b16d8 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataCache.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2MetadataCache.kt
@@ -81,6 +81,10 @@
         }
     }
 
+    fun readCameraMetadata(cameraId: CameraId): CameraMetadata {
+        return createCameraMetadata(cameraId, isMetadataRedacted())
+    }
+
     private fun createCameraMetadata(cameraId: CameraId, redacted: Boolean): Camera2CameraMetadata {
         val start = Timestamps.now()
 
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt
index 1e232b8..275b27a 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt
@@ -26,7 +26,7 @@
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.StreamId
 import androidx.camera.camera2.pipe.compat.OutputConfigurationWrapper.Companion.SURFACE_GROUP_ID_NONE
-import androidx.camera.camera2.pipe.config.CameraGraphScope
+import androidx.camera.camera2.pipe.config.Camera2ControllerScope
 import androidx.camera.camera2.pipe.core.Log
 import androidx.camera.camera2.pipe.core.Threads
 import androidx.camera.camera2.pipe.graph.StreamGraphImpl
@@ -51,9 +51,9 @@
 }
 
 @Module
-internal object SessionFactoryModule {
+internal object Camera2CaptureSessionsModule {
     @SuppressLint("ObsoleteSdkInt")
-    @CameraGraphScope
+    @Camera2ControllerScope
     @Provides
     fun provideSessionFactory(
         androidLProvider: Provider<AndroidLSessionFactory>,
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
new file mode 100644
index 0000000..6af025d
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.config
+
+import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.StreamGraph
+import androidx.camera.camera2.pipe.CameraBackend
+import androidx.camera.camera2.pipe.CameraController
+import androidx.camera.camera2.pipe.compat.Camera2Backend
+import androidx.camera.camera2.pipe.compat.Camera2CameraController
+import androidx.camera.camera2.pipe.compat.Camera2CaptureSessionsModule
+import androidx.camera.camera2.pipe.compat.Camera2RequestProcessorFactory
+import androidx.camera.camera2.pipe.compat.StandardCamera2RequestProcessorFactory
+import androidx.camera.camera2.pipe.core.Threads
+import androidx.camera.camera2.pipe.graph.GraphListener
+import androidx.camera.camera2.pipe.graph.StreamGraphImpl
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import dagger.Subcomponent
+import javax.inject.Scope
+import kotlinx.coroutines.CoroutineName
+import kotlinx.coroutines.CoroutineScope
+
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@Module(
+    subcomponents = [
+        Camera2ControllerComponent::class
+    ]
+)
+internal abstract class Camera2Module {
+    @Binds
+    @CameraPipeCameraBackend
+    abstract fun bindCameraPipeCameraBackend(camera2Backend: Camera2Backend): CameraBackend
+}
+
+@Scope
+internal annotation class Camera2ControllerScope
+
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@Camera2ControllerScope
+@Subcomponent(
+    modules = [
+        Camera2ControllerConfig::class,
+        Camera2ControllerModule::class,
+        Camera2CaptureSessionsModule::class
+    ]
+)
+internal interface Camera2ControllerComponent {
+    fun cameraController(): CameraController
+
+    @Subcomponent.Builder
+    interface Builder {
+        fun camera2ControllerConfig(config: Camera2ControllerConfig): Builder
+        fun build(): Camera2ControllerComponent
+    }
+}
+
+@Module
+internal class Camera2ControllerConfig(
+    private val cameraBackend: CameraBackend,
+    private val graphConfig: CameraGraph.Config,
+    private val graphListener: GraphListener,
+    private val streamGraph: StreamGraph,
+) {
+    @Provides
+    fun provideCameraGraphConfig() = graphConfig
+
+    @Provides
+    fun provideCameraBackend() = cameraBackend
+
+    @Provides
+    fun provideStreamGraph() = streamGraph as StreamGraphImpl
+
+    @Provides
+    fun provideGraphListener() = graphListener
+}
+
+@Module
+internal abstract class Camera2ControllerModule {
+    @Binds
+    abstract fun bindCamera2RequestProcessorFactory(
+        factoryStandard: StandardCamera2RequestProcessorFactory
+    ): Camera2RequestProcessorFactory
+
+    @Binds
+    abstract fun bindCameraController(
+        camera2CameraController: Camera2CameraController
+    ): CameraController
+
+    companion object {
+        @Camera2ControllerScope
+        @Provides
+        fun provideCoroutineScope(threads: Threads): CoroutineScope {
+            return CoroutineScope(
+                threads.lightweightDispatcher.plus(CoroutineName("CXCP-Camera2Controller"))
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraGraphComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraGraphComponent.kt
index 413553e..b83853a 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraGraphComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraGraphComponent.kt
@@ -19,21 +19,20 @@
 package androidx.camera.camera2.pipe.config
 
 import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraBackend
+import androidx.camera.camera2.pipe.CameraBackends
+import androidx.camera.camera2.pipe.CameraContext
+import androidx.camera.camera2.pipe.CameraController
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraMetadata
 import androidx.camera.camera2.pipe.Request
-import androidx.camera.camera2.pipe.compat.Camera2Camera2Controller
-import androidx.camera.camera2.pipe.compat.Camera2MetadataCache
-import androidx.camera.camera2.pipe.compat.Camera2RequestProcessorFactory
-import androidx.camera.camera2.pipe.compat.Camera2Controller
-import androidx.camera.camera2.pipe.compat.SessionFactoryModule
-import androidx.camera.camera2.pipe.compat.StandardCamera2RequestProcessorFactory
 import androidx.camera.camera2.pipe.core.Threads
 import androidx.camera.camera2.pipe.graph.CameraGraphImpl
 import androidx.camera.camera2.pipe.graph.GraphListener
 import androidx.camera.camera2.pipe.graph.GraphProcessor
 import androidx.camera.camera2.pipe.graph.GraphProcessorImpl
 import androidx.camera.camera2.pipe.graph.Listener3A
+import androidx.camera.camera2.pipe.graph.StreamGraphImpl
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
@@ -52,9 +51,9 @@
 @CameraGraphScope
 @Subcomponent(
     modules = [
-        CameraGraphModules::class,
+        SharedCameraGraphModules::class,
+        InternalCameraGraphModules::class,
         CameraGraphConfigModule::class,
-        Camera2CameraGraphModules::class,
     ]
 )
 internal interface CameraGraphComponent {
@@ -76,7 +75,7 @@
 }
 
 @Module
-internal abstract class CameraGraphModules {
+internal abstract class SharedCameraGraphModules {
     @Binds
     abstract fun bindCameraGraph(cameraGraph: CameraGraphImpl): CameraGraph
 
@@ -91,7 +90,9 @@
         @Provides
         @ForCameraGraph
         fun provideCameraGraphCoroutineScope(threads: Threads): CoroutineScope {
-            return CoroutineScope(threads.lightweightDispatcher.plus(CoroutineName("CXCP-Graph")))
+            return CoroutineScope(
+                threads.lightweightDispatcher.plus(CoroutineName("CXCP-Graph"))
+            )
         }
 
         @CameraGraphScope
@@ -115,27 +116,54 @@
     }
 }
 
-@Module(
-    includes = [
-        SessionFactoryModule::class
-    ]
-)
-internal abstract class Camera2CameraGraphModules {
-    @Binds
-    abstract fun bindRequestProcessorFactory(
-        factoryStandard: StandardCamera2RequestProcessorFactory
-    ): Camera2RequestProcessorFactory
-
-    @Binds
-    abstract fun bindGraphState(camera2CameraState: Camera2Camera2Controller): Camera2Controller
-
+@Module
+internal abstract class InternalCameraGraphModules {
     companion object {
+        @CameraGraphScope
         @Provides
-        fun provideCamera2Metadata(
+        fun provideCameraBackend(
+            cameraBackends: CameraBackends,
             graphConfig: CameraGraph.Config,
-            metadataCache: Camera2MetadataCache
+            cameraContext: CameraContext
+        ): CameraBackend {
+            val customCameraBackend = graphConfig.customCameraBackend
+            if (customCameraBackend != null) {
+                return customCameraBackend.create(cameraContext)
+            }
+
+            val cameraBackendId = graphConfig.cameraBackendId
+            if (cameraBackendId != null) {
+                cameraBackends[cameraBackendId]
+            }
+            return cameraBackends.default
+        }
+
+        @CameraGraphScope
+        @Provides
+        fun provideCameraMetadata(
+            graphConfig: CameraGraph.Config,
+            cameraBackend: CameraBackend
         ): CameraMetadata {
-            return metadataCache.awaitMetadata(graphConfig.camera)
+            // TODO: It might be a good idea to cache and go through caches for some of these calls
+            //   instead of reading it directly from the backend.
+            return cameraBackend.readCameraMetadata(graphConfig.camera)
+        }
+
+        @CameraGraphScope
+        @Provides
+        fun provideCameraController(
+            graphConfig: CameraGraph.Config,
+            cameraBackend: CameraBackend,
+            cameraContext: CameraContext,
+            graphProcessor: GraphProcessorImpl,
+            streamGraph: StreamGraphImpl,
+        ): CameraController {
+            return cameraBackend.createCameraController(
+                cameraContext,
+                graphConfig,
+                graphProcessor,
+                streamGraph
+            )
         }
     }
 }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
index de31e8c..081771c 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
@@ -21,22 +21,36 @@
 import android.content.Context
 import android.hardware.camera2.CameraManager
 import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraBackend
+import androidx.camera.camera2.pipe.CameraBackendFactory
+import androidx.camera.camera2.pipe.CameraBackendId
+import androidx.camera.camera2.pipe.CameraBackends
+import androidx.camera.camera2.pipe.internal.CameraBackendsImpl
+import androidx.camera.camera2.pipe.CameraContext
 import androidx.camera.camera2.pipe.CameraDevices
 import androidx.camera.camera2.pipe.CameraPipe
 import androidx.camera.camera2.pipe.CameraPipe.CameraMetadataConfig
 import androidx.camera.camera2.pipe.compat.Camera2CameraDevices
+import androidx.camera.camera2.pipe.core.Debug
+import androidx.camera.camera2.pipe.core.Threads
 import dagger.Binds
 import dagger.Component
 import dagger.Module
 import dagger.Provides
 import dagger.Reusable
+import javax.inject.Provider
+import javax.inject.Qualifier
 import javax.inject.Singleton
 
+@Qualifier
+internal annotation class CameraPipeCameraBackend
+
 @Singleton
 @Component(
     modules = [
         CameraPipeConfigModule::class,
-        Camera2CameraPipeModules::class,
+        CameraPipeModules::class,
+        Camera2Module::class,
     ]
 )
 internal interface CameraPipeComponent {
@@ -54,7 +68,7 @@
 }
 
 @Module
-internal abstract class Camera2CameraPipeModules {
+internal abstract class CameraPipeModules {
     @Binds
     abstract fun bindCameras(impl: Camera2CameraDevices): CameraDevices
 
@@ -70,5 +84,50 @@
         @Provides
         fun provideCameraManager(context: Context): CameraManager =
             context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
+
+        @Singleton
+        @Provides
+        fun provideCameraContext(
+            context: Context,
+            threads: Threads,
+            cameraBackends: CameraBackends
+        ): CameraContext =
+            object : CameraContext {
+                override val appContext: Context = context
+                override val threads: Threads = threads
+                override val cameraBackends: CameraBackends = cameraBackends
+            }
+
+        @Singleton
+        @Provides
+        fun provideCameraBackends(
+            config: CameraPipe.Config,
+            @CameraPipeCameraBackend cameraPipeCameraBackend: Provider<CameraBackend>,
+            appContext: Context,
+            threads: Threads,
+        ): CameraBackends {
+            // This is intentionally lazy. If an internalBackend is defined as part of the
+            // CameraPipe configuration, we will never create the default cameraPipeCameraBackend.
+            val internalBackend = config.cameraBackendConfig.internalBackend
+                ?: Debug.trace("Initialize cameraPipeCameraBackend") {
+                    cameraPipeCameraBackend.get()
+                }
+
+            // Make sure that the list of additional backends does not contain the
+            check(!config.cameraBackendConfig.cameraBackends.containsKey(internalBackend.id)) {
+                "CameraBackendConfig#cameraBackends should not contain a backend with " +
+                    "${internalBackend.id}. Use CameraBackendConfig#internalBackend field instead."
+            }
+            val allBackends: Map<CameraBackendId, CameraBackendFactory> =
+                config.cameraBackendConfig.cameraBackends +
+                    (internalBackend.id to CameraBackendFactory { internalBackend })
+
+            val defaultBackendId = config.cameraBackendConfig.defaultBackend ?: internalBackend.id
+            check(allBackends.containsKey(defaultBackendId)) {
+                "Failed to find $defaultBackendId in the list of available CameraPipe backends! " +
+                    "Available values are ${allBackends.keys}"
+            }
+            return CameraBackendsImpl(defaultBackendId, allBackends, appContext, threads)
+        }
     }
 }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
index 544c072..bb13f5f 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
@@ -18,11 +18,13 @@
 
 package androidx.camera.camera2.pipe.config
 
+import android.view.Surface
 import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraController
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraMetadata
 import androidx.camera.camera2.pipe.RequestProcessor
-import androidx.camera.camera2.pipe.compat.Camera2Controller
+import androidx.camera.camera2.pipe.StreamId
 import androidx.camera.camera2.pipe.graph.GraphListener
 import dagger.Module
 import dagger.Provides
@@ -32,7 +34,7 @@
 @CameraGraphScope
 @Subcomponent(
     modules = [
-        CameraGraphModules::class,
+        SharedCameraGraphModules::class,
         ExternalCameraGraphConfigModule::class
     ]
 )
@@ -59,8 +61,8 @@
     fun provideCameraMetadata(): CameraMetadata = cameraMetadata
 
     @Provides
-    fun provideGraphController(graphListener: GraphListener): Camera2Controller =
-        object : Camera2Controller {
+    fun provideGraphController(graphListener: GraphListener): CameraController =
+        object : CameraController {
             var started = atomic(false)
             override fun start() {
                 if (started.compareAndSet(expect = false, update = true)) {
@@ -74,9 +76,10 @@
                 }
             }
 
-            override fun restart() {
-                stop()
-                start()
+            override fun close() {
+            }
+
+            override fun updateSurfaceMap(surfaceMap: Map<StreamId, Surface>) {
             }
         }
 }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt
index 3f8796a..74ca0c5 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt
@@ -14,17 +14,15 @@
  * limitations under the License.
  */
 
-@file:RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-
 package androidx.camera.camera2.pipe.graph
 
 import android.view.Surface
 import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraController
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraMetadata
 import androidx.camera.camera2.pipe.StreamGraph
 import androidx.camera.camera2.pipe.StreamId
-import androidx.camera.camera2.pipe.compat.Camera2Controller
 import androidx.camera.camera2.pipe.config.CameraGraphScope
 import androidx.camera.camera2.pipe.core.Debug
 import androidx.camera.camera2.pipe.core.Log
@@ -36,13 +34,15 @@
 
 internal val cameraGraphIds = atomic(0)
 
+@RequiresApi(21)
 @CameraGraphScope
 internal class CameraGraphImpl @Inject constructor(
     graphConfig: CameraGraph.Config,
     metadata: CameraMetadata,
     private val graphProcessor: GraphProcessor,
     private val streamGraph: StreamGraphImpl,
-    private val camera2Controller: Camera2Controller,
+    private val surfaceGraph: SurfaceGraph,
+    private val cameraController: CameraController,
     private val graphState3A: GraphState3A,
     private val listener3A: Listener3A
 ) : CameraGraph {
@@ -66,14 +66,14 @@
     override fun start() {
         Debug.traceStart { "$this#start" }
         Log.info { "Starting $this" }
-        camera2Controller.start()
+        cameraController.start()
         Debug.traceStop()
     }
 
     override fun stop() {
         Debug.traceStart { "$this#stop" }
         Log.info { "Stopping $this" }
-        camera2Controller.stop()
+        cameraController.stop()
         Debug.traceStop()
     }
 
@@ -98,7 +98,7 @@
         check(surface == null || surface.isValid) {
             "Failed to set $surface to $stream: The surface was not valid."
         }
-        streamGraph[stream] = surface
+        surfaceGraph[stream] = surface
         Debug.traceStop()
     }
 
@@ -107,7 +107,7 @@
         Log.info { "Closing $this" }
         sessionLock.close()
         graphProcessor.close()
-        camera2Controller.stop()
+        cameraController.close()
         Debug.traceStop()
     }
 
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/StreamGraphImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/StreamGraphImpl.kt
index d684d72..12050cf 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/StreamGraphImpl.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/StreamGraphImpl.kt
@@ -39,7 +39,6 @@
 import androidx.camera.camera2.pipe.StreamId
 import androidx.camera.camera2.pipe.compat.Api24Compat
 import androidx.camera.camera2.pipe.config.CameraGraphScope
-import androidx.camera.camera2.pipe.core.Log
 import javax.inject.Inject
 import kotlinx.atomicfu.atomic
 
@@ -65,7 +64,6 @@
     cameraMetadata: CameraMetadata,
     graphConfig: CameraGraph.Config
 ) : StreamGraph {
-    private val surfaceMap: MutableMap<StreamId, Surface> = mutableMapOf()
     private val _streamMap: Map<CameraStream.Config, CameraStream>
 
     internal val outputConfigs: List<OutputConfig>
@@ -168,63 +166,6 @@
         outputConfigs = outputConfigListBuilder
     }
 
-    private var _listener: SurfaceListener? = null
-    var listener: SurfaceListener?
-        get() = _listener
-        set(value) {
-            _listener = value
-            if (value != null) {
-                maybeUpdateSurfaces()
-            }
-        }
-
-    operator fun set(stream: StreamId, surface: Surface?) {
-        Log.info {
-            if (surface != null) {
-                "Configured $stream to use $surface"
-            } else {
-                "Removed surface for $stream"
-            }
-        }
-        if (surface == null) {
-            // TODO: Tell the graph processor that it should resubmit the repeating request or
-            //  reconfigure the camera2 captureSession
-            surfaceMap.remove(stream)
-        } else {
-            surfaceMap[stream] = surface
-        }
-        maybeUpdateSurfaces()
-    }
-
-    private fun maybeUpdateSurfaces() {
-        val surfaceListener = _listener ?: return
-        val surfaces = buildSurfaceMap()
-        if (surfaces.isEmpty()) {
-            return
-        }
-        surfaceListener.onSurfaceMapUpdated(surfaces)
-    }
-
-    private fun buildSurfaceMap(): Map<StreamId, Surface> {
-        // Rules:
-        // 1. There must be at least one non-null, valid surface.
-        // 2. All non-deferrable streams must have a valid surface.
-        val surfaces = mutableMapOf<StreamId, Surface>()
-        for (outputConfig in outputConfigs) {
-            for (stream in outputConfig.streamBuilder) {
-                val surface = surfaceMap[stream.id]
-                if (surface == null) {
-                    if (!outputConfig.deferrable) {
-                        return emptyMap()
-                    }
-                } else {
-                    surfaces[stream.id] = surface
-                }
-            }
-        }
-        return surfaces
-    }
-
     @Suppress("SyntheticAccessor") // StreamId generates a synthetic constructor
     class OutputConfig(
         val id: OutputConfigId,
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/SurfaceGraph.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/SurfaceGraph.kt
new file mode 100644
index 0000000..c107afa
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/SurfaceGraph.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.graph
+
+import android.view.Surface
+import androidx.annotation.GuardedBy
+import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraController
+import androidx.camera.camera2.pipe.StreamId
+import androidx.camera.camera2.pipe.config.CameraGraphScope
+import androidx.camera.camera2.pipe.core.Log
+import androidx.camera.camera2.pipe.CameraGraph
+import javax.inject.Inject
+
+/**
+ * A SurfaceGraph tracks the current stream-to-surface mapping state for a [CameraGraph] instance.
+ *
+ * It's primary responsibility is aggregating the current stream-to-surface mapping and passing the
+ * most up to date version to the [CameraController] instance.
+ */
+@RequiresApi(21)
+@CameraGraphScope
+internal class SurfaceGraph @Inject constructor(
+    private val streamGraph: StreamGraphImpl,
+    private val cameraController: CameraController
+) {
+    private val lock = Any()
+
+    @GuardedBy("lock")
+    private val surfaceMap: MutableMap<StreamId, Surface> = mutableMapOf()
+
+    operator fun set(stream: StreamId, surface: Surface?) {
+        Log.info {
+            if (surface != null) {
+                "Configured $stream to use $surface"
+            } else {
+                "Removed surface for $stream"
+            }
+        }
+
+        synchronized(lock) {
+            if (surface == null) {
+                // TODO: Tell the graph processor that it should resubmit the repeating request or
+                //  reconfigure the camera2 captureSession
+                surfaceMap.remove(stream)
+            } else {
+                surfaceMap[stream] = surface
+            }
+        }
+
+        maybeUpdateSurfaces()
+    }
+
+    private fun maybeUpdateSurfaces() {
+        // Rules:
+        // 1. There must be at least one non-null surface.
+        // 2. All non-deferrable streams must have a non-null surface.
+
+        val surfaces = buildSurfaceMap()
+        if (surfaces.isEmpty()) {
+            return
+        }
+        cameraController.updateSurfaceMap(surfaces)
+    }
+
+    private fun buildSurfaceMap(): Map<StreamId, Surface> = synchronized(lock) {
+        val surfaces = mutableMapOf<StreamId, Surface>()
+        for (outputConfig in streamGraph.outputConfigs) {
+            for (stream in outputConfig.streamBuilder) {
+                val surface = surfaceMap[stream.id]
+                if (surface == null) {
+                    if (!outputConfig.deferrable) {
+                        // If output is non-deferrable, a surface must be available or the config
+                        // is not yet valid. Exit now with an empty map.
+                        return emptyMap()
+                    }
+                } else {
+                    surfaces[stream.id] = surface
+                }
+            }
+        }
+        return surfaces
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraBackendsImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraBackendsImpl.kt
new file mode 100644
index 0000000..e7ed8fc
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraBackendsImpl.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.internal
+
+import android.content.Context
+import androidx.annotation.GuardedBy
+import androidx.camera.camera2.pipe.CameraBackend
+import androidx.camera.camera2.pipe.CameraBackendFactory
+import androidx.camera.camera2.pipe.CameraBackendId
+import androidx.camera.camera2.pipe.CameraBackends
+import androidx.camera.camera2.pipe.CameraContext
+import androidx.camera.camera2.pipe.core.Threads
+
+/**
+ * Provides an implementation for interacting with CameraBackends.
+ */
+internal class CameraBackendsImpl(
+    private val defaultBackendId: CameraBackendId,
+    private val cameraBackends: Map<CameraBackendId, CameraBackendFactory>,
+    private val appContext: Context,
+    private val threads: Threads
+) : CameraBackends {
+    private val lock = Any()
+
+    @GuardedBy("lock")
+    private val activeCameraBackends = mutableMapOf<CameraBackendId, CameraBackend>()
+
+    override val default: CameraBackend = checkNotNull(get(defaultBackendId)) {
+        "Failed to load the default backend for $defaultBackendId! Available backends are " +
+            "${cameraBackends.keys}"
+    }
+
+    override val allIds: Set<CameraBackendId>
+        get() = cameraBackends.keys
+    override val activeIds: Set<CameraBackendId>
+        get() = synchronized(lock) { activeCameraBackends.keys }
+
+    override fun get(backendId: CameraBackendId): CameraBackend? {
+        synchronized(lock) {
+            val existing = activeCameraBackends[backendId]
+            if (existing != null) return existing
+
+            val backend = cameraBackends[backendId]?.create(
+                CameraBackendContext(appContext, threads, this)
+            )
+            if (backend != null) {
+                check(backendId == backend.id) {
+                    "Unexpected backend id! Expected $backendId but it was actually ${backend.id}"
+                }
+                activeCameraBackends[backendId] = backend
+            }
+            return backend
+        }
+    }
+
+    internal class CameraBackendContext(
+        override val appContext: Context,
+        override val threads: Threads,
+        override val cameraBackends: CameraBackends
+    ) : CameraContext
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
index c6c2ef3..3ed5505 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * Copyright 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,9 +28,9 @@
 import androidx.camera.camera2.pipe.RequestProcessor
 import androidx.camera.camera2.pipe.StreamFormat
 import androidx.camera.camera2.pipe.StreamId
-import androidx.camera.camera2.pipe.config.Camera2CameraGraphModules
-import androidx.camera.camera2.pipe.config.Camera2CameraPipeModules
-import androidx.camera.camera2.pipe.config.CameraGraphModules
+import androidx.camera.camera2.pipe.config.Camera2ControllerScope
+import androidx.camera.camera2.pipe.config.CameraPipeModules
+import androidx.camera.camera2.pipe.config.SharedCameraGraphModules
 import androidx.camera.camera2.pipe.config.CameraGraphScope
 import androidx.camera.camera2.pipe.config.ThreadConfigModule
 import androidx.camera.camera2.pipe.graph.StreamGraphImpl
@@ -69,10 +69,11 @@
 
     @Test
     fun canCreateSessionFactoryTestComponent() = runTest {
-        val component: CameraSessionTestComponent = DaggerCameraSessionTestComponent.builder()
-            .fakeCameraPipeModule(FakeCameraPipeModule(context, testCamera))
-            .threadConfigModule(ThreadConfigModule(CameraPipe.ThreadConfig()))
-            .build()
+        val component: Camera2CaptureSessionTestComponent =
+            DaggerCamera2CaptureSessionTestComponent.builder()
+                .fakeCameraPipeModule(FakeCameraPipeModule(context, testCamera))
+                .threadConfigModule(ThreadConfigModule(CameraPipe.ThreadConfig()))
+                .build()
 
         val sessionFactory = component.sessionFactory()
         assertThat(sessionFactory).isNotNull()
@@ -80,10 +81,11 @@
 
     @Test
     fun createCameraCaptureSession() = runTest {
-        val component: CameraSessionTestComponent = DaggerCameraSessionTestComponent.builder()
-            .fakeCameraPipeModule(FakeCameraPipeModule(context, testCamera))
-            .threadConfigModule(ThreadConfigModule(CameraPipe.ThreadConfig()))
-            .build()
+        val component: Camera2CaptureSessionTestComponent =
+            DaggerCamera2CaptureSessionTestComponent.builder()
+                .fakeCameraPipeModule(FakeCameraPipeModule(context, testCamera))
+                .threadConfigModule(ThreadConfigModule(CameraPipe.ThreadConfig()))
+                .build()
 
         val sessionFactory = component.sessionFactory()
         val streamMap = component.streamMap()
@@ -125,13 +127,15 @@
 
 @Singleton
 @CameraGraphScope
+@Camera2ControllerScope
 @Component(
     modules = [
         FakeCameraGraphModule::class,
-        FakeCameraPipeModule::class
+        FakeCameraPipeModule::class,
+        Camera2CaptureSessionsModule::class
     ]
 )
-internal interface CameraSessionTestComponent {
+internal interface Camera2CaptureSessionTestComponent {
     fun graphConfig(): CameraGraph.Config
     fun sessionFactory(): CaptureSessionFactory
     fun streamMap(): StreamGraphImpl
@@ -140,7 +144,7 @@
 /**
  * Utility module for testing the Dagger generated graph with a a reasonable default config.
  */
-@Module(includes = [ThreadConfigModule::class, Camera2CameraPipeModules::class])
+@Module(includes = [ThreadConfigModule::class, CameraPipeModules::class])
 class FakeCameraPipeModule(
     private val context: Context,
     private val fakeCamera: RobolectricCameras.FakeCamera
@@ -153,10 +157,14 @@
     fun provideFakeCameraPipeConfig() = CameraPipe.Config(context)
 }
 
-@Module(includes = [CameraGraphModules::class, Camera2CameraGraphModules::class])
+@Module(includes = [SharedCameraGraphModules::class])
 class FakeCameraGraphModule {
     @Provides
     @CameraGraphScope
+    fun provideFakeCameraMetadata(fakeCamera: RobolectricCameras.FakeCamera) = fakeCamera.metadata
+
+    @Provides
+    @CameraGraphScope
     fun provideFakeGraphConfig(fakeCamera: RobolectricCameras.FakeCamera): CameraGraph.Config {
         val stream = CameraStream.Config.create(
             Size(640, 480),
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt
index a7094ff..33f40d7 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt
@@ -21,7 +21,7 @@
 import android.os.Build
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.Request
-import androidx.camera.camera2.pipe.testing.FakeCamera2Controller
+import androidx.camera.camera2.pipe.testing.FakeCameraController
 import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
 import androidx.camera.camera2.pipe.testing.FakeGraphProcessor
 import androidx.camera.camera2.pipe.testing.RobolectricCameraPipeTestRunner
@@ -44,7 +44,7 @@
         cameraId = fakeCameraId
     )
     private val fakeGraphProcessor = FakeGraphProcessor()
-    private val fakeCameraController = FakeCamera2Controller()
+    private val fakeCameraController = FakeCameraController()
     private lateinit var impl: CameraGraphImpl
 
     @Before
@@ -53,14 +53,18 @@
             camera = fakeCameraId,
             streams = listOf(),
         )
+        val streamGraph = StreamGraphImpl(
+            fakeMetadata,
+            config
+        )
+        val surfaceGraph = SurfaceGraph(streamGraph, fakeCameraController)
+
         impl = CameraGraphImpl(
             config,
             fakeMetadata,
             fakeGraphProcessor,
-            StreamGraphImpl(
-                fakeMetadata,
-                config
-            ),
+            streamGraph,
+            surfaceGraph,
             fakeCameraController,
             GraphState3A(),
             Listener3A()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/StreamGraphImplTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/StreamGraphImplTest.kt
index 17b0ac5..4037146 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/StreamGraphImplTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/StreamGraphImplTest.kt
@@ -16,19 +16,14 @@
 
 package androidx.camera.camera2.pipe.graph
 
-import android.graphics.SurfaceTexture
-import android.hardware.camera2.CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL
-import android.hardware.camera2.CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL
 import android.os.Build
 import android.util.Size
-import android.view.Surface
 import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.CameraStream
 import androidx.camera.camera2.pipe.OutputStream
 import androidx.camera.camera2.pipe.StreamFormat
-import androidx.camera.camera2.pipe.StreamId
-import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
+import androidx.camera.camera2.pipe.testing.FakeCameraGraphConfig
 import androidx.camera.camera2.pipe.testing.RobolectricCameraPipeTestRunner
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
@@ -40,65 +35,25 @@
 @DoNotInstrument
 @Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
 internal class StreamGraphImplTest {
-    private val fakeMetadata = FakeCameraMetadata(
-        mapOf(INFO_SUPPORTED_HARDWARE_LEVEL to INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
-    )
-
-    private val camera1 = CameraId("TestCamera-1")
-    private val camera2 = CameraId("TestCamera-2")
-
-    private val streamConfig1 = CameraStream.Config.create(
-        size = Size(100, 100),
-        format = StreamFormat.YUV_420_888
-    )
-    private val streamConfig2 = CameraStream.Config.create(
-        size = Size(123, 321),
-        format = StreamFormat.YUV_420_888,
-        camera = camera1
-    )
-    private val streamConfig3 = CameraStream.Config.create(
-        size = Size(200, 200),
-        format = StreamFormat.YUV_420_888,
-        camera = camera2,
-        outputType = OutputStream.OutputType.SURFACE_TEXTURE
-    )
-    private val sharedOutputConfig = OutputStream.Config.create(
-        size = Size(200, 200),
-        format = StreamFormat.YUV_420_888,
-        camera = camera1
-    )
-    private val sharedStreamConfig1 = CameraStream.Config.create(sharedOutputConfig)
-    private val sharedStreamConfig2 = CameraStream.Config.create(sharedOutputConfig)
-
-    private val graphConfig = CameraGraph.Config(
-        camera = camera1,
-        streams = listOf(
-            streamConfig1,
-            streamConfig2,
-            streamConfig3,
-            sharedStreamConfig1,
-            sharedStreamConfig2
-        ),
-        streamSharingGroups = listOf(listOf(streamConfig1, streamConfig2))
-    )
+    private val config = FakeCameraGraphConfig()
 
     @Test
     fun testPrecomputedTestData() {
-        val streamGraph = StreamGraphImpl(fakeMetadata, graphConfig)
+        val streamGraph = StreamGraphImpl(config.fakeMetadata, config.graphConfig)
 
         assertThat(streamGraph.streams).hasSize(5)
         assertThat(streamGraph.streams).hasSize(5)
         assertThat(streamGraph.outputConfigs).hasSize(4)
 
-        val stream1 = streamGraph[streamConfig1]!!
+        val stream1 = streamGraph[config.streamConfig1]!!
         val outputStream1 = stream1.outputs.single()
         assertThat(outputStream1.format).isEqualTo(StreamFormat.YUV_420_888)
         assertThat(outputStream1.size.width).isEqualTo(100)
         assertThat(outputStream1.size.height).isEqualTo(100)
 
-        val stream2 = streamGraph[streamConfig2]!!
+        val stream2 = streamGraph[config.streamConfig2]!!
         val outputStream2 = stream2.outputs.single()
-        assertThat(outputStream2.camera).isEqualTo(graphConfig.camera)
+        assertThat(outputStream2.camera).isEqualTo(config.graphConfig.camera)
         assertThat(outputStream2.format).isEqualTo(StreamFormat.YUV_420_888)
         assertThat(outputStream2.size.width).isEqualTo(123)
         assertThat(outputStream2.size.height).isEqualTo(321)
@@ -106,10 +61,10 @@
 
     @Test
     fun testStreamGraphPopulatesCameraId() {
-        val streamGraph = StreamGraphImpl(fakeMetadata, graphConfig)
-        val stream = streamGraph[streamConfig1]!!
-        assertThat(streamConfig1.outputs.single().camera).isNull()
-        assertThat(stream.outputs.single().camera).isEqualTo(graphConfig.camera)
+        val streamGraph = StreamGraphImpl(config.fakeMetadata, config.graphConfig)
+        val stream = streamGraph[config.streamConfig1]!!
+        assertThat(config.streamConfig1.outputs.single().camera).isNull()
+        assertThat(stream.outputs.single().camera).isEqualTo(config.graphConfig.camera)
     }
 
     @Test
@@ -131,11 +86,11 @@
                 ),
             )
         )
-        val config = CameraGraph.Config(
+        val graphConfig = CameraGraph.Config(
             camera = CameraId("TestCamera"),
             streams = listOf(streamConfig),
         )
-        val streamGraph = StreamGraphImpl(fakeMetadata, config)
+        val streamGraph = StreamGraphImpl(config.fakeMetadata, graphConfig)
 
         assertThat(streamGraph.streams).hasSize(1)
         assertThat(streamGraph.streams).hasSize(1)
@@ -144,32 +99,32 @@
 
     @Test
     fun testStreamMapConvertsConfigObjectsToStreamIds() {
-        val streamGraph = StreamGraphImpl(fakeMetadata, graphConfig)
+        val streamGraph = StreamGraphImpl(config.fakeMetadata, config.graphConfig)
 
-        assertThat(streamGraph[streamConfig1]).isNotNull()
-        assertThat(streamGraph[streamConfig2]).isNotNull()
-        assertThat(streamGraph[streamConfig3]).isNotNull()
+        assertThat(streamGraph[config.streamConfig1]).isNotNull()
+        assertThat(streamGraph[config.streamConfig2]).isNotNull()
+        assertThat(streamGraph[config.streamConfig3]).isNotNull()
 
-        val stream1 = streamGraph[streamConfig1]!!
-        val stream2 = streamGraph[streamConfig2]!!
-        val stream3 = streamGraph[streamConfig3]!!
+        val stream1 = streamGraph[config.streamConfig1]!!
+        val stream2 = streamGraph[config.streamConfig2]!!
+        val stream3 = streamGraph[config.streamConfig3]!!
 
-        assertThat(stream1).isEqualTo(streamGraph[streamConfig1])
-        assertThat(stream2).isEqualTo(streamGraph[streamConfig2])
-        assertThat(stream3).isEqualTo(streamGraph[streamConfig3])
+        assertThat(stream1).isEqualTo(streamGraph[config.streamConfig1])
+        assertThat(stream2).isEqualTo(streamGraph[config.streamConfig2])
+        assertThat(stream3).isEqualTo(streamGraph[config.streamConfig3])
 
-        assertThat(streamConfig1).isNotEqualTo(streamConfig2)
-        assertThat(streamConfig1).isNotEqualTo(streamConfig3)
-        assertThat(streamConfig2).isNotEqualTo(streamConfig3)
+        assertThat(config.streamConfig1).isNotEqualTo(config.streamConfig2)
+        assertThat(config.streamConfig1).isNotEqualTo(config.streamConfig3)
+        assertThat(config.streamConfig2).isNotEqualTo(config.streamConfig3)
     }
 
     @Test
     fun testStreamMapIdsAreNotEqualAcrossMultipleStreamMapInstances() {
-        val streamGraphA = StreamGraphImpl(fakeMetadata, graphConfig)
-        val streamGraphB = StreamGraphImpl(fakeMetadata, graphConfig)
+        val streamGraphA = StreamGraphImpl(config.fakeMetadata, config.graphConfig)
+        val streamGraphB = StreamGraphImpl(config.fakeMetadata, config.graphConfig)
 
-        val stream1A = streamGraphA[streamConfig1]!!
-        val stream1B = streamGraphB[streamConfig1]!!
+        val stream1A = streamGraphA[config.streamConfig1]!!
+        val stream1B = streamGraphB[config.streamConfig1]!!
 
         assertThat(stream1A).isNotEqualTo(stream1B)
         assertThat(stream1A.id).isNotEqualTo(stream1B.id)
@@ -177,9 +132,9 @@
 
     @Test
     fun testSharedStreamsHaveOneOutputConfig() {
-        val streamGraph = StreamGraphImpl(fakeMetadata, graphConfig)
-        val stream1 = streamGraph[sharedStreamConfig1]!!
-        val stream2 = streamGraph[sharedStreamConfig2]!!
+        val streamGraph = StreamGraphImpl(config.fakeMetadata, config.graphConfig)
+        val stream1 = streamGraph[config.sharedStreamConfig1]!!
+        val stream2 = streamGraph[config.sharedStreamConfig2]!!
 
         val outputConfigForStream1 =
             streamGraph.outputConfigs.filter { it.streams.contains(stream1) }
@@ -193,18 +148,18 @@
 
     @Test
     fun testSharedStreamsHaveDifferentOutputStreams() {
-        val streamGraph = StreamGraphImpl(fakeMetadata, graphConfig)
-        val stream1 = streamGraph[sharedStreamConfig1]!!
-        val stream2 = streamGraph[sharedStreamConfig2]!!
+        val streamGraph = StreamGraphImpl(config.fakeMetadata, config.graphConfig)
+        val stream1 = streamGraph[config.sharedStreamConfig1]!!
+        val stream2 = streamGraph[config.sharedStreamConfig2]!!
 
         assertThat(stream1.outputs.first()).isNotEqualTo(stream2.outputs.first())
     }
 
     @Test
     fun testGroupedStreamsHaveSameGroupNumber() {
-        val streamGraph = StreamGraphImpl(fakeMetadata, graphConfig)
-        val stream1 = streamGraph[streamConfig1]!!
-        val stream2 = streamGraph[streamConfig2]!!
+        val streamGraph = StreamGraphImpl(config.fakeMetadata, config.graphConfig)
+        val stream1 = streamGraph[config.streamConfig1]!!
+        val stream2 = streamGraph[config.streamConfig2]!!
 
         val outputConfigForStream1 =
             streamGraph.outputConfigs.filter { it.streams.contains(stream1) }
@@ -221,170 +176,4 @@
         assertThat(config2.groupNumber).isGreaterThan(-1)
         assertThat(config1.groupNumber).isEqualTo(config2.groupNumber)
     }
-
-    @Test
-    fun outputSurfacesArePassedToListenerImmediately() {
-        val streamMap = StreamGraphImpl(fakeMetadata, graphConfig)
-        val stream1 = streamMap[streamConfig1]!!
-        val stream2 = streamMap[streamConfig2]!!
-        val stream3 = streamMap[streamConfig3]!!
-        val stream4 = streamMap[sharedStreamConfig1]!!
-        val stream5 = streamMap[sharedStreamConfig2]!!
-
-        val fakeSurface1 = Surface(SurfaceTexture(1))
-        val fakeSurface2 = Surface(SurfaceTexture(2))
-        val fakeSurface3 = Surface(SurfaceTexture(3))
-        val fakeSurface4 = Surface(SurfaceTexture(4))
-        val fakeSurface5 = Surface(SurfaceTexture(5))
-
-        streamMap[stream1.id] = fakeSurface1
-        streamMap[stream2.id] = fakeSurface2
-        streamMap[stream3.id] = fakeSurface3
-        streamMap[stream4.id] = fakeSurface4
-        streamMap[stream5.id] = fakeSurface5
-
-        val session = FakeSurfaceListener()
-
-        streamMap.listener = session
-
-        assertThat(session.surfaces).isNotNull()
-        assertThat(session.surfaces?.get(stream1.id)).isEqualTo(fakeSurface1)
-        assertThat(session.surfaces?.get(stream2.id)).isEqualTo(fakeSurface2)
-        assertThat(session.surfaces?.get(stream3.id)).isEqualTo(fakeSurface3)
-    }
-
-    @Test
-    fun outputSurfacesArePassedToListenerWhenAvailable() {
-        val streamMap = StreamGraphImpl(fakeMetadata, graphConfig)
-        val stream1 = streamMap[streamConfig1]!!
-        val stream2 = streamMap[streamConfig2]!!
-        val stream3 = streamMap[streamConfig3]!!
-        val stream4 = streamMap[sharedStreamConfig1]!!
-        val stream5 = streamMap[sharedStreamConfig2]!!
-
-        val fakeSurface1 = Surface(SurfaceTexture(1))
-        val fakeSurface2 = Surface(SurfaceTexture(2))
-        val fakeSurface3 = Surface(SurfaceTexture(3))
-        val fakeSurface4 = Surface(SurfaceTexture(4))
-        val fakeSurface5 = Surface(SurfaceTexture(5))
-
-        val session = FakeSurfaceListener()
-        streamMap.listener = session
-        assertThat(session.surfaces).isNull()
-
-        streamMap[stream1.id] = fakeSurface1
-        streamMap[stream2.id] = fakeSurface2
-        streamMap[stream3.id] = fakeSurface3
-        assertThat(session.surfaces).isNull()
-
-        streamMap[stream4.id] = fakeSurface4
-        streamMap[stream5.id] = fakeSurface5
-
-        assertThat(session.surfaces).isNotNull()
-        assertThat(session.surfaces?.get(stream1.id)).isEqualTo(fakeSurface1)
-        assertThat(session.surfaces?.get(stream2.id)).isEqualTo(fakeSurface2)
-        assertThat(session.surfaces?.get(stream3.id)).isEqualTo(fakeSurface3)
-        assertThat(session.surfaces?.get(stream4.id)).isEqualTo(fakeSurface4)
-        assertThat(session.surfaces?.get(stream5.id)).isEqualTo(fakeSurface5)
-    }
-
-    @Test
-    fun onlyFinalSurfacesAreSentToSession() {
-        val streamMap = StreamGraphImpl(fakeMetadata, graphConfig)
-        val stream1 = streamMap[streamConfig1]!!
-        val stream2 = streamMap[streamConfig2]!!
-        val stream3 = streamMap[streamConfig3]!!
-        val stream4 = streamMap[sharedStreamConfig1]!!
-        val stream5 = streamMap[sharedStreamConfig2]!!
-
-        val fakeSurface1A = Surface(SurfaceTexture(1))
-        val fakeSurface1B = Surface(SurfaceTexture(2))
-        val fakeSurface2 = Surface(SurfaceTexture(3))
-        val fakeSurface3 = Surface(SurfaceTexture(4))
-        val fakeSurface4 = Surface(SurfaceTexture(5))
-        val fakeSurface5 = Surface(SurfaceTexture(6))
-
-        val session = FakeSurfaceListener()
-        streamMap.listener = session
-        streamMap[stream1.id] = fakeSurface1A
-        streamMap[stream1.id] = fakeSurface1B
-        assertThat(session.surfaces).isNull()
-
-        streamMap[stream2.id] = fakeSurface2
-        streamMap[stream3.id] = fakeSurface3
-        streamMap[stream4.id] = fakeSurface4
-        streamMap[stream5.id] = fakeSurface5
-
-        assertThat(session.surfaces).isNotNull()
-        assertThat(session.surfaces?.get(stream1.id)).isEqualTo(fakeSurface1B)
-        assertThat(session.surfaces?.get(stream2.id)).isEqualTo(fakeSurface2)
-        assertThat(session.surfaces?.get(stream3.id)).isEqualTo(fakeSurface3)
-        assertThat(session.surfaces?.get(stream4.id)).isEqualTo(fakeSurface4)
-        assertThat(session.surfaces?.get(stream5.id)).isEqualTo(fakeSurface5)
-    }
-
-    @Test
-    fun settingListenerToNullDoesNotClearSurfaces() {
-        val streamMap = StreamGraphImpl(fakeMetadata, graphConfig)
-        val stream1 = streamMap[streamConfig1]!!
-        val stream2 = streamMap[streamConfig2]!!
-        val stream3 = streamMap[streamConfig3]!!
-
-        val fakeSurface1 = Surface(SurfaceTexture(1))
-        val fakeSurface2 = Surface(SurfaceTexture(2))
-        val fakeSurface3 = Surface(SurfaceTexture(3))
-
-        val session = FakeSurfaceListener()
-        streamMap.listener = session
-        streamMap[stream1.id] = fakeSurface1
-        streamMap.listener = null
-
-        streamMap[stream2.id] = fakeSurface2
-        streamMap[stream3.id] = fakeSurface3
-
-        assertThat(session.surfaces).isNull()
-    }
-
-    @Test
-    fun replacingSessionPassesSurfacesToNewSession() {
-        val streamMap = StreamGraphImpl(fakeMetadata, graphConfig)
-        val stream1 = streamMap[streamConfig1]!!
-        val stream2 = streamMap[streamConfig2]!!
-        val stream3 = streamMap[streamConfig3]!!
-        val stream4 = streamMap[sharedStreamConfig1]!!
-        val stream5 = streamMap[sharedStreamConfig2]!!
-
-        val fakeSurface1 = Surface(SurfaceTexture(1))
-        val fakeSurface2 = Surface(SurfaceTexture(2))
-        val fakeSurface3 = Surface(SurfaceTexture(3))
-        val fakeSurface4 = Surface(SurfaceTexture(4))
-        val fakeSurface5 = Surface(SurfaceTexture(5))
-
-        streamMap[stream1.id] = fakeSurface1
-        streamMap[stream2.id] = fakeSurface2
-        streamMap[stream3.id] = fakeSurface3
-        streamMap[stream4.id] = fakeSurface4
-        streamMap[stream5.id] = fakeSurface5
-
-        val listener1 = FakeSurfaceListener()
-        streamMap.listener = listener1
-
-        val listener2 = FakeSurfaceListener()
-        streamMap.listener = listener2
-
-        assertThat(listener2.surfaces).isNotNull()
-        assertThat(listener2.surfaces?.get(stream1.id)).isEqualTo(fakeSurface1)
-        assertThat(listener2.surfaces?.get(stream2.id)).isEqualTo(fakeSurface2)
-        assertThat(listener2.surfaces?.get(stream3.id)).isEqualTo(fakeSurface3)
-        assertThat(listener2.surfaces?.get(stream4.id)).isEqualTo(fakeSurface4)
-        assertThat(listener2.surfaces?.get(stream5.id)).isEqualTo(fakeSurface5)
-    }
-
-    class FakeSurfaceListener : StreamGraphImpl.SurfaceListener {
-        var surfaces: Map<StreamId, Surface>? = null
-
-        override fun onSurfaceMapUpdated(surfaces: Map<StreamId, Surface>) {
-            this.surfaces = surfaces
-        }
-    }
 }
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/SurfaceGraphTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/SurfaceGraphTest.kt
new file mode 100644
index 0000000..dc5def5
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/SurfaceGraphTest.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.graph
+
+import android.graphics.SurfaceTexture
+import android.os.Build
+import android.view.Surface
+import androidx.camera.camera2.pipe.testing.FakeCameraController
+import androidx.camera.camera2.pipe.testing.FakeCameraGraphConfig
+import androidx.camera.camera2.pipe.testing.RobolectricCameraPipeTestRunner
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(RobolectricCameraPipeTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class SurfaceGraphTest {
+    private val config = FakeCameraGraphConfig()
+
+    private val streamMap = StreamGraphImpl(config.fakeMetadata, config.graphConfig)
+    private val controller = FakeCameraController()
+    private val surfaceGraph = SurfaceGraph(streamMap, controller)
+
+    private val stream1 = streamMap[config.streamConfig1]!!
+    private val stream2 = streamMap[config.streamConfig2]!!
+    private val stream3 = streamMap[config.streamConfig3]!!
+    private val stream4 = streamMap[config.sharedStreamConfig1]!!
+    private val stream5 = streamMap[config.sharedStreamConfig2]!!
+
+    private val fakeSurface1 = Surface(SurfaceTexture(1))
+    private val fakeSurface2 = Surface(SurfaceTexture(2))
+    private val fakeSurface3 = Surface(SurfaceTexture(3))
+    private val fakeSurface4 = Surface(SurfaceTexture(4))
+    private val fakeSurface5 = Surface(SurfaceTexture(5))
+
+    @Test
+    fun outputSurfacesArePassedToControllerImmediately() {
+        surfaceGraph[stream1.id] = fakeSurface1
+        surfaceGraph[stream2.id] = fakeSurface2
+        surfaceGraph[stream3.id] = fakeSurface3
+        surfaceGraph[stream4.id] = fakeSurface4
+        surfaceGraph[stream5.id] = fakeSurface5
+
+        assertThat(controller.surfaceMap).isNotNull()
+        assertThat(controller.surfaceMap?.get(stream1.id)).isEqualTo(fakeSurface1)
+        assertThat(controller.surfaceMap?.get(stream2.id)).isEqualTo(fakeSurface2)
+        assertThat(controller.surfaceMap?.get(stream3.id)).isEqualTo(fakeSurface3)
+    }
+
+    @Test
+    fun outputSurfacesArePassedToListenerWhenAvailable() {
+        assertThat(controller.surfaceMap).isNull()
+
+        surfaceGraph[stream1.id] = fakeSurface1
+        surfaceGraph[stream2.id] = fakeSurface2
+        surfaceGraph[stream3.id] = fakeSurface3
+        assertThat(controller.surfaceMap).isNull()
+
+        surfaceGraph[stream4.id] = fakeSurface4
+        surfaceGraph[stream5.id] = fakeSurface5
+
+        assertThat(controller.surfaceMap).isNotNull()
+        assertThat(controller.surfaceMap?.get(stream1.id)).isEqualTo(fakeSurface1)
+        assertThat(controller.surfaceMap?.get(stream2.id)).isEqualTo(fakeSurface2)
+        assertThat(controller.surfaceMap?.get(stream3.id)).isEqualTo(fakeSurface3)
+        assertThat(controller.surfaceMap?.get(stream4.id)).isEqualTo(fakeSurface4)
+        assertThat(controller.surfaceMap?.get(stream5.id)).isEqualTo(fakeSurface5)
+    }
+
+    @Test
+    fun onlyMostRecentSurfacesArePassedToSession() {
+        val fakeSurface1A = Surface(SurfaceTexture(7))
+        val fakeSurface1B = Surface(SurfaceTexture(8))
+
+        surfaceGraph[stream1.id] = fakeSurface1A
+        surfaceGraph[stream1.id] = fakeSurface1B
+        assertThat(controller.surfaceMap).isNull()
+
+        surfaceGraph[stream2.id] = fakeSurface2
+        surfaceGraph[stream3.id] = fakeSurface3
+        surfaceGraph[stream4.id] = fakeSurface4
+        surfaceGraph[stream5.id] = fakeSurface5
+
+        assertThat(controller.surfaceMap).isNotNull()
+        assertThat(controller.surfaceMap?.get(stream1.id)).isEqualTo(fakeSurface1B)
+        assertThat(controller.surfaceMap?.get(stream2.id)).isEqualTo(fakeSurface2)
+        assertThat(controller.surfaceMap?.get(stream3.id)).isEqualTo(fakeSurface3)
+        assertThat(controller.surfaceMap?.get(stream4.id)).isEqualTo(fakeSurface4)
+        assertThat(controller.surfaceMap?.get(stream5.id)).isEqualTo(fakeSurface5)
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCamera2Controller.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt
similarity index 64%
rename from camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCamera2Controller.kt
rename to camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt
index 9d1643c..136fe8e 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCamera2Controller.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt
@@ -16,11 +16,14 @@
 
 package androidx.camera.camera2.pipe.testing
 
-import androidx.camera.camera2.pipe.compat.Camera2Controller
+import android.view.Surface
+import androidx.camera.camera2.pipe.CameraController
+import androidx.camera.camera2.pipe.StreamId
 
-internal class FakeCamera2Controller : Camera2Controller {
+internal class FakeCameraController : CameraController {
     var active = false
-    var reconfigured = false
+    var closed = false
+    var surfaceMap: Map<StreamId, Surface>? = null
 
     override fun start() {
         active = true
@@ -30,7 +33,12 @@
         active = false
     }
 
-    override fun restart() {
-        reconfigured = true
+    override fun close() {
+        closed = true
+        active = false
+    }
+
+    override fun updateSurfaceMap(surfaceMap: Map<StreamId, Surface>) {
+        this.surfaceMap = surfaceMap
     }
 }
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraGraphConfig.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraGraphConfig.kt
new file mode 100644
index 0000000..47f4e62
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraGraphConfig.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.testing
+
+import android.hardware.camera2.CameraCharacteristics
+import android.util.Size
+import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.CameraStream
+import androidx.camera.camera2.pipe.OutputStream
+import androidx.camera.camera2.pipe.StreamFormat
+
+/**
+ * Fake CameraGraph configuration that can be used for more complicated tests that need a realistic
+ * configuration for tests.
+ */
+internal class FakeCameraGraphConfig {
+    private val camera1 = CameraId("TestCamera-1")
+    private val camera2 = CameraId("TestCamera-2")
+
+    val fakeMetadata = FakeCameraMetadata(
+        mapOf(
+            CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL to
+                CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL
+        ),
+        cameraId = camera1
+    )
+
+    val streamConfig1 = CameraStream.Config.create(
+        size = Size(100, 100),
+        format = StreamFormat.YUV_420_888
+    )
+    val streamConfig2 = CameraStream.Config.create(
+        size = Size(123, 321),
+        format = StreamFormat.YUV_420_888,
+        camera = camera1
+    )
+    val streamConfig3 = CameraStream.Config.create(
+        size = Size(200, 200),
+        format = StreamFormat.YUV_420_888,
+        camera = camera2,
+        outputType = OutputStream.OutputType.SURFACE_TEXTURE
+    )
+    val sharedOutputConfig = OutputStream.Config.create(
+        size = Size(200, 200),
+        format = StreamFormat.YUV_420_888,
+        camera = camera1
+    )
+    val sharedStreamConfig1 = CameraStream.Config.create(sharedOutputConfig)
+    val sharedStreamConfig2 = CameraStream.Config.create(sharedOutputConfig)
+
+    val graphConfig = CameraGraph.Config(
+        camera = camera1,
+        streams = listOf(
+            streamConfig1,
+            streamConfig2,
+            streamConfig3,
+            sharedStreamConfig1,
+            sharedStreamConfig2
+        ),
+        streamSharingGroups = listOf(listOf(streamConfig1, streamConfig2))
+    )
+}
\ No newline at end of file
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/RecorderTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/RecorderTest.kt
index 470370c..6d048c5 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/RecorderTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/RecorderTest.kt
@@ -35,7 +35,9 @@
 import android.provider.MediaStore
 import android.util.Size
 import androidx.camera.camera2.Camera2Config
+import androidx.camera.camera2.pipe.integration.CameraPipeConfig
 import androidx.camera.core.CameraSelector
+import androidx.camera.core.CameraXConfig
 import androidx.camera.core.Preview
 import androidx.camera.core.SurfaceRequest
 import androidx.camera.core.impl.ImageFormatConstants
@@ -59,7 +61,6 @@
 import androidx.camera.video.internal.encoder.InvalidConfigException
 import androidx.core.util.Consumer
 import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
 import androidx.test.platform.app.InstrumentationRegistry
@@ -90,6 +91,7 @@
 import org.junit.Test
 import org.junit.rules.TestName
 import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.any
 import org.mockito.ArgumentMatchers.argThat
@@ -106,13 +108,16 @@
 private const val TEST_ATTRIBUTION_TAG = "testAttribution"
 
 @LargeTest
-@RunWith(AndroidJUnit4::class)
+@RunWith(Parameterized::class)
 @SdkSuppress(minSdkVersion = 21)
-class RecorderTest {
+class RecorderTest(
+    private val implName: String,
+    private val cameraConfig: CameraXConfig,
+) {
 
     @get:Rule
     val cameraRule = CameraUtil.grantCameraPermissionAndPreTest(
-        CameraUtil.PreTestCameraIdList(Camera2Config.defaultConfig())
+        CameraUtil.PreTestCameraIdList(cameraConfig)
     )
 
     @get:Rule
@@ -128,6 +133,15 @@
     @get:Rule
     val labTest: LabTestRule = LabTestRule()
 
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun data() = listOf(
+            arrayOf(Camera2Config::class.simpleName, Camera2Config.defaultConfig()),
+            arrayOf(CameraPipeConfig::class.simpleName, CameraPipeConfig.defaultConfig())
+        )
+    }
+
     private val instrumentation = InstrumentationRegistry.getInstrumentation()
     private val context: Context = ApplicationProvider.getApplicationContext()
     private val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
@@ -153,7 +167,7 @@
 
         CameraXUtil.initialize(
             context,
-            Camera2Config.defaultConfig()
+            cameraConfig
         ).get()
         cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(context, cameraSelector)
 
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/VideoEncoderTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/VideoEncoderTest.kt
index b6abcd4..d20a2f9 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/VideoEncoderTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/VideoEncoderTest.kt
@@ -26,6 +26,7 @@
 import android.util.Size
 import android.view.Surface
 import androidx.camera.camera2.Camera2Config
+import androidx.camera.camera2.pipe.integration.CameraPipeConfig
 import androidx.camera.core.CameraSelector
 import androidx.camera.core.CameraXConfig
 import androidx.camera.core.Preview
@@ -45,7 +46,6 @@
 import androidx.concurrent.futures.ResolvableFuture
 import androidx.core.content.ContextCompat
 import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
 import androidx.test.platform.app.InstrumentationRegistry
@@ -61,6 +61,7 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.any
 import org.mockito.Mockito.atLeast
@@ -78,16 +79,28 @@
 private const val I_FRAME_INTERVAL = 1
 
 @LargeTest
-@RunWith(AndroidJUnit4::class)
+@RunWith(Parameterized::class)
 @Suppress("DEPRECATION")
 @SdkSuppress(minSdkVersion = 21)
-class VideoEncoderTest {
+class VideoEncoderTest(
+    private val implName: String,
+    private val cameraConfig: CameraXConfig,
+) {
 
     @get:Rule
     val cameraRule = CameraUtil.grantCameraPermissionAndPreTest(
-        CameraUtil.PreTestCameraIdList(Camera2Config.defaultConfig())
+        CameraUtil.PreTestCameraIdList(cameraConfig)
     )
 
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun data() = listOf(
+            arrayOf(Camera2Config::class.simpleName, Camera2Config.defaultConfig()),
+            arrayOf(CameraPipeConfig::class.simpleName, CameraPipeConfig.defaultConfig())
+        )
+    }
+
     private val instrumentation = InstrumentationRegistry.getInstrumentation()
     private val context: Context = ApplicationProvider.getApplicationContext()
     private val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 81befd7..df01294 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -31,6 +31,7 @@
 hilt = "2.42"
 incap = "0.2"
 kotlin = "1.7.10"
+kotlinBenchmark = "0.4.4"
 kotlinNative = "1.7.10"
 kotlinCompileTesting = "1.4.1"
 kotlinCoroutines = "1.6.1"
@@ -108,6 +109,7 @@
 gradleIncapHelper = { module = "net.ltgt.gradle.incap:incap", version.ref = "incap" }
 gradleIncapHelperProcessor = { module = "net.ltgt.gradle.incap:incap-processor", version.ref = "incap" }
 kotlinAnnotationProcessingEmbeddable = { module = "org.jetbrains.kotlin:kotlin-annotation-processing-embeddable", version.ref = "kotlin" }
+kotlinBenchmarkRuntime = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime", version.ref = "kotlinBenchmark" }
 kotlinCompiler = { module = "org.jetbrains.kotlin:kotlin-compiler", version.ref = "kotlin" }
 kotlinCompilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlin" }
 kotlinCompileTesting = { module = "com.github.tschuchortdev:kotlin-compile-testing", version.ref = "kotlinCompileTesting" }
@@ -197,6 +199,7 @@
 xmlpull = { module = "xmlpull:xmlpull", version = "1.1.3.1" }
 
 [plugins]
+kotlinBenchmark = { id = "org.jetbrains.kotlinx.benchmark", version.ref = "kotlinBenchmark" }
 kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
 kotlinMp = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
 kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
diff --git a/gradle/verification-keyring.keys b/gradle/verification-keyring.keys
index cee15ae..53064d2 100644
--- a/gradle/verification-keyring.keys
+++ b/gradle/verification-keyring.keys
@@ -502,6 +502,84 @@
 -----END PGP PUBLIC KEY BLOCK-----
 
 
+pub    0D3B328562A119A7
+sub    C45D01093DCFC371
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+UGyrigQZu0gUujkogzGo8f7UOwHRBoA=
+=7aNS
+-----END PGP PUBLIC KEY BLOCK-----
+
+
 pub    0DA8A5EC02D11EAD
 sub    71499A87DC1FF84B
 -----BEGIN PGP PUBLIC KEY BLOCK-----
@@ -4363,6 +4441,43 @@
 -----END PGP PUBLIC KEY BLOCK-----
 
 
+pub    685C46769DBB5E5D
+uid    Egor Andreevici <egor@squareup.com>
+
+sub    CA7AE93399B1ED99
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFqHCi8BCACgRpCaVCiJ2MccCN01SbHYowmM255nSYKOnfItBmXYAMtc4rL9
+n1y1qFtc4LBbkIrPH8CO2zpEImUTZel4W93BQkluPOO3EX/hLCTCFfXrO89L1u4V
+XL4siS8vZl3DVDdY7m9G4vcpiIsggGF683KNctN2KXZ0D3tu9C1X7eJk3GyDo6W7
+MJwiiCm10968VqFqIFn1rTkvtGtXGP61Vqy7kLTdiBrKbo1HkZDbryl6nvCmT++E
+auJXEDYH9R+vsODy10a5in0n0EzQD4DYadL6cQTbwP2SvMbRRRQ7AnNtys6cNCCb
+CIJ8iySLaHYi65w6FEbiBM2XQ2hzf8Dek9yDABEBAAG0I0Vnb3IgQW5kcmVldmlj
+aSA8ZWdvckBzcXVhcmV1cC5jb20+iQFUBBMBCAA+FiEEaC92XupxjSULvbLxaFxG
+dp27Xl0FAlqHCi8CGwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ
+aFxGdp27Xl03AAgAgtnhNsz++UIqtiETzp0Y5v40STwdI+8KYhvbhzL2MARmnYr8
+US+NqeALovuWPNoP8CuzGN6dQP4tFMVr/4GtDJRqzi9EGUHIk6KzliK69Eir04TP
+3CgJb4OqrfgqU/tbXTPFVVKbpyWnrrzg50THhIigMxkezvTWa8iLWswBHb/E/NRn
+1NOfVkPqHY0D0Z+KeAR1/20n+aEh5JrLsxzIp3vNF+qXSN4gKtmdj2fYH9eovM85
+0NzlZnaqwetTtBxeu9mYvCHLCbTLrQTY2MvqBpZbUdVJytJrvOTAddmRrNiBz1w9
+yxzGOKXDSB0t6LVWldwAuTM0eGXqaDgInbe7r7kBDQRahwovAQgAzYHtmnHEZVad
+1Th2c8oFr3/QaH7UP7Xz+lhKyYgq/FsKmkQy88qxcxTX4kMfSB8ssKFdaCtBQI6y
+pFVvaUm8jn1LC0dVPZJHKHOdDEiLdg7B20bPzdY0x5+Yav7SJjYIq53V3pkJGZyH
+P9CvZ/L5uJ5+2sFx1nj1qyK1FWVx2VZk2TsFmL4fpiAi6SOXRoGVLlO0sCqUvlH2
+eR873/1u5Ya387En4krWnu0T+dHyg5/xu9S2Q7XKmO7GyEUXRnXsJPur6CwXpUao
+eoXIcydpdjl+TR70OgxyAGsrfQYVNjPvRVK4yUv839Xz8mCIp21CRscsx1IIeshM
+BqRGXIo8BQARAQABiQE8BBgBCAAmFiEEaC92XupxjSULvbLxaFxGdp27Xl0FAlqH
+Ci8CGwwFCQPCZwAACgkQaFxGdp27Xl2rCAf9EwynJ3Pb70PcSVboGozFCnSayE+c
+/SboSK2Cujfw1Fy2Qr0YizXL4RAE4jXzI+Y3EYZpcJ7XMxUheBTZrxO8ACvMrAwm
+MC2vf1EoM3DQVpyoVCv5d1OIY6rYCjyHeBT4rwsl8GLZZ9vsjGWpI9m8Jcpi3jhM
+ih+zfrdaYJpFzu5MA2y/dV3aYn0kpODuN+WVWRyF/3jhLCZtrNFnZb3pfrS/jcDM
++kdiyqH9wE6iyvIxX8Rk7a+1H0zFmKQNetxdMQPYODUSXQEuygXaZFzm+bfWU+E9
+x+HCpeZqmOpBQgdhFZFEX+ru97s07kBMVUlWM4s4uETNKLIwzkAk2FlbGw==
+=S5Ep
+-----END PGP PUBLIC KEY BLOCK-----
+
+
 pub    689CBE64F4BC997F
 uid    Szczepan Faber <szczepiq@gmail.com>
 
@@ -6776,6 +6891,1628 @@
 -----END PGP PUBLIC KEY BLOCK-----
 
 
+pub    9AE296FD02E9F65B
+uid    Luc Maisonobe (CODE SIGNING KEY) <luc@apache.org>
+uid    Luc Maisonobe <Luc.Maisonobe@c-s.fr>
+uid    Luc Maisonobe <luc@orekit.org>
+uid    Luc Maisonobe <Luc.Maisonobe@free.fr>
+
+sub    2F3C9EEB05D1D1E3
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+IChSZWxlYXNlIFNpZ25pbmcgS2V5KSA8amltQGFwYWNoZS5vcmc+IBxKaW0gSmFn
+aWVsc2tpIDxqaW1AamFndU5FVC5jb20+HxxKaW0gSmFnaWVsc2tpIDxqaW1Aamlt
+amFnLmNvbT4ACgkQNOp25nkUhagzfA//fDOf2r4R4NmRxMBYksilQGdgtrenELGh
+0WXsPv9ogvau+7nuJ+nIVG9b7S4+rac7Lim9L+15SqWnwASdw+yVOUI7r6VHHaQY
+6mYh3PtjdkuXkT04jCBKnEBXLLUariGTPIYEJEWH4FUzORg6nt/9vQBzXbG0DG4J
+7DzDmFGKS9nQDAqxKRbrRVth9IumhIh4kuwDJbN1PHdJAYHHRyD98f5uTxzMvU7r
+5VmG009oAG4JCVBMW9enj0/qu9mLmNm4IxyvmbuC3ZiJXwQUn2qDJobv9BtDnvJw
+YCNtFJYHtu8lpJZyk2wxP+tpcvny5D39iQRDG0WpymtDZcZt8I5S86PrhxVXEem3
+7INHiXVsMDLGdfNpfdezAqvIkYVmVfK4gYhDLj1oka4ruiergwW3H8BakStpeGqd
+tp2tNMNGQXuoKbyjqK1WFNVUKN3s7efjrgoh2XR+yFjBop4pNLktbjo+LXGc0e4u
+T7exRrpSlHLUuEa2rZeeKtntnT4DKv3y4ebJ5f34VegBAb4e4Xsd6XgtDPYX/HUG
+seSjj72OPN7pAUtbBTO2q1NFG6vUPZBSLiV9ZzOu1lPYWEV0g+cIKPmLmIsRnETP
+346vWx2wq5EIWh7T3fTfYkYnsD3vyApPkG9MqMgotR+FIKlWFglPNEv0V2cZgcgV
+exvw5RD8TMuIygQQEQIAigUCTNK0Qx8cSmltIEphZ2llbHNraSA8amltQGFwYWNo
+ZS5vcmc+IBxKaW0gSmFnaWVsc2tpIDxqaW1AamFndU5FVC5jb20+HxxKaW0gSmFn
+aWVsc2tpIDxqaW1AamltamFnLmNvbT4iHEppbSBKYWdpZWxza2kgPGppbWpAY292
+YWxlbnQubmV0PgAKCRCLOmAfCMl15cvtAKCStVtCjnhZQeccqgGtwJqnGXba+ACd
+E1osWknKnvFCvurObyp6OPRoyuiJAhwEEAEKAAYFAkzStckACgkQgngd5G1ZVPqI
+ehAAihtxeHdh36A6no5dt9LwrV3WDApxM4M9G8zfN9f3sr5RKq/9cebZjiVWOKYu
+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
+wT3/uLspPh8CTR7DkLU0twAr+POjct6QdzOlwv4bCh3EII4e9u5lqLlmlvvp/X7z
+8GzeDwxK2oDyUSIoN+FMPuS8ESVhMV+ST409io7p9On/MpgQ4F471UsYuzpLXfHB
+l4l32Ra3haNIfW477XgRHz3tfLUvFQWQ9PH7OFJV4rXDFyiLPQsJgW7TTgz0zJt4
+N2x/2awenMOp3T3IXnIpO80ENO4VcPmVSjL9aXkMiS6YicZG1YkCXQQQAQIARwUC
+TNLXrEAcSm9zZXBoIEVkd2FyZCBCZXJnbWFyayAoQ09ERSBTSUdOSU5HIEtFWSkg
+PGJlcmdtYXJrQGFwYWNoZS5vcmc+AAoJELDZkbR8QIc3jXIP/1R4765cKL59YnFp
+QuJNwrJmchg6oh4E+C60cWes955cYCitUPzRkHeHCSmC55TcFWwhGtzQH8Ql4Xle
+UJk7AXh8yMv3KSxG7Ic5/w4MTXAaY53r1q/ImTHnlSmF0+iMq4LF2BfLGW1lWXz+
+5D1Fm2fqlyYJ7BfDRwhbQZiQAxeddf+Ydx8d8Zk1CVqQOkhTFWpN9O+oxiEyxfo5
+SNOZzcCKi+cR0E7AB9qet/OTjecnKy4vFqG4adc6RNPU7d+20GOiJAZMOChdgl6k
+nrX3b11ilu41ri1Y2PqHyjBJnm4zSVw8x8HxbpHt5TB/TIy7YwVnZs13mitxRoa5
+CwuMeyDCz/8Ob5K3fTF7/0UAsG7c/dhZBA6ENzjHYSxhlYDDL0mTUG+b8C6ZypLH
+eS00rky8g8mNV901vsGxoJhu/w2diFRf/o4QAbj+9nttxxtYvBKTvuHSEGFErOLV
+35ChixhsMdr+Sl4eBWF3HxRJUsyIT/kRZzL41usXP2KH8CbkerQVaMzOb3M9RfO6
+7VLPfb+q2JW+BdHMlbVsQdfWhLJoMTLHGgxhXCA7Fpd6slI3HrUvlFxd/f9DHmZu
+E63mvtjgI9GRdbDOHdkhJ5yTd1uQe3p+QWXsgq/YOIQj+oIVI5R8ZMXHzsec4vPF
+xok1uajMV/fXeqdDYutbZrQgj56piQKpBBABAgCTBQJM0uOxIBxTYW5kZXIgVGVt
+bWUgPHNhbmRlckB0ZW1tZS5uZXQ+IhxTYW5kZXIgVGVtbWUgPHNjdGVtbWVAYXBh
+Y2hlLm9yZz4dHFNhbmRlciBUZW1tZSA8c2FuZGVyQG1lLmNvbT4qHFNhbmRlciBU
+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
+zuF5mZ85CvswdQE31umGLWlHhgJq5DB2rMY+bIvoeIMPAan3ZgPPAB1rDKNUzNQU
+peO678gaJqS81TIHQbcXKxzfCem5auHz7hVfENZKkKPh11XPzIA1HJTpkYQleOQK
+sc8B5qUwQd2ecATfrfIY1KTAmT7qcTnBpdO/TTwnw7M9wwpZBP1IfJwB4nmlWkI8
+Bnllv289lQWAdw12F/4gjJ46MxQwtHrWOpcxWAUTcF/QJZf7UUT8EkzW6aveTP3P
+7IkAkAvvadEWzZcMwVEy70ceayrufDlMYZ7ia24WKFyzm8zCQKWV5X94uQhPQ1e6
+osaXf1wTpshbnmqhRSqZC1FvAVsWNS4330T78p1bQAMYesmYQQkSa53ecW3/////
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+////////iQEcBBABAgAGBQJQmioNAAoJEO0JbZPu7UfaclUH/RezKHySASl/1t/o
+9TixCcyysDuSeRbhuNlQNZDeOtvnaajMnPpRZEs067uK/YVqNj/BEtDn+vM/sNzs
+Nu69EaaSZZvM7wn2Ig9MywCFaCCpdeuzD8cVG6uuYwO4vIvMrc5dKcFoQQA5bOEQ
+rYofqsOPePChce5dE4kxBN8MjcgHFIBh3WzPs8ohXzNWzNKU/lew0StEKbbR3CPz
+dYwQ5/Xe5IvYlkZtaCWgX+r1vVjxuKK5NUWez+5crHICtuhVy06E3PRHKM4elh/G
+wPVzcP8cspMgofAM9cSHKjFfopynq0RqXEPldG8xJm55uFacOUag4P4PE26t/7Cj
+sY1d+e+JAhwEEAECAAYFAlCaQ9wACgkQNiWQp/XP2RUr5hAAhpLsiBfJJN0wWDh0
+dH3MbXiZ69vWibHd/CNG3WZhxxoxnfT5M1P7Xdu+k1vUjBGCTT8mYuHzMUyZRa2q
+vGIZK1cn/eZzjS1AuV9yR45WIcYtl8eqekvpI9wN200B0oGWkV//9mWO232s79eB
+9j/t9XkozQ7HkFaKevPQ70s6oLfKBT41VTgFSlqylSkoFIeekynwk33Ne3SHwZEj
+kJeJv770unXeTxeGjuIXdYAnk7EkI1E8ysskyGTYzrjDn5Z3m1gqd//msjEXSXXU
+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
+RnQfDzV75TMLdPbRNKk6/9AQtZUDSSf2rmAJDso1/Hw1uXRzhWUSQjP2NKgqDg1h
+kSsrxVcf/HT+/qEDV3c50RxRCkRXWnie+7DE7gV9VxYVGFp/RDcI/CCo7zk8opuy
+we779RU9Tds6ngXMmcbi4HdJBIVavr8ZlCyZ5mj7HSenujIUhnDqKZf/JE2CIxmJ
+UUQbD3LVlOZByPKowa+nR2WzfezkRCNhw20aSxOWch7qb6dFGQBRHdi2E9Ovy3JR
+xAyh+mLc5OMx3yBqe54v0cn+Ov/WYCb5LqtPKc2qd/Oy27pfo0Ly2eE4AU5EVcV2
+PpetTpC5W2xZqVxFd6irpyp8/lFiXb09FpNe4ykad22GA87SIzoGAEUK3Eyx+K06
+CVunXKc3PR/WyK+tM8KPVc3L9g+OzVL9Jnj5HasNO+NJyfNVvCY6f0vmBrZEsRbn
+lG7lGJ7HSbB5kHgTZGQFfxu+ftrXWkg/xg+bUQcPGIGlKh9lMVeZk4kdkt6fRewc
+0GI6h51FD3S5T6kKDBhEt6wXshYaTVxRHNWw0dd5sMzNar6CHkyaFVaJAhwEEAEC
+AAYFAlCiZnMACgkQRmNAdwvZNvFYVw//cKPW7WtU0HIVvkDD4EsXe9ejDOH3Wg4d
+4XT4bYFl8p78/msZipDTX9lTZzYHEW2Hhvl40frtA4mOUfZdwyB8qQSVjgvwnJD2
+Skp6MMuCOOEv1m29PACXjNzt/UJcVKEr8e8A8DdWmZx/ifeNrKx4qB6mKm0f2AU4
+qjMCApncUBPvpTxPTsO2pw+HOObXbApxwva4kC43QEHbqiBVqI4n0YIRQo6bWClN
+/FbxfzF959iaL/JY9hUY0KTkPfPrNlq12CY5M/PoAlOpP0o3l5ZfI6zf2VHhXB46
+XdTGvwxZsJ21fGADLh2RlXRONM5mtkVuY8cgfRmr1u1VzJWCiWsTig/kkGm/OjjV
+qCc9+7rFrCqI7Bs90Kf7+VDrHLEEjLM2Qgr95jqaD7c2QJWmns9DQ2l4ilKSOfkE
+eQWFu+nbXVRhu5qB5X2ZzcvZmTc5kx43bGJTemEettzmdGyLUk8RZvotuCBeWiUs
+X4/Ko56pIEjODjXfCeT6J4ysvCnRscxkcSY02KWJbR77vZP3scrx6rSch/H7V/hX
+xmslCUErHpYsmzSaCoh153fSQaiyfKUT+loPTas3x/1fbJRsDBwhgCJXuVVkE7Kh
+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
+7efjrgoh2XR+yFjBop4pNLktbjo+LXGc0e4uT7exRrpSlHLUuEa2rZeeKtntnT4D
+Kv3y4ebJ5f34VegBAb4e4Xsd6XgtDPYX/HUGseSjj72OPN7pAUtbBTO2q1NFG6vU
+PZBSLiV9ZzOu1lPYWEV0g+cIKPmLmIsRnETP346vWx2wq5EIWh7T3fTfYkYnsD3v
+yApPkG9MqMgotR+FIKlWFglPNEv0V2cZgcgVexvw5RD8TMuIygQQEQIAigUCTNK0
+Qx8cSmltIEphZ2llbHNraSA8amltQGFwYWNoZS5vcmc+IBxKaW0gSmFnaWVsc2tp
+IDxqaW1AamFndU5FVC5jb20+HxxKaW0gSmFnaWVsc2tpIDxqaW1AamltamFnLmNv
+bT4iHEppbSBKYWdpZWxza2kgPGppbWpAY292YWxlbnQubmV0PgAKCRCLOmAfCMl1
+5cvtAKCStVtCjnhZQeccqgGtwJqnGXba+ACdE1osWknKnvFCvurObyp6OPRoyuiJ
+AhwEEAEKAAYFAkzStckACgkQgngd5G1ZVPrnSg/+L4892O4wSVGmIZ7AGHtq08NP
+TLNfzfkcKtMUOBP3hnH9tyiKkxmQKuUAAUAatx3AkxYfsN8e3Rd/w7SfyeqCeQBY
+B/fmBWVegpUkIUmUDnAT89EXParMOBk+NAmTfBo5H+zS/lo8y2MC8WXJYHWI9TE8
+uft0nHn8hLCVqA2YcLD8oxQ9YP4lKCQsbZc0zz1GEZzcxgXFKm3HPHPSymr5sBbh
+TlKAXZ0kjzUgAz8asHbyAuvNmIMstRjZuqhvig/E9JkWgBdGOk9UfLFbQ9p9Hzah
+LnWkutfhSVcs1IJ2kf7P71NpfZl1/sifqojWUkrLcVwYUqfu9A8tICu7zE1xluRs
+cdv/3mx4yyWvMk4Eu0WTOrIWeQyoy6Sg9zt7ymjw/iMvFs0Lq1KgvI4TEL2KR4ln
+FU9BJQYwTVaWIWwWnTP5361nU7ixCYBQu+Vgv0sIQMauu6RZrfb1mQPpBigwFTh4
+GYBhQwgfF32g/4oiELkHQJ+Sf/6Z6oyE/sSdz3vsNFSxF6av4Yr5iSXojBXD/jt7
+ivOUOE/K00mNVNSW/T9oJGy/S/7XkOTV90MvtWSC3CWbLv7YNMYUN/3TgYV8esz7
+wG1Df0ogD4PbLUXwyXHXoFbiwIe2a3+XTHb5zUbl7LUgN+LAGzT7GItaPTjNgj+K
+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
+Ky4vFqG4adc6RNPU7d+20GOiJAZMOChdgl6knrX3b11ilu41ri1Y2PqHyjBJnm4z
+SVw8x8HxbpHt5TB/TIy7YwVnZs13mitxRoa5CwuMeyDCz/8Ob5K3fTF7/0UAsG7c
+/dhZBA6ENzjHYSxhlYDDL0mTUG+b8C6ZypLHeS00rky8g8mNV901vsGxoJhu/w2d
+iFRf/o4QAbj+9nttxxtYvBKTvuHSEGFErOLV35ChixhsMdr+Sl4eBWF3HxRJUsyI
+T/kRZzL41usXP2KH8CbkerQVaMzOb3M9RfO67VLPfb+q2JW+BdHMlbVsQdfWhLJo
+MTLHGgxhXCA7Fpd6slI3HrUvlFxd/f9DHmZuE63mvtjgI9GRdbDOHdkhJ5yTd1uQ
+e3p+QWXsgq/YOIQj+oIVI5R8ZMXHzsec4vPFxok1uajMV/fXeqdDYutbZrQgj56p
+iQKpBBABAgCTBQJM0uOxIBxTYW5kZXIgVGVtbWUgPHNhbmRlckB0ZW1tZS5uZXQ+
+IhxTYW5kZXIgVGVtbWUgPHNjdGVtbWVAYXBhY2hlLm9yZz4dHFNhbmRlciBUZW1t
+ZSA8c2FuZGVyQG1lLmNvbT4qHFNhbmRlciBUZW1tZSA8c2N0ZW1tZUBrZXlzaW50
+aGVjbG91ZC5jb20+AAoJEJu4Y7D1G7iKmpUQAK9EKFrhM2xi5GeTFv/nhzwArK2M
+pncvQTBGousnyJYeqW3dptSl/u0gB2CpOZdtMwvdOciB39B/s0+uvXOV/ZCh8Joz
+Sqsr7u2dJ2tjFw1v18ZwKDk7meZ/M/VJqUkEOC49FjU36Kx3EhPdN58u/V6kR4b6
+G08FSTjozwpCNK70GFNZz5pY4D3Pe70BFZhShVmHmdk3qA0ECbFs0bSk5cF5utQr
+iqvWiAWsO/6dU9NiaB9aZoQsEc+nKwl0gCgzvNhmYGKz6S7bjfdF/pXIgI1UAI2o
+dtHuMCU/E6OCFZIX9zROMJSNADmNSQhzfSlC72NJm2XBgvIKWigDIbHfIxm7To9y
+xB5WiBo9qG8mFH2kfe3Mo896wy0p2Ag369GuAg62c89B5uuV6nO1GVXEyOIEaklr
+ZC5NYb0r0Fh9w+Vndq1Hnd5GEMDDe/s4yJ+5JCTBgNpEv2L8ngabzKFvG7LRag8Q
+HmXm8yR6+CmKM7Ebhgweqdb3zk1wqIwloOEOy7dlJCcs/g9EzDSBZ8nNXQWkZXQP
+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
+YXJrQGFwYWNoZS5vcmc+AAoJELDZkbR8QIc3jXIP/1R4765cKL59YnFpQuJNwrJm
+chg6oh4E+C60cWes955cYCitUPzRkHeHCSmC55TcFWwhGtzQH8Ql4XleUJk7AXh8
+yMv3KSxG7Ic5/w4MTXAaY53r1q/ImTHnlSmF0+iMq4LF2BfLGW1lWXz+5D1Fm2fq
+lyYJ7BfDRwhbQZiQAxeddf+Ydx8d8Zk1CVqQOkhTFWpN9O+oxiEyxfo5SNOZzcCK
+i+cR0E7AB9qet/OTjecnKy4vFqG4adc6RNPU7d+20GOiJAZMOChdgl6knrX3b11i
+lu41ri1Y2PqHyjBJnm4zSVw8x8HxbpHt5TB/TIy7YwVnZs13mitxRoa5CwuMeyDC
+z/8Ob5K3fTF7/0UAsG7c/dhZBA6ENzjHYSxhlYDDL0mTUG+b8C6ZypLHeS00rky8
+g8mNV901vsGxoJhu/w2diFRf/o4QAbj+9nttxxtYvBKTvuHSEGFErOLV35Chixhs
+Mdr+Sl4eBWF3HxRJUsyIT/kRZzL41usXP2KH8CbkerQVaMzOb3M9RfO67VLPfb+q
+2JW+BdHMlbVsQdfWhLJoMTLHGgxhXCA7Fpd6slI3HrUvlFxd/f9DHmZuE63mvtjg
+I9GRdbDOHdkhJ5yTd1uQe3p+QWXsgq/YOIQj+oIVI5R8ZMXHzsec4vPFxok1uajM
+V/fXeqdDYutbZrQgj56piQKpBBABAgCTBQJM0uOxIBxTYW5kZXIgVGVtbWUgPHNh
+bmRlckB0ZW1tZS5uZXQ+IhxTYW5kZXIgVGVtbWUgPHNjdGVtbWVAYXBhY2hlLm9y
+Zz4dHFNhbmRlciBUZW1tZSA8c2FuZGVyQG1lLmNvbT4qHFNhbmRlciBUZW1tZSA8
+c2N0ZW1tZUBrZXlzaW50aGVjbG91ZC5jb20+AAoJEJu4Y7D1G7iKmpUQAK9EKFrh
+M2xi5GeTFv/nhzwArK2MpncvQTBGousnyJYeqW3dptSl/u0gB2CpOZdtMwvdOciB
+39B/s0+uvXOV/ZCh8JozSqsr7u2dJ2tjFw1v18ZwKDk7meZ/M/VJqUkEOC49FjU3
+6Kx3EhPdN58u/V6kR4b6G08FSTjozwpCNK70GFNZz5pY4D3Pe70BFZhShVmHmdk3
+qA0ECbFs0bSk5cF5utQriqvWiAWsO/6dU9NiaB9aZoQsEc+nKwl0gCgzvNhmYGKz
+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
+aGUub3JnPiAcSmltIEphZ2llbHNraSA8amltQGphZ3VORVQuY29tPh8cSmltIEph
+Z2llbHNraSA8amltQGppbWphZy5jb20+AAoJEDTqduZ5FIWoM3wP/3wzn9q+EeDZ
+kcTAWJLIpUBnYLa3pxCxodFl7D7/aIL2rvu57ifpyFRvW+0uPq2nOy4pvS/teUql
+p8AEncPslTlCO6+lRx2kGOpmIdz7Y3ZLl5E9OIwgSpxAVyy1Gq4hkzyGBCRFh+BV
+MzkYOp7f/b0Ac12xtAxuCew8w5hRikvZ0AwKsSkW60VbYfSLpoSIeJLsAyWzdTx3
+SQGBx0cg/fH+bk8czL1O6+VZhtNPaABuCQlQTFvXp49P6rvZi5jZuCMcr5m7gt2Y
+iV8EFJ9qgyaG7/QbQ57ycGAjbRSWB7bvJaSWcpNsMT/raXL58uQ9/YkEQxtFqcpr
+Q2XGbfCOUvOj64cVVxHpt+yDR4l1bDAyxnXzaX3XswKryJGFZlXyuIGIQy49aJGu
+K7onq4MFtx/AWpEraXhqnbadrTTDRkF7qCm8o6itVhTVVCjd7O3n464KIdl0fshY
+waKeKTS5LW46Pi1xnNHuLk+3sUa6UpRy1LhGtq2XnirZ7Z0+Ayr98uHmyeX9+FXo
+AQG+HuF7Hel4LQz2F/x1BrHko4+9jjze6QFLWwUztqtTRRur1D2QUi4lfWczrtZT
+2FhFdIPnCCj5i5iLEZxEz9+Or1sdsKuRCFoe093032JGJ7A978gKT5BvTKjIKLUf
+hSCpVhYJTzRL9FdnGYHIFXsb8OUQ/EzLiMoEEBECAIoFAkzStEMfHEppbSBKYWdp
+ZWxza2kgPGppbUBhcGFjaGUub3JnPiAcSmltIEphZ2llbHNraSA8amltQGphZ3VO
+RVQuY29tPh8cSmltIEphZ2llbHNraSA8amltQGppbWphZy5jb20+IhxKaW0gSmFn
+aWVsc2tpIDxqaW1qQGNvdmFsZW50Lm5ldD4ACgkQizpgHwjJdeXL7QCgkrVbQo54
+WUHnHKoBrcCapxl22vgAnRNaLFpJyp7xQr7qzm8qejj0aMroiQIcBBABCgAGBQJM
+0rXJAAoJEIJ4HeRtWVT6q4kP/2bGNVdu/6oI+aERmV/m8oaQK6BCwJXsAN4dKXRx
+bevuFEyic/HZqztb+7Eq7DRAusx99uJVwWYEUP9lgP9G2ZctNXP1Y1YloIZY+Aoy
+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
+xCCOHvbuZai5Zpb76f1+8/Bs3g8MStqA8lEiKDfhTD7kvBElYTFfkk+NPYqO6fTp
+/zKYEOBeO9VLGLs6S13xwZeJd9kWt4WjSH1uO+14ER897Xy1LxUFkPTx+zhSVeK1
+wxcoiz0LCYFu004M9MybeDdsf9msHpzDqd09yF5yKTvNBDTuFXD5lUoy/Wl5DIku
+mInGRtWJAl0EEAECAEcFAkzS16xAHEpvc2VwaCBFZHdhcmQgQmVyZ21hcmsgKENP
+REUgU0lHTklORyBLRVkpIDxiZXJnbWFya0BhcGFjaGUub3JnPgAKCRCw2ZG0fECH
+N41yD/9UeO+uXCi+fWJxaULiTcKyZnIYOqIeBPgutHFnrPeeXGAorVD80ZB3hwkp
+gueU3BVsIRrc0B/EJeF5XlCZOwF4fMjL9yksRuyHOf8ODE1wGmOd69avyJkx55Up
+hdPojKuCxdgXyxltZVl8/uQ9RZtn6pcmCewXw0cIW0GYkAMXnXX/mHcfHfGZNQla
+kDpIUxVqTfTvqMYhMsX6OUjTmc3AiovnEdBOwAfanrfzk43nJysuLxahuGnXOkTT
+1O3fttBjoiQGTDgoXYJepJ61929dYpbuNa4tWNj6h8owSZ5uM0lcPMfB8W6R7eUw
+f0yMu2MFZ2bNd5orcUaGuQsLjHsgws//Dm+St30xe/9FALBu3P3YWQQOhDc4x2Es
+YZWAwy9Jk1Bvm/AumcqSx3ktNK5MvIPJjVfdNb7BsaCYbv8NnYhUX/6OEAG4/vZ7
+bccbWLwSk77h0hBhRKzi1d+QoYsYbDHa/kpeHgVhdx8USVLMiE/5EWcy+NbrFz9i
+h/Am5Hq0FWjMzm9zPUXzuu1Sz32/qtiVvgXRzJW1bEHX1oSyaDEyxxoMYVwgOxaX
+erJSNx61L5RcXf3/Qx5mbhOt5r7Y4CPRkXWwzh3ZISeck3dbkHt6fkFl7IKv2DiE
+I/qCFSOUfGTFx87HnOLzxcaJNbmozFf313qnQ2LrW2a0II+eqYkCqQQQAQIAkwUC
+TNLjsSAcU2FuZGVyIFRlbW1lIDxzYW5kZXJAdGVtbWUubmV0PiIcU2FuZGVyIFRl
+bW1lIDxzY3RlbW1lQGFwYWNoZS5vcmc+HRxTYW5kZXIgVGVtbWUgPHNhbmRlckBt
+ZS5jb20+KhxTYW5kZXIgVGVtbWUgPHNjdGVtbWVAa2V5c2ludGhlY2xvdWQuY29t
+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
+1Rd/N9uAngaAuoqGAThmyfc=
+=G1yK
+-----END PGP PUBLIC KEY BLOCK-----
+
+
 pub    9B1FDA9F3C062231
 sub    458AF764D812A037
 -----BEGIN PGP PUBLIC KEY BLOCK-----
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 948919c..e28fe80 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -30,6 +30,7 @@
       <trusted-keys>
          <trusted-key id="00089ee8c3afa95a854d0f1df800dd0933ecf7f7" group="com.google.guava" name="guava"/>
          <trusted-key id="012579464d01c06a" group="org.apache"/>
+         <trusted-key id="019082bc00e0324e2aef4cf00d3b328562a119a7" group="org.openjdk.jmh"/>
          <trusted-key id="02216ed811210daa" group="io.github.detekt.sarif4k"/>
          <trusted-key id="0315bfb7970a144f">
             <trusting group="com.sun.istack"/>
@@ -65,6 +66,7 @@
          <trusted-key id="1188b69f6d6259ca" group="com.google.accompanist"/>
          <trusted-key id="11b581967f079a30a3e93140d57506cd188fd842" group="com.google.api.grpc"/>
          <trusted-key id="120d6f34e627ed3a772ebbfe55c7e5e701832382" group="org.snakeyaml"/>
+         <trusted-key id="12d16069219c90212a974d119ae296fd02e9f65b" group="org.apache.commons" name="commons-math3"/>
          <trusted-key id="147b691a19097624902f4ea9689cbe64f4bc997f" group="^org[.]mockito($|([.].*))" regex="true"/>
          <trusted-key id="151ba00a46886a5f95441a0f5d67bffcba1f9a39" group="com.google.gradle" name="osdetector-gradle-plugin"/>
          <trusted-key id="160a7a9cf46221a56b06ad64461a804f2609fd89" group="com.github.shyiko.klob" name="klob"/>
@@ -221,6 +223,7 @@
          <trusted-key id="635ee627345f3c1dd422b2e207d3516820bcf6b1" group="com.github.ben-manes.caffeine"/>
          <trusted-key id="6525fd70cc303655" group="org.codehaus.mojo"/>
          <trusted-key id="666a4692ce11b7b3f4eb7b3410066a9707090cf9" group="org.javassist" name="javassist"/>
+         <trusted-key id="682f765eea718d250bbdb2f1685c46769dbb5e5d" group="com.squareup" name="kotlinpoet"/>
          <trusted-key id="694621a7227d8d5289699830abe9f3126bb741c1">
             <trusting group="com.google.guava"/>
             <trusting group="com.google.jimfs"/>
@@ -705,6 +708,19 @@
             <sha256 value="4df94aaeee8d900be431386e31ef44e82a66e57c3ae30866aec2875aff01fe70" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.jetbrains.kotlinx" name="kotlinx-benchmark-plugin" version="0.4.4" androidx:reason="https://youtrack.jetbrains.com/issue/KT-53461">
+         <artifact name="kotlinx-benchmark-plugin-0.4.4.jar">
+            <sha256 value="b818d2b6c62cb6f46edbd098c4a6a71cec6f277f8fc3c51bca60d6f538693512" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="kotlinx-benchmark-plugin-0.4.4.pom">
+            <sha256 value="57f0bbbf1d4d182e79f400d7cea1ebdd48bd1b4a092411756ccac054d1e07d5c" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
+      <component group="org.jetbrains.kotlinx.benchmark" name="org.jetbrains.kotlinx.benchmark.gradle.plugin" version="0.4.4" androidx:reason="https://youtrack.jetbrains.com/issue/KT-53461">
+         <artifact name="org.jetbrains.kotlinx.benchmark.gradle.plugin-0.4.4.pom">
+            <sha256 value="72b338deead79e32f508da7ca3a8ac46a3ce3c76ce468e6b1b313ef4ddfb5cbd" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.ow2" name="ow2" version="1.5" androidx:reason="https://gitlab.ow2.org/asm/asm/-/merge_requests/354">
          <artifact name="ow2-1.5.pom">
             <sha256 value="0f8a1b116e760b8fe6389c51b84e4b07a70fc11082d4f936e453b583dd50b43b" origin="Generated by Gradle"/>
diff --git a/javascriptengine/javascriptengine/api/current.txt b/javascriptengine/javascriptengine/api/current.txt
index 782c21f..e808cea 100644
--- a/javascriptengine/javascriptengine/api/current.txt
+++ b/javascriptengine/javascriptengine/api/current.txt
@@ -1,37 +1,46 @@
 // Signature format: 4.0
 package androidx.javascriptengine {
 
-  public class EvaluationFailedException extends androidx.javascriptengine.JsException {
+  public final class EvaluationFailedException extends androidx.javascriptengine.JavaScriptException {
     ctor public EvaluationFailedException(String);
   }
 
-  public class IsolateTerminatedException extends androidx.javascriptengine.JsException {
+  public final class IsolateStartupParameters {
+    ctor public IsolateStartupParameters();
+    method @IntRange(from=0) public long getMaxHeapSizeBytes();
+    method @RequiresFeature(name=androidx.javascriptengine.JavaScriptSandbox.JS_FEATURE_ISOLATE_MAX_HEAP_SIZE, enforcement="androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported") public void setMaxHeapSizeBytes(@IntRange(from=0) long);
+    field public static final long DEFAULT_ISOLATE_HEAP_SIZE = 0L; // 0x0L
+  }
+
+  public final class IsolateTerminatedException extends androidx.javascriptengine.JavaScriptException {
     ctor public IsolateTerminatedException();
   }
 
-  public class JsException extends java.lang.Exception {
-    ctor public JsException(String);
-    ctor public JsException();
+  public class JavaScriptException extends java.lang.Exception {
+    ctor public JavaScriptException(String);
+    ctor public JavaScriptException();
   }
 
-  public class JsIsolate implements java.lang.AutoCloseable {
+  public final class JavaScriptIsolate implements java.lang.AutoCloseable {
     method public void close();
-    method public com.google.common.util.concurrent.ListenableFuture<java.lang.String!> evaluateJavaScriptAsync(String);
-    method @RequiresFeature(name=androidx.javascriptengine.JsSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER, enforcement="androidx.javascriptengine.JsSandbox#isFeatureSupported") public boolean provideNamedData(String, byte[]);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.String!> evaluateJavaScriptAsync(@org.intellij.lang.annotations.Language("javascript") String);
+    method @RequiresFeature(name=androidx.javascriptengine.JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER, enforcement="androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported") public boolean provideNamedData(String, byte[]);
   }
 
-  public class JsSandbox implements java.lang.AutoCloseable {
+  public final class JavaScriptSandbox implements java.lang.AutoCloseable {
     method public void close();
-    method public static com.google.common.util.concurrent.ListenableFuture<androidx.javascriptengine.JsSandbox!> createConnectedInstanceAsync(android.content.Context);
-    method public androidx.javascriptengine.JsIsolate createIsolate();
+    method public static com.google.common.util.concurrent.ListenableFuture<androidx.javascriptengine.JavaScriptSandbox!> createConnectedInstanceAsync(android.content.Context);
+    method public androidx.javascriptengine.JavaScriptIsolate createIsolate();
+    method public androidx.javascriptengine.JavaScriptIsolate createIsolate(androidx.javascriptengine.IsolateStartupParameters);
     method public boolean isFeatureSupported(String);
+    field public static final String JS_FEATURE_ISOLATE_MAX_HEAP_SIZE = "JS_FEATURE_ISOLATE_MAX_HEAP_SIZE";
     field public static final String JS_FEATURE_ISOLATE_TERMINATION = "JS_FEATURE_ISOLATE_TERMINATION";
     field public static final String JS_FEATURE_PROMISE_RETURN = "JS_FEATURE_PROMISE_RETURN";
     field public static final String JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER = "JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER";
     field public static final String JS_FEATURE_WASM_COMPILATION = "JS_FEATURE_WASM_COMPILATION";
   }
 
-  public class SandboxDeadException extends androidx.javascriptengine.JsException {
+  public final class SandboxDeadException extends androidx.javascriptengine.JavaScriptException {
     ctor public SandboxDeadException();
   }
 
diff --git a/javascriptengine/javascriptengine/api/public_plus_experimental_current.txt b/javascriptengine/javascriptengine/api/public_plus_experimental_current.txt
index 782c21f..e808cea 100644
--- a/javascriptengine/javascriptengine/api/public_plus_experimental_current.txt
+++ b/javascriptengine/javascriptengine/api/public_plus_experimental_current.txt
@@ -1,37 +1,46 @@
 // Signature format: 4.0
 package androidx.javascriptengine {
 
-  public class EvaluationFailedException extends androidx.javascriptengine.JsException {
+  public final class EvaluationFailedException extends androidx.javascriptengine.JavaScriptException {
     ctor public EvaluationFailedException(String);
   }
 
-  public class IsolateTerminatedException extends androidx.javascriptengine.JsException {
+  public final class IsolateStartupParameters {
+    ctor public IsolateStartupParameters();
+    method @IntRange(from=0) public long getMaxHeapSizeBytes();
+    method @RequiresFeature(name=androidx.javascriptengine.JavaScriptSandbox.JS_FEATURE_ISOLATE_MAX_HEAP_SIZE, enforcement="androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported") public void setMaxHeapSizeBytes(@IntRange(from=0) long);
+    field public static final long DEFAULT_ISOLATE_HEAP_SIZE = 0L; // 0x0L
+  }
+
+  public final class IsolateTerminatedException extends androidx.javascriptengine.JavaScriptException {
     ctor public IsolateTerminatedException();
   }
 
-  public class JsException extends java.lang.Exception {
-    ctor public JsException(String);
-    ctor public JsException();
+  public class JavaScriptException extends java.lang.Exception {
+    ctor public JavaScriptException(String);
+    ctor public JavaScriptException();
   }
 
-  public class JsIsolate implements java.lang.AutoCloseable {
+  public final class JavaScriptIsolate implements java.lang.AutoCloseable {
     method public void close();
-    method public com.google.common.util.concurrent.ListenableFuture<java.lang.String!> evaluateJavaScriptAsync(String);
-    method @RequiresFeature(name=androidx.javascriptengine.JsSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER, enforcement="androidx.javascriptengine.JsSandbox#isFeatureSupported") public boolean provideNamedData(String, byte[]);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.String!> evaluateJavaScriptAsync(@org.intellij.lang.annotations.Language("javascript") String);
+    method @RequiresFeature(name=androidx.javascriptengine.JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER, enforcement="androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported") public boolean provideNamedData(String, byte[]);
   }
 
-  public class JsSandbox implements java.lang.AutoCloseable {
+  public final class JavaScriptSandbox implements java.lang.AutoCloseable {
     method public void close();
-    method public static com.google.common.util.concurrent.ListenableFuture<androidx.javascriptengine.JsSandbox!> createConnectedInstanceAsync(android.content.Context);
-    method public androidx.javascriptengine.JsIsolate createIsolate();
+    method public static com.google.common.util.concurrent.ListenableFuture<androidx.javascriptengine.JavaScriptSandbox!> createConnectedInstanceAsync(android.content.Context);
+    method public androidx.javascriptengine.JavaScriptIsolate createIsolate();
+    method public androidx.javascriptengine.JavaScriptIsolate createIsolate(androidx.javascriptengine.IsolateStartupParameters);
     method public boolean isFeatureSupported(String);
+    field public static final String JS_FEATURE_ISOLATE_MAX_HEAP_SIZE = "JS_FEATURE_ISOLATE_MAX_HEAP_SIZE";
     field public static final String JS_FEATURE_ISOLATE_TERMINATION = "JS_FEATURE_ISOLATE_TERMINATION";
     field public static final String JS_FEATURE_PROMISE_RETURN = "JS_FEATURE_PROMISE_RETURN";
     field public static final String JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER = "JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER";
     field public static final String JS_FEATURE_WASM_COMPILATION = "JS_FEATURE_WASM_COMPILATION";
   }
 
-  public class SandboxDeadException extends androidx.javascriptengine.JsException {
+  public final class SandboxDeadException extends androidx.javascriptengine.JavaScriptException {
     ctor public SandboxDeadException();
   }
 
diff --git a/javascriptengine/javascriptengine/api/restricted_current.txt b/javascriptengine/javascriptengine/api/restricted_current.txt
index 782c21f..e808cea 100644
--- a/javascriptengine/javascriptengine/api/restricted_current.txt
+++ b/javascriptengine/javascriptengine/api/restricted_current.txt
@@ -1,37 +1,46 @@
 // Signature format: 4.0
 package androidx.javascriptengine {
 
-  public class EvaluationFailedException extends androidx.javascriptengine.JsException {
+  public final class EvaluationFailedException extends androidx.javascriptengine.JavaScriptException {
     ctor public EvaluationFailedException(String);
   }
 
-  public class IsolateTerminatedException extends androidx.javascriptengine.JsException {
+  public final class IsolateStartupParameters {
+    ctor public IsolateStartupParameters();
+    method @IntRange(from=0) public long getMaxHeapSizeBytes();
+    method @RequiresFeature(name=androidx.javascriptengine.JavaScriptSandbox.JS_FEATURE_ISOLATE_MAX_HEAP_SIZE, enforcement="androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported") public void setMaxHeapSizeBytes(@IntRange(from=0) long);
+    field public static final long DEFAULT_ISOLATE_HEAP_SIZE = 0L; // 0x0L
+  }
+
+  public final class IsolateTerminatedException extends androidx.javascriptengine.JavaScriptException {
     ctor public IsolateTerminatedException();
   }
 
-  public class JsException extends java.lang.Exception {
-    ctor public JsException(String);
-    ctor public JsException();
+  public class JavaScriptException extends java.lang.Exception {
+    ctor public JavaScriptException(String);
+    ctor public JavaScriptException();
   }
 
-  public class JsIsolate implements java.lang.AutoCloseable {
+  public final class JavaScriptIsolate implements java.lang.AutoCloseable {
     method public void close();
-    method public com.google.common.util.concurrent.ListenableFuture<java.lang.String!> evaluateJavaScriptAsync(String);
-    method @RequiresFeature(name=androidx.javascriptengine.JsSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER, enforcement="androidx.javascriptengine.JsSandbox#isFeatureSupported") public boolean provideNamedData(String, byte[]);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.String!> evaluateJavaScriptAsync(@org.intellij.lang.annotations.Language("javascript") String);
+    method @RequiresFeature(name=androidx.javascriptengine.JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER, enforcement="androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported") public boolean provideNamedData(String, byte[]);
   }
 
-  public class JsSandbox implements java.lang.AutoCloseable {
+  public final class JavaScriptSandbox implements java.lang.AutoCloseable {
     method public void close();
-    method public static com.google.common.util.concurrent.ListenableFuture<androidx.javascriptengine.JsSandbox!> createConnectedInstanceAsync(android.content.Context);
-    method public androidx.javascriptengine.JsIsolate createIsolate();
+    method public static com.google.common.util.concurrent.ListenableFuture<androidx.javascriptengine.JavaScriptSandbox!> createConnectedInstanceAsync(android.content.Context);
+    method public androidx.javascriptengine.JavaScriptIsolate createIsolate();
+    method public androidx.javascriptengine.JavaScriptIsolate createIsolate(androidx.javascriptengine.IsolateStartupParameters);
     method public boolean isFeatureSupported(String);
+    field public static final String JS_FEATURE_ISOLATE_MAX_HEAP_SIZE = "JS_FEATURE_ISOLATE_MAX_HEAP_SIZE";
     field public static final String JS_FEATURE_ISOLATE_TERMINATION = "JS_FEATURE_ISOLATE_TERMINATION";
     field public static final String JS_FEATURE_PROMISE_RETURN = "JS_FEATURE_PROMISE_RETURN";
     field public static final String JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER = "JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER";
     field public static final String JS_FEATURE_WASM_COMPILATION = "JS_FEATURE_WASM_COMPILATION";
   }
 
-  public class SandboxDeadException extends androidx.javascriptengine.JsException {
+  public final class SandboxDeadException extends androidx.javascriptengine.JavaScriptException {
     ctor public SandboxDeadException();
   }
 
diff --git a/javascriptengine/javascriptengine/build.gradle b/javascriptengine/javascriptengine/build.gradle
index ed63ae3..eae553f 100644
--- a/javascriptengine/javascriptengine/build.gradle
+++ b/javascriptengine/javascriptengine/build.gradle
@@ -25,6 +25,7 @@
     api("androidx.annotation:annotation:1.3.0")
     api("androidx.concurrent:concurrent-futures:1.0.0")
     api("androidx.core:core:1.1.0")
+    implementation("org.jetbrains:annotations:13.0")
     implementation(libs.guavaAndroid)
     androidTestImplementation 'junit:junit:4.12'
     annotationProcessor(libs.nullaway)
diff --git a/javascriptengine/javascriptengine/src/androidTest/java/androidx/javascriptengine/WebViewJsSandboxTest.java b/javascriptengine/javascriptengine/src/androidTest/java/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java
similarity index 65%
rename from javascriptengine/javascriptengine/src/androidTest/java/androidx/javascriptengine/WebViewJsSandboxTest.java
rename to javascriptengine/javascriptengine/src/androidTest/java/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java
index 195bd05..491edec 100644
--- a/javascriptengine/javascriptengine/src/androidTest/java/androidx/javascriptengine/WebViewJsSandboxTest.java
+++ b/javascriptengine/javascriptengine/src/androidTest/java/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java
@@ -37,12 +37,12 @@
 
 /** Instrumentation test for JsSandboxService. */
 @RunWith(AndroidJUnit4.class)
-public class WebViewJsSandboxTest {
+public class WebViewJavaScriptSandboxTest {
     private boolean canCreateJsSandbox() throws Throwable {
         Context context = ApplicationProvider.getApplicationContext();
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox;
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox;
         try {
             jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
         } catch (ExecutionException e) {
@@ -66,10 +66,10 @@
         final String expected = "PASS";
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-        JsIsolate jsIsolate = jsSandbox.createIsolate();
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+        JavaScriptIsolate jsIsolate = jsSandbox.createIsolate();
         ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code);
         String result = resultFuture.get(5, TimeUnit.SECONDS);
         jsIsolate.close();
@@ -85,11 +85,11 @@
         final String expected = "PASS";
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-        JsIsolate jsIsolate1 = jsSandbox.createIsolate();
-        JsIsolate jsIsolate2 = jsSandbox.createIsolate();
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+        JavaScriptIsolate jsIsolate1 = jsSandbox.createIsolate();
+        JavaScriptIsolate jsIsolate2 = jsSandbox.createIsolate();
         jsIsolate1.close();
         ListenableFuture<String> resultFuture = jsIsolate2.evaluateJavaScriptAsync(code);
         String result = resultFuture.get(5, TimeUnit.SECONDS);
@@ -109,13 +109,13 @@
 
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-        JsIsolate jsIsolate1 = jsSandbox.createIsolate();
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+        JavaScriptIsolate jsIsolate1 = jsSandbox.createIsolate();
         ListenableFuture<String> resultFuture1 = jsIsolate1.evaluateJavaScriptAsync(code1);
         String result1 = resultFuture1.get(5, TimeUnit.SECONDS);
-        JsIsolate jsIsolate2 = jsSandbox.createIsolate();
+        JavaScriptIsolate jsIsolate2 = jsSandbox.createIsolate();
         ListenableFuture<String> resultFuture2 = jsIsolate2.evaluateJavaScriptAsync(code2);
         String result2 = resultFuture2.get(5, TimeUnit.SECONDS);
         jsIsolate1.close();
@@ -135,13 +135,13 @@
         final String expected2 = "undefined PASS";
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-        JsIsolate jsIsolate1 = jsSandbox.createIsolate();
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+        JavaScriptIsolate jsIsolate1 = jsSandbox.createIsolate();
         ListenableFuture<String> resultFuture1 = jsIsolate1.evaluateJavaScriptAsync(code1);
         String result1 = resultFuture1.get(5, TimeUnit.SECONDS);
-        JsIsolate jsIsolate2 = jsSandbox.createIsolate();
+        JavaScriptIsolate jsIsolate2 = jsSandbox.createIsolate();
         ListenableFuture<String> resultFuture2 = jsIsolate2.evaluateJavaScriptAsync(code2);
         String result2 = resultFuture2.get(5, TimeUnit.SECONDS);
         jsIsolate1.close();
@@ -161,10 +161,10 @@
         final String expected2 = "PASS PASS";
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-        JsIsolate jsIsolate1 = jsSandbox.createIsolate();
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+        JavaScriptIsolate jsIsolate1 = jsSandbox.createIsolate();
         ListenableFuture<String> resultFuture1 = jsIsolate1.evaluateJavaScriptAsync(code1);
         String result1 = resultFuture1.get(5, TimeUnit.SECONDS);
         ListenableFuture<String> resultFuture2 = jsIsolate1.evaluateJavaScriptAsync(code2);
@@ -183,10 +183,10 @@
         final String contains = "RandomLinkError";
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-        JsIsolate jsIsolate = jsSandbox.createIsolate();
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+        JavaScriptIsolate jsIsolate = jsSandbox.createIsolate();
         ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code);
         boolean isOfCorrectType = false;
         String error = "";
@@ -209,12 +209,13 @@
         final String code = "while(true){}";
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-        Assume.assumeTrue(jsSandbox.isFeatureSupported(JsSandbox.JS_FEATURE_ISOLATE_TERMINATION));
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+        Assume.assumeTrue(
+                jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_ISOLATE_TERMINATION));
 
-        JsIsolate jsIsolate = jsSandbox.createIsolate();
+        JavaScriptIsolate jsIsolate = jsSandbox.createIsolate();
         ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code);
         boolean isOfCorrectType = false;
         try {
@@ -235,12 +236,13 @@
         final int num_of_evaluations = 10;
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-        Assume.assumeTrue(jsSandbox.isFeatureSupported(JsSandbox.JS_FEATURE_ISOLATE_TERMINATION));
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+        Assume.assumeTrue(
+                jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_ISOLATE_TERMINATION));
 
-        JsIsolate jsIsolate = jsSandbox.createIsolate();
+        JavaScriptIsolate jsIsolate = jsSandbox.createIsolate();
         Vector<ListenableFuture<String>> resultFutures = new Vector<ListenableFuture<String>>();
         for (int i = 0; i < num_of_evaluations; i++) {
             ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code);
@@ -273,14 +275,15 @@
                 + " return ab2str(value);"
                 + "});";
         Context context = ApplicationProvider.getApplicationContext();
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        try (JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-             JsIsolate jsIsolate = jsSandbox.createIsolate()) {
-            Assume.assumeTrue(jsSandbox.isFeatureSupported(JsSandbox.JS_FEATURE_PROMISE_RETURN));
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        try (JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+             JavaScriptIsolate jsIsolate = jsSandbox.createIsolate()) {
+            Assume.assumeTrue(
+                    jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN));
             Assume.assumeTrue(
                     jsSandbox.isFeatureSupported(
-                            JsSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER));
+                            JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER));
 
             boolean provideNamedDataReturn = jsIsolate.provideNamedData("id-1", bytes);
             Assert.assertTrue(provideNamedDataReturn);
@@ -304,15 +307,17 @@
                 + "  });"
                 + "});";
         Context context = ApplicationProvider.getApplicationContext();
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        try (JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-             JsIsolate jsIsolate = jsSandbox.createIsolate()) {
-            Assume.assumeTrue(jsSandbox.isFeatureSupported(JsSandbox.JS_FEATURE_PROMISE_RETURN));
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        try (JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+             JavaScriptIsolate jsIsolate = jsSandbox.createIsolate()) {
+            Assume.assumeTrue(
+                    jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN));
             Assume.assumeTrue(
                     jsSandbox.isFeatureSupported(
-                            JsSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER));
-            Assume.assumeTrue(jsSandbox.isFeatureSupported(JsSandbox.JS_FEATURE_WASM_COMPILATION));
+                            JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER));
+            Assume.assumeTrue(
+                    jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_WASM_COMPILATION));
 
             boolean provideNamedDataReturn = jsIsolate.provideNamedData("id-1", bytes);
             Assert.assertTrue(provideNamedDataReturn);
@@ -329,11 +334,12 @@
         final String code = "Promise.resolve(\"PASS\")";
         final String expected = "PASS";
         Context context = ApplicationProvider.getApplicationContext();
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        try (JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-             JsIsolate jsIsolate = jsSandbox.createIsolate()) {
-            Assume.assumeTrue(jsSandbox.isFeatureSupported(JsSandbox.JS_FEATURE_PROMISE_RETURN));
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        try (JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+             JavaScriptIsolate jsIsolate = jsSandbox.createIsolate()) {
+            Assume.assumeTrue(
+                    jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN));
 
             ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code);
             String result = resultFuture.get(5, TimeUnit.SECONDS);
@@ -354,11 +360,12 @@
         final String expected = "PASS";
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        try (JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-             JsIsolate jsIsolate = jsSandbox.createIsolate()) {
-            Assume.assumeTrue(jsSandbox.isFeatureSupported(JsSandbox.JS_FEATURE_PROMISE_RETURN));
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        try (JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+             JavaScriptIsolate jsIsolate = jsSandbox.createIsolate()) {
+            Assume.assumeTrue(
+                    jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN));
 
             ListenableFuture<String> resultFuture1 = jsIsolate.evaluateJavaScriptAsync(code1);
             ListenableFuture<String> resultFuture2 = jsIsolate.evaluateJavaScriptAsync(code2);
@@ -389,13 +396,14 @@
                 + " });"
                 + "});";
         Context context = ApplicationProvider.getApplicationContext();
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        try (JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-             JsIsolate jsIsolate = jsSandbox.createIsolate()) {
-            Assume.assumeTrue(jsSandbox.isFeatureSupported(JsSandbox.JS_FEATURE_PROMISE_RETURN));
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        try (JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+             JavaScriptIsolate jsIsolate = jsSandbox.createIsolate()) {
+            Assume.assumeTrue(
+                    jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN));
             Assume.assumeTrue(jsSandbox.isFeatureSupported(
-                    JsSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER));
+                    JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER));
 
             jsIsolate.provideNamedData("id-1", bytes);
             jsIsolate.provideNamedData("id-2", bytes);
@@ -422,13 +430,14 @@
         final String contains = "RandomLinkError";
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        try (JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-             JsIsolate jsIsolate = jsSandbox.createIsolate()) {
-            Assume.assumeTrue(jsSandbox.isFeatureSupported(JsSandbox.JS_FEATURE_PROMISE_RETURN));
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        try (JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+             JavaScriptIsolate jsIsolate = jsSandbox.createIsolate()) {
+            Assume.assumeTrue(
+                    jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN));
             Assume.assumeTrue(jsSandbox.isFeatureSupported(
-                    JsSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER));
+                    JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER));
 
             ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code);
             try {
@@ -449,10 +458,10 @@
         final String code = "while(true){}";
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
-        JsIsolate jsIsolate = jsSandbox.createIsolate();
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS);
+        JavaScriptIsolate jsIsolate = jsSandbox.createIsolate();
         ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code);
         try {
             jsSandbox.close();
@@ -470,13 +479,13 @@
     public void testMultipleSandboxesCannotCoexist() throws Throwable {
         Context context = ApplicationProvider.getApplicationContext();
         final String contains = "already bound";
-        ListenableFuture<JsSandbox> JsSandboxFuture1 =
-                JsSandbox.createConnectedInstanceAsync(context);
-        try (JsSandbox jsSandbox1 = JsSandboxFuture1.get(5, TimeUnit.SECONDS)) {
-            ListenableFuture<JsSandbox> JsSandboxFuture2 =
-                    JsSandbox.createConnectedInstanceAsync(context);
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture1 =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        try (JavaScriptSandbox jsSandbox1 = JsSandboxFuture1.get(5, TimeUnit.SECONDS)) {
+            ListenableFuture<JavaScriptSandbox> JsSandboxFuture2 =
+                    JavaScriptSandbox.createConnectedInstanceAsync(context);
             try {
-                JsSandbox jsSandbox2 = JsSandboxFuture2.get(5, TimeUnit.SECONDS);
+                JavaScriptSandbox jsSandbox2 = JsSandboxFuture2.get(5, TimeUnit.SECONDS);
                 Assert.fail("Should have thrown.");
             } catch (ExecutionException e) {
                 if (!(e.getCause() instanceof RuntimeException)) {
@@ -494,18 +503,46 @@
         final String expected = "PASS";
         Context context = ApplicationProvider.getApplicationContext();
 
-        ListenableFuture<JsSandbox> JsSandboxFuture1 =
-                JsSandbox.createConnectedInstanceAsync(context);
-        JsSandbox jsSandbox1 = JsSandboxFuture1.get(5, TimeUnit.SECONDS);
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture1 =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        JavaScriptSandbox jsSandbox1 = JsSandboxFuture1.get(5, TimeUnit.SECONDS);
         jsSandbox1.close();
-        ListenableFuture<JsSandbox> JsSandboxFuture2 =
-                JsSandbox.createConnectedInstanceAsync(context);
-        try (JsSandbox jsSandbox2 = JsSandboxFuture2.get(5, TimeUnit.SECONDS);
-             JsIsolate jsIsolate = jsSandbox2.createIsolate()) {
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture2 =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        try (JavaScriptSandbox jsSandbox2 = JsSandboxFuture2.get(5, TimeUnit.SECONDS);
+             JavaScriptIsolate jsIsolate = jsSandbox2.createIsolate()) {
             ListenableFuture<String> resultFuture1 = jsIsolate.evaluateJavaScriptAsync(code);
             String result = resultFuture1.get(5, TimeUnit.SECONDS);
 
             Assert.assertEquals(expected, result);
         }
     }
+
+    @Test
+    @MediumTest
+    public void testHeapSize() throws Throwable {
+        final String code = "const buffer = new ArrayBuffer(500000000);"
+                + "\"PASS\"";
+        Context context = ApplicationProvider.getApplicationContext();
+        ListenableFuture<JavaScriptSandbox> JsSandboxFuture =
+                JavaScriptSandbox.createConnectedInstanceAsync(context);
+        try (JavaScriptSandbox jsSandbox = JsSandboxFuture.get(5, TimeUnit.SECONDS)) {
+            Assume.assumeTrue(
+                    jsSandbox.isFeatureSupported(
+                            JavaScriptSandbox.JS_FEATURE_ISOLATE_MAX_HEAP_SIZE));
+            IsolateStartupParameters isolateStartupParameters = new IsolateStartupParameters();
+            isolateStartupParameters.setMaxHeapSizeBytes(10000);
+            try (JavaScriptIsolate jsIsolate = jsSandbox.createIsolate(isolateStartupParameters)) {
+                ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code);
+                try {
+                    resultFuture.get(5, TimeUnit.SECONDS);
+                    Assert.fail("Should have thrown.");
+                } catch (ExecutionException e) {
+                    if (!(e.getCause() instanceof SandboxDeadException)) {
+                        throw e;
+                    }
+                }
+            }
+        }
+    }
 }
diff --git a/javascriptengine/javascriptengine/src/main/aidl/org/chromium/android_webview/js_sandbox/common/IJsSandboxService.aidl b/javascriptengine/javascriptengine/src/main/aidl/org/chromium/android_webview/js_sandbox/common/IJsSandboxService.aidl
index 55f34a8..157b4cc 100644
--- a/javascriptengine/javascriptengine/src/main/aidl/org/chromium/android_webview/js_sandbox/common/IJsSandboxService.aidl
+++ b/javascriptengine/javascriptengine/src/main/aidl/org/chromium/android_webview/js_sandbox/common/IJsSandboxService.aidl
@@ -42,8 +42,12 @@
      */
     const String WASM_FROM_ARRAY_BUFFER = "WASM_FROM_ARRAY_BUFFER";
 
+    const String ISOLATE_MAX_HEAP_SIZE_LIMIT = "ISOLATE_MAX_HEAP_SIZE_LIMIT";
+
     /**
      * @return A list of feature names supported by this implementation.
      */
     List<String> getSupportedFeatures() = 1;
+
+    IJsSandboxIsolate createIsolateWithMaxHeapSizeBytes(long maxHeapSize) = 2;
 }
diff --git a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/EvaluationFailedException.java b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/EvaluationFailedException.java
index 179cac9..b42738c 100644
--- a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/EvaluationFailedException.java
+++ b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/EvaluationFailedException.java
@@ -19,7 +19,7 @@
 import androidx.annotation.NonNull;
 
 /** Wrapper for the exception thrown by the JS evaluation engine. */
-public class EvaluationFailedException extends JsException {
+public final class EvaluationFailedException extends JavaScriptException {
     public EvaluationFailedException(@NonNull String error) {
         super(error);
     }
diff --git a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/IsolateStartupParameters.java b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/IsolateStartupParameters.java
new file mode 100644
index 0000000..5e13f74
--- /dev/null
+++ b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/IsolateStartupParameters.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.javascriptengine;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.RequiresFeature;
+
+/**
+ * Class used to set startup parameters for {@link JavaScriptIsolate}.
+ */
+public final class IsolateStartupParameters {
+    private long mMaxHeapSizeBytes;
+    public static final long DEFAULT_ISOLATE_HEAP_SIZE = 0;
+    public IsolateStartupParameters(){};
+
+    /**
+     * Sets the max heap size used by the {@link JavaScriptIsolate}.
+     *
+     * A heap size of {@link IsolateStartupParameters#DEFAULT_ISOLATE_HEAP_SIZE} indicates no
+     * limit.
+     * <p>
+     * If a value higher than the device specific maximum heap size limit is supplied, this limit
+     * will be used as the maximum heap size.
+     *
+     * @param size heap size in bytes
+     */
+    @RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_ISOLATE_MAX_HEAP_SIZE,
+            enforcement =
+                    "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
+    public void setMaxHeapSizeBytes(@IntRange(from = 0) long size) {
+        if (size < 0) {
+            throw new IllegalArgumentException("maxHeapSizeBytes should be >= 0");
+        }
+        mMaxHeapSizeBytes = size;
+    }
+
+    /**
+     * Gets the max heap size used by the {@link JavaScriptIsolate}.
+     *
+     * If not set using {@link IsolateStartupParameters#setMaxHeapSizeBytes(long)}, the default
+     * value is {@link IsolateStartupParameters#DEFAULT_ISOLATE_HEAP_SIZE} which indicates no heap
+     * size limit.
+     *
+     * @return heap size in bytes
+     */
+    public @IntRange(from = 0) long getMaxHeapSizeBytes() {
+        return mMaxHeapSizeBytes;
+    }
+}
diff --git a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/IsolateTerminatedException.java b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/IsolateTerminatedException.java
index 8c4b514..56e6fb8 100644
--- a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/IsolateTerminatedException.java
+++ b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/IsolateTerminatedException.java
@@ -17,9 +17,10 @@
 package androidx.javascriptengine;
 
 /**
- * Exception thrown when evaluation is terminated due the {@link JsIsolate} being terminated.
+ * Exception thrown when evaluation is terminated due to {@link JavaScriptIsolate} being
+ * closed. This can occur when the {@link JavaScriptIsolate#close()} is called.
  */
-public class IsolateTerminatedException extends JsException {
+public final class IsolateTerminatedException extends JavaScriptException {
     public IsolateTerminatedException() {
         super();
     }
diff --git a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JsException.java b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptException.java
similarity index 74%
rename from javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JsException.java
rename to javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptException.java
index 0d3f38f..da93785 100644
--- a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JsException.java
+++ b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptException.java
@@ -19,14 +19,15 @@
 import androidx.annotation.NonNull;
 
 /**
- * Super class for all exceptions resolved by {@link JsIsolate#evaluateJavaScriptAsync(String)}.
+ * Super class for all exceptions resolved by
+ * {@link JavaScriptIsolate#evaluateJavaScriptAsync(String)}.
  */
-public class JsException extends Exception {
-    public JsException(@NonNull String error) {
+public class JavaScriptException extends Exception {
+    public JavaScriptException(@NonNull String error) {
         super(error);
     }
 
-    public JsException() {
+    public JavaScriptException() {
         super();
     }
 }
diff --git a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JsIsolate.java b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptIsolate.java
similarity index 81%
rename from javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JsIsolate.java
rename to javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptIsolate.java
index 4e5fb80..3797ad2 100644
--- a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JsIsolate.java
+++ b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptIsolate.java
@@ -30,6 +30,7 @@
 
 import org.chromium.android_webview.js_sandbox.common.IJsSandboxIsolate;
 import org.chromium.android_webview.js_sandbox.common.IJsSandboxIsolateCallback;
+import org.intellij.lang.annotations.Language;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -43,22 +44,23 @@
 import javax.annotation.concurrent.GuardedBy;
 
 /**
- * Environment within a {@link JsSandbox} where Javascript is executed.
+ * Environment within a {@link JavaScriptSandbox} where Javascript is executed.
  *
- * A single {@link JsSandbox} process can contain any number of {@link JsIsolate} instances where JS
- * can be evaluated independently and in parallel.
+ * A single {@link JavaScriptSandbox} process can contain any number of {@link JavaScriptIsolate}
+ * instances where JS can be evaluated independently and in parallel.
  * <p>
  * Each isolate has its own state and JS global object,
  * and cannot interact with any other isolate through JS APIs. There is only a <em>moderate</em>
- * security boundary between isolates in a single {@link JsSandbox}. If the code in one {@link
- * JsIsolate} is able to compromise the security of the JS engine then it may be able to observe or
- * manipulate other isolates, since they run in the same process. For strong isolation multiple
- * {@link JsSandbox} processes should be used, but it is not supported at the moment.
+ * security boundary between isolates in a single {@link JavaScriptSandbox}. If the code in one
+ * {@link JavaScriptIsolate} is able to compromise the security of the JS engine then it may be
+ * able to observe or manipulate other isolates, since they run in the same process. For strong
+ * isolation multiple {@link JavaScriptSandbox} processes should be used, but it is not supported
+ * at the moment. Please find the feature request <a href="https://crbug.com/1349860">here</a>.
  * <p>
  * Each isolate object must only be used from one thread.
  */
-public class JsIsolate implements AutoCloseable {
-    private static final String TAG = "JsIsolate";
+public final class JavaScriptIsolate implements AutoCloseable {
+    private static final String TAG = "JavaScriptIsolate";
     private final Object mSetLock = new Object();
     @Nullable
     private IJsSandboxIsolate mJsIsolateStub;
@@ -69,10 +71,11 @@
 
                 @Override
                 public Thread newThread(Runnable r) {
-                    return new Thread(r, "JsIsolate Thread #" + mCount.getAndIncrement());
+                    return new Thread(
+                            r, "JavaScriptIsolate Thread #" + mCount.getAndIncrement());
                 }
             });
-    private final JsSandbox mJsSandbox;
+    private final JavaScriptSandbox mJsSandbox;
 
     @Nullable
     @GuardedBy("mSetLock")
@@ -100,7 +103,7 @@
         }
     }
 
-    JsIsolate(IJsSandboxIsolate jsIsolateStub, JsSandbox sandbox) {
+    JavaScriptIsolate(IJsSandboxIsolate jsIsolateStub, JavaScriptSandbox sandbox) {
         mJsSandbox = sandbox;
         mJsIsolateStub = jsIsolateStub;
         mGuard.open("close");
@@ -115,10 +118,10 @@
      *   <li><strong>If the JS expression returns a JS String</strong>, then the Java Future
      * resolves to Java String.</li>
      *   <li><strong>If the JS expression returns a JS Promise</strong>,
-     * and if {@link JsSandbox#isFeatureSupported(String)} for
-     * {@link JsSandbox#JS_FEATURE_PROMISE_RETURN} returns {@code true}, Java Future resolves to
-     * Java String once the promise resolves. If it returns {@code false}, then the Future
-     * resolves to an empty string.</li>
+     * and if {@link JavaScriptSandbox#isFeatureSupported(String)} for
+     * {@link JavaScriptSandbox#JS_FEATURE_PROMISE_RETURN} returns {@code true}, Java Future
+     * resolves to Java String once the promise resolves. If it returns {@code false}, then the
+     * Future resolves to an empty string.</li>
      *   <li><strong>If the JS expression returns another data type</strong>, then Java Future
      * resolves to empty Java String.</li>
      * </ul>
@@ -134,14 +137,16 @@
      * transaction limit. Refer {@link android.os.TransactionTooLargeException} for more details.
      *
      * @param code JavaScript code that is evaluated, it should return a JavaScript String or a
-     *         Promise of a String in case {@link JsSandbox#JS_FEATURE_PROMISE_RETURN} is supported
+     *         Promise of a String in case {@link JavaScriptSandbox#JS_FEATURE_PROMISE_RETURN} is
+     *             supported
      *
      * @return Future that evaluates to the result String of the evaluation or exceptions({@link
      *         IsolateTerminatedException}, {@link SandboxDeadException}) if there is an error
      */
     @SuppressWarnings("NullAway")
     @NonNull
-    public ListenableFuture<String> evaluateJavaScriptAsync(@NonNull String code) {
+    public ListenableFuture<String> evaluateJavaScriptAsync(
+            @NonNull @Language("javascript") String code) {
         if (mJsIsolateStub == null) {
             throw new IllegalStateException(
                     "Calling evaluateJavascript() after closing the Isolate");
@@ -173,13 +178,13 @@
     }
 
     /**
-     * Closes the {@link JsIsolate} object and renders it unusable.
+     * Closes the {@link JavaScriptIsolate} object and renders it unusable.
      *
      * Once closed, no more method calls should be made. Pending evaluations resolve with
      * {@link IsolateTerminatedException} immediately.
      * <p>
-     * If {@link JsSandbox#isFeatureSupported(String)} is {@code true} for {@link
-     * JsSandbox#JS_FEATURE_ISOLATE_TERMINATION}, then any pending evaluation is immediately
+     * If {@link JavaScriptSandbox#isFeatureSupported(String)} is {@code true} for {@link
+     * JavaScriptSandbox#JS_FEATURE_ISOLATE_TERMINATION}, then any pending evaluation is immediately
      * terminated and memory is freed. If it is {@code false}, the isolate will not get cleaned
      * up until the pending evaluations have run to completion and will consume resources until
      * then.
@@ -212,13 +217,13 @@
      * was used when calling this method. This is a one-time transfer and the calls should be
      * paired.
      * <p>
-     * A single name can only be used once in a particular {@link JsIsolate}.
+     * A single name can only be used once in a particular {@link JavaScriptIsolate}.
      * Clients can generate unique names for each call if they
      * need to use this method multiple times. The same name should be included into the JS code.
      * <p>
      * This API can be used to pass a WASM module into the JS
-     * environment for compilation if {@link JsSandbox#isFeatureSupported(String)} returns {@code
-     * true} for {@link JsSandbox#JS_FEATURE_WASM_COMPILATION}.
+     * environment for compilation if {@link JavaScriptSandbox#isFeatureSupported(String)} returns
+     * {@code true} for {@link JavaScriptSandbox#JS_FEATURE_WASM_COMPILATION}.
      * <br>
      * In Java,
      * <pre>
@@ -237,18 +242,19 @@
      * #evaluateJavaScriptAsync(String)} and {@link #provideNamedData(String, byte[])} methods.
      * <p>
      * This method should only be called if
-     * {@link JsSandbox#isFeatureSupported(String)}
-     * returns true for {@link JsSandbox#JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER}.
+     * {@link JavaScriptSandbox#isFeatureSupported(String)}
+     * returns true for {@link JavaScriptSandbox#JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER}.
      *
      * @param name Identifier for the data that is passed, the same identifier should be used in the
      *         JavaScript environment to refer to the data
      * @param inputBytes Bytes to be passed into the JavaScript environment
      *
-     * @return {@code true} on success, {@code false} otherwise
+     * @return {@code true} on success, {@code false} if the name has already been used before,
+ *              in which case the client should use an unused name
      */
-    @RequiresFeature(name = JsSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER,
+    @RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER,
             enforcement =
-                    "androidx.javascriptengine.JsSandbox#isFeatureSupported")
+                    "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
     public boolean provideNamedData(@NonNull String name, @NonNull byte[] inputBytes) {
         if (mJsIsolateStub == null) {
             throw new IllegalStateException("Calling provideNamedData() after closing the Isolate");
diff --git a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JsSandbox.java b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptSandbox.java
similarity index 69%
rename from javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JsSandbox.java
rename to javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptSandbox.java
index aa39a9d..a756777 100644
--- a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JsSandbox.java
+++ b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/JavaScriptSandbox.java
@@ -52,9 +52,9 @@
 /**
  * Sandbox that provides APIs for JavaScript evaluation in a restricted environment.
  *
- * JsSandbox represents a connection to an isolated process. The isolated process is exclusive
- * to the calling app (i.e. it doesn't share anything with, and can't be compromised by another
- * app's isolated process).
+ * JavaScriptSandbox represents a connection to an isolated process. The isolated process is
+ * exclusive to the calling app (i.e. it doesn't share anything with, and can't be compromised by
+ * another app's isolated process).
  * <p>
  * Code that is run in a sandbox does not have any access to data
  * belonging to the original app unless explicitly passed into it by using the methods of this
@@ -64,17 +64,18 @@
  * The calling app can only have only one isolated process at a time, so only one
  * instance of this object can exist at a time.
  * <p>
- * It's safe to share a single {@link JsSandbox}
+ * It's safe to share a single {@link JavaScriptSandbox}
  * object with multiple threads and use it from multiple threads at once.
- * For example, {@link JsSandbox} can be stored at a global location and multiple threads can create
- * their own {@link JsIsolate} objects from it but the {@link JsIsolate} object cannot be shared.
+ * For example, {@link JavaScriptSandbox} can be stored at a global location and multiple threads
+ * can create their own {@link JavaScriptIsolate} objects from it but the
+ * {@link JavaScriptIsolate} object cannot be shared.
  */
-public class JsSandbox implements AutoCloseable {
+public final class JavaScriptSandbox implements AutoCloseable {
     // TODO(crbug.com/1297672): Add capability to this class to support spawning
     // different processes as needed. This might require that we have a static
     // variable in here that tracks the existing services we are connected to and
     // connect to a different one when creating a new object.
-    private static final String TAG = "JsSandbox";
+    private static final String TAG = "JavaScriptSandbox";
     private static final String JS_SANDBOX_SERVICE_NAME =
             "org.chromium.android_webview.js_sandbox.service.JsSandboxService0";
     static AtomicBoolean sIsReadyToConnect = new AtomicBoolean(true);
@@ -89,7 +90,7 @@
 
     @Nullable
     @GuardedBy("mLock")
-    private HashSet<JsIsolate> mActiveIsolateSet = new HashSet<JsIsolate>();
+    private HashSet<JavaScriptIsolate> mActiveIsolateSet = new HashSet<JavaScriptIsolate>();
 
     /**
      * @hide
@@ -110,14 +111,14 @@
      * Feature for {@link #isFeatureSupported(String)}.
      *
      * When this
-     * feature is present, {@link JsIsolate#close()} terminates the currently running JS
-     * evaluation and close the isolate. If it is absent, {@link JsIsolate#close()} cannot terminate
-     * any running or queued evaluations in the background,
-     * so the isolate continues to consume resources until they complete.
+     * feature is present, {@link JavaScriptIsolate#close()} terminates the currently running JS
+     * evaluation and close the isolate. If it is absent, {@link JavaScriptIsolate#close()} cannot
+     * terminate any running or queued evaluations in the background, so the isolate continues to
+     * consume resources until they complete.
      * <p>
-     * Irrespective of this feature, calling {@link JsSandbox#close()} terminates all
-     * {@link JsIsolate} objects (and the isolated process) immediately and all pending
-     * {@link JsIsolate#evaluateJavaScriptAsync(String)} futures resolve with {@link
+     * Irrespective of this feature, calling {@link JavaScriptSandbox#close()} terminates all
+     * {@link JavaScriptIsolate} objects (and the isolated process) immediately and all pending
+     * {@link JavaScriptIsolate#evaluateJavaScriptAsync(String)} futures resolve with {@link
      * IsolateTerminatedException}.
      */
     public static final String JS_FEATURE_ISOLATE_TERMINATION = "JS_FEATURE_ISOLATE_TERMINATION";
@@ -126,14 +127,15 @@
      * Feature for {@link #isFeatureSupported(String)}.
      *
      * When this feature is present, JS expressions may return promises. The Future returned by
-     * {@link JsIsolate#evaluateJavaScriptAsync(String)} resolves to the promise's result,
+     * {@link JavaScriptIsolate#evaluateJavaScriptAsync(String)} resolves to the promise's result,
      * once the promise resolves.
      */
     public static final String JS_FEATURE_PROMISE_RETURN = "JS_FEATURE_PROMISE_RETURN";
 
     /**
      * Feature for {@link #isFeatureSupported(String)}.
-     * When this feature is present, {@link JsIsolate#provideNamedData(String, byte[])} can be used.
+     * When this feature is present, {@link JavaScriptIsolate#provideNamedData(String, byte[])}
+     * can be used.
      * <p>
      * This also covers the JS API android.consumeNamedDataAsArrayBuffer(string).
      */
@@ -144,26 +146,35 @@
      * Feature for {@link #isFeatureSupported(String)}.
      *
      * This features provides additional behavior to {@link
-     * JsIsolate#evaluateJavaScriptAsync(String)} ()}. When this feature is present, the JS API
-     * WebAssembly.compile(ArrayBuffer) can be used.
+     * JavaScriptIsolate#evaluateJavaScriptAsync(String)} ()}. When this feature is present, the JS
+     * API WebAssembly.compile(ArrayBuffer) can be used.
      */
     public static final String JS_FEATURE_WASM_COMPILATION = "JS_FEATURE_WASM_COMPILATION";
 
+    /**
+     * Feature for {@link #isFeatureSupported(String)}.
+     *
+     * When this feature is present,
+     * {@link JavaScriptSandbox#createIsolate(IsolateStartupParameters)} can be used.
+     */
+    public static final String JS_FEATURE_ISOLATE_MAX_HEAP_SIZE =
+            "JS_FEATURE_ISOLATE_MAX_HEAP_SIZE";
+
     @Nullable
     private HashSet<String> mClientSideFeatureSet;
 
     static class ConnectionSetup implements ServiceConnection {
         @Nullable
-        private CallbackToFutureAdapter.Completer<JsSandbox> mCompleter;
+        private CallbackToFutureAdapter.Completer<JavaScriptSandbox> mCompleter;
         @Nullable
-        private JsSandbox mJsSandbox;
+        private JavaScriptSandbox mJsSandbox;
         Context mContext;
 
         @Override
         @SuppressWarnings("NullAway")
         public void onServiceConnected(ComponentName name, IBinder service) {
             IJsSandboxService jsSandboxService = IJsSandboxService.Stub.asInterface(service);
-            mJsSandbox = new JsSandbox(this, jsSandboxService);
+            mJsSandbox = new JavaScriptSandbox(this, jsSandboxService);
             mCompleter.set(mJsSandbox);
             mCompleter = null;
         }
@@ -174,17 +185,20 @@
         @Override
         public void onServiceDisconnected(ComponentName name) {
             runShutdownTasks(
-                    new RuntimeException("JsSandbox internal error: onServiceDisconnected()"));
+                    new RuntimeException(
+                            "JavaScriptSandbox internal error: onServiceDisconnected()"));
         }
 
         @Override
         public void onBindingDied(ComponentName name) {
-            runShutdownTasks(new RuntimeException("JsSandbox internal error: onBindingDead()"));
+            runShutdownTasks(
+                    new RuntimeException("JavaScriptSandbox internal error: onBindingDead()"));
         }
 
         @Override
         public void onNullBinding(ComponentName name) {
-            runShutdownTasks(new RuntimeException("JsSandbox internal error: onNullBinding()"));
+            runShutdownTasks(
+                    new RuntimeException("JavaScriptSandbox internal error: onNullBinding()"));
         }
 
         private void runShutdownTasks(Exception e) {
@@ -201,7 +215,7 @@
         }
 
         ConnectionSetup(Context context,
-                @NonNull CallbackToFutureAdapter.Completer<JsSandbox> completer) {
+                @NonNull CallbackToFutureAdapter.Completer<JavaScriptSandbox> completer) {
             mContext = context;
             mCompleter = completer;
         }
@@ -217,11 +231,11 @@
      *         application
      *     context if the connection is expected to outlive a single activity or service.
      *
-     * @return Future that evaluates to a connected {@link JsSandbox} instance or an exception if
-     *     binding to service fails.
+     * @return Future that evaluates to a connected {@link JavaScriptSandbox} instance or an
+     *         exception if binding to service fails.
      */
     @NonNull
-    public static ListenableFuture<JsSandbox> createConnectedInstanceAsync(
+    public static ListenableFuture<JavaScriptSandbox> createConnectedInstanceAsync(
             @NonNull Context context) {
         PackageInfo systemWebViewPackage = WebView.getCurrentWebViewPackage();
         ComponentName compName =
@@ -240,22 +254,22 @@
      *         application
      *     context if the connection is expected to outlive a single activity/service.
      *
-     * @return Future that evaluates to a connected {@link JsSandbox} instance or an exception if
-     *     binding to service fails.
+     * @return Future that evaluates to a connected {@link JavaScriptSandbox} instance or an
+     *         exception if binding to service fails.
      *
      * @hide
      */
     @NonNull
     @VisibleForTesting
     @RestrictTo(RestrictTo.Scope.LIBRARY)
-    public static ListenableFuture<JsSandbox> createConnectedInstanceForTestingAsync(
+    public static ListenableFuture<JavaScriptSandbox> createConnectedInstanceForTestingAsync(
             @NonNull Context context) {
         ComponentName compName = new ComponentName(context, JS_SANDBOX_SERVICE_NAME);
         int flag = Context.BIND_AUTO_CREATE;
         return bindToServiceWithCallback(context, compName, flag);
     }
 
-    @NonNull private static ListenableFuture<JsSandbox> bindToServiceWithCallback(
+    @NonNull private static ListenableFuture<JavaScriptSandbox> bindToServiceWithCallback(
             Context context, ComponentName compName, int flag) {
         Intent intent = new Intent();
         intent.setComponent(compName);
@@ -288,12 +302,13 @@
             }
 
             // Debug string.
-            return "JsSandbox Future";
+            return "JavaScriptSandbox Future";
         });
     }
 
-    // We prevent direct initializations of this class. Use JsSandbox.createConnectedInstance().
-    JsSandbox(ConnectionSetup connectionSetup, IJsSandboxService jsSandboxService) {
+    // We prevent direct initializations of this class.
+    // Use JavaScriptSandbox.createConnectedInstance().
+    JavaScriptSandbox(ConnectionSetup connectionSetup, IJsSandboxService jsSandboxService) {
         mConnection = connectionSetup;
         mJsSandboxService = jsSandboxService;
         mGuard.open("close");
@@ -301,24 +316,56 @@
     }
 
     /**
-     * Creates and returns an {@link JsIsolate} within which JS can be executed.
+     * Creates and returns an {@link JavaScriptIsolate} within which JS can be executed with default
+     * settings.
      */
     @NonNull
-    @SuppressWarnings("NullAway")
-    public JsIsolate createIsolate() {
+    public JavaScriptIsolate createIsolate() {
         synchronized (mLock) {
             if (mJsSandboxService == null) {
                 throw new IllegalStateException(
                         "Attempting to createIsolate on a service that isn't connected");
             }
+            IJsSandboxIsolate isolateStub;
             try {
-                IJsSandboxIsolate isolateStub = mJsSandboxService.createIsolate();
-                JsIsolate isolate = new JsIsolate(isolateStub, this);
-                mActiveIsolateSet.add(isolate);
-                return isolate;
+                isolateStub = mJsSandboxService.createIsolate();
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
+            return createJsIsolateLocked(isolateStub);
+        }
+    }
+
+    /**
+     * Creates and returns an {@link JavaScriptIsolate} within which JS can be executed with the
+     * specified settings.
+     *
+     * @param settings configuration used to set up the isolate
+     */
+    @NonNull
+    public JavaScriptIsolate createIsolate(@NonNull IsolateStartupParameters settings) {
+        synchronized (mLock) {
+            if (mJsSandboxService == null) {
+                throw new IllegalStateException(
+                        "Attempting to createIsolate on a service that isn't connected");
+            }
+            IJsSandboxIsolate isolateStub;
+            try {
+                if (settings.getMaxHeapSizeBytes()
+                        == IsolateStartupParameters.DEFAULT_ISOLATE_HEAP_SIZE) {
+                    isolateStub = mJsSandboxService.createIsolate();
+                } else {
+                    isolateStub = mJsSandboxService.createIsolateWithMaxHeapSizeBytes(
+                            settings.getMaxHeapSizeBytes());
+                    if (isolateStub == null) {
+                        throw new RuntimeException(
+                                "Service implementation doesn't support setting maximum heap size");
+                    }
+                }
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+            return createJsIsolateLocked(isolateStub);
         }
     }
 
@@ -340,6 +387,17 @@
             mClientSideFeatureSet.add(JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER);
             mClientSideFeatureSet.add(JS_FEATURE_WASM_COMPILATION);
         }
+        if (features.contains(IJsSandboxService.ISOLATE_MAX_HEAP_SIZE_LIMIT)) {
+            mClientSideFeatureSet.add(JS_FEATURE_ISOLATE_MAX_HEAP_SIZE);
+        }
+    }
+
+    @GuardedBy("mLock")
+    @SuppressWarnings("NullAway")
+    private JavaScriptIsolate createJsIsolateLocked(IJsSandboxIsolate isolateStub) {
+        JavaScriptIsolate isolate = new JavaScriptIsolate(isolateStub, this);
+        mActiveIsolateSet.add(isolate);
+        return isolate;
     }
 
     /**
@@ -369,7 +427,7 @@
         }
     }
 
-    void removeFromIsolateSet(JsIsolate isolate) {
+    void removeFromIsolateSet(JavaScriptIsolate isolate) {
         synchronized (mLock) {
             if (mActiveIsolateSet != null) {
                 mActiveIsolateSet.remove(isolate);
@@ -378,14 +436,15 @@
     }
 
     /**
-     * Closes the {@link JsSandbox} object and renders it unusable.
+     * Closes the {@link JavaScriptSandbox} object and renders it unusable.
      *
      * The client is expected to call this method explicitly to terminate the isolated process.
      * <p>
-     * Once closed, no more {@link JsSandbox} and {@link JsIsolate} method calls can be made.
-     * Closing terminates the isolated process immediately. All pending evaluations are
-     * immediately terminated. Once closed, the client may call {@link
-     * JsSandbox#createConnectedInstanceAsync(Context)} to create another {@link JsSandbox}.
+     * Once closed, no more {@link JavaScriptSandbox} and {@link JavaScriptIsolate} method calls
+     * can be made. Closing terminates the isolated process immediately. All pending evaluations are
+     * immediately terminated. Once closed, the client may call
+     * {@link JavaScriptSandbox#createConnectedInstanceAsync(Context)} to create another
+     * {@link JavaScriptSandbox}.
      */
     @Override
     public void close() {
@@ -409,7 +468,7 @@
 
     @GuardedBy("mLock")
     private void cancelPendingEvaluationsLocked(Exception e) {
-        for (JsIsolate ele : mActiveIsolateSet) {
+        for (JavaScriptIsolate ele : mActiveIsolateSet) {
             ele.cancelAllPendingEvaluations(e);
         }
         mActiveIsolateSet = null;
diff --git a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/SandboxDeadException.java b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/SandboxDeadException.java
index 3bed154..735d8ef 100644
--- a/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/SandboxDeadException.java
+++ b/javascriptengine/javascriptengine/src/main/java/androidx/javascriptengine/SandboxDeadException.java
@@ -17,9 +17,14 @@
 package androidx.javascriptengine;
 
 /**
- * Exception thrown when evaluation is terminated due the {@link JsSandbox} being dead.
+ * Exception thrown when evaluation is terminated due the {@link JavaScriptSandbox} being dead.
+ * This can happen when {@link JavaScriptSandbox#close()} is called or when the sandbox process
+ * is killed by the framework.
+ * <p>
+ * This is different from {@link IsolateTerminatedException} which occurs when the
+ * {@link JavaScriptIsolate} within a {@link JavaScriptSandbox} is terminated.
  */
-public class SandboxDeadException extends JsException {
+public final class SandboxDeadException extends JavaScriptException {
     public SandboxDeadException() {
         super();
     }
diff --git a/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt b/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt
index 62c2cea..7a509bc 100644
--- a/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt
+++ b/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt
@@ -91,6 +91,14 @@
             it.mavenCentral()
             it.gradlePluginPortal().content {
                 it.includeModule(
+                    "org.jetbrains.kotlinx",
+                    "kotlinx-benchmark-plugin"
+                )
+                it.includeModule(
+                    "org.jetbrains.kotlinx.benchmark",
+                    "org.jetbrains.kotlinx.benchmark.gradle.plugin"
+                )
+                it.includeModule(
                     "org.jetbrains.kotlin.plugin.serialization",
                     "org.jetbrains.kotlin.plugin.serialization.gradle.plugin"
                 )
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/InvalidationTrackerTrojan.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/InvalidationTrackerTrojan.java
index c57639a..0f2698df 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/InvalidationTrackerTrojan.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/InvalidationTrackerTrojan.java
@@ -20,8 +20,9 @@
  * Trojan class to be able to assert internal state.
  */
 public class InvalidationTrackerTrojan {
+    @SuppressWarnings("KotlinInternalInJava") // For testing
     public static int countObservers(InvalidationTracker tracker) {
-        return tracker.observerMap.size();
+        return tracker.getObserverMap$room_runtime_debug().size();
     }
 
     private InvalidationTrackerTrojan() {
diff --git a/room/room-paging/src/androidTest/kotlin/androidx/room/InvalidationTrackerExtRoomPaging.kt b/room/room-paging/src/androidTest/kotlin/androidx/room/InvalidationTrackerExtRoomPaging.kt
index 6d83c13..654a96e 100644
--- a/room/room-paging/src/androidTest/kotlin/androidx/room/InvalidationTrackerExtRoomPaging.kt
+++ b/room/room-paging/src/androidTest/kotlin/androidx/room/InvalidationTrackerExtRoomPaging.kt
@@ -20,13 +20,6 @@
 import java.util.concurrent.TimeUnit
 
 /**
- * Makes refresh runnable accessible in tests. Used for LimitOffsetPagingSource unit tests that
- * needs to block InvalidationTracker's invalidation notification
- */
-val InvalidationTracker.refreshRunnableForTest: Runnable
-    get() = this.refreshRunnable
-
-/**
  * True if invalidation tracker is pending a refresh event to get database changes.
  */
 val InvalidationTracker.pendingRefreshForTest
diff --git a/room/room-runtime/api/current.ignore b/room/room-runtime/api/current.ignore
index 8a044d9..62d9a375 100644
--- a/room/room-runtime/api/current.ignore
+++ b/room/room-runtime/api/current.ignore
@@ -1,4 +1,8 @@
 // Baseline format: 1.0
+AddedFinal: androidx.room.Room:
+    Class androidx.room.Room added 'final' qualifier
+
+
 ChangedType: androidx.room.DatabaseConfiguration#autoMigrationSpecs:
     Field androidx.room.DatabaseConfiguration.autoMigrationSpecs has changed type from java.util.List<androidx.room.migration.AutoMigrationSpec!> to java.util.List<androidx.room.migration.AutoMigrationSpec>
 ChangedType: androidx.room.DatabaseConfiguration#callbacks:
@@ -55,3 +59,7 @@
     Method androidx.room.RoomDatabase.MigrationContainer.findMigrationPath has changed return type from java.util.List<androidx.room.migration.Migration!> to java.util.List<androidx.room.migration.Migration>
 ChangedType: androidx.room.RoomDatabase.MigrationContainer#getMigrations():
     Method androidx.room.RoomDatabase.MigrationContainer.getMigrations has changed return type from java.util.Map<java.lang.Integer!,java.util.Map<java.lang.Integer!,androidx.room.migration.Migration!>!> to java.util.Map<java.lang.Integer,java.util.Map<java.lang.Integer,androidx.room.migration.Migration>>
+
+
+RemovedDeprecatedMethod: androidx.room.Room#Room():
+    Removed deprecated constructor androidx.room.Room()
diff --git a/room/room-runtime/api/current.txt b/room/room-runtime/api/current.txt
index de130d6..0c4e5aa 100644
--- a/room/room-runtime/api/current.txt
+++ b/room/room-runtime/api/current.txt
@@ -40,19 +40,13 @@
     method public abstract void onInvalidated(java.util.Set<java.lang.String> tables);
   }
 
-  public class Room {
-    ctor @Deprecated public Room();
-    method public static final <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> databaseBuilder(android.content.Context context, Class<T> klass, String? name);
-    method public static final <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> inMemoryDatabaseBuilder(android.content.Context context, Class<T> klass);
-    field public static final androidx.room.Room.Companion Companion;
+  public final class Room {
+    method public static <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> databaseBuilder(android.content.Context context, Class<T> klass, String? name);
+    method public static <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> inMemoryDatabaseBuilder(android.content.Context context, Class<T> klass);
+    field public static final androidx.room.Room INSTANCE;
     field public static final String MASTER_TABLE_NAME = "room_master_table";
   }
 
-  public static final class Room.Companion {
-    method public <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> databaseBuilder(android.content.Context context, Class<T> klass, String? name);
-    method public <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> inMemoryDatabaseBuilder(android.content.Context context, Class<T> klass);
-  }
-
   public abstract class RoomDatabase {
     ctor public RoomDatabase();
     method @Deprecated public void beginTransaction();
diff --git a/room/room-runtime/api/public_plus_experimental_current.txt b/room/room-runtime/api/public_plus_experimental_current.txt
index 9af4092..408b98b 100644
--- a/room/room-runtime/api/public_plus_experimental_current.txt
+++ b/room/room-runtime/api/public_plus_experimental_current.txt
@@ -48,19 +48,13 @@
     method public android.os.IBinder onBind(android.content.Intent intent);
   }
 
-  public class Room {
-    ctor @Deprecated public Room();
-    method public static final <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> databaseBuilder(android.content.Context context, Class<T> klass, String? name);
-    method public static final <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> inMemoryDatabaseBuilder(android.content.Context context, Class<T> klass);
-    field public static final androidx.room.Room.Companion Companion;
+  public final class Room {
+    method public static <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> databaseBuilder(android.content.Context context, Class<T> klass, String? name);
+    method public static <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> inMemoryDatabaseBuilder(android.content.Context context, Class<T> klass);
+    field public static final androidx.room.Room INSTANCE;
     field public static final String MASTER_TABLE_NAME = "room_master_table";
   }
 
-  public static final class Room.Companion {
-    method public <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> databaseBuilder(android.content.Context context, Class<T> klass, String? name);
-    method public <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> inMemoryDatabaseBuilder(android.content.Context context, Class<T> klass);
-  }
-
   public abstract class RoomDatabase {
     ctor public RoomDatabase();
     method @Deprecated public void beginTransaction();
diff --git a/room/room-runtime/api/restricted_current.ignore b/room/room-runtime/api/restricted_current.ignore
index 58e4397..d53b9c9 100644
--- a/room/room-runtime/api/restricted_current.ignore
+++ b/room/room-runtime/api/restricted_current.ignore
@@ -1,4 +1,8 @@
 // Baseline format: 1.0
+AddedFinal: androidx.room.Room:
+    Class androidx.room.Room added 'final' qualifier
+
+
 ChangedType: androidx.room.DatabaseConfiguration#autoMigrationSpecs:
     Field androidx.room.DatabaseConfiguration.autoMigrationSpecs has changed type from java.util.List<androidx.room.migration.AutoMigrationSpec!> to java.util.List<androidx.room.migration.AutoMigrationSpec>
 ChangedType: androidx.room.DatabaseConfiguration#callbacks:
@@ -117,6 +121,8 @@
     Removed deprecated constructor androidx.room.DatabaseConfiguration(android.content.Context,String,androidx.sqlite.db.SupportSQLiteOpenHelper.Factory,androidx.room.RoomDatabase.MigrationContainer,java.util.List<androidx.room.RoomDatabase.Callback>,boolean,androidx.room.RoomDatabase.JournalMode,java.util.concurrent.Executor,java.util.concurrent.Executor,boolean,boolean,boolean,java.util.Set<java.lang.Integer>,String,java.io.File,java.util.concurrent.Callable<java.io.InputStream>,androidx.room.RoomDatabase.PrepackagedDatabaseCallback,java.util.List<java.lang.Object>)
 RemovedDeprecatedMethod: androidx.room.DatabaseConfiguration#DatabaseConfiguration(android.content.Context, String, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory, androidx.room.RoomDatabase.MigrationContainer, java.util.List<androidx.room.RoomDatabase.Callback>, boolean, androidx.room.RoomDatabase.JournalMode, java.util.concurrent.Executor, java.util.concurrent.Executor, boolean, boolean, boolean, java.util.Set<java.lang.Integer>, String, java.io.File, java.util.concurrent.Callable<java.io.InputStream>, androidx.room.RoomDatabase.PrepackagedDatabaseCallback, java.util.List<java.lang.Object>, java.util.List<androidx.room.migration.AutoMigrationSpec>):
     Removed deprecated constructor androidx.room.DatabaseConfiguration(android.content.Context,String,androidx.sqlite.db.SupportSQLiteOpenHelper.Factory,androidx.room.RoomDatabase.MigrationContainer,java.util.List<androidx.room.RoomDatabase.Callback>,boolean,androidx.room.RoomDatabase.JournalMode,java.util.concurrent.Executor,java.util.concurrent.Executor,boolean,boolean,boolean,java.util.Set<java.lang.Integer>,String,java.io.File,java.util.concurrent.Callable<java.io.InputStream>,androidx.room.RoomDatabase.PrepackagedDatabaseCallback,java.util.List<java.lang.Object>,java.util.List<androidx.room.migration.AutoMigrationSpec>)
+RemovedDeprecatedMethod: androidx.room.Room#Room():
+    Removed deprecated constructor androidx.room.Room()
 
 
 RemovedMethod: androidx.room.DatabaseConfiguration#DatabaseConfiguration(android.content.Context, String, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory, androidx.room.RoomDatabase.MigrationContainer, java.util.List<androidx.room.RoomDatabase.Callback>, boolean, androidx.room.RoomDatabase.JournalMode, java.util.concurrent.Executor, java.util.concurrent.Executor, android.content.Intent, boolean, boolean, java.util.Set<java.lang.Integer>, String, java.io.File, java.util.concurrent.Callable<java.io.InputStream>, androidx.room.RoomDatabase.PrepackagedDatabaseCallback, java.util.List<java.lang.Object>, java.util.List<androidx.room.migration.AutoMigrationSpec>):
diff --git a/room/room-runtime/api/restricted_current.txt b/room/room-runtime/api/restricted_current.txt
index ddee7ea..b066005 100644
--- a/room/room-runtime/api/restricted_current.txt
+++ b/room/room-runtime/api/restricted_current.txt
@@ -91,19 +91,13 @@
     method public abstract void onInvalidated(java.util.Set<java.lang.String> tables);
   }
 
-  public class Room {
-    ctor @Deprecated public Room();
-    method public static final <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> databaseBuilder(android.content.Context context, Class<T> klass, String? name);
-    method public static final <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> inMemoryDatabaseBuilder(android.content.Context context, Class<T> klass);
-    field public static final androidx.room.Room.Companion Companion;
+  public final class Room {
+    method public static <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> databaseBuilder(android.content.Context context, Class<T> klass, String? name);
+    method public static <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> inMemoryDatabaseBuilder(android.content.Context context, Class<T> klass);
+    field public static final androidx.room.Room INSTANCE;
     field public static final String MASTER_TABLE_NAME = "room_master_table";
   }
 
-  public static final class Room.Companion {
-    method public <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> databaseBuilder(android.content.Context context, Class<T> klass, String? name);
-    method public <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T> inMemoryDatabaseBuilder(android.content.Context context, Class<T> klass);
-  }
-
   public abstract class RoomDatabase {
     ctor public RoomDatabase();
     method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void assertNotMainThread();
diff --git a/room/room-runtime/src/main/java/androidx/room/AutoCloser.kt b/room/room-runtime/src/main/java/androidx/room/AutoCloser.kt
index a0a5ea1..f79f982 100644
--- a/room/room-runtime/src/main/java/androidx/room/AutoCloser.kt
+++ b/room/room-runtime/src/main/java/androidx/room/AutoCloser.kt
@@ -19,7 +19,6 @@
 import android.os.Looper
 import android.os.SystemClock
 import androidx.annotation.GuardedBy
-import androidx.annotation.RestrictTo
 import androidx.annotation.VisibleForTesting
 import androidx.room.util.SneakyThrow
 import androidx.sqlite.db.SupportSQLiteDatabase
@@ -38,10 +37,7 @@
  * @param autoCloseTimeoutAmount time for auto close timer
  * @param autoCloseTimeUnit      time unit for autoCloseTimeoutAmount
  * @param autoCloseExecutor      the executor on which the auto close operation will happen
- *
- * @hide
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
 internal class AutoCloser(
     autoCloseTimeoutAmount: Long,
     autoCloseTimeUnit: TimeUnit,
diff --git a/room/room-runtime/src/main/java/androidx/room/InvalidationTracker.kt b/room/room-runtime/src/main/java/androidx/room/InvalidationTracker.kt
index 8b83f50..b766d6f 100644
--- a/room/room-runtime/src/main/java/androidx/room/InvalidationTracker.kt
+++ b/room/room-runtime/src/main/java/androidx/room/InvalidationTracker.kt
@@ -27,7 +27,7 @@
 import androidx.annotation.WorkerThread
 import androidx.arch.core.internal.SafeIterableMap
 import androidx.lifecycle.LiveData
-import androidx.room.Room.Companion.LOG_TAG
+import androidx.room.Room.LOG_TAG
 import androidx.room.util.useCursor
 import androidx.sqlite.db.SimpleSQLiteQuery
 import androidx.sqlite.db.SupportSQLiteDatabase
@@ -53,37 +53,26 @@
 // memory table table, flipping the invalidated flag ON.
 // * When multi-instance invalidation is turned on, MultiInstanceInvalidationClient will be created.
 // It works as an Observer, and notifies other instances of table invalidation.
-
 open class InvalidationTracker @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) constructor(
-    @get:RestrictTo(RestrictTo.Scope.LIBRARY)
-    @field:RestrictTo(RestrictTo.Scope.LIBRARY)
-    protected val database: RoomDatabase,
+    internal val database: RoomDatabase,
     private val shadowTablesMap: Map<String, String>,
     private val viewTables: Map<String, @JvmSuppressWildcards Set<String>>,
     vararg tableNames: String
 ) {
-    @JvmField
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    val tableIdLookup: Map<String, Int>
-
-    @JvmField
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    val tablesNames: Array<String>
+    internal val tableIdLookup: Map<String, Int>
+    internal val tablesNames: Array<String>
 
     private var autoCloser: AutoCloser? = null
 
-    @JvmField
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY)
+    @field:RestrictTo(RestrictTo.Scope.LIBRARY)
     val pendingRefresh = AtomicBoolean(false)
 
     @Volatile
     private var initialized = false
 
     @Volatile
-    @get:RestrictTo(RestrictTo.Scope.LIBRARY)
-    @set:RestrictTo(RestrictTo.Scope.LIBRARY)
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    var cleanupStatement: SupportSQLiteStatement? = null
+    internal var cleanupStatement: SupportSQLiteStatement? = null
 
     private val observedTableTracker: ObservedTableTracker = ObservedTableTracker(tableNames.size)
 
@@ -91,17 +80,7 @@
         InvalidationLiveDataContainer(database)
 
     @GuardedBy("observerMap")
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    @JvmField
-    @VisibleForTesting
-    protected val observerMap = SafeIterableMap<Observer, ObserverWrapper>()
-
-    @GuardedBy("observerMap")
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    @VisibleForTesting
-    fun getObserverMap(): SafeIterableMap<Observer, ObserverWrapper> {
-        return observerMap
-    }
+    internal val observerMap = SafeIterableMap<Observer, ObserverWrapper>()
 
     private var multiInstanceInvalidationClient: MultiInstanceInvalidationClient? = null
 
@@ -165,9 +144,7 @@
      *
      * You should never call this method, it is called by the generated code.
      */
-    // TODO (b/218894771): Make internal when RoomDatabase is converted to Kotlin
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    fun internalInit(database: SupportSQLiteDatabase) {
+    internal fun internalInit(database: SupportSQLiteDatabase) {
         synchronized(trackerLock) {
             if (initialized) {
                 Log.e(LOG_TAG, "Invalidation tracker is initialized twice :/.")
@@ -193,7 +170,6 @@
         }
     }
 
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
     internal fun startMultiInstanceInvalidation(
         context: Context,
         name: String,
@@ -208,7 +184,6 @@
         )
     }
 
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
     internal fun stopMultiInstanceInvalidation() {
         multiInstanceInvalidationClient?.stop()
         multiInstanceInvalidationClient = null
@@ -353,8 +328,7 @@
         }
     }
 
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    protected fun ensureInitialization(): Boolean {
+    internal fun ensureInitialization(): Boolean {
         if (!database.isOpen) {
             return false
         }
@@ -503,7 +477,6 @@
         }
     }
 
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
     internal fun syncTriggers(database: SupportSQLiteDatabase) {
         if (database.inTransaction()) {
             // we won't run this inside another transaction.
@@ -552,8 +525,7 @@
      *
      * This api should eventually be public.
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    fun syncTriggers() {
+    internal fun syncTriggers() {
         if (!database.isOpen) {
             return
         }
@@ -613,15 +585,10 @@
      *
      * Internally table ids are used which may change from database to database so the table
      * related information is kept here rather than in the Observer.
-     *
-     * @hide
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    class ObserverWrapper(
-        @get:RestrictTo(RestrictTo.Scope.LIBRARY)
-        val observer: Observer,
-        @get:RestrictTo(RestrictTo.Scope.LIBRARY)
-        val tableIds: IntArray,
+    internal class ObserverWrapper(
+        internal val observer: Observer,
+        internal val tableIds: IntArray,
         private val tableNames: Array<String>
     ) {
         private val singleTableSet = if (tableNames.isNotEmpty()) {
@@ -640,8 +607,7 @@
          *
          * @param invalidatedTablesIds The table ids of the tables that are invalidated.
          */
-        @RestrictTo(RestrictTo.Scope.LIBRARY)
-        fun notifyByTableInvalidStatus(invalidatedTablesIds: Set<Int?>) {
+        internal fun notifyByTableInvalidStatus(invalidatedTablesIds: Set<Int?>) {
             val invalidatedTables = when (tableIds.size) {
                 0 -> emptySet()
                 1 -> if (invalidatedTablesIds.contains(tableIds[0])) {
@@ -669,8 +635,7 @@
          *
          * @param tables The invalidated table names.
          */
-        @RestrictTo(RestrictTo.Scope.LIBRARY)
-        fun notifyByTableNames(tables: Array<out String>) {
+        internal fun notifyByTableNames(tables: Array<out String>) {
             val invalidatedTables = when (tableNames.size) {
                 0 -> emptySet()
                 1 -> if (tables.any { it.equals(tableNames[0], ignoreCase = true) }) {
@@ -698,7 +663,7 @@
     /**
      * An observer that can listen for changes in the database.
      */
-    abstract class Observer(@get:RestrictTo(RestrictTo.Scope.LIBRARY) val tables: Array<String>) {
+    abstract class Observer(internal val tables: Array<String>) {
         /**
          * Observes the given list of tables and views.
          *
@@ -721,8 +686,7 @@
          */
         abstract fun onInvalidated(tables: Set<String>)
 
-        @get:RestrictTo(RestrictTo.Scope.LIBRARY)
-        open val isRemote: Boolean
+        internal open val isRemote: Boolean
             get() = false
     }
 
@@ -819,8 +783,7 @@
             }
         }
 
-        @RestrictTo(RestrictTo.Scope.LIBRARY)
-        companion object {
+        internal companion object {
             const val NO_OP = 0 // don't change trigger state for this table
             const val ADD = 1 // add triggers for this table
             const val REMOVE = 2 // remove triggers for this table
@@ -857,14 +820,12 @@
                 "$INVALIDATED_COLUMN_NAME INTEGER NOT NULL DEFAULT 0)"
 
         @VisibleForTesting
-        @RestrictTo(RestrictTo.Scope.LIBRARY)
-        const val RESET_UPDATED_TABLES_SQL =
+        internal const val RESET_UPDATED_TABLES_SQL =
             "UPDATE $UPDATE_TABLE_NAME SET $INVALIDATED_COLUMN_NAME = 0 " +
                 "WHERE $INVALIDATED_COLUMN_NAME = 1"
 
         @VisibleForTesting
-        @RestrictTo(RestrictTo.Scope.LIBRARY)
-        const val SELECT_UPDATED_TABLES_SQL =
+        internal const val SELECT_UPDATED_TABLES_SQL =
             "SELECT * FROM $UPDATE_TABLE_NAME WHERE $INVALIDATED_COLUMN_NAME = 1;"
 
         internal fun getTriggerName(
diff --git a/room/room-runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.kt b/room/room-runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.kt
index bd52304..e4eb340 100644
--- a/room/room-runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.kt
+++ b/room/room-runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.kt
@@ -22,7 +22,7 @@
 import android.os.IBinder
 import android.os.RemoteException
 import android.util.Log
-import androidx.room.Room.Companion.LOG_TAG
+import androidx.room.Room.LOG_TAG
 import java.util.concurrent.Executor
 import java.util.concurrent.atomic.AtomicBoolean
 
diff --git a/room/room-runtime/src/main/java/androidx/room/MultiInstanceInvalidationService.kt b/room/room-runtime/src/main/java/androidx/room/MultiInstanceInvalidationService.kt
index 9b8e836..9d72873 100644
--- a/room/room-runtime/src/main/java/androidx/room/MultiInstanceInvalidationService.kt
+++ b/room/room-runtime/src/main/java/androidx/room/MultiInstanceInvalidationService.kt
@@ -21,7 +21,7 @@
 import android.os.IBinder
 import android.os.RemoteException
 import android.util.Log
-import androidx.room.Room.Companion.LOG_TAG
+import androidx.room.Room.LOG_TAG
 
 /**
  * A [Service] for remote invalidation among multiple [InvalidationTracker] instances.
diff --git a/room/room-runtime/src/main/java/androidx/room/Room.kt b/room/room-runtime/src/main/java/androidx/room/Room.kt
index dd72c02..9a68205 100644
--- a/room/room-runtime/src/main/java/androidx/room/Room.kt
+++ b/room/room-runtime/src/main/java/androidx/room/Room.kt
@@ -21,102 +21,96 @@
 /**
  * Utility functions for Room.
  */
-// TODO (b/225972678) remove class and make top-level functions in Room 3.0.
-open class Room {
-    /** This type should not be instantiated as it contains only static methods. */
-    @Deprecated("This type should not be instantiated as it contains only static methods. ")
-    @SuppressWarnings("PrivateConstructorForUtilityClass")
-    constructor()
+object Room {
 
-    companion object {
-        internal const val LOG_TAG = "ROOM"
+    internal const val LOG_TAG = "ROOM"
 
-        /**
-         * The master table where room keeps its metadata information.
-         */
-        const val MASTER_TABLE_NAME = RoomMasterTable.TABLE_NAME
-        private const val CURSOR_CONV_SUFFIX = "_CursorConverter"
+    /**
+     * The master table where room keeps its metadata information.
+     */
+    const val MASTER_TABLE_NAME = RoomMasterTable.TABLE_NAME
 
-        @Suppress("UNCHECKED_CAST")
-        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-        @JvmStatic
-        fun <T, C> getGeneratedImplementation(
-            klass: Class<C>,
-            suffix: String
-        ): T {
-            val fullPackage = klass.getPackage()!!.name
-            val name: String = klass.canonicalName!!
-            val postPackageName =
-                if (fullPackage.isEmpty()) name else name.substring(fullPackage.length + 1)
-            val implName = postPackageName.replace('.', '_') + suffix
-            return try {
-                val fullClassName = if (fullPackage.isEmpty()) {
-                    implName
-                } else {
-                    "$fullPackage.$implName"
-                }
-                val aClass = Class.forName(
-                    fullClassName, true, klass.classLoader
-                ) as Class<T>
-                aClass.newInstance()
-            } catch (e: ClassNotFoundException) {
-                throw RuntimeException(
-                    "Cannot find implementation for ${klass.canonicalName}. $implName does not " +
-                        "exist"
-                )
-            } catch (e: IllegalAccessException) {
-                throw RuntimeException(
-                    "Cannot access the constructor $klass.canonicalName"
-                )
-            } catch (e: InstantiationException) {
-                throw RuntimeException(
-                    "Failed to create an instance of $klass.canonicalName"
-                )
+    private const val CURSOR_CONV_SUFFIX = "_CursorConverter"
+
+    @Suppress("UNCHECKED_CAST")
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    @JvmStatic
+    fun <T, C> getGeneratedImplementation(
+        klass: Class<C>,
+        suffix: String
+    ): T {
+        val fullPackage = klass.getPackage()!!.name
+        val name: String = klass.canonicalName!!
+        val postPackageName =
+            if (fullPackage.isEmpty()) name else name.substring(fullPackage.length + 1)
+        val implName = postPackageName.replace('.', '_') + suffix
+        return try {
+            val fullClassName = if (fullPackage.isEmpty()) {
+                implName
+            } else {
+                "$fullPackage.$implName"
             }
+            val aClass = Class.forName(
+                fullClassName, true, klass.classLoader
+            ) as Class<T>
+            aClass.newInstance()
+        } catch (e: ClassNotFoundException) {
+            throw RuntimeException(
+                "Cannot find implementation for ${klass.canonicalName}. $implName does not " +
+                    "exist"
+            )
+        } catch (e: IllegalAccessException) {
+            throw RuntimeException(
+                "Cannot access the constructor $klass.canonicalName"
+            )
+        } catch (e: InstantiationException) {
+            throw RuntimeException(
+                "Failed to create an instance of $klass.canonicalName"
+            )
         }
+    }
 
-        /**
-         * Creates a RoomDatabase.Builder for an in memory database. Information stored in an in memory
-         * database disappears when the process is killed.
-         * Once a database is built, you should keep a reference to it and re-use it.
-         *
-         * @param context The context for the database. This is usually the Application context.
-         * @param klass   The abstract class which is annotated with [Database] and extends
-         * [RoomDatabase].
-         * @param T     The type of the database class.
-         * @return A `RoomDatabaseBuilder<T>` which you can use to create the database.
-         */
-        @JvmStatic
-        fun <T : RoomDatabase> inMemoryDatabaseBuilder(
-            context: Context,
-            klass: Class<T>
-        ): RoomDatabase.Builder<T> {
-            return RoomDatabase.Builder(context, klass, null)
-        }
+    /**
+     * Creates a RoomDatabase.Builder for an in memory database. Information stored in an in memory
+     * database disappears when the process is killed.
+     * Once a database is built, you should keep a reference to it and re-use it.
+     *
+     * @param context The context for the database. This is usually the Application context.
+     * @param klass   The abstract class which is annotated with [Database] and extends
+     * [RoomDatabase].
+     * @param T     The type of the database class.
+     * @return A `RoomDatabaseBuilder<T>` which you can use to create the database.
+     */
+    @JvmStatic
+    fun <T : RoomDatabase> inMemoryDatabaseBuilder(
+        context: Context,
+        klass: Class<T>
+    ): RoomDatabase.Builder<T> {
+        return RoomDatabase.Builder(context, klass, null)
+    }
 
-        /**
-         * Creates a RoomDatabase.Builder for a persistent database. Once a database is built, you
-         * should keep a reference to it and re-use it.
-         *
-         * @param context The context for the database. This is usually the Application context.
-         * @param klass   The abstract class which is annotated with [Database] and extends
-         * [RoomDatabase].
-         * @param name    The name of the database file.
-         * @param T     The type of the database class.
-         * @return A `RoomDatabaseBuilder<T>` which you can use to create the database.
-         */
-        @JvmStatic
-        fun <T : RoomDatabase> databaseBuilder(
-            context: Context,
-            klass: Class<T>,
-            name: String?
-        ): RoomDatabase.Builder<T> {
-            require(!name.isNullOrBlank()) {
-                "Cannot build a database with null or empty name." +
-                    " If you are trying to create an in memory database, use Room" +
-                    ".inMemoryDatabaseBuilder"
-            }
-            return RoomDatabase.Builder(context, klass, name)
+    /**
+     * Creates a RoomDatabase.Builder for a persistent database. Once a database is built, you
+     * should keep a reference to it and re-use it.
+     *
+     * @param context The context for the database. This is usually the Application context.
+     * @param klass   The abstract class which is annotated with [Database] and extends
+     * [RoomDatabase].
+     * @param name    The name of the database file.
+     * @param T     The type of the database class.
+     * @return A `RoomDatabaseBuilder<T>` which you can use to create the database.
+     */
+    @JvmStatic
+    fun <T : RoomDatabase> databaseBuilder(
+        context: Context,
+        klass: Class<T>,
+        name: String?
+    ): RoomDatabase.Builder<T> {
+        require(!name.isNullOrBlank()) {
+            "Cannot build a database with null or empty name." +
+                " If you are trying to create an in memory database, use Room" +
+                ".inMemoryDatabaseBuilder"
         }
+        return RoomDatabase.Builder(context, klass, name)
     }
 }
\ No newline at end of file
diff --git a/room/room-runtime/src/main/java/androidx/room/RoomDatabase.kt b/room/room-runtime/src/main/java/androidx/room/RoomDatabase.kt
index b2885b2..1c5732e 100644
--- a/room/room-runtime/src/main/java/androidx/room/RoomDatabase.kt
+++ b/room/room-runtime/src/main/java/androidx/room/RoomDatabase.kt
@@ -29,6 +29,7 @@
 import androidx.annotation.RestrictTo
 import androidx.annotation.WorkerThread
 import androidx.arch.core.executor.ArchTaskExecutor
+import androidx.room.Room.LOG_TAG
 import androidx.room.migration.AutoMigrationSpec
 import androidx.room.migration.Migration
 import androidx.sqlite.db.SimpleSQLiteQuery
@@ -137,8 +138,7 @@
      *
      * @return The lock for [close].
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    open fun getCloseLock(): Lock {
+    internal fun getCloseLock(): Lock {
         return readWriteLock.readLock()
     }
 
@@ -174,7 +174,7 @@
     }
 
     /**
-     * Called by [Room] when it is initialized.
+     * Called by Room when it is initialized.
      *
      * @throws IllegalArgumentException if initialization fails.
      *
@@ -657,8 +657,7 @@
         /**
          * Resolves [AUTOMATIC] to either [TRUNCATE] or [WRITE_AHEAD_LOGGING].
          */
-        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-        open fun resolve(context: Context): JournalMode {
+        internal fun resolve(context: Context): JournalMode {
             if (this != AUTOMATIC) {
                 return this
             }
@@ -1384,7 +1383,7 @@
             val targetMap = migrations.getOrPut(start) { TreeMap<Int, Migration>() }
 
             if (targetMap.contains(end)) {
-                Log.w(Room.LOG_TAG, "Overriding migration ${targetMap[end]} with $migration")
+                Log.w(LOG_TAG, "Overriding migration ${targetMap[end]} with $migration")
             }
             targetMap[end] = migration
         }
diff --git a/room/room-runtime/src/main/java/androidx/room/SQLiteCopyOpenHelper.kt b/room/room-runtime/src/main/java/androidx/room/SQLiteCopyOpenHelper.kt
index 0e34980..834ecec 100644
--- a/room/room-runtime/src/main/java/androidx/room/SQLiteCopyOpenHelper.kt
+++ b/room/room-runtime/src/main/java/androidx/room/SQLiteCopyOpenHelper.kt
@@ -19,6 +19,7 @@
 import android.os.Build
 import android.util.Log
 import androidx.annotation.RequiresApi
+import androidx.room.Room.LOG_TAG
 import androidx.room.util.readVersion
 import androidx.room.util.copy
 import androidx.sqlite.db.SupportSQLiteDatabase
@@ -119,7 +120,7 @@
             val currentVersion = try {
                 readVersion(databaseFile)
             } catch (e: IOException) {
-                Log.w(Room.LOG_TAG, "Unable to read database version.", e)
+                Log.w(LOG_TAG, "Unable to read database version.", e)
                 return
             }
             if (currentVersion == databaseVersion) {
@@ -136,11 +137,11 @@
                 } catch (e: IOException) {
                     // We are more forgiving copying a database on a destructive migration since
                     // there is already a database file that can be opened.
-                    Log.w(Room.LOG_TAG, "Unable to copy database file.", e)
+                    Log.w(LOG_TAG, "Unable to copy database file.", e)
                 }
             } else {
                 Log.w(
-                    Room.LOG_TAG, "Failed to delete database file ($name) for " +
+                    LOG_TAG, "Failed to delete database file ($name) for " +
                         "a copy destructive migration."
                 )
             }
diff --git a/room/room-runtime/src/test/java/androidx/room/InvalidationTrackerTest.kt b/room/room-runtime/src/test/java/androidx/room/InvalidationTrackerTest.kt
index b897d80..6e3f170 100644
--- a/room/room-runtime/src/test/java/androidx/room/InvalidationTrackerTest.kt
+++ b/room/room-runtime/src/test/java/androidx/room/InvalidationTrackerTest.kt
@@ -152,11 +152,11 @@
     fun addRemoveObserver() {
         val observer: InvalidationTracker.Observer = LatchObserver(1, "a")
         mTracker.addObserver(observer)
-        assertThat(mTracker.getObserverMap().size()).isEqualTo(1)
+        assertThat(mTracker.observerMap.size()).isEqualTo(1)
         mTracker.removeObserver(LatchObserver(1, "a"))
-        assertThat(mTracker.getObserverMap().size()).isEqualTo(1)
+        assertThat(mTracker.observerMap.size()).isEqualTo(1)
         mTracker.removeObserver(observer)
-        assertThat(mTracker.getObserverMap().size()).isEqualTo(0)
+        assertThat(mTracker.observerMap.size()).isEqualTo(0)
     }
 
     private fun drainTasks() {
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiScrollable.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiScrollable.java
index 7a463ac..bc2e4f7 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiScrollable.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiScrollable.java
@@ -16,14 +16,11 @@
 
 package androidx.test.uiautomator;
 
-import static androidx.annotation.RestrictTo.Scope.LIBRARY;
-
 import android.graphics.Rect;
 import android.util.Log;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
 
 /**
  * UiScrollable is a {@link UiCollection} and provides support for searching
@@ -306,7 +303,6 @@
      * @throws UiObjectNotFoundException
      * @hide
      */
-    @RestrictTo(LIBRARY)
     public boolean ensureFullyVisible(@NonNull UiObject childObject)
             throws UiObjectNotFoundException {
         Rect actual = childObject.getBounds();