Merge "Add tests for request_type ParseResult functions."
diff --git a/android/bazel.go b/android/bazel.go
index b54ae64..b3f9d88 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -135,45 +135,45 @@
 
 	// Per-module denylist to always opt modules out.
 	bp2buildModuleDoNotConvertList = []string{
-		"libBionicBenchmarksUtils",      // ruperts@, cc_library_static
+		"libBionicBenchmarksUtils",      // ruperts@, cc_library_static, 'map' file not found
 		"libbionic_spawn_benchmark",     // ruperts@, cc_library_static, depends on //system/libbase
 		"libc_jemalloc_wrapper",         // ruperts@, cc_library_static, depends on //external/jemalloc_new
-		"libc_bootstrap",                // ruperts@, cc_library_static
-		"libc_init_static",              // ruperts@, cc_library_static
-		"libc_init_dynamic",             // ruperts@, cc_library_static
-		"libc_tzcode",                   // ruperts@, cc_library_static
-		"libc_freebsd",                  // ruperts@, cc_library_static
-		"libc_freebsd_large_stack",      // ruperts@, cc_library_static
-		"libc_netbsd",                   // ruperts@, cc_library_static
-		"libc_openbsd_ndk",              // ruperts@, cc_library_static
-		"libc_openbsd_large_stack",      // ruperts@, cc_library_static
-		"libc_openbsd",                  // ruperts@, cc_library_static
-		"libc_gdtoa",                    // ruperts@, cc_library_static
-		"libc_fortify",                  // ruperts@, cc_library_static
-		"libc_bionic",                   // ruperts@, cc_library_static
+		"libc_bootstrap",                // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_init_static",              // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_init_dynamic",             // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_tzcode",                   // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_freebsd",                  // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_freebsd_large_stack",      // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_netbsd",                   // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_openbsd_ndk",              // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_openbsd_large_stack",      // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_openbsd",                  // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_gdtoa",                    // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_fortify",                  // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_bionic",                   // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
 		"libc_bionic_ndk",               // ruperts@, cc_library_static, depends on //bionic/libc/system_properties
-		"libc_bionic_systrace",          // ruperts@, cc_library_static
-		"libc_pthread",                  // ruperts@, cc_library_static
-		"libc_syscalls",                 // ruperts@, cc_library_static
-		"libc_aeabi",                    // ruperts@, cc_library_static
+		"libc_bionic_systrace",          // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_pthread",                  // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_syscalls",                 // ruperts@, cc_library_static, mutator panic cannot get direct dep syscalls-arm64.S of libc_syscalls
+		"libc_aeabi",                    // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
 		"libc_ndk",                      // ruperts@, cc_library_static, depends on //bionic/libm:libm
 		"libc_nopthread",                // ruperts@, cc_library_static, depends on //external/arm-optimized-routines
 		"libc_common",                   // ruperts@, cc_library_static, depends on //bionic/libc:libc_nopthread
-		"libc_static_dispatch",          // ruperts@, cc_library_static
-		"libc_dynamic_dispatch",         // ruperts@, cc_library_static
+		"libc_static_dispatch",          // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
+		"libc_dynamic_dispatch",         // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
 		"libc_common_static",            // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
 		"libc_common_shared",            // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
-		"libc_unwind_static",            // ruperts@, cc_library_static
+		"libc_unwind_static",            // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
 		"libc_nomalloc",                 // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
-		"libasync_safe",                 // ruperts@, cc_library_static
+		"libasync_safe",                 // ruperts@, cc_library_static, 'private/CachedProperty.h' file not found
 		"libc_malloc_debug_backtrace",   // ruperts@, cc_library_static, depends on //system/libbase
 		"libsystemproperties",           // ruperts@, cc_library_static, depends on //system/core/property_service/libpropertyinfoparser
-		"libdl_static",                  // ruperts@, cc_library_static
+		"libdl_static",                  // ruperts@, cc_library_static, 'private/CFIShadow.h' file not found
 		"liblinker_main",                // ruperts@, cc_library_static, depends on //system/libbase
 		"liblinker_malloc",              // ruperts@, cc_library_static, depends on //system/logging/liblog:liblog
 		"liblinker_debuggerd_stub",      // ruperts@, cc_library_static, depends on //system/libbase
-		"libbionic_tests_headers_posix", // ruperts@, cc_library_static
-		"libc_dns",                      // ruperts@, cc_library_static
+		"libbionic_tests_headers_posix", // ruperts@, cc_library_static, 'complex.h' file not found
+		"libc_dns",                      // ruperts@, cc_library_static, 'bionic/libc/async_safe' is a subpackage
 
 		"note_memtag_heap_async", // jingwen@, b/185079815, features.h includes not found
 		"note_memtag_heap_sync",  // jingwen@, b/185079815, features.h includes not found
diff --git a/android/paths.go b/android/paths.go
index 37b04dd..df12228 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1101,11 +1101,12 @@
 		// a single file.
 		files, err = gctx.GlobWithDeps(path.String(), nil)
 	} else {
-		var deps []string
+		var result pathtools.GlobResult
 		// We cannot add build statements in this context, so we fall back to
 		// AddNinjaFileDeps
-		files, deps, err = ctx.Config().fs.Glob(path.String(), nil, pathtools.FollowSymlinks)
-		ctx.AddNinjaFileDeps(deps...)
+		result, err = ctx.Config().fs.Glob(path.String(), nil, pathtools.FollowSymlinks)
+		ctx.AddNinjaFileDeps(result.Deps...)
+		files = result.Matches
 	}
 
 	if err != nil {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ee4255e..61e8864 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4375,9 +4375,7 @@
 // These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the
 // propagation of paths to dex implementation jars from the former to the latter.
 func TestPrebuiltExportDexImplementationJars(t *testing.T) {
-	transform := func(config *dexpreopt.GlobalConfig) {
-		// Empty transformation.
-	}
+	transform := android.NullFixturePreparer
 
 	checkDexJarBuildPath := func(t *testing.T, ctx *android.TestContext, name string) {
 		// Make sure the import has been given the correct path to the dex jar.
@@ -4547,9 +4545,7 @@
 }
 
 func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
-	transform := func(config *dexpreopt.GlobalConfig) {
-		config.BootJars = android.CreateTestConfiguredJarList([]string{"myapex:libfoo", "myapex:libbar"})
-	}
+	preparer := java.FixtureConfigureBootJars("myapex:libfoo", "myapex:libbar")
 
 	checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
 		t.Helper()
@@ -4605,7 +4601,7 @@
 		}
 	`
 
-		ctx := testDexpreoptWithApexes(t, bp, "", transform)
+		ctx := testDexpreoptWithApexes(t, bp, "", preparer)
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
@@ -4639,7 +4635,7 @@
 		}
 	`
 
-		ctx := testDexpreoptWithApexes(t, bp, "", transform)
+		ctx := testDexpreoptWithApexes(t, bp, "", preparer)
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
@@ -4698,7 +4694,7 @@
 		// prebuilt_apex module always depends on the prebuilt, and so it doesn't
 		// find the dex boot jar in it. We either need to disable the source libfoo
 		// or make the prebuilt libfoo preferred.
-		testDexpreoptWithApexes(t, bp, "failed to find a dex jar path for module 'libfoo'", transform)
+		testDexpreoptWithApexes(t, bp, "failed to find a dex jar path for module 'libfoo'", preparer)
 	})
 
 	t.Run("prebuilt library preferred with source", func(t *testing.T) {
@@ -4746,7 +4742,7 @@
 		}
 	`
 
-		ctx := testDexpreoptWithApexes(t, bp, "", transform)
+		ctx := testDexpreoptWithApexes(t, bp, "", preparer)
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
@@ -4813,7 +4809,7 @@
 		}
 	`
 
-		ctx := testDexpreoptWithApexes(t, bp, "", transform)
+		ctx := testDexpreoptWithApexes(t, bp, "", preparer)
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar")
 
@@ -4882,7 +4878,7 @@
 		}
 	`
 
-		ctx := testDexpreoptWithApexes(t, bp, "", transform)
+		ctx := testDexpreoptWithApexes(t, bp, "", preparer)
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
@@ -6440,7 +6436,7 @@
 	android.AssertStringEquals(t, "myapex input", extractorOutput, copiedApex.Input.String())
 }
 
-func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) {
+func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer android.FixturePreparer) {
 	t.Helper()
 
 	bp := `
@@ -6528,10 +6524,10 @@
 		}
 	`
 
-	testDexpreoptWithApexes(t, bp, errmsg, transformDexpreoptConfig)
+	testDexpreoptWithApexes(t, bp, errmsg, preparer)
 }
 
-func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) *android.TestContext {
+func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.FixturePreparer) *android.TestContext {
 	t.Helper()
 
 	fs := android.MockFS{
@@ -6557,17 +6553,7 @@
 		java.PrepareForTestWithJavaDefaultModules,
 		java.PrepareForTestWithJavaSdkLibraryFiles,
 		PrepareForTestWithApexBuildComponents,
-		android.FixtureModifyConfig(func(config android.Config) {
-			pathCtx := android.PathContextForTesting(config)
-			dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
-			transformDexpreoptConfig(dexpreoptConfig)
-			dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
-
-			// Make sure that any changes to these dexpreopt properties are mirrored in the corresponding
-			// product variables.
-			config.TestProductVariables.BootJars = dexpreoptConfig.BootJars
-			config.TestProductVariables.UpdatableBootJars = dexpreoptConfig.UpdatableBootJars
-		}),
+		preparer,
 		fs.AddToFixture(),
 	).
 		ExtendWithErrorHandler(errorHandler).
@@ -6608,92 +6594,95 @@
 }
 
 func TestNoUpdatableJarsInBootImage(t *testing.T) {
-	var err string
-	var transform func(*dexpreopt.GlobalConfig)
+	// Set the BootJars in dexpreopt.GlobalConfig and productVariables to the same value. This can
+	// result in an invalid configuration as it does not set the ArtApexJars and allows art apex
+	// modules to be included in the BootJars.
+	prepareSetBootJars := func(bootJars ...string) android.FixturePreparer {
+		return android.GroupFixturePreparers(
+			dexpreopt.FixtureSetBootJars(bootJars...),
+			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+				variables.BootJars = android.CreateTestConfiguredJarList(bootJars)
+			}),
+		)
+	}
+
+	// Set the ArtApexJars and BootJars in dexpreopt.GlobalConfig and productVariables all to the
+	// same value. This can result in an invalid configuration as it allows non art apex jars to be
+	// specified in the ArtApexJars configuration.
+	prepareSetArtJars := func(bootJars ...string) android.FixturePreparer {
+		return android.GroupFixturePreparers(
+			dexpreopt.FixtureSetArtBootJars(bootJars...),
+			dexpreopt.FixtureSetBootJars(bootJars...),
+			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+				variables.BootJars = android.CreateTestConfiguredJarList(bootJars)
+			}),
+		)
+	}
 
 	t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
-		transform = func(config *dexpreopt.GlobalConfig) {
-			config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"com.android.art.debug:some-art-lib"})
-		}
-		testNoUpdatableJarsInBootImage(t, "", transform)
+		preparer := java.FixtureConfigureBootJars("com.android.art.debug:some-art-lib")
+		testNoUpdatableJarsInBootImage(t, "", preparer)
 	})
 
 	t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
-		err = `module "some-art-lib" from updatable apexes \["com.android.art.debug"\] is not allowed in the framework boot image`
-		transform = func(config *dexpreopt.GlobalConfig) {
-			config.BootJars = android.CreateTestConfiguredJarList([]string{"com.android.art.debug:some-art-lib"})
-		}
-		testNoUpdatableJarsInBootImage(t, err, transform)
+		err := `module "some-art-lib" from updatable apexes \["com.android.art.debug"\] is not allowed in the framework boot image`
+		// Update the dexpreopt BootJars directly.
+		preparer := prepareSetBootJars("com.android.art.debug:some-art-lib")
+		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
 	t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
-		err = `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the ART boot image`
-		transform = func(config *dexpreopt.GlobalConfig) {
-			config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"some-updatable-apex:some-updatable-apex-lib"})
-		}
-		testNoUpdatableJarsInBootImage(t, err, transform)
+		err := `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the ART boot image`
+		// Update the dexpreopt ArtApexJars directly.
+		preparer := prepareSetArtJars("some-updatable-apex:some-updatable-apex-lib")
+		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
 	t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
-		err = `module "some-non-updatable-apex-lib" is not allowed in the ART boot image`
-		transform = func(config *dexpreopt.GlobalConfig) {
-			config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
-		}
-		testNoUpdatableJarsInBootImage(t, err, transform)
+		err := `module "some-non-updatable-apex-lib" is not allowed in the ART boot image`
+		// Update the dexpreopt ArtApexJars directly.
+		preparer := prepareSetArtJars("some-non-updatable-apex:some-non-updatable-apex-lib")
+		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
 	t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) {
-		err = `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the framework boot image`
-		transform = func(config *dexpreopt.GlobalConfig) {
-			config.BootJars = android.CreateTestConfiguredJarList([]string{"some-updatable-apex:some-updatable-apex-lib"})
-		}
-		testNoUpdatableJarsInBootImage(t, err, transform)
+		err := `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the framework boot image`
+		preparer := java.FixtureConfigureBootJars("some-updatable-apex:some-updatable-apex-lib")
+		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
 	t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) {
-		transform = func(config *dexpreopt.GlobalConfig) {
-			config.BootJars = android.CreateTestConfiguredJarList([]string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
-		}
-		testNoUpdatableJarsInBootImage(t, "", transform)
+		preparer := java.FixtureConfigureBootJars("some-non-updatable-apex:some-non-updatable-apex-lib")
+		testNoUpdatableJarsInBootImage(t, "", preparer)
 	})
 
 	t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) {
-		err = "failed to find a dex jar path for module 'nonexistent'"
-		transform = func(config *dexpreopt.GlobalConfig) {
-			config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"platform:nonexistent"})
-		}
-		testNoUpdatableJarsInBootImage(t, err, transform)
+		err := "failed to find a dex jar path for module 'nonexistent'"
+		preparer := java.FixtureConfigureBootJars("platform:nonexistent")
+		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
 	t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) {
-		err = "failed to find a dex jar path for module 'nonexistent'"
-		transform = func(config *dexpreopt.GlobalConfig) {
-			config.BootJars = android.CreateTestConfiguredJarList([]string{"platform:nonexistent"})
-		}
-		testNoUpdatableJarsInBootImage(t, err, transform)
+		err := "failed to find a dex jar path for module 'nonexistent'"
+		preparer := java.FixtureConfigureBootJars("platform:nonexistent")
+		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
 	t.Run("platform jar in the ART boot image => error", func(t *testing.T) {
-		err = `module "some-platform-lib" is not allowed in the ART boot image`
-		transform = func(config *dexpreopt.GlobalConfig) {
-			config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"platform:some-platform-lib"})
-		}
-		testNoUpdatableJarsInBootImage(t, err, transform)
+		err := `module "some-platform-lib" is not allowed in the ART boot image`
+		// Update the dexpreopt ArtApexJars directly.
+		preparer := prepareSetArtJars("platform:some-platform-lib")
+		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
 	t.Run("platform jar in the framework boot image => ok", func(t *testing.T) {
-		transform = func(config *dexpreopt.GlobalConfig) {
-			config.BootJars = android.CreateTestConfiguredJarList([]string{"platform:some-platform-lib"})
-		}
-		testNoUpdatableJarsInBootImage(t, "", transform)
+		preparer := java.FixtureConfigureBootJars("platform:some-platform-lib")
+		testNoUpdatableJarsInBootImage(t, "", preparer)
 	})
-
 }
 
 func TestDexpreoptAccessDexFilesFromPrebuiltApex(t *testing.T) {
-	transform := func(config *dexpreopt.GlobalConfig) {
-		config.BootJars = android.CreateTestConfiguredJarList([]string{"myapex:libfoo"})
-	}
+	preparer := java.FixtureConfigureBootJars("myapex:libfoo")
 	t.Run("prebuilt no source", func(t *testing.T) {
 		testDexpreoptWithApexes(t, `
 			prebuilt_apex {
@@ -6713,7 +6702,7 @@
 			name: "libfoo",
 			jars: ["libfoo.jar"],
 		}
-`, "", transform)
+`, "", preparer)
 	})
 
 	t.Run("prebuilt no source", func(t *testing.T) {
@@ -6735,7 +6724,7 @@
 			name: "libfoo",
 			jars: ["libfoo.jar"],
 		}
-`, "", transform)
+`, "", preparer)
 	})
 }
 
diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go
index aa0d9c4..d447d70 100644
--- a/apex/boot_image_test.go
+++ b/apex/boot_image_test.go
@@ -19,7 +19,6 @@
 	"testing"
 
 	"android/soong/android"
-	"android/soong/dexpreopt"
 	"android/soong/java"
 )
 
@@ -42,8 +41,7 @@
 	result := android.GroupFixturePreparers(
 		prepareForTestWithBootImage,
 		// Configure some libraries in the art and framework boot images.
-		dexpreopt.FixtureSetArtBootJars("com.android.art:baz", "com.android.art:quuz"),
-		dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar"),
+		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "platform:foo", "platform:bar"),
 		prepareForTestWithArtApex,
 
 		java.PrepareForTestWithJavaSdkLibraryFiles,
@@ -169,7 +167,7 @@
 		prepareForTestWithArtApex,
 
 		// Configure some libraries in the art boot image.
-		dexpreopt.FixtureSetArtBootJars("com.android.art:foo", "com.android.art:bar"),
+		java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
 	).RunTestWithBp(t, `
 		apex {
 			name: "com.android.art",
@@ -264,7 +262,7 @@
 		}),
 
 		// Configure some libraries in the art boot image.
-		dexpreopt.FixtureSetArtBootJars("com.android.art:foo", "com.android.art:bar"),
+		java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
 	).RunTestWithBp(t, `
 		prebuilt_apex {
 			name: "com.android.art",
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 2ea6401..74830d3 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -18,7 +18,6 @@
 	"testing"
 
 	"android/soong/android"
-	"android/soong/dexpreopt"
 	"android/soong/java"
 	"github.com/google/blueprint"
 )
@@ -37,9 +36,8 @@
 		prepareForTestWithArtApex,
 		prepareForTestWithMyapex,
 		// Configure some libraries in the art and framework boot images.
-		dexpreopt.FixtureSetArtBootJars("com.android.art:baz", "com.android.art:quuz"),
-		dexpreopt.FixtureSetBootJars("platform:foo"),
-		dexpreopt.FixtureSetUpdatableBootJars("myapex:bar"),
+		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "platform:foo"),
+		java.FixtureConfigureUpdatableBootJars("myapex:bar"),
 		java.PrepareForTestWithJavaSdkLibraryFiles,
 		java.FixtureWithLastReleaseApis("foo"),
 	).RunTestWithBp(t, `
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 465283d..e4dfc97 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -244,6 +244,120 @@
 	}
 }
 
+func checkInstallPartition(t *testing.T, ctx *android.TestContext, name, variant, expected string) {
+	mod := ctx.ModuleForTests(name, variant).Module().(*Module)
+	partitionDefined := false
+	checkPartition := func(specific bool, partition string) {
+		if specific {
+			if expected != partition && !partitionDefined {
+				// The variant is installed to the 'partition'
+				t.Errorf("%s variant of %q must not be installed to %s partition", variant, name, partition)
+			}
+			partitionDefined = true
+		} else {
+			// The variant is not installed to the 'partition'
+			if expected == partition {
+				t.Errorf("%s variant of %q must be installed to %s partition", variant, name, partition)
+			}
+		}
+	}
+	socSpecific := func(m *Module) bool {
+		return m.SocSpecific() || m.socSpecificModuleContext()
+	}
+	deviceSpecific := func(m *Module) bool {
+		return m.DeviceSpecific() || m.deviceSpecificModuleContext()
+	}
+	productSpecific := func(m *Module) bool {
+		return m.ProductSpecific() || m.productSpecificModuleContext()
+	}
+	systemExtSpecific := func(m *Module) bool {
+		return m.SystemExtSpecific()
+	}
+	checkPartition(socSpecific(mod), "vendor")
+	checkPartition(deviceSpecific(mod), "odm")
+	checkPartition(productSpecific(mod), "product")
+	checkPartition(systemExtSpecific(mod), "system_ext")
+	if !partitionDefined && expected != "system" {
+		t.Errorf("%s variant of %q is expected to be installed to %s partition,"+
+			" but installed to system partition", variant, name, expected)
+	}
+}
+
+func TestInstallPartition(t *testing.T) {
+	t.Helper()
+	ctx := prepareForCcTest.RunTestWithBp(t, `
+		cc_library {
+			name: "libsystem",
+		}
+		cc_library {
+			name: "libsystem_ext",
+			system_ext_specific: true,
+		}
+		cc_library {
+			name: "libproduct",
+			product_specific: true,
+		}
+		cc_library {
+			name: "libvendor",
+			vendor: true,
+		}
+		cc_library {
+			name: "libodm",
+			device_specific: true,
+		}
+		cc_library {
+			name: "liball_available",
+			vendor_available: true,
+			product_available: true,
+		}
+		cc_library {
+			name: "libsystem_ext_all_available",
+			system_ext_specific: true,
+			vendor_available: true,
+			product_available: true,
+		}
+		cc_library {
+			name: "liball_available_odm",
+			odm_available: true,
+			product_available: true,
+		}
+		cc_library {
+			name: "libproduct_vendoravailable",
+			product_specific: true,
+			vendor_available: true,
+		}
+		cc_library {
+			name: "libproduct_odmavailable",
+			product_specific: true,
+			odm_available: true,
+		}
+	`).TestContext
+
+	checkInstallPartition(t, ctx, "libsystem", coreVariant, "system")
+	checkInstallPartition(t, ctx, "libsystem_ext", coreVariant, "system_ext")
+	checkInstallPartition(t, ctx, "libproduct", productVariant, "product")
+	checkInstallPartition(t, ctx, "libvendor", vendorVariant, "vendor")
+	checkInstallPartition(t, ctx, "libodm", vendorVariant, "odm")
+
+	checkInstallPartition(t, ctx, "liball_available", coreVariant, "system")
+	checkInstallPartition(t, ctx, "liball_available", productVariant, "product")
+	checkInstallPartition(t, ctx, "liball_available", vendorVariant, "vendor")
+
+	checkInstallPartition(t, ctx, "libsystem_ext_all_available", coreVariant, "system_ext")
+	checkInstallPartition(t, ctx, "libsystem_ext_all_available", productVariant, "product")
+	checkInstallPartition(t, ctx, "libsystem_ext_all_available", vendorVariant, "vendor")
+
+	checkInstallPartition(t, ctx, "liball_available_odm", coreVariant, "system")
+	checkInstallPartition(t, ctx, "liball_available_odm", productVariant, "product")
+	checkInstallPartition(t, ctx, "liball_available_odm", vendorVariant, "odm")
+
+	checkInstallPartition(t, ctx, "libproduct_vendoravailable", productVariant, "product")
+	checkInstallPartition(t, ctx, "libproduct_vendoravailable", vendorVariant, "vendor")
+
+	checkInstallPartition(t, ctx, "libproduct_odmavailable", productVariant, "product")
+	checkInstallPartition(t, ctx, "libproduct_odmavailable", vendorVariant, "odm")
+}
+
 func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string,
 	isVndkSp bool, extends string, variant string) {
 
diff --git a/cc/gen.go b/cc/gen.go
index 83c019c..b152e02 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -111,9 +111,7 @@
 	return ret
 }
 
-func genAidl(ctx android.ModuleContext, rule *android.RuleBuilder, aidlFile android.Path,
-	outFile, depFile android.ModuleGenPath, aidlFlags string) android.Paths {
-
+func genAidl(ctx android.ModuleContext, rule *android.RuleBuilder, aidlFile android.Path, aidlFlags string) (cppFile android.OutputPath, headerFiles android.Paths) {
 	aidlPackage := strings.TrimSuffix(aidlFile.Rel(), aidlFile.Base())
 	baseName := strings.TrimSuffix(aidlFile.Base(), aidlFile.Ext())
 	shortName := baseName
@@ -126,6 +124,8 @@
 	}
 
 	outDir := android.PathForModuleGen(ctx, "aidl")
+	cppFile = outDir.Join(ctx, aidlPackage, baseName+".cpp")
+	depFile := outDir.Join(ctx, aidlPackage, baseName+".cpp.d")
 	headerI := outDir.Join(ctx, aidlPackage, baseName+".h")
 	headerBn := outDir.Join(ctx, aidlPackage, "Bn"+shortName+".h")
 	headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h")
@@ -142,14 +142,14 @@
 		Flag(aidlFlags).
 		Input(aidlFile).
 		OutputDir().
-		Output(outFile).
+		Output(cppFile).
 		ImplicitOutputs(android.WritablePaths{
 			headerI,
 			headerBn,
 			headerBp,
 		})
 
-	return android.Paths{
+	return cppFile, android.Paths{
 		headerI,
 		headerBn,
 		headerBp,
@@ -293,10 +293,9 @@
 				aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"),
 					android.PathForModuleGen(ctx, "aidl.sbox.textproto"))
 			}
-			cppFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp")
-			depFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp.d")
+			cppFile, aidlHeaders := genAidl(ctx, aidlRule, srcFile, buildFlags.aidlFlags)
 			srcFiles[i] = cppFile
-			aidlHeaders := genAidl(ctx, aidlRule, srcFile, cppFile, depFile, buildFlags.aidlFlags)
+
 			info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...)
 			// Use the generated headers as order only deps to ensure that they are up to date when
 			// needed.
diff --git a/cc/image.go b/cc/image.go
index afe6a0e..ca00ac9 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -49,21 +49,15 @@
 )
 
 func (ctx *moduleContext) ProductSpecific() bool {
-	// Additionally check if this module is inProduct() that means it is a "product" variant of a
-	// module. As well as product specific modules, product variants must be installed to /product.
-	return ctx.ModuleContext.ProductSpecific() || ctx.mod.InProduct()
+	return ctx.ModuleContext.ProductSpecific() || ctx.mod.productSpecificModuleContext()
 }
 
 func (ctx *moduleContext) SocSpecific() bool {
-	// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
-	// module. As well as SoC specific modules, vendor variants must be installed to /vendor
-	// unless they have "odm_available: true".
-	return ctx.ModuleContext.SocSpecific() || (ctx.mod.InVendor() && !ctx.mod.VendorVariantToOdm())
+	return ctx.ModuleContext.SocSpecific() || ctx.mod.socSpecificModuleContext()
 }
 
 func (ctx *moduleContext) DeviceSpecific() bool {
-	// Some vendor variants want to be installed to /odm by setting "odm_available: true".
-	return ctx.ModuleContext.DeviceSpecific() || (ctx.mod.InVendor() && ctx.mod.VendorVariantToOdm())
+	return ctx.ModuleContext.DeviceSpecific() || ctx.mod.deviceSpecificModuleContext()
 }
 
 func (ctx *moduleContextImpl) inProduct() bool {
@@ -86,6 +80,24 @@
 	return ctx.mod.InRecovery()
 }
 
+func (c *Module) productSpecificModuleContext() bool {
+	// Additionally check if this module is inProduct() that means it is a "product" variant of a
+	// module. As well as product specific modules, product variants must be installed to /product.
+	return c.InProduct()
+}
+
+func (c *Module) socSpecificModuleContext() bool {
+	// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
+	// module. As well as SoC specific modules, vendor variants must be installed to /vendor
+	// unless they have "odm_available: true".
+	return c.HasVendorVariant() && c.InVendor() && !c.VendorVariantToOdm()
+}
+
+func (c *Module) deviceSpecificModuleContext() bool {
+	// Some vendor variants want to be installed to /odm by setting "odm_available: true".
+	return c.InVendor() && c.VendorVariantToOdm()
+}
+
 // Returns true when this module is configured to have core and vendor variants.
 func (c *Module) HasVendorVariant() bool {
 	return Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Odm_available)
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 1863ece..431d621 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -75,8 +75,8 @@
 	return ctx
 }
 
-func newConfig(srcDir string) android.Config {
-	configuration, err := android.NewConfig(srcDir, bootstrap.CmdlineBuildDir(), bootstrap.CmdlineModuleListFile())
+func newConfig(srcDir, outDir string) android.Config {
+	configuration, err := android.NewConfig(srcDir, outDir, bootstrap.CmdlineModuleListFile())
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "%s", err)
 		os.Exit(1)
@@ -127,7 +127,7 @@
 }
 
 func writeMetrics(configuration android.Config) {
-	metricsFile := filepath.Join(bootstrap.CmdlineBuildDir(), "soong_build_metrics.pb")
+	metricsFile := filepath.Join(configuration.BuildDir(), "soong_build_metrics.pb")
 	err := android.WriteMetrics(configuration, metricsFile)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err)
@@ -193,7 +193,7 @@
 	usedVariablesFile := shared.JoinPath(outDir, "soong.environment.used")
 	// The top-level Blueprints file is passed as the first argument.
 	srcDir := filepath.Dir(flag.Arg(0))
-	configuration := newConfig(srcDir)
+	configuration := newConfig(srcDir, outDir)
 	extraNinjaDeps := []string{
 		configuration.ProductVariablesFileName,
 		shared.JoinPath(outDir, "soong.environment.used"),
@@ -203,10 +203,6 @@
 		configuration.SetAllowMissingDependencies()
 	}
 
-	// These two are here so that we restart a non-debugged soong_build when the
-	// user sets SOONG_DELVE the first time.
-	configuration.Getenv("SOONG_DELVE")
-	configuration.Getenv("SOONG_DELVE_PATH")
 	if shared.IsDebugging() {
 		// Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
 		// enabled even if it completed successfully.
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 3dcc416..29a8a39 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -61,7 +61,7 @@
 	Vendor_boot *bool
 
 	// Optional kernel commandline
-	Cmdline *string
+	Cmdline *string `android:"arch_variant"`
 
 	// File that contains bootconfig parameters. This can be set only when `vendor_boot` is true
 	// and `header_version` is greater than or equal to 4.
diff --git a/java/Android.bp b/java/Android.bp
index f8ba1b6..2a4b596 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -32,6 +32,7 @@
         "boot_image.go",
         "boot_jars.go",
         "builder.go",
+        "classpath_fragment.go",
         "device_host_converter.go",
         "dex.go",
         "dexpreopt.go",
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
new file mode 100644
index 0000000..adbe490
--- /dev/null
+++ b/java/classpath_fragment.go
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 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 java
+
+import (
+	"android/soong/android"
+)
+
+// Build rules and utilities to generate individual packages/modules/SdkExtensions/proto/classpaths.proto
+// config files based on build configuration to embed into /system and /apex on a device.
+//
+// See `derive_classpath` service that reads the configs at runtime and defines *CLASSPATH variables
+// on the device.
+
+type classpathType int
+
+const (
+	// Matches definition in packages/modules/SdkExtensions/proto/classpaths.proto
+	BOOTCLASSPATH classpathType = iota
+	DEX2OATBOOTCLASSPATH
+	SYSTEMSERVERCLASSPATH
+)
+
+func (c classpathType) String() string {
+	return [...]string{"BOOTCLASSPATH", "DEX2OATBOOTCLASSPATH", "SYSTEMSERVERCLASSPATH"}[c]
+}
+
+type classpathFragmentProperties struct {
+}
+
+// classpathFragment interface is implemented by a module that contributes jars to a *CLASSPATH
+// variables at runtime.
+type classpathFragment interface {
+	android.Module
+
+	classpathFragmentBase() *classpathFragmentBase
+}
+
+// classpathFragmentBase is meant to be embedded in any module types that implement classpathFragment;
+// such modules are expected to call initClasspathFragment().
+type classpathFragmentBase struct {
+	properties classpathFragmentProperties
+
+	classpathType classpathType
+
+	outputFilepath android.OutputPath
+}
+
+// Initializes classpathFragmentBase struct. Must be called by all modules that include classpathFragmentBase.
+func initClasspathFragment(c classpathFragment) {
+	base := c.classpathFragmentBase()
+	c.AddProperties(&base.properties)
+}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 641e19f..6ba5f35 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -15,8 +15,6 @@
 package java
 
 import (
-	"fmt"
-
 	"android/soong/android"
 )
 
@@ -27,7 +25,6 @@
 func RegisterHiddenApiSingletonComponents(ctx android.RegistrationContext) {
 	ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
 	ctx.RegisterSingletonType("hiddenapi_index", hiddenAPIIndexSingletonFactory)
-	ctx.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory)
 }
 
 var PrepareForTestWithHiddenApiBuildComponents = android.FixtureRegisterWithContext(RegisterHiddenApiSingletonComponents)
@@ -101,11 +98,15 @@
 // yet been created.
 func hiddenAPISingletonPaths(ctx android.PathContext) hiddenAPISingletonPathsStruct {
 	return ctx.Config().Once(hiddenAPISingletonPathsKey, func() interface{} {
+		// Make the paths relative to the out/soong/hiddenapi directory instead of to the out/soong/
+		// directory. This ensures that if they are used as java_resources they do not end up in a
+		// hiddenapi directory in the resulting APK.
+		hiddenapiDir := android.PathForOutput(ctx, "hiddenapi")
 		return hiddenAPISingletonPathsStruct{
-			flags:     android.PathForOutput(ctx, "hiddenapi", "hiddenapi-flags.csv"),
-			index:     android.PathForOutput(ctx, "hiddenapi", "hiddenapi-index.csv"),
-			metadata:  android.PathForOutput(ctx, "hiddenapi", "hiddenapi-unsupported.csv"),
-			stubFlags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-stub-flags.txt"),
+			flags:     hiddenapiDir.Join(ctx, "hiddenapi-flags.csv"),
+			index:     hiddenapiDir.Join(ctx, "hiddenapi-index.csv"),
+			metadata:  hiddenapiDir.Join(ctx, "hiddenapi-unsupported.csv"),
+			stubFlags: hiddenapiDir.Join(ctx, "hiddenapi-stub-flags.txt"),
 		}
 	}).(hiddenAPISingletonPathsStruct)
 }
@@ -388,51 +389,6 @@
 		Text(")")
 }
 
-type hiddenAPIFlagsProperties struct {
-	// name of the file into which the flags will be copied.
-	Filename *string
-}
-
-type hiddenAPIFlags struct {
-	android.ModuleBase
-
-	properties hiddenAPIFlagsProperties
-
-	outputFilePath android.OutputPath
-}
-
-func (h *hiddenAPIFlags) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	filename := String(h.properties.Filename)
-
-	inputPath := hiddenAPISingletonPaths(ctx).flags
-	h.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
-
-	// This ensures that outputFilePath has the correct name for others to
-	// use, as the source file may have a different name.
-	ctx.Build(pctx, android.BuildParams{
-		Rule:   android.Cp,
-		Output: h.outputFilePath,
-		Input:  inputPath,
-	})
-}
-
-func (h *hiddenAPIFlags) OutputFiles(tag string) (android.Paths, error) {
-	switch tag {
-	case "":
-		return android.Paths{h.outputFilePath}, nil
-	default:
-		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
-	}
-}
-
-// hiddenapi-flags provides access to the hiddenapi-flags.csv file generated during the build.
-func hiddenAPIFlagsFactory() android.Module {
-	module := &hiddenAPIFlags{}
-	module.AddProperties(&module.properties)
-	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
-	return module
-}
-
 func hiddenAPIIndexSingletonFactory() android.Singleton {
 	return &hiddenAPIIndexSingleton{}
 }
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 5c449e5..e5e1c25 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -23,12 +23,6 @@
 	"github.com/google/blueprint/proptools"
 )
 
-func fixtureSetBootJarsProductVariable(bootJars ...string) android.FixturePreparer {
-	return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
-		variables.BootJars = android.CreateTestConfiguredJarList(bootJars)
-	})
-}
-
 func fixtureSetPrebuiltHiddenApiDirProductVariable(prebuiltHiddenApiDir *string) android.FixturePreparer {
 	return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
 		variables.PrebuiltHiddenApiDir = prebuiltHiddenApiDir
@@ -41,7 +35,7 @@
 func TestHiddenAPISingleton(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		hiddenApiFixtureFactory,
-		fixtureSetBootJarsProductVariable("platform:foo"),
+		FixtureConfigureBootJars("platform:foo"),
 	).RunTestWithBp(t, `
 		java_library {
 			name: "foo",
@@ -61,7 +55,7 @@
 		hiddenApiFixtureFactory,
 		PrepareForTestWithJavaSdkLibraryFiles,
 		FixtureWithLastReleaseApis("bar"),
-		fixtureSetBootJarsProductVariable("platform:foo", "platform:bar"),
+		FixtureConfigureBootJars("platform:foo", "platform:bar"),
 	).RunTestWithBp(t, `
 		java_library {
 			name: "foo",
@@ -119,7 +113,7 @@
 
 	android.GroupFixturePreparers(
 		hiddenApiFixtureFactory,
-		fixtureSetBootJarsProductVariable("platform:foo"),
+		FixtureConfigureBootJars("platform:foo"),
 	).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorMessage)).
 		RunTestWithBp(t, `
 		java_library {
@@ -139,7 +133,7 @@
 func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		hiddenApiFixtureFactory,
-		fixtureSetBootJarsProductVariable("platform:foo"),
+		FixtureConfigureBootJars("platform:foo"),
 	).RunTestWithBp(t, `
 		java_import {
 			name: "foo",
@@ -157,7 +151,7 @@
 func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		hiddenApiFixtureFactory,
-		fixtureSetBootJarsProductVariable("platform:foo"),
+		FixtureConfigureBootJars("platform:foo"),
 	).RunTestWithBp(t, `
 		java_library {
 			name: "foo",
@@ -185,7 +179,7 @@
 func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		hiddenApiFixtureFactory,
-		fixtureSetBootJarsProductVariable("platform:foo"),
+		FixtureConfigureBootJars("platform:foo"),
 	).RunTestWithBp(t, `
 		java_library {
 			name: "foo",
@@ -295,7 +289,7 @@
 
 	result := android.GroupFixturePreparers(
 		hiddenApiFixtureFactory,
-		fixtureSetBootJarsProductVariable("platform:foo"),
+		FixtureConfigureBootJars("platform:foo"),
 		fixtureSetPrebuiltHiddenApiDirProductVariable(&prebuiltHiddenApiDir),
 	).RunTestWithBp(t, `
 		java_import {
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index e292d80..d98ce67 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -15,6 +15,8 @@
 package java
 
 import (
+	"fmt"
+
 	"android/soong/android"
 	"android/soong/dexpreopt"
 	"github.com/google/blueprint"
@@ -69,6 +71,15 @@
 	//
 	// Currently only for testing.
 	fragments []android.Module
+
+	// Path to the monolithic hiddenapi-flags.csv file.
+	hiddenAPIFlagsCSV android.OutputPath
+
+	// Path to the monolithic hiddenapi-index.csv file.
+	hiddenAPIIndexCSV android.OutputPath
+
+	// Path to the monolithic hiddenapi-unsupported.csv file.
+	hiddenAPIMetadataCSV android.OutputPath
 }
 
 // ApexVariantReference specifies a particular apex variant of a module.
@@ -98,6 +109,34 @@
 	return m
 }
 
+var _ android.OutputFileProducer = (*platformBootclasspathModule)(nil)
+
+// A minimal AndroidMkEntries is needed in order to support the dists property.
+func (b *platformBootclasspathModule) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{
+		{
+			Class: "FAKE",
+			// Need at least one output file in order for this to take effect.
+			OutputFile: android.OptionalPathForPath(b.hiddenAPIFlagsCSV),
+			Include:    "$(BUILD_PHONY_PACKAGE)",
+		},
+	}
+}
+
+// Make the hidden API files available from the platform-bootclasspath module.
+func (b *platformBootclasspathModule) OutputFiles(tag string) (android.Paths, error) {
+	switch tag {
+	case "hiddenapi-flags.csv":
+		return android.Paths{b.hiddenAPIFlagsCSV}, nil
+	case "hiddenapi-index.csv":
+		return android.Paths{b.hiddenAPIIndexCSV}, nil
+	case "hiddenapi-metadata.csv":
+		return android.Paths{b.hiddenAPIMetadataCSV}, nil
+	}
+
+	return nil, fmt.Errorf("unknown tag %s", tag)
+}
+
 func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorContext) {
 	if SkipDexpreoptBootJars(ctx) {
 		return
@@ -222,6 +261,25 @@
 // generateHiddenAPIBuildActions generates all the hidden API related build rules.
 func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module) {
 
+	// Save the paths to the monolithic files for retrieval via OutputFiles().
+	b.hiddenAPIFlagsCSV = hiddenAPISingletonPaths(ctx).flags
+	b.hiddenAPIIndexCSV = hiddenAPISingletonPaths(ctx).index
+	b.hiddenAPIMetadataCSV = hiddenAPISingletonPaths(ctx).metadata
+
+	// Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true. This is a performance
+	// optimization that can be used to reduce the incremental build time but as its name suggests it
+	// can be unsafe to use, e.g. when the changes affect anything that goes on the bootclasspath.
+	if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+		paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV}
+		for _, path := range paths {
+			ctx.Build(pctx, android.BuildParams{
+				Rule:   android.Touch,
+				Output: path,
+			})
+		}
+		return
+	}
+
 	moduleSpecificFlagsPaths := android.Paths{}
 	for _, module := range modules {
 		if h, ok := module.(hiddenAPIIntf); ok {
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index ebbe3a5..c740911 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -31,7 +31,7 @@
 func TestPlatformBootclasspath(t *testing.T) {
 	preparer := android.GroupFixturePreparers(
 		prepareForTestWithPlatformBootclasspath,
-		dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar"),
+		FixtureConfigureBootJars("platform:foo", "platform:bar"),
 		android.FixtureWithRootAndroidBp(`
 			platform_bootclasspath {
 				name: "platform-bootclasspath",
@@ -131,3 +131,44 @@
 		})
 	})
 }
+
+func TestPlatformBootclasspath_Dist(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForTestWithPlatformBootclasspath,
+		FixtureConfigureBootJars("platform:foo", "platform:bar"),
+		android.PrepareForTestWithAndroidMk,
+		android.FixtureWithRootAndroidBp(`
+			platform_bootclasspath {
+				name: "platform-bootclasspath",
+				dists: [
+					{
+						targets: ["droidcore"],
+						tag: "hiddenapi-flags.csv",
+					},
+				],
+			}
+
+			java_library {
+				name: "bar",
+				srcs: ["a.java"],
+				system_modules: "none",
+				sdk_version: "none",
+				compile_dex: true,
+			}
+
+			java_library {
+				name: "foo",
+				srcs: ["a.java"],
+				system_modules: "none",
+				sdk_version: "none",
+				compile_dex: true,
+			}
+		`),
+	).RunTest(t)
+
+	platformBootclasspath := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
+	entries := android.AndroidMkEntriesForTest(t, result.TestContext, platformBootclasspath)
+	goals := entries[0].GetDistForGoals(platformBootclasspath)
+	android.AssertStringEquals(t, "platform dist goals phony", ".PHONY: droidcore\n", goals[0])
+	android.AssertStringEquals(t, "platform dist goals call", "$(call dist-for-goals,droidcore,out/soong/hiddenapi/hiddenapi-flags.csv:hiddenapi-flags.csv)\n", android.StringRelativeToTop(result.Config, goals[1]))
+}
diff --git a/java/testing.go b/java/testing.go
index 6ebc747..aee0710 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -178,6 +178,43 @@
 	return fs
 }
 
+// FixtureConfigureBootJars configures the boot jars in both the dexpreopt.GlobalConfig and
+// Config.productVariables structs. As a side effect that enables dexpreopt.
+func FixtureConfigureBootJars(bootJars ...string) android.FixturePreparer {
+	artBootJars := []string{}
+	for _, j := range bootJars {
+		artApex := false
+		for _, artApexName := range artApexNames {
+			if strings.HasPrefix(j, artApexName+":") {
+				artApex = true
+				break
+			}
+		}
+		if artApex {
+			artBootJars = append(artBootJars, j)
+		}
+	}
+	return android.GroupFixturePreparers(
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.BootJars = android.CreateTestConfiguredJarList(bootJars)
+		}),
+		dexpreopt.FixtureSetBootJars(bootJars...),
+		dexpreopt.FixtureSetArtBootJars(artBootJars...),
+	)
+}
+
+// FixtureConfigureUpdatableBootJars configures the updatable boot jars in both the
+// dexpreopt.GlobalConfig and Config.productVariables structs. As a side effect that enables
+// dexpreopt.
+func FixtureConfigureUpdatableBootJars(bootJars ...string) android.FixturePreparer {
+	return android.GroupFixturePreparers(
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.UpdatableBootJars = android.CreateTestConfiguredJarList(bootJars)
+		}),
+		dexpreopt.FixtureSetUpdatableBootJars(bootJars...),
+	)
+}
+
 // registerRequiredBuildComponentsForTest registers the build components used by
 // PrepareForTestWithJavaDefaultModules.
 //
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 6035e68..6b0a943 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -70,10 +70,12 @@
 }
 
 func (fuzzer *fuzzDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
-	deps.StaticLibs = append(deps.StaticLibs,
-		config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
-	deps.SharedLibs = append(deps.SharedLibs,
-		config.LibclangRuntimeLibrary(ctx.toolchain(), "asan"))
+	if libFuzzerRuntimeLibrary := config.LibFuzzerRuntimeLibrary(ctx.toolchain()); libFuzzerRuntimeLibrary != "" {
+		deps.StaticLibs = append(deps.StaticLibs, libFuzzerRuntimeLibrary)
+	}
+	if libclangRuntimeLibrary := config.LibclangRuntimeLibrary(ctx.toolchain(), "asan"); libclangRuntimeLibrary != "" {
+		deps.SharedLibs = append(deps.SharedLibs, libclangRuntimeLibrary)
+	}
 	deps.SharedLibs = append(deps.SharedLibs, "libc++")
 	deps.Rlibs = append(deps.Rlibs, "liblibfuzzer_sys")
 
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index b2f7b2b..5271f8d 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -295,6 +295,118 @@
   grep -q "Make it so" out/soong/build.ninja || fail "New action not present"
 }
 
+# Tests a glob in a build= statement in an Android.bp file, which is interpreted
+# during bootstrapping.
+function test_glob_during_bootstrapping() {
+  setup
+
+  mkdir -p a
+  cat > a/Android.bp <<'EOF'
+build=["foo*.bp"]
+EOF
+  cat > a/fooa.bp <<'EOF'
+bootstrap_go_package {
+  name: "picard-soong-rules",
+  pkgPath: "android/soong/picard",
+  deps: [
+    "blueprint",
+    "soong",
+    "soong-android",
+  ],
+  srcs: [
+    "picard.go",
+  ],
+  pluginFor: ["soong_build"],
+}
+EOF
+
+  cat > a/picard.go <<'EOF'
+package picard
+
+import (
+  "android/soong/android"
+  "github.com/google/blueprint"
+)
+
+var (
+  pctx = android.NewPackageContext("picard")
+)
+
+func init() {
+  android.RegisterSingletonType("picard", PicardSingleton)
+}
+
+func PicardSingleton() android.Singleton {
+  return &picardSingleton{}
+}
+
+type picardSingleton struct{}
+
+var Message = "Make it so."
+
+func (p *picardSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+  picardRule := ctx.Rule(pctx, "picard",
+    blueprint.RuleParams{
+      Command: "echo " + Message + " > ${out}",
+      CommandDeps: []string{},
+      Description: "Something quotable",
+    })
+
+  outputFile := android.PathForOutput(ctx, "picard", "picard.txt")
+  var deps android.Paths
+
+  ctx.Build(pctx, android.BuildParams{
+    Rule: picardRule,
+    Output: outputFile,
+    Inputs: deps,
+  })
+}
+
+EOF
+
+  run_soong
+  local mtime1=$(stat -c "%y" out/soong/build.ninja)
+
+  grep -q "Make it so" out/soong/build.ninja || fail "Original action not present"
+
+  cat > a/foob.bp <<'EOF'
+bootstrap_go_package {
+  name: "worf-soong-rules",
+  pkgPath: "android/soong/worf",
+  deps: [
+    "blueprint",
+    "soong",
+    "soong-android",
+    "picard-soong-rules",
+  ],
+  srcs: [
+    "worf.go",
+  ],
+  pluginFor: ["soong_build"],
+}
+EOF
+
+  cat > a/worf.go <<'EOF'
+package worf
+
+import "android/soong/picard"
+
+func init() {
+   picard.Message = "Engage."
+}
+EOF
+
+  run_soong
+  local mtime2=$(stat -c "%y" out/soong/build.ninja)
+  if [[ "$mtime1" == "$mtime2" ]]; then
+    fail "Output Ninja file did not change"
+  fi
+
+  grep -q "Engage" out/soong/build.ninja || fail "New action not present"
+
+  grep -q "Make it so" out/soong/build.ninja && fail "Original action still present"
+}
+
 function test_null_build_after_docs {
   setup
   run_soong
@@ -326,5 +438,6 @@
 test_change_android_bp
 test_delete_android_bp
 test_add_file_to_soong_build
+test_glob_during_bootstrapping
 test_soong_build_rerun_iff_environment_changes
 test_dump_json_module_graph
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 9afcb88..0089075 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -104,6 +104,11 @@
 	args.GlobFile = shared.JoinPath(config.SoongOutDir(), ".bootstrap/soong-build-globs.ninja")
 	args.GeneratingPrimaryBuilder = true
 
+	args.DelveListen = os.Getenv("SOONG_DELVE")
+	if args.DelveListen != "" {
+		args.DelvePath = shared.ResolveDelveBinary()
+	}
+
 	blueprintCtx := blueprint.NewContext()
 	blueprintCtx.SetIgnoreUnknownModuleTypes(true)
 	blueprintConfig := BlueprintConfig{
@@ -138,11 +143,6 @@
 
 	soongBuildEnv := config.Environment().Copy()
 	soongBuildEnv.Set("TOP", os.Getenv("TOP"))
-	// These two dependencies are read from bootstrap.go, but also need to be here
-	// so that soong_build can declare a dependency on them
-	soongBuildEnv.Set("SOONG_DELVE", os.Getenv("SOONG_DELVE"))
-	soongBuildEnv.Set("SOONG_DELVE_PATH", os.Getenv("SOONG_DELVE_PATH"))
-	soongBuildEnv.Set("SOONG_OUTDIR", config.SoongOutDir())
 	// For Bazel mixed builds.
 	soongBuildEnv.Set("BAZEL_PATH", "./tools/bazel")
 	soongBuildEnv.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
@@ -215,13 +215,6 @@
 		// This is currently how the command line to invoke soong_build finds the
 		// root of the source tree and the output root
 		ninjaEnv.Set("TOP", os.Getenv("TOP"))
-		ninjaEnv.Set("SOONG_OUTDIR", config.SoongOutDir())
-
-		// For debugging
-		if os.Getenv("SOONG_DELVE") != "" {
-			ninjaEnv.Set("SOONG_DELVE", os.Getenv("SOONG_DELVE"))
-			ninjaEnv.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary())
-		}
 
 		cmd.Environment = &ninjaEnv
 		cmd.Sandbox = soongSandbox
diff --git a/zip/zip.go b/zip/zip.go
index a6490d4..84e974b 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -292,11 +292,11 @@
 				continue
 			}
 
-			globbed, _, err := z.fs.Glob(s, nil, followSymlinks)
+			result, err := z.fs.Glob(s, nil, followSymlinks)
 			if err != nil {
 				return err
 			}
-			if len(globbed) == 0 {
+			if len(result.Matches) == 0 {
 				err := &os.PathError{
 					Op:   "lstat",
 					Path: s,
@@ -308,7 +308,7 @@
 					return err
 				}
 			}
-			srcs = append(srcs, globbed...)
+			srcs = append(srcs, result.Matches...)
 		}
 		if fa.GlobDir != "" {
 			if exists, isDir, err := z.fs.Exists(fa.GlobDir); err != nil {
@@ -336,11 +336,11 @@
 					return err
 				}
 			}
-			globbed, _, err := z.fs.Glob(filepath.Join(fa.GlobDir, "**/*"), nil, followSymlinks)
+			result, err := z.fs.Glob(filepath.Join(fa.GlobDir, "**/*"), nil, followSymlinks)
 			if err != nil {
 				return err
 			}
-			srcs = append(srcs, globbed...)
+			srcs = append(srcs, result.Matches...)
 		}
 		for _, src := range srcs {
 			err := fillPathPairs(fa, src, &pathMappings, args.NonDeflatedFiles, noCompression)