Merge changes from topics "errProne_bp2build_manually_enabled", "error_prone_config" into main

* changes:
  Bp2build for errorprone modules that manually enabled/disabled it
  Make errorprone a configurable attribute for bazel conversion
diff --git a/android/Android.bp b/android/Android.bp
index fc5198f..f5bb785 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -107,6 +107,7 @@
         "bazel_test.go",
         "config_test.go",
         "config_bp2build_test.go",
+        "configured_jars_test.go",
         "csuite_config_test.go",
         "defaults_test.go",
         "depset_test.go",
diff --git a/android/bazel.go b/android/bazel.go
index 1bfbdec..0d2c777 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -255,7 +255,7 @@
 	if b.ShouldConvertWithBp2build(ctx) {
 		return bp2buildModuleLabel(ctx, module)
 	}
-	panic(fmt.Errorf("requested non-existent label for module ", module.Name()))
+	panic(fmt.Errorf("requested non-existent label for module %s", module.Name()))
 }
 
 type Bp2BuildConversionAllowlist struct {
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 872e908..2f5ff64 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -198,7 +198,7 @@
 	}
 	labels := expandSrcsForBazel(ctx, paths, excluded)
 	labels.Excludes = excludeLabels.Includes
-	labels = transformSubpackagePaths(ctx, labels)
+	labels = TransformSubpackagePaths(ctx.Config(), ctx.ModuleDir(), labels)
 	return labels
 }
 
@@ -237,7 +237,7 @@
 // if the "async_safe" directory is actually a package and not just a directory.
 //
 // In particular, paths that extend into packages are transformed into absolute labels beginning with //.
-func transformSubpackagePath(ctx BazelConversionPathContext, path bazel.Label) bazel.Label {
+func transformSubpackagePath(cfg Config, dir string, path bazel.Label) bazel.Label {
 	var newPath bazel.Label
 
 	// Don't transform OriginalModuleName
@@ -281,7 +281,7 @@
 	for i := len(pathComponents) - 1; i >= 0; i-- {
 		pathComponent := pathComponents[i]
 		var sep string
-		if !foundPackageBoundary && isPackageBoundary(ctx.Config(), ctx.ModuleDir(), pathComponents, i) {
+		if !foundPackageBoundary && isPackageBoundary(cfg, dir, pathComponents, i) {
 			sep = ":"
 			foundPackageBoundary = true
 		} else {
@@ -295,7 +295,7 @@
 	}
 	if foundPackageBoundary {
 		// Ensure paths end up looking like //bionic/... instead of //./bionic/...
-		moduleDir := ctx.ModuleDir()
+		moduleDir := dir
 		if strings.HasPrefix(moduleDir, ".") {
 			moduleDir = moduleDir[1:]
 		}
@@ -313,13 +313,13 @@
 
 // Transform paths to acknowledge package boundaries
 // See transformSubpackagePath() for more information
-func transformSubpackagePaths(ctx BazelConversionPathContext, paths bazel.LabelList) bazel.LabelList {
+func TransformSubpackagePaths(cfg Config, dir string, paths bazel.LabelList) bazel.LabelList {
 	var newPaths bazel.LabelList
 	for _, include := range paths.Includes {
-		newPaths.Includes = append(newPaths.Includes, transformSubpackagePath(ctx, include))
+		newPaths.Includes = append(newPaths.Includes, transformSubpackagePath(cfg, dir, include))
 	}
 	for _, exclude := range paths.Excludes {
-		newPaths.Excludes = append(newPaths.Excludes, transformSubpackagePath(ctx, exclude))
+		newPaths.Excludes = append(newPaths.Excludes, transformSubpackagePath(cfg, dir, exclude))
 	}
 	return newPaths
 }
diff --git a/android/bazel_paths_test.go b/android/bazel_paths_test.go
index 450bf76..60c0a14 100644
--- a/android/bazel_paths_test.go
+++ b/android/bazel_paths_test.go
@@ -175,7 +175,7 @@
 		"./z/b.c": "z/b.c",
 	}
 	for in, out := range pairs {
-		actual := transformSubpackagePath(ctx, bazel.Label{Label: in}).Label
+		actual := transformSubpackagePath(ctx.Config(), ctx.ModuleDir(), bazel.Label{Label: in}).Label
 		if actual != out {
 			t.Errorf("expected:\n%v\nactual:\n%v", out, actual)
 		}
diff --git a/android/configured_jars.go b/android/configured_jars.go
index 1281bae..c7b808f 100644
--- a/android/configured_jars.go
+++ b/android/configured_jars.go
@@ -178,7 +178,7 @@
 func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) WritablePaths {
 	paths := make(WritablePaths, l.Len())
 	for i, jar := range l.jars {
-		paths[i] = dir.Join(ctx, ModuleStem(jar)+".jar")
+		paths[i] = dir.Join(ctx, ModuleStem(ctx.Config(), l.Apex(i), jar)+".jar")
 	}
 	return paths
 }
@@ -187,8 +187,8 @@
 // prefix.
 func (l *ConfiguredJarList) BuildPathsByModule(ctx PathContext, dir OutputPath) map[string]WritablePath {
 	paths := map[string]WritablePath{}
-	for _, jar := range l.jars {
-		paths[jar] = dir.Join(ctx, ModuleStem(jar)+".jar")
+	for i, jar := range l.jars {
+		paths[jar] = dir.Join(ctx, ModuleStem(ctx.Config(), l.Apex(i), jar)+".jar")
 	}
 	return paths
 }
@@ -228,24 +228,32 @@
 	return json.Marshal(list)
 }
 
-// ModuleStem hardcodes the stem of framework-minus-apex to return "framework".
-//
-// TODO(b/139391334): hard coded until we find a good way to query the stem of a
-// module before any other mutators are run.
-func ModuleStem(module string) string {
-	if module == "framework-minus-apex" {
-		return "framework"
+func OverrideConfiguredJarLocationFor(cfg Config, apex string, jar string) (newApex string, newJar string) {
+	for _, entry := range cfg.productVariables.ConfiguredJarLocationOverrides {
+		tuple := strings.Split(entry, ":")
+		if len(tuple) != 4 {
+			panic("malformed configured jar location override '%s', expected format: <old_apex>:<old_jar>:<new_apex>:<new_jar>")
+		}
+		if apex == tuple[0] && jar == tuple[1] {
+			return tuple[2], tuple[3]
+		}
 	}
-	return module
+	return apex, jar
+}
+
+// ModuleStem returns the overridden jar name.
+func ModuleStem(cfg Config, apex string, jar string) string {
+	_, newJar := OverrideConfiguredJarLocationFor(cfg, apex, jar)
+	return newJar
 }
 
 // DevicePaths computes the on-device paths for the list of (apex, jar) pairs,
 // based on the operating system.
 func (l *ConfiguredJarList) DevicePaths(cfg Config, ostype OsType) []string {
 	paths := make([]string, l.Len())
-	for i, jar := range l.jars {
-		apex := l.apexes[i]
-		name := ModuleStem(jar) + ".jar"
+	for i := 0; i < l.Len(); i++ {
+		apex, jar := OverrideConfiguredJarLocationFor(cfg, l.Apex(i), l.Jar(i))
+		name := jar + ".jar"
 
 		var subdir string
 		if apex == "platform" {
diff --git a/android/configured_jars_test.go b/android/configured_jars_test.go
new file mode 100644
index 0000000..32c3613
--- /dev/null
+++ b/android/configured_jars_test.go
@@ -0,0 +1,46 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"testing"
+)
+
+func TestOverrideConfiguredJarLocationFor(t *testing.T) {
+	cfg := NullConfig("", "")
+
+	cfg.productVariables = productVariables{
+		ConfiguredJarLocationOverrides: []string{
+			"platform:libfoo-old:com.android.foo:libfoo-new",
+			"com.android.bar:libbar-old:platform:libbar-new",
+		},
+	}
+
+	apex, jar := OverrideConfiguredJarLocationFor(cfg, "platform", "libfoo-old")
+	AssertStringEquals(t, "", "com.android.foo", apex)
+	AssertStringEquals(t, "", "libfoo-new", jar)
+
+	apex, jar = OverrideConfiguredJarLocationFor(cfg, "platform", "libbar-old")
+	AssertStringEquals(t, "", "platform", apex)
+	AssertStringEquals(t, "", "libbar-old", jar)
+
+	apex, jar = OverrideConfiguredJarLocationFor(cfg, "com.android.bar", "libbar-old")
+	AssertStringEquals(t, "", "platform", apex)
+	AssertStringEquals(t, "", "libbar-new", jar)
+
+	apex, jar = OverrideConfiguredJarLocationFor(cfg, "platform", "libbar-old")
+	AssertStringEquals(t, "", "platform", apex)
+	AssertStringEquals(t, "", "libbar-old", jar)
+}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 155fbdf..0438eb8 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -582,10 +582,8 @@
 
 		// Add copy rules to the manifest to copy each output file from the sbox directory.
 		// to the output directory after running the commands.
-		sboxOutputs := make([]string, len(outputs))
-		for i, output := range outputs {
+		for _, output := range outputs {
 			rel := Rel(r.ctx, r.outDir.String(), output.String())
-			sboxOutputs[i] = filepath.Join(sboxOutDir, rel)
 			command.CopyAfter = append(command.CopyAfter, &sbox_proto.Copy{
 				From: proto.String(filepath.Join(sboxOutSubDir, rel)),
 				To:   proto.String(output.String()),
diff --git a/android/variable.go b/android/variable.go
index 3bec854..4442a09 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -401,9 +401,10 @@
 
 	WithDexpreopt bool `json:",omitempty"`
 
-	ManifestPackageNameOverrides []string `json:",omitempty"`
-	CertificateOverrides         []string `json:",omitempty"`
-	PackageNameOverrides         []string `json:",omitempty"`
+	ManifestPackageNameOverrides   []string `json:",omitempty"`
+	CertificateOverrides           []string `json:",omitempty"`
+	PackageNameOverrides           []string `json:",omitempty"`
+	ConfiguredJarLocationOverrides []string `json:",omitempty"`
 
 	ApexGlobalMinSdkVersionOverride *string `json:",omitempty"`
 
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 7be8477..f30f7f6 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -297,6 +297,7 @@
 			// Configure some libraries in the art bootclasspath_fragment that match the source
 			// bootclasspath_fragment's contents property.
 			java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+			dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:foo", "com.android.art:bar"),
 			addSource("foo", "bar"),
 			java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
 		).RunTest(t)
@@ -315,7 +316,7 @@
 
 		// Make sure that the source bootclasspath_fragment copies its dex files to the predefined
 		// locations for the art image.
-		module := result.ModuleForTests("art-bootclasspath-fragment", "android_common_apex10000")
+		module := result.ModuleForTests("dex_bootjars", "android_common")
 		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
 	})
 
@@ -364,6 +365,7 @@
 			// Configure some libraries in the art bootclasspath_fragment that match the source
 			// bootclasspath_fragment's contents property.
 			java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+			dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:foo", "com.android.art:bar"),
 			addSource("foo", "bar"),
 
 			// Make sure that a preferred prebuilt with consistent contents doesn't affect the apex.
@@ -386,7 +388,7 @@
 
 		// Make sure that the prebuilt bootclasspath_fragment copies its dex files to the predefined
 		// locations for the art image.
-		module := result.ModuleForTests("prebuilt_art-bootclasspath-fragment", "android_common_com.android.art")
+		module := result.ModuleForTests("dex_bootjars", "android_common")
 		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
 	})
 
@@ -462,6 +464,7 @@
 
 		// Configure some libraries in the art bootclasspath_fragment.
 		java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+		dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:foo", "com.android.art:bar"),
 		java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
 	)
 
@@ -537,7 +540,7 @@
 			`prebuilt_foo`,
 		})
 
-		module := result.ModuleForTests("art-bootclasspath-fragment", "android_common_com.android.art")
+		module := result.ModuleForTests("dex_bootjars", "android_common")
 		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
 	})
 
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index ff8f912..2e828ca 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -138,8 +138,8 @@
 		prepareForTestWithArtApex,
 	).RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt))
 
-	platformBootclasspath := result.ModuleForTests("platform-bootclasspath", "android_common")
-	rule := platformBootclasspath.Output(ruleFile)
+	dexBootJars := result.ModuleForTests("dex_bootjars", "android_common")
+	rule := dexBootJars.Output(ruleFile)
 
 	inputs := rule.Implicits.Strings()
 	sort.Strings(inputs)
@@ -162,8 +162,8 @@
 		"out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar",
 		"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
 		"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
-		"out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art/boot.prof",
-		"out/soong/.intermediates/platform-bootclasspath/android_common/boot/boot.prof",
+		"out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof",
+		"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
 	}
 
 	expectedOutputs := []string{
@@ -200,7 +200,7 @@
 		"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
 		"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
 		"out/soong/.intermediates/com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
-		"out/soong/.intermediates/platform-bootclasspath/android_common/boot/boot.prof",
+		"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
 	}
 
 	expectedOutputs := []string{
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 782a88c..f889693 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -19,6 +19,7 @@
         "testing.go",
     ],
     deps: [
+        "blueprint-bootstrap",
         "soong-aidl-library",
         "soong-android",
         "soong-android-allowlists",
@@ -37,6 +38,7 @@
         "soong-ui-metrics",
     ],
     testSrcs: [
+        "go_conversion_test.go",
         "aar_conversion_test.go",
         "aidl_library_conversion_test.go",
         "android_app_certificate_conversion_test.go",
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 46a5bd8..a817386 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -30,6 +30,7 @@
 	"android/soong/starlark_fmt"
 	"android/soong/ui/metrics/bp2build_metrics_proto"
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/bootstrap"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -252,6 +253,235 @@
 	return r.buildFileToTargets
 }
 
+// struct to store state of go bazel targets
+// this implements bp2buildModule interface and is passed to generateBazelTargets
+type goBazelTarget struct {
+	targetName            string
+	targetPackage         string
+	bazelRuleClass        string
+	bazelRuleLoadLocation string
+	bazelAttributes       []interface{}
+}
+
+var _ bp2buildModule = (*goBazelTarget)(nil)
+
+func (g goBazelTarget) TargetName() string {
+	return g.targetName
+}
+
+func (g goBazelTarget) TargetPackage() string {
+	return g.targetPackage
+}
+
+func (g goBazelTarget) BazelRuleClass() string {
+	return g.bazelRuleClass
+}
+
+func (g goBazelTarget) BazelRuleLoadLocation() string {
+	return g.bazelRuleLoadLocation
+}
+
+func (g goBazelTarget) BazelAttributes() []interface{} {
+	return g.bazelAttributes
+}
+
+// Creates a target_compatible_with entry that is *not* compatible with android
+func targetNotCompatibleWithAndroid() bazel.LabelListAttribute {
+	ret := bazel.LabelListAttribute{}
+	ret.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid,
+		bazel.MakeLabelList(
+			[]bazel.Label{
+				bazel.Label{
+					Label: "@platforms//:incompatible",
+				},
+			},
+		),
+	)
+	return ret
+}
+
+// helper function to return labels for srcs used in bootstrap_go_package and bootstrap_go_binary
+// this function has the following limitations which make it unsuitable for widespread use
+// - wildcard patterns in srcs
+// This is ok for go since build/blueprint does not support it.
+//
+// Prefer to use `BazelLabelForModuleSrc` instead
+func goSrcLabels(cfg android.Config, moduleDir string, srcs []string, linuxSrcs, darwinSrcs []string) bazel.LabelListAttribute {
+	labels := func(srcs []string) bazel.LabelList {
+		ret := []bazel.Label{}
+		for _, src := range srcs {
+			srcLabel := bazel.Label{
+				Label: src,
+			}
+			ret = append(ret, srcLabel)
+		}
+		// Respect package boundaries
+		return android.TransformSubpackagePaths(
+			cfg,
+			moduleDir,
+			bazel.MakeLabelList(ret),
+		)
+	}
+
+	ret := bazel.LabelListAttribute{}
+	// common
+	ret.SetSelectValue(bazel.NoConfigAxis, "", labels(srcs))
+	// linux
+	ret.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsLinux, labels(linuxSrcs))
+	// darwin
+	ret.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsDarwin, labels(darwinSrcs))
+	return ret
+}
+
+func goDepLabels(deps []string, goModulesMap nameToGoLibraryModule) bazel.LabelListAttribute {
+	labels := []bazel.Label{}
+	for _, dep := range deps {
+		moduleDir := goModulesMap[dep].Dir
+		if moduleDir == "." {
+			moduleDir = ""
+		}
+		label := bazel.Label{
+			Label: fmt.Sprintf("//%s:%s", moduleDir, dep),
+		}
+		labels = append(labels, label)
+	}
+	return bazel.MakeLabelListAttribute(bazel.MakeLabelList(labels))
+}
+
+// attributes common to blueprint_go_binary and bootstap_go_package
+type goAttributes struct {
+	Importpath             bazel.StringAttribute
+	Srcs                   bazel.LabelListAttribute
+	Deps                   bazel.LabelListAttribute
+	Target_compatible_with bazel.LabelListAttribute
+}
+
+func generateBazelTargetsGoPackage(ctx *android.Context, g *bootstrap.GoPackage, goModulesMap nameToGoLibraryModule) ([]BazelTarget, []error) {
+	ca := android.CommonAttributes{
+		Name: g.Name(),
+	}
+
+	// For this bootstrap_go_package dep chain,
+	// A --> B --> C ( ---> depends on)
+	// Soong provides the convenience of only listing B as deps of A even if a src file of A imports C
+	// Bazel OTOH
+	// 1. requires C to be listed in `deps` expllicity.
+	// 2. does not require C to be listed if src of A does not import C
+	//
+	// bp2build does not have sufficient info on whether C is a direct dep of A or not, so for now collect all transitive deps and add them to deps
+	transitiveDeps := transitiveGoDeps(g.Deps(), goModulesMap)
+
+	ga := goAttributes{
+		Importpath: bazel.StringAttribute{
+			Value: proptools.StringPtr(g.GoPkgPath()),
+		},
+		Srcs: goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs()),
+		Deps: goDepLabels(
+			android.FirstUniqueStrings(transitiveDeps),
+			goModulesMap,
+		),
+		Target_compatible_with: targetNotCompatibleWithAndroid(),
+	}
+
+	lib := goBazelTarget{
+		targetName:            g.Name(),
+		targetPackage:         ctx.ModuleDir(g),
+		bazelRuleClass:        "go_library",
+		bazelRuleLoadLocation: "@io_bazel_rules_go//go:def.bzl",
+		bazelAttributes:       []interface{}{&ca, &ga},
+	}
+	// TODO - b/284483729: Create go_test target from testSrcs
+	libTarget, err := generateBazelTarget(ctx, lib)
+	if err != nil {
+		return []BazelTarget{}, []error{err}
+	}
+	return []BazelTarget{libTarget}, nil
+}
+
+type goLibraryModule struct {
+	Dir  string
+	Deps []string
+}
+
+type nameToGoLibraryModule map[string]goLibraryModule
+
+// Visit each module in the graph
+// If a module is of type `bootstrap_go_package`, return a map containing metadata like its dir and deps
+func createGoLibraryModuleMap(ctx *android.Context) nameToGoLibraryModule {
+	ret := nameToGoLibraryModule{}
+	ctx.VisitAllModules(func(m blueprint.Module) {
+		moduleType := ctx.ModuleType(m)
+		// We do not need to store information about blueprint_go_binary since it does not have any rdeps
+		if moduleType == "bootstrap_go_package" {
+			ret[m.Name()] = goLibraryModule{
+				Dir:  ctx.ModuleDir(m),
+				Deps: m.(*bootstrap.GoPackage).Deps(),
+			}
+		}
+	})
+	return ret
+}
+
+// Returns the deps in the transitive closure of a go target
+func transitiveGoDeps(directDeps []string, goModulesMap nameToGoLibraryModule) []string {
+	allDeps := directDeps
+	i := 0
+	for i < len(allDeps) {
+		curr := allDeps[i]
+		allDeps = append(allDeps, goModulesMap[curr].Deps...)
+		i += 1
+	}
+	allDeps = android.SortedUniqueStrings(allDeps)
+	return allDeps
+}
+
+func generateBazelTargetsGoBinary(ctx *android.Context, g *bootstrap.GoBinary, goModulesMap nameToGoLibraryModule) ([]BazelTarget, []error) {
+	ca := android.CommonAttributes{
+		Name: g.Name(),
+	}
+
+	// For this bootstrap_go_package dep chain,
+	// A --> B --> C ( ---> depends on)
+	// Soong provides the convenience of only listing B as deps of A even if a src file of A imports C
+	// Bazel OTOH
+	// 1. requires C to be listed in `deps` expllicity.
+	// 2. does not require C to be listed if src of A does not import C
+	//
+	// bp2build does not have sufficient info on whether C is a direct dep of A or not, so for now collect all transitive deps and add them to deps
+	transitiveDeps := transitiveGoDeps(g.Deps(), goModulesMap)
+
+	ga := goAttributes{
+		Srcs:                   goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs()),
+		Deps:                   goDepLabels(transitiveDeps, goModulesMap),
+		Target_compatible_with: targetNotCompatibleWithAndroid(),
+	}
+
+	bin := goBazelTarget{
+		targetName:            g.Name(),
+		targetPackage:         ctx.ModuleDir(g),
+		bazelRuleClass:        "go_binary",
+		bazelRuleLoadLocation: "@io_bazel_rules_go//go:def.bzl",
+		bazelAttributes:       []interface{}{&ca, &ga},
+	}
+	// TODO - b/284483729: Create go_test target from testSrcs
+	binTarget, err := generateBazelTarget(ctx, bin)
+	if err != nil {
+		return []BazelTarget{}, []error{err}
+	}
+	return []BazelTarget{binTarget}, nil
+}
+
+var (
+	// TODO - b/284483729: Remove this denyilst
+	// Temporary denylist of go binaries that are currently used in mixed builds
+	// This denylist allows us to rollout bp2build converters for go targets without affecting mixed builds
+	goBinaryDenylist = []string{
+		"soong_zip",
+		"zip2zip",
+		"bazel_notice_gen",
+	}
+)
+
 func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (conversionResults, []error) {
 	buildFileToTargets := make(map[string]BazelTargets)
 
@@ -262,6 +492,10 @@
 
 	var errs []error
 
+	// Visit go libraries in a pre-run and store its state in a map
+	// The time complexity remains O(N), and this does not add significant wall time.
+	nameToGoLibMap := createGoLibraryModuleMap(ctx.Context())
+
 	bpCtx := ctx.Context()
 	bpCtx.VisitAllModules(func(m blueprint.Module) {
 		dir := bpCtx.ModuleDir(m)
@@ -269,6 +503,7 @@
 		dirs[dir] = true
 
 		var targets []BazelTarget
+		var targetErrs []error
 
 		switch ctx.Mode() {
 		case Bp2Build:
@@ -317,7 +552,6 @@
 						return
 					}
 				}
-				var targetErrs []error
 				targets, targetErrs = generateBazelTargets(bpCtx, aModule)
 				errs = append(errs, targetErrs...)
 				for _, t := range targets {
@@ -336,6 +570,14 @@
 					metrics.AddUnconvertedModule(m, moduleType, dir, *reason)
 				}
 				return
+			} else if glib, ok := m.(*bootstrap.GoPackage); ok {
+				targets, targetErrs = generateBazelTargetsGoPackage(bpCtx, glib, nameToGoLibMap)
+				errs = append(errs, targetErrs...)
+				metrics.IncrementRuleClassCount("go_library")
+			} else if gbin, ok := m.(*bootstrap.GoBinary); ok && !android.InList(m.Name(), goBinaryDenylist) {
+				targets, targetErrs = generateBazelTargetsGoBinary(bpCtx, gbin, nameToGoLibMap)
+				errs = append(errs, targetErrs...)
+				metrics.IncrementRuleClassCount("go_binary")
 			} else {
 				metrics.AddUnconvertedModule(m, moduleType, dir, android.UnconvertedReason{
 					ReasonType: int(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED),
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 18cb9e1..4b36cc7 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -881,7 +881,7 @@
 		targets: []testBazelTarget{
 			{"cc_binary", "foo", AttrNameToString{
 				"local_includes": `["."]`,
-				"features":       `["ubsan_blocklist_foo_blocklist_txt"]`,
+				"features":       `["sanitizer_blocklist_foo_blocklist_txt"]`,
 			}},
 		},
 	})
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 1e3d72e..490cd91 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -4194,11 +4194,11 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
-				"features":       `["ubsan_blocklist_foo_blocklist_txt"]`,
+				"features":       `["sanitizer_blocklist_foo_blocklist_txt"]`,
 				"local_includes": `["."]`,
 			}),
 			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"features":       `["ubsan_blocklist_foo_blocklist_txt"]`,
+				"features":       `["sanitizer_blocklist_foo_blocklist_txt"]`,
 				"local_includes": `["."]`,
 			}),
 		},
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 2d61d53..ccb426f 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -1225,7 +1225,7 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"features":       `["ubsan_blocklist_foo_blocklist_txt"]`,
+				"features":       `["sanitizer_blocklist_foo_blocklist_txt"]`,
 				"local_includes": `["."]`,
 			}),
 		},
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 18225df..8084a5d 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1918,7 +1918,7 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
-				"features":       `["ubsan_blocklist_foo_blocklist_txt"]`,
+				"features":       `["sanitizer_blocklist_foo_blocklist_txt"]`,
 				"local_includes": `["."]`,
 			}),
 		},
diff --git a/bp2build/go_conversion_test.go b/bp2build/go_conversion_test.go
new file mode 100644
index 0000000..507fbf0
--- /dev/null
+++ b/bp2build/go_conversion_test.go
@@ -0,0 +1,150 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// 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 bp2build
+
+import (
+	"testing"
+
+	"github.com/google/blueprint/bootstrap"
+
+	"android/soong/android"
+)
+
+func runGoTests(t *testing.T, tc Bp2buildTestCase) {
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+		tCtx := ctx.(*android.TestContext)
+		bootstrap.RegisterGoModuleTypes(tCtx.Context.Context) // android.TestContext --> android.Context --> blueprint.Context
+	}, tc)
+}
+
+func TestConvertGoPackage(t *testing.T) {
+	bp := `
+bootstrap_go_package {
+	name: "foo",
+	pkgPath: "android/foo",
+	deps: [
+		"bar",
+	],
+	srcs: [
+		"foo1.go",
+		"foo2.go",
+	],
+	linux: {
+		srcs: [
+			"foo_linux.go",
+		],
+	},
+	darwin: {
+		srcs: [
+			"foo_darwin.go",
+		],
+	},
+	testSrcs: [
+		"foo1_test.go",
+		"foo2_test.go",
+	],
+}
+`
+	depBp := `
+bootstrap_go_package {
+	name: "bar",
+}
+`
+	t.Parallel()
+	runGoTests(t, Bp2buildTestCase{
+		Description:         "Convert bootstrap_go_package to go_library",
+		ModuleTypeUnderTest: "bootrstap_go_package",
+		Blueprint:           bp,
+		Filesystem: map[string]string{
+			"bar/Android.bp": depBp, // Put dep in Android.bp to reduce boilerplate in ExpectedBazelTargets
+		},
+		ExpectedBazelTargets: []string{makeBazelTargetHostOrDevice("go_library", "foo",
+			AttrNameToString{
+				"deps":       `["//bar:bar"]`,
+				"importpath": `"android/foo"`,
+				"srcs": `[
+        "foo1.go",
+        "foo2.go",
+    ] + select({
+        "//build/bazel/platforms/os:darwin": ["foo_darwin.go"],
+        "//build/bazel/platforms/os:linux_glibc": ["foo_linux.go"],
+        "//conditions:default": [],
+    })`,
+			},
+			android.HostSupported,
+		)},
+	})
+}
+
+func TestConvertGoBinaryWithTransitiveDeps(t *testing.T) {
+	bp := `
+blueprint_go_binary {
+	name: "foo",
+	srcs: ["main.go"],
+	deps: ["bar"],
+}
+`
+	depBp := `
+bootstrap_go_package {
+	name: "bar",
+	deps: ["baz"],
+}
+bootstrap_go_package {
+	name: "baz",
+}
+`
+	t.Parallel()
+	runGoTests(t, Bp2buildTestCase{
+		Description: "Convert blueprint_go_binary to go_binary",
+		Blueprint:   bp,
+		Filesystem: map[string]string{
+			"bar/Android.bp": depBp, // Put dep in Android.bp to reduce boilerplate in ExpectedBazelTargets
+		},
+		ExpectedBazelTargets: []string{makeBazelTargetHostOrDevice("go_binary", "foo",
+			AttrNameToString{
+				"deps": `[
+        "//bar:bar",
+        "//bar:baz",
+    ]`,
+				"srcs": `["main.go"]`,
+			},
+			android.HostSupported,
+		)},
+	})
+}
+
+func TestConvertGoBinaryWithSrcInDifferentPackage(t *testing.T) {
+	bp := `
+blueprint_go_binary {
+	name: "foo",
+	srcs: ["subdir/main.go"],
+}
+`
+	t.Parallel()
+	runGoTests(t, Bp2buildTestCase{
+		Description: "Convert blueprint_go_binary with src in different package",
+		Blueprint:   bp,
+		Filesystem: map[string]string{
+			"subdir/Android.bp": "",
+		},
+		ExpectedBazelTargets: []string{makeBazelTargetHostOrDevice("go_binary", "foo",
+			AttrNameToString{
+				"deps": `[]`,
+				"srcs": `["//subdir:main.go"]`,
+			},
+			android.HostSupported,
+		)},
+	})
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 5459595..85a2284 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -1819,7 +1819,7 @@
 			if blocklist != nil {
 				// Format the blocklist name to be used in a feature name
 				blocklistFeatureSuffix := strings.Replace(strings.ToLower(*blocklist), ".", "_", -1)
-				features = append(features, "ubsan_blocklist_"+blocklistFeatureSuffix)
+				features = append(features, "sanitizer_blocklist_"+blocklistFeatureSuffix)
 			}
 			if sanitizerProps.Sanitize.Cfi != nil && !proptools.Bool(sanitizerProps.Sanitize.Cfi) {
 				features = append(features, "-android_cfi")
diff --git a/cc/cc_test.go b/cc/cc_test.go
index fe54463..7534db2 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -4979,7 +4979,6 @@
 
 	conly := []string{"-fPIC", "${config.CommonGlobalConlyflags}"}
 	cppOnly := []string{"-fPIC", "${config.CommonGlobalCppflags}", "${config.DeviceGlobalCppflags}", "${config.ArmCppflags}"}
-	ltoFlags := []string{"-flto=thin", "-fsplit-lto-unit"}
 
 	cflags := []string{"-Werror", "-std=candcpp"}
 	cstd := []string{"-std=gnu17", "-std=conly"}
@@ -5006,17 +5005,17 @@
 		{
 			name:     "c",
 			src:      "foo.c",
-			expected: combineSlices(baseExpectedFlags, conly, expectedIncludes, cflags, ltoFlags, cstd, lastIncludes, []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"}),
+			expected: combineSlices(baseExpectedFlags, conly, expectedIncludes, cflags, cstd, lastIncludes, []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"}),
 		},
 		{
 			name:     "cc",
 			src:      "foo.cc",
-			expected: combineSlices(baseExpectedFlags, cppOnly, expectedIncludes, cflags, ltoFlags, cppstd, lastIncludes, []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"}),
+			expected: combineSlices(baseExpectedFlags, cppOnly, expectedIncludes, cflags, cppstd, lastIncludes, []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"}),
 		},
 		{
 			name:     "assemble",
 			src:      "foo.s",
-			expected: combineSlices(baseExpectedFlags, []string{"${config.CommonGlobalAsflags}"}, expectedIncludes, ltoFlags, lastIncludes),
+			expected: combineSlices(baseExpectedFlags, []string{"${config.CommonGlobalAsflags}"}, expectedIncludes, lastIncludes),
 		},
 	}
 
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 3bc1e69..40919c0 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -26,9 +26,6 @@
 		// Help catch common 32/64-bit errors.
 		"-Werror=implicit-function-declaration",
 		"-fno-emulated-tls",
-		// A temporary fix for SExtWRemoval miscompilation bug.
-		"-mllvm",
-		"-riscv-disable-sextw-removal=true",
 		"-march=rv64gc_zba_zbb_zbs",
 	}
 
diff --git a/cc/lto.go b/cc/lto.go
index ff2bf5a..44361db 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -74,6 +74,9 @@
 	} else if ctx.Host() {
 		// Performance and binary size are less important for host binaries.
 		ltoDefault = false
+	} else if ctx.Arch().ArchType.Multilib == "lib32" {
+		// LP32 has many subtle issues and less test coverage.
+		ltoDefault = false
 	}
 
 	// Then, determine the actual LTO mode to use. If different from `ltoDefault`, a variant needs
@@ -108,7 +111,7 @@
 		var ltoLdFlags []string
 
 		// The module did not explicitly turn on LTO. Only leverage LTO's
-		// better dead code elinmination and CFG simplification, but do
+		// better dead code elimination and CFG simplification, but do
 		// not perform costly optimizations for a balance between compile
 		// time, binary size and performance.
 		if !lto.ThinLTO() {
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index ba0648d..3fb4454 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -556,7 +556,8 @@
     {{- end}}
     {{- end}}
     {{- if .IsApk}}
-    presigned: true
+    preprocessed: true,
+    presigned: true,
     {{- end}}
 
 }
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 682fb75..4097e8a 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -218,6 +218,11 @@
 
 	trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
 
+	log.Verbose("Command Line: ")
+	for i, arg := range os.Args {
+		log.Verbosef("  [%d] %s", i, arg)
+	}
+
 	defer func() {
 		stat.Finish()
 		criticalPath.WriteToMetrics(met)
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index bb83dc8..ba41f4a 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -45,7 +45,8 @@
 	BootJars     android.ConfiguredJarList // modules for jars that form the boot class path
 	ApexBootJars android.ConfiguredJarList // jars within apex that form the boot class path
 
-	ArtApexJars android.ConfiguredJarList // modules for jars that are in the ART APEX
+	ArtApexJars              android.ConfiguredJarList // modules for jars that are in the ART APEX
+	TestOnlyArtBootImageJars android.ConfiguredJarList // modules for jars to be included in the ART boot image for testing
 
 	SystemServerJars               android.ConfiguredJarList // system_server classpath jars on the platform
 	SystemServerApps               []string                  // apps that are loaded into system server
@@ -700,6 +701,7 @@
 		BootJars:                           android.EmptyConfiguredJarList(),
 		ApexBootJars:                       android.EmptyConfiguredJarList(),
 		ArtApexJars:                        android.EmptyConfiguredJarList(),
+		TestOnlyArtBootImageJars:           android.EmptyConfiguredJarList(),
 		SystemServerJars:                   android.EmptyConfiguredJarList(),
 		SystemServerApps:                   nil,
 		ApexSystemServerJars:               android.EmptyConfiguredJarList(),
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index 6ed0736..147a562 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -111,6 +111,13 @@
 	})
 }
 
+// FixtureSetTestOnlyArtBootImageJars enables dexpreopt and sets the TestOnlyArtBootImageJars property.
+func FixtureSetTestOnlyArtBootImageJars(bootJars ...string) android.FixturePreparer {
+	return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
+		dexpreoptConfig.TestOnlyArtBootImageJars = android.CreateTestConfiguredJarList(bootJars)
+	})
+}
+
 // FixtureSetBootJars enables dexpreopt and sets the BootJars property.
 func FixtureSetBootJars(bootJars ...string) android.FixturePreparer {
 	return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index 22703fd..c6fa030 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -97,8 +97,6 @@
 		"BlueberryFacadeGeneratedStub_cc",
 		"BlueberryFacadeGeneratedStub_h",
 		"BluetoothGeneratedDumpsysDataSchema_h",
-		"OpenwrtControlServerProto_cc",
-		"OpenwrtControlServerProto_h",
 		"c2hal_test_genc++",
 		"c2hal_test_genc++_headers",
 		"hidl2aidl_test_gen_aidl",
diff --git a/java/base.go b/java/base.go
index f2ad5c2..cb08ef3 100644
--- a/java/base.go
+++ b/java/base.go
@@ -500,6 +500,8 @@
 	maxSdkVersion android.ApiLevel
 
 	sourceExtensions []string
+
+	annoSrcJars android.Paths
 }
 
 func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -1255,8 +1257,9 @@
 			// this module, or else we could have duplicated errorprone messages.
 			errorproneFlags := enableErrorproneFlags(flags)
 			errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
+			errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar")
 
-			transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneFlags, nil,
+			transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil,
 				"errorprone", "errorprone")
 
 			extraJarDeps = append(extraJarDeps, errorprone)
@@ -1657,13 +1660,15 @@
 	srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath {
 
 	kzipName := pathtools.ReplaceExtension(jarName, "kzip")
+	annoSrcJar := android.PathForModuleOut(ctx, "javac", "anno.srcjar")
 	if idx >= 0 {
 		kzipName = strings.TrimSuffix(jarName, filepath.Ext(jarName)) + strconv.Itoa(idx) + ".kzip"
+		annoSrcJar = android.PathForModuleOut(ctx, "javac", "anno-"+strconv.Itoa(idx)+".srcjar")
 		jarName += strconv.Itoa(idx)
 	}
 
 	classes := android.PathForModuleOut(ctx, "javac", jarName).OutputPath
-	TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, flags, extraJarDeps)
+	TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps)
 
 	if ctx.Config().EmitXrefRules() {
 		extractionFile := android.PathForModuleOut(ctx, kzipName)
@@ -1671,6 +1676,10 @@
 		j.kytheFiles = append(j.kytheFiles, extractionFile)
 	}
 
+	if len(flags.processorPath) > 0 {
+		j.annoSrcJars = append(j.annoSrcJars, annoSrcJar)
+	}
+
 	return classes
 }
 
@@ -1850,6 +1859,7 @@
 	dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...)
 	dpInfo.Static_libs = append(dpInfo.Static_libs, j.properties.Static_libs...)
 	dpInfo.Libs = append(dpInfo.Libs, j.properties.Libs...)
+	dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
 }
 
 func (j *Module) CompilerDeps() []string {
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index 29eed79..c7dc3af 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -185,6 +185,9 @@
 // The tag used for dependencies onto bootclasspath_fragments.
 var bootclasspathFragmentDepTag = bootclasspathDependencyTag{name: "fragment"}
 
+// The tag used for dependencies onto platform_bootclasspath.
+var platformBootclasspathDepTag = bootclasspathDependencyTag{name: "platform"}
+
 // BootclasspathNestedAPIProperties defines properties related to the API provided by parts of the
 // bootclasspath that are nested within the main BootclasspathAPIProperties.
 type BootclasspathNestedAPIProperties struct {
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index ac45ce1..dcc2dec 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -242,7 +242,7 @@
 	modulePaths []string
 
 	// Path to the boot image profile.
-	profilePath android.Path
+	profilePath android.WritablePath
 }
 
 // commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt
@@ -256,16 +256,6 @@
 	// versioned sdk.
 	produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
 
-	// produceBootImageFiles will attempt to produce rules to create the boot image files at the paths
-	// predefined in the bootImageConfig.
-	//
-	// If it could not create the files then it will return nil. Otherwise, it will return a map from
-	// android.ArchType to the predefined paths of the boot image files.
-	produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs
-
-	// getImageName returns the `image_name` property of this fragment.
-	getImageName() *string
-
 	// getProfilePath returns the path to the boot image profile.
 	getProfilePath() android.Path
 }
@@ -295,9 +285,6 @@
 				return
 			}
 		}
-
-		// Initialize the contents property from the image_name.
-		bootclasspathFragmentInitContentsFromImage(ctx, m)
 	})
 	return m
 }
@@ -308,9 +295,7 @@
 	return m
 }
 
-// bootclasspathFragmentInitContentsFromImage will initialize the contents property from the image_name if
-// necessary.
-func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, m *BootclasspathFragmentModule) {
+func (m *BootclasspathFragmentModule) bootclasspathFragmentPropertyCheck(ctx android.EarlyModuleContext) {
 	contents := m.properties.Contents
 	if len(contents) == 0 {
 		ctx.PropertyErrorf("contents", "required property is missing")
@@ -332,6 +317,18 @@
 	// too early in the Soong processing for that to work.
 	global := dexpreopt.GetGlobalConfig(ctx)
 	modules := global.ArtApexJars
+	configuredJars := modules.CopyOfJars()
+
+	// Skip the check if the configured jars list is empty as that is a common configuration when
+	// building targets that do not result in a system image.
+	if len(configuredJars) == 0 {
+		return
+	}
+
+	if !reflect.DeepEqual(configuredJars, contents) {
+		ctx.ModuleErrorf("inconsistency in specification of contents. ArtApexJars configuration specifies %#v, contents property specifies %#v",
+			configuredJars, contents)
+	}
 
 	// Make sure that the apex specified in the configuration is consistent and is one for which
 	// this boot image is available.
@@ -357,33 +354,6 @@
 	}
 }
 
-// bootclasspathImageNameContentsConsistencyCheck checks that the configuration that applies to this
-// module (if any) matches the contents.
-//
-// This should be a noop as if image_name="art" then the contents will be set from the ArtApexJars
-// config by bootclasspathFragmentInitContentsFromImage so it will be guaranteed to match. However,
-// in future this will not be the case.
-func (b *BootclasspathFragmentModule) bootclasspathImageNameContentsConsistencyCheck(ctx android.BaseModuleContext) {
-	imageName := proptools.String(b.properties.Image_name)
-	if imageName == "art" {
-		// Get the configuration for the art apex jars.
-		modules := b.getImageConfig(ctx).modules
-		configuredJars := modules.CopyOfJars()
-
-		// Skip the check if the configured jars list is empty as that is a common configuration when
-		// building targets that do not result in a system image.
-		if len(configuredJars) == 0 {
-			return
-		}
-
-		contents := b.properties.Contents
-		if !reflect.DeepEqual(configuredJars, contents) {
-			ctx.ModuleErrorf("inconsistency in specification of contents. ArtApexJars configuration specifies %#v, contents property specifies %#v",
-				configuredJars, contents)
-		}
-	}
-}
-
 var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider(BootclasspathFragmentApexContentInfo{})
 
 // BootclasspathFragmentApexContentInfo contains the bootclasspath_fragments contributions to the
@@ -495,7 +465,7 @@
 	// unused prebuilt that was created without instrumentation from breaking an instrumentation
 	// build.
 	if isActiveModule(ctx.Module()) {
-		b.bootclasspathImageNameContentsConsistencyCheck(ctx)
+		b.bootclasspathFragmentPropertyCheck(ctx)
 	}
 
 	// Generate classpaths.proto config
@@ -515,34 +485,15 @@
 
 	fragments := gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
 
-	// Verify that the image_name specified on a bootclasspath_fragment is valid even if this is a
-	// prebuilt which will not use the image config.
-	imageConfig := b.getImageConfig(ctx)
-
 	// Perform hidden API processing.
 	hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
 
-	var bootImageFiles bootImageOutputs
-	if imageConfig != nil {
-		// Delegate the production of the boot image files to a module type specific method.
-		common := ctx.Module().(commonBootclasspathFragment)
-		bootImageFiles = common.produceBootImageFiles(ctx, imageConfig)
-		b.profilePath = bootImageFiles.profile
-
-		if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
-			// Zip the boot image files up, if available. This will generate the zip file in a
-			// predefined location.
-			buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFiles.byArch)
-
-			// Copy the dex jars of this fragment's content modules to their predefined locations.
-			copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
-		}
-	}
-
-	// A prebuilt fragment cannot contribute to an apex.
-	if !android.IsModulePrebuilt(ctx.Module()) {
-		// Provide the apex content info.
-		b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFiles)
+	if android.IsModulePrebuilt(ctx.Module()) {
+		b.profilePath = ctx.Module().(*PrebuiltBootclasspathFragmentModule).produceBootImageProfile(ctx)
+	} else {
+		b.profilePath = b.produceBootImageProfileFromSource(ctx, contents, hiddenAPIOutput.EncodedBootDexFilesByModule)
+		// Provide the apex content info. A prebuilt fragment cannot contribute to an apex.
+		b.provideApexContentInfo(ctx, hiddenAPIOutput, b.profilePath)
 	}
 
 	// In order for information about bootclasspath_fragment modules to be added to module-info.json
@@ -556,44 +507,37 @@
 	}
 }
 
-// shouldCopyBootFilesToPredefinedLocations determines whether the current module should copy boot
-// files, e.g. boot dex jars or boot image files, to the predefined location expected by the rest
-// of the build.
-//
-// This ensures that only a single module will copy its files to the image configuration.
-func shouldCopyBootFilesToPredefinedLocations(ctx android.ModuleContext, imageConfig *bootImageConfig) bool {
+// getProfileProviderApex returns the name of the apex that provides a boot image profile, or an
+// empty string if this module should not provide a boot image profile.
+func (b *BootclasspathFragmentModule) getProfileProviderApex(ctx android.BaseModuleContext) string {
+	// Only use the profile from the module that is preferred.
+	if !isActiveModule(ctx.Module()) {
+		return ""
+	}
+
 	// Bootclasspath fragment modules that are for the platform do not produce boot related files.
 	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
-	if apexInfo.IsForPlatform() {
-		return false
+	for _, apex := range apexInfo.InApexVariants {
+		if isProfileProviderApex(ctx, apex) {
+			return apex
+		}
 	}
 
-	// If the image configuration has no modules specified then it means that the build has been
-	// configured to build something other than a boot image, e.g. an sdk, so do not try and copy the
-	// files.
-	if imageConfig.modules.Len() == 0 {
-		return false
-	}
-
-	// Only copy files from the module that is preferred.
-	return isActiveModule(ctx.Module())
+	return ""
 }
 
 // provideApexContentInfo creates, initializes and stores the apex content info for use by other
 // modules.
-func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFiles bootImageOutputs) {
+func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, hiddenAPIOutput *HiddenAPIOutput, profile android.WritablePath) {
 	// Construct the apex content info from the config.
 	info := BootclasspathFragmentApexContentInfo{
 		// Populate the apex content info with paths to the dex jars.
 		contentModuleDexJarPaths: hiddenAPIOutput.EncodedBootDexFilesByModule,
 	}
 
-	if imageConfig != nil {
-		global := dexpreopt.GetGlobalConfig(ctx)
-		if !global.DisableGenerateProfile {
-			info.profilePathOnHost = bootImageFiles.profile
-			info.profileInstallPathInApex = imageConfig.profileInstallPathInApex
-		}
+	if profile != nil {
+		info.profilePathOnHost = profile
+		info.profileInstallPathInApex = profileInstallPathInApex
 	}
 
 	// Make the apex content info available for other modules.
@@ -614,12 +558,12 @@
 }
 
 func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
-	if "art" == proptools.String(b.properties.Image_name) {
-		return b.getImageConfig(ctx).modules
-	}
-
 	global := dexpreopt.GetGlobalConfig(ctx)
 
+	if "art" == proptools.String(b.properties.Image_name) {
+		return global.ArtApexJars
+	}
+
 	possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag)
 	jars, unknown := global.ApexBootJars.Filter(possibleUpdatableModules)
 
@@ -645,25 +589,6 @@
 	return jars
 }
 
-func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
-	// Get a map of the image configs that are supported.
-	imageConfigs := genBootImageConfigs(ctx)
-
-	// Retrieve the config for this image.
-	imageNamePtr := b.properties.Image_name
-	if imageNamePtr == nil {
-		return nil
-	}
-
-	imageName := *imageNamePtr
-	imageConfig := imageConfigs[imageName]
-	if imageConfig == nil {
-		ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedKeys(imageConfigs), ", "))
-		return nil
-	}
-	return imageConfig
-}
-
 // generateHiddenAPIBuildActions generates all the hidden API related build rules.
 func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput {
 
@@ -846,48 +771,22 @@
 	return output
 }
 
-// produceBootImageFiles builds the boot image files from the source if it is required.
-func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
-	// Only generate the boot image if the configuration does not skip it.
-	return b.generateBootImageBuildActions(ctx, imageConfig)
-}
-
-// generateBootImageBuildActions generates ninja rules to create the boot image if required for this
-// module.
-//
-// If it could not create the files then it will return nil. Otherwise, it will return a map from
-// android.ArchType to the predefined paths of the boot image files.
-func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
-	global := dexpreopt.GetGlobalConfig(ctx)
-	if !shouldBuildBootImages(ctx.Config(), global) {
-		return bootImageOutputs{}
+// produceBootImageProfileFromSource builds the boot image profile from the source if it is required.
+func (b *BootclasspathFragmentModule) produceBootImageProfileFromSource(ctx android.ModuleContext, contents []android.Module, modules bootDexJarByModule) android.WritablePath {
+	apex := b.getProfileProviderApex(ctx)
+	if apex == "" {
+		return nil
 	}
 
-	// Bootclasspath fragment modules that are for the platform do not produce a boot image.
-	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
-	if apexInfo.IsForPlatform() {
-		return bootImageOutputs{}
+	dexPaths := make(android.Paths, 0, len(contents))
+	dexLocations := make([]string, 0, len(contents))
+	for _, module := range contents {
+		dexPaths = append(dexPaths, modules[module.Name()])
+		dexLocations = append(dexLocations, filepath.Join("/", "apex", apex, "javalib", module.Name() + ".jar"))
 	}
 
-	// Build a profile for the image config and then use that to build the boot image.
-	profile := bootImageProfileRule(ctx, imageConfig)
-
-	// If dexpreopt of boot image jars should be skipped, generate only a profile.
-	if SkipDexpreoptBootJars(ctx) {
-		return bootImageOutputs{
-			profile: profile,
-		}
-	}
-
-	// Build boot image files for the host variants.
-	buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
-
-	// Build boot image files for the android variants.
-	bootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
-
-	// Return the boot image files for the android variants for inclusion in an APEX and to be zipped
-	// up for the dist.
-	return bootImageFiles
+	// Build a profile for the modules in this fragment.
+	return bootImageProfileRuleCommon(ctx, b.Name(), dexPaths, dexLocations)
 }
 
 func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries {
@@ -910,10 +809,6 @@
 	return entriesList
 }
 
-func (b *BootclasspathFragmentModule) getImageName() *string {
-	return b.properties.Image_name
-}
-
 func (b *BootclasspathFragmentModule) getProfilePath() android.Path {
 	return b.profilePath
 }
@@ -1183,39 +1078,19 @@
 	return &output
 }
 
-// produceBootImageFiles extracts the boot image files from the APEX if available.
-func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
-	if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
-		return bootImageOutputs{}
+// produceBootImageProfile extracts the boot image profile from the APEX if available.
+func (module *PrebuiltBootclasspathFragmentModule) produceBootImageProfile(ctx android.ModuleContext) android.WritablePath {
+	// This module does not provide a boot image profile.
+	if module.getProfileProviderApex(ctx) == "" {
+		return nil
 	}
 
 	di := android.FindDeapexerProviderForModule(ctx)
 	if di == nil {
-		return bootImageOutputs{} // An error has been reported by FindDeapexerProviderForModule.
+		return nil // An error has been reported by FindDeapexerProviderForModule.
 	}
 
-	profile := (android.WritablePath)(nil)
-	if imageConfig.profileInstallPathInApex != "" {
-		profile = di.PrebuiltExportPath(imageConfig.profileInstallPathInApex)
-	}
-
-	// Build the boot image files for the host variants. These are always built from the dex files
-	// provided by the contents of this module as prebuilt versions of the host boot image files are
-	// not available, i.e. there is no host specific prebuilt apex containing them. This has to be
-	// built without a profile as the prebuilt modules do not provide a profile.
-	buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
-
-	if profile == nil && imageConfig.isProfileGuided() {
-		ctx.ModuleErrorf("Unable to produce boot image files: profiles not found in the prebuilt apex")
-		return bootImageOutputs{}
-	}
-	// Build boot image files for the android variants from the dex files provided by the contents
-	// of this module.
-	return buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
-}
-
-func (b *PrebuiltBootclasspathFragmentModule) getImageName() *string {
-	return b.properties.Image_name
+	return di.PrebuiltExportPath(profileInstallPathInApex)
 }
 
 func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path {
@@ -1230,14 +1105,10 @@
 // If there is no image config associated with this fragment then it returns nil. Otherwise, it
 // returns the files that are listed in the image config.
 func (module *PrebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
-	imageConfig := module.getImageConfig(ctx)
-	if imageConfig != nil {
-		files := []string{}
-		if imageConfig.profileInstallPathInApex != "" {
-			// Add the boot image profile.
-			files = append(files, imageConfig.profileInstallPathInApex)
+	for _, apex := range module.ApexProperties.Apex_available {
+		if isProfileProviderApex(ctx, apex) {
+			return []string{profileInstallPathInApex}
 		}
-		return files
 	}
 	return nil
 }
@@ -1253,9 +1124,5 @@
 	android.InitApexModule(m)
 	android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
 
-	// Initialize the contents property from the image_name.
-	android.AddLoadHook(m, func(ctx android.LoadHookContext) {
-		bootclasspathFragmentInitContentsFromImage(ctx, &m.BootclasspathFragmentModule)
-	})
 	return m
 }
diff --git a/java/builder.go b/java/builder.go
index c4395e9..be4af55 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -42,7 +42,8 @@
 	// TODO(b/143658984): goma can't handle the --system argument to javac.
 	javac, javacRE = pctx.MultiCommandRemoteStaticRules("javac",
 		blueprint.RuleParams{
-			Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" "$out" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
+			Command: `rm -rf "$outDir" "$annoDir" "$annoSrcJar" "$srcJarDir" "$out" && ` +
+				`mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
 				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
 				`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
 				`${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` +
@@ -50,6 +51,7 @@
 				`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
 				`-source $javaVersion -target $javaVersion ` +
 				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` +
+				`$annoSrcJarTemplate${config.SoongZipCmd} -jar -o $annoSrcJar -C $annoDir -D $annoDir && ` +
 				`$zipTemplate${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` +
 				`rm -rf "$srcJarDir"`,
 			CommandDeps: []string{
@@ -73,8 +75,15 @@
 				ExecStrategy: "${config.REJavacExecStrategy}",
 				Platform:     map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
 			},
+			"$annoSrcJarTemplate": &remoteexec.REParams{
+				Labels:       map[string]string{"type": "tool", "name": "soong_zip"},
+				Inputs:       []string{"${config.SoongZipCmd}", "$annoDir"},
+				OutputFiles:  []string{"$annoSrcJar"},
+				ExecStrategy: "${config.REJavacExecStrategy}",
+				Platform:     map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+			},
 		}, []string{"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir",
-			"outDir", "annoDir", "javaVersion"}, nil)
+			"outDir", "annoDir", "annoSrcJar", "javaVersion"}, nil)
 
 	_ = pctx.VariableFunc("kytheCorpus",
 		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
@@ -312,7 +321,7 @@
 }
 
 func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int,
-	srcFiles, srcJars android.Paths, flags javaBuilderFlags, deps android.Paths) {
+	srcFiles, srcJars android.Paths, annoSrcJar android.WritablePath, flags javaBuilderFlags, deps android.Paths) {
 
 	// Compile java sources into .class files
 	desc := "javac"
@@ -320,7 +329,7 @@
 		desc += strconv.Itoa(shardIdx)
 	}
 
-	transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc)
+	transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, annoSrcJar, flags, deps, "javac", desc)
 }
 
 // Emits the rule to generate Xref input file (.kzip file) for the given set of source files and source jars
@@ -494,7 +503,7 @@
 // suffix will be appended to various intermediate files and directories to avoid collisions when
 // this function is called twice in the same module directory.
 func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
-	shardIdx int, srcFiles, srcJars android.Paths,
+	shardIdx int, srcFiles, srcJars android.Paths, annoSrcJar android.WritablePath,
 	flags javaBuilderFlags, deps android.Paths,
 	intermediatesDir, desc string) {
 
@@ -541,11 +550,12 @@
 		rule = javacRE
 	}
 	ctx.Build(pctx, android.BuildParams{
-		Rule:        rule,
-		Description: desc,
-		Output:      outputFile,
-		Inputs:      srcFiles,
-		Implicits:   deps,
+		Rule:           rule,
+		Description:    desc,
+		Output:         outputFile,
+		ImplicitOutput: annoSrcJar,
+		Inputs:         srcFiles,
+		Implicits:      deps,
 		Args: map[string]string{
 			"javacFlags":    flags.javacFlags,
 			"bootClasspath": bootClasspath,
@@ -556,6 +566,7 @@
 			"srcJarDir":     android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(),
 			"outDir":        android.PathForModuleOut(ctx, intermediatesDir, outDir).String(),
 			"annoDir":       android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(),
+			"annoSrcJar":    annoSrcJar.String(),
 			"javaVersion":   flags.javaVersion.String(),
 		},
 	})
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 7b56a19..003f2de 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -16,7 +16,6 @@
 
 import (
 	"path/filepath"
-	"sort"
 	"strings"
 
 	"android/soong/android"
@@ -224,6 +223,11 @@
 	"com.google.android.art.testing",
 }
 
+var (
+	dexpreoptBootJarDepTag  = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"}
+	dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments")
+)
+
 func init() {
 	RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext)
 }
@@ -241,6 +245,9 @@
 	// Image name (used in directory names and ninja rule names).
 	name string
 
+	// If the module with the given name exists, this config is enabled.
+	enabledIfExists string
+
 	// Basename of the image: the resulting filenames are <stem>[-<jar>].{art,oat,vdex}.
 	stem string
 
@@ -257,10 +264,6 @@
 	// the location is relative to "/".
 	installDir string
 
-	// Install path of the boot image profile if it needs to be installed in the APEX, or empty if not
-	// needed.
-	profileInstallPathInApex string
-
 	// A list of (location, jar) pairs for the Java modules in this image.
 	modules android.ConfiguredJarList
 
@@ -296,10 +299,9 @@
 	// The "--single-image" argument.
 	singleImage bool
 
-	// Profiles imported from other boot image configs. Each element must represent a
-	// `bootclasspath_fragment` of an APEX (i.e., the `name` field of each element must refer to the
-	// `image_name` property of a `bootclasspath_fragment`).
-	profileImports []*bootImageConfig
+	// Profiles imported from APEXes, in addition to the profile at the default path. Each entry must
+	// be the name of an APEX module.
+	profileImports []string
 }
 
 // Target-dependent description of a boot image.
@@ -384,7 +386,7 @@
 	m := image.modules.Jar(idx)
 	name := image.stem
 	if idx != 0 || image.extends != nil {
-		name += "-" + android.ModuleStem(m)
+		name += "-" + android.ModuleStem(ctx.Config(), image.modules.Apex(idx), m)
 	}
 	return name
 }
@@ -458,18 +460,26 @@
 	return image.compilerFilter == "speed-profile"
 }
 
+func (image *bootImageConfig) isEnabled(ctx android.BaseModuleContext) bool {
+	return ctx.OtherModuleExists(image.enabledIfExists)
+}
+
 func dexpreoptBootJarsFactory() android.SingletonModule {
 	m := &dexpreoptBootJars{}
-	android.InitAndroidModule(m)
+	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
 }
 
 func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) {
 	ctx.RegisterParallelSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory)
+	ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("dex_bootjars_deps", DexpreoptBootJarsMutator).Parallel()
+	})
 }
 
 func SkipDexpreoptBootJars(ctx android.PathContext) bool {
-	return dexpreopt.GetGlobalConfig(ctx).DisablePreoptBootImages
+	global := dexpreopt.GetGlobalConfig(ctx)
+	return global.DisablePreoptBootImages || !shouldBuildBootImages(ctx.Config(), global)
 }
 
 // Singleton module for generating boot image build rules.
@@ -492,38 +502,90 @@
 	dexpreoptConfigForMake android.WritablePath
 }
 
-// Provide paths to boot images for use by modules that depend upon them.
-//
-// The build rules are created in GenerateSingletonBuildActions().
-func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	// Placeholder for now.
+func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) {
+	if _, ok := ctx.Module().(*dexpreoptBootJars); !ok {
+		return
+	}
+
+	if dexpreopt.IsDex2oatNeeded(ctx) {
+		// Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
+		// path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
+		dexpreopt.RegisterToolDeps(ctx)
+	}
+
+	imageConfigs := genBootImageConfigs(ctx)
+	for _, config := range imageConfigs {
+		if !config.isEnabled(ctx) {
+			continue
+		}
+		// For accessing the boot jars.
+		addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJarDepTag)
+	}
+
+	if ctx.OtherModuleExists("platform-bootclasspath") {
+		// For accessing all bootclasspath fragments.
+		addDependencyOntoApexModulePair(ctx, "platform", "platform-bootclasspath", platformBootclasspathDepTag)
+	} else if ctx.OtherModuleExists("art-bootclasspath-fragment") {
+		// For accessing the ART bootclasspath fragment on a thin manifest (e.g., master-art) where
+		// platform-bootclasspath doesn't exist.
+		addDependencyOntoApexModulePair(ctx, "com.android.art", "art-bootclasspath-fragment", bootclasspathFragmentDepTag)
+	}
 }
 
-// Generate build rules for boot images.
-func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) {
-	if dexpreopt.GetCachedGlobalSoongConfig(ctx) == nil {
-		// No module has enabled dexpreopting, so we assume there will be no boot image to make.
-		return
-	}
-	d.dexpreoptConfigForMake = android.PathForOutput(ctx, getDexpreoptDirName(ctx), "dexpreopt.config")
-	writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
+func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module {
+	return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} {
+		fragments := make(map[string]android.Module)
+		ctx.WalkDeps(func(child, parent android.Module) bool {
+			if !isActiveModule(child) {
+				return false
+			}
+			tag := ctx.OtherModuleDependencyTag(child)
+			if tag == platformBootclasspathDepTag {
+				return true
+			}
+			if tag == bootclasspathFragmentDepTag {
+				apexInfo := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo)
+				for _, apex := range apexInfo.InApexVariants {
+					fragments[apex] = child
+				}
+				return false
+			}
+			return false
+		})
+		return fragments
+	}).(map[string]android.Module)
+}
 
-	global := dexpreopt.GetGlobalConfig(ctx)
-	if !shouldBuildBootImages(ctx.Config(), global) {
-		return
-	}
+func getBootclasspathFragmentByApex(ctx android.ModuleContext, apexName string) android.Module {
+	return gatherBootclasspathFragments(ctx)[apexName]
+}
 
-	defaultImageConfig := defaultBootImageConfig(ctx)
-	d.defaultBootImage = defaultImageConfig
+// GenerateAndroidBuildActions generates the build rules for boot images.
+func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	imageConfigs := genBootImageConfigs(ctx)
+	d.defaultBootImage = defaultBootImageConfig(ctx)
 	d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1)
-	for _, config := range imageConfigs {
-		if config != defaultImageConfig {
+	for _, name := range getImageNames() {
+		config := imageConfigs[name]
+		if config != d.defaultBootImage {
 			d.otherImages = append(d.otherImages, config)
 		}
+		if !config.isEnabled(ctx) {
+			continue
+		}
+		generateBootImage(ctx, config)
+		if config == d.defaultBootImage {
+			bootFrameworkProfileRule(ctx, config)
+		}
 	}
 }
 
+// GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make.
+func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) {
+	d.dexpreoptConfigForMake = android.PathForOutput(ctx, getDexpreoptDirName(ctx), "dexpreopt.config")
+	writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
+}
+
 // shouldBuildBootImages determines whether boot images should be built.
 func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig) bool {
 	// Skip recompiling the boot image for the second sanitization phase. We'll get separate paths
@@ -536,6 +598,101 @@
 	return true
 }
 
+func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) {
+	apexJarModulePairs := getModulesForImage(ctx, imageConfig)
+
+	// Copy module dex jars to their predefined locations.
+	bootDexJarsByModule := extractEncodedDexJarsFromModulesOrBootclasspathFragments(ctx, apexJarModulePairs)
+	copyBootJarsToPredefinedLocations(ctx, bootDexJarsByModule, imageConfig.dexPathsByModule)
+
+	// Build a profile for the image config from the profile at the default path. The profile will
+	// then be used along with profiles imported from APEXes to build the boot image.
+	profile := bootImageProfileRule(ctx, imageConfig)
+
+	// If dexpreopt of boot image jars should be skipped, stop after generating a profile.
+	if SkipDexpreoptBootJars(ctx) {
+		return
+	}
+
+	// Build boot image files for the android variants.
+	androidBootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
+
+	// Zip the android variant boot image files up.
+	buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFiles.byArch)
+
+	// Build boot image files for the host variants. There are use directly by ART host side tests.
+	buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
+
+	// Create a `dump-oat-<image-name>` rule that runs `oatdump` for debugging purposes.
+	dumpOatRules(ctx, imageConfig)
+}
+
+type apexJarModulePair struct {
+	apex string
+	jarModule android.Module
+}
+
+func getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig) []apexJarModulePair {
+	modules := make([]apexJarModulePair, 0, imageConfig.modules.Len())
+	for i := 0; i < imageConfig.modules.Len(); i++ {
+		found := false
+		for _, module := range gatherApexModulePairDepsWithTag(ctx, dexpreoptBootJarDepTag) {
+			name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+			if name == imageConfig.modules.Jar(i) {
+				modules = append(modules, apexJarModulePair{
+					apex: imageConfig.modules.Apex(i),
+					jarModule: module,
+				})
+				found = true
+				break
+			}
+		}
+		if !found && !ctx.Config().AllowMissingDependencies() {
+			ctx.ModuleErrorf(
+				"Boot image '%s' module '%s' not added as a dependency of dex_bootjars",
+				imageConfig.name,
+				imageConfig.modules.Jar(i))
+			return []apexJarModulePair{}
+		}
+	}
+	return modules
+}
+
+// extractEncodedDexJarsFromModulesOrBootclasspathFragments gets the hidden API encoded dex jars for
+// the given modules.
+func extractEncodedDexJarsFromModulesOrBootclasspathFragments(ctx android.ModuleContext, apexJarModulePairs []apexJarModulePair) bootDexJarByModule {
+	encodedDexJarsByModuleName := bootDexJarByModule{}
+	for _, pair := range apexJarModulePairs {
+		var path android.Path
+		if android.IsConfiguredJarForPlatform(pair.apex) || android.IsModulePrebuilt(pair.jarModule) {
+			// This gives us the dex jar with the hidden API flags encoded from the monolithic hidden API
+			// files or the dex jar extracted from a prebuilt APEX. We can't use this for a boot jar for
+			// a source APEX because there is no guarantee that it is the same as the jar packed into the
+			// APEX. In practice, they are the same when we are building from a full source tree, but they
+			// are different when we are building from a thin manifest (e.g., master-art), where there is
+			// no monolithic hidden API files at all.
+			path = retrieveEncodedBootDexJarFromModule(ctx, pair.jarModule)
+		} else {
+			// Use exactly the same jar that is packed into the APEX.
+			fragment := getBootclasspathFragmentByApex(ctx, pair.apex)
+			if fragment == nil {
+				ctx.ModuleErrorf("Boot jar '%[1]s' is from APEX '%[2]s', but a bootclasspath_fragment for "+
+					"APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars",
+					pair.jarModule.Name(),
+					pair.apex)
+			}
+			bootclasspathFragmentInfo := ctx.OtherModuleProvider(fragment, BootclasspathFragmentApexContentInfoProvider).(BootclasspathFragmentApexContentInfo)
+			jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule)
+			if err != nil {
+				ctx.ModuleErrorf("%s", err)
+			}
+			path = jar
+		}
+		encodedDexJarsByModuleName.addPath(pair.jarModule, path)
+	}
+	return encodedDexJarsByModuleName
+}
+
 // copyBootJarsToPredefinedLocations generates commands that will copy boot jars to predefined
 // paths in the global config.
 func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJarsByModule bootDexJarByModule, dstBootJarsByModule map[string]android.WritablePath) {
@@ -686,10 +843,12 @@
 	rule.Command().Text("rm").Flag("-f").
 		Flag(symbolsDir.Join(ctx, "*.art").String()).
 		Flag(symbolsDir.Join(ctx, "*.oat").String()).
+		Flag(symbolsDir.Join(ctx, "*.vdex").String()).
 		Flag(symbolsDir.Join(ctx, "*.invocation").String())
 	rule.Command().Text("rm").Flag("-f").
 		Flag(outputDir.Join(ctx, "*.art").String()).
 		Flag(outputDir.Join(ctx, "*.oat").String()).
+		Flag(outputDir.Join(ctx, "*.vdex").String()).
 		Flag(outputDir.Join(ctx, "*.invocation").String())
 
 	cmd := rule.Command()
@@ -711,36 +870,31 @@
 		Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatImageXms).
 		Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatImageXmx)
 
-	if profile != nil {
-		cmd.FlagWithInput("--profile-file=", profile)
-	}
+	if image.isProfileGuided() && !global.DisableGenerateProfile {
+		if profile != nil {
+			cmd.FlagWithInput("--profile-file=", profile)
+		}
 
-	fragments := make(map[string]commonBootclasspathFragment)
-	ctx.VisitDirectDepsWithTag(bootclasspathFragmentDepTag, func(child android.Module) {
-		fragment := child.(commonBootclasspathFragment)
-		if fragment.getImageName() != nil && android.IsModulePreferred(child) {
-			fragments[*fragment.getImageName()] = fragment
+		for _, apex := range image.profileImports {
+			fragment := getBootclasspathFragmentByApex(ctx, apex)
+			if fragment == nil {
+				ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but a "+
+					"bootclasspath_fragment for APEX '%[2]s' doesn't exist or is not added as a "+
+					"dependency of dex_bootjars",
+					image.name,
+					apex)
+				return bootImageVariantOutputs{}
+			}
+			importedProfile := fragment.(commonBootclasspathFragment).getProfilePath()
+			if importedProfile == nil {
+				ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but '%[2]s' "+
+					"doesn't provide a profile",
+					image.name,
+					apex)
+				return bootImageVariantOutputs{}
+			}
+			cmd.FlagWithInput("--profile-file=", importedProfile)
 		}
-	})
-
-	for _, profileImport := range image.profileImports {
-		fragment := fragments[profileImport.name]
-		if fragment == nil {
-			ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but a "+
-				"bootclasspath_fragment with image name '%[2]s' doesn't exist or is not added as a "+
-				"dependency of '%[1]s'",
-				image.name,
-				profileImport.name)
-			return bootImageVariantOutputs{}
-		}
-		if fragment.getProfilePath() == nil {
-			ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but '%[2]s' "+
-				"doesn't provide a profile",
-				image.name,
-				profileImport.name)
-			return bootImageVariantOutputs{}
-		}
-		cmd.FlagWithInput("--profile-file=", fragment.getProfilePath())
 	}
 
 	dirtyImageFile := "frameworks/base/config/dirty-image-objects"
@@ -1059,11 +1213,9 @@
 		ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(dexPaths.Strings(), " "))
 		ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(dexLocations, " "))
 
-		var imageNames []string
 		// The primary ART boot image is exposed to Make for testing (gtests) and benchmarking
 		// (golem) purposes.
 		for _, current := range append(d.otherImages, image) {
-			imageNames = append(imageNames, current.name)
 			for _, variant := range current.variants {
 				suffix := ""
 				if variant.target.Os.Class == android.Host {
@@ -1084,8 +1236,6 @@
 			ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE"+current.name, strings.Join(imageLocationsOnDevice, ":"))
 			ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
 		}
-		// Ensure determinism.
-		sort.Strings(imageNames)
-		ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
+		ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(getImageNames(), " "))
 	}
 }
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index abbb96a..0f4bd9b 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -40,57 +40,67 @@
 }
 
 var (
-	bootImageConfigKey     = android.NewOnceKey("bootImageConfig")
-	bootImageConfigRawKey  = android.NewOnceKey("bootImageConfigRaw")
-	artBootImageName       = "art"
-	frameworkBootImageName = "boot"
-	mainlineBootImageName  = "mainline"
-	bootImageStem          = "boot"
+	bootImageConfigKey       = android.NewOnceKey("bootImageConfig")
+	bootImageConfigRawKey    = android.NewOnceKey("bootImageConfigRaw")
+	frameworkBootImageName   = "boot"
+	mainlineBootImageName    = "mainline"
+	bootImageStem            = "boot"
+	profileInstallPathInApex = "etc/boot-image.prof"
 )
 
+// getImageNames returns an ordered list of image names. The order doesn't matter but needs to be
+// deterministic. The names listed here must match the map keys returned by genBootImageConfigs.
+func getImageNames() []string {
+	return []string{"art", "boot", "mainline"}
+}
+
 func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig {
 	return ctx.Config().Once(bootImageConfigRawKey, func() interface{} {
 		global := dexpreopt.GetGlobalConfig(ctx)
 
-		artModules := global.ArtApexJars
-		frameworkModules := global.BootJars // This includes `artModules`.
+		artBootImageName := "art"           // Keep this local to avoid accidental references.
+		frameworkModules := global.BootJars // This includes `global.ArtApexJars`.
 		mainlineBcpModules := global.ApexBootJars
 		frameworkSubdir := "system/framework"
 
-		// ART config for the primary boot image in the ART apex.
-		// It includes the Core Libraries.
+		profileImports := []string{"com.android.art"}
+
+		// ART boot image for testing only. Do not rely on it to make any build-time decision.
 		artCfg := bootImageConfig{
-			name:                     artBootImageName,
-			stem:                     bootImageStem,
-			installDir:               "apex/art_boot_images/javalib",
-			profileInstallPathInApex: "etc/boot-image.prof",
-			modules:                  artModules,
-			preloadedClassesFile:     "art/build/boot/preloaded-classes",
-			compilerFilter:           "speed-profile",
-			singleImage:              false,
+			name:                 artBootImageName,
+			enabledIfExists:      "art-bootclasspath-fragment",
+			stem:                 bootImageStem,
+			installDir:           "apex/art_boot_images/javalib",
+			modules:              global.TestOnlyArtBootImageJars,
+			preloadedClassesFile: "art/build/boot/preloaded-classes",
+			compilerFilter:       "speed-profile",
+			singleImage:          false,
+			profileImports:       profileImports,
 		}
 
 		// Framework config for the boot image extension.
 		// It includes framework libraries and depends on the ART config.
 		frameworkCfg := bootImageConfig{
 			name:                 frameworkBootImageName,
+			enabledIfExists:      "platform-bootclasspath",
 			stem:                 bootImageStem,
 			installDir:           frameworkSubdir,
 			modules:              frameworkModules,
 			preloadedClassesFile: "frameworks/base/config/preloaded-classes",
 			compilerFilter:       "speed-profile",
 			singleImage:          false,
-			profileImports:       []*bootImageConfig{&artCfg},
+			profileImports:       profileImports,
 		}
 
 		mainlineCfg := bootImageConfig{
-			extends:        &frameworkCfg,
-			name:           mainlineBootImageName,
-			stem:           bootImageStem,
-			installDir:     frameworkSubdir,
-			modules:        mainlineBcpModules,
-			compilerFilter: "verify",
-			singleImage:    true,
+			extends:         &frameworkCfg,
+			name:            mainlineBootImageName,
+			enabledIfExists: "platform-bootclasspath",
+			stem:            bootImageStem,
+			installDir:      frameworkSubdir,
+			modules:         mainlineBcpModules,
+			compilerFilter:  "verify",
+			singleImage:     true,
 		}
 
 		return map[string]*bootImageConfig{
@@ -180,10 +190,6 @@
 	}
 }
 
-func artBootImageConfig(ctx android.PathContext) *bootImageConfig {
-	return genBootImageConfigs(ctx)[artBootImageName]
-}
-
 func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig {
 	return genBootImageConfigs(ctx)[frameworkBootImageName]
 }
@@ -192,6 +198,18 @@
 	return genBootImageConfigs(ctx)[mainlineBootImageName]
 }
 
+// isProfileProviderApex returns true if this apex provides a boot image profile.
+func isProfileProviderApex(ctx android.PathContext, apexName string) bool {
+	for _, config := range genBootImageConfigs(ctx) {
+		for _, profileImport := range config.profileImports {
+			if profileImport == apexName {
+				return true
+			}
+		}
+	}
+	return false
+}
+
 // Apex boot config allows to access build/install paths of apex boot jars without going
 // through the usual trouble of registering dependencies on those modules and extracting build paths
 // from those dependencies.
diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go
index cd7f295..44d2127 100644
--- a/java/dexpreopt_config_test.go
+++ b/java/dexpreopt_config_test.go
@@ -16,6 +16,7 @@
 
 import (
 	"runtime"
+	"sort"
 	"testing"
 
 	"android/soong/android"
@@ -35,3 +36,22 @@
 	CheckFrameworkBootImageConfig(t, result)
 	CheckMainlineBootImageConfig(t, result)
 }
+
+func TestImageNames(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		PrepareForBootImageConfigTest,
+	).RunTest(t)
+
+	names := getImageNames()
+	sort.Strings(names)
+
+	ctx := &android.TestPathContext{TestResult: result}
+	configs := genBootImageConfigs(ctx)
+	namesFromConfigs := make([]string, 0, len(configs))
+	for name, _ := range configs {
+		namesFromConfigs = append(namesFromConfigs, name)
+	}
+	sort.Strings(namesFromConfigs)
+
+	android.AssertArrayString(t, "getImageNames vs genBootImageConfigs", names, namesFromConfigs)
+}
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
index 56f16e0..176c251 100644
--- a/java/dexpreopt_config_testing.go
+++ b/java/dexpreopt_config_testing.go
@@ -29,6 +29,7 @@
 	"testing"
 
 	"android/soong/android"
+	"android/soong/dexpreopt"
 )
 
 // PrepareForBootImageConfigTest is the minimal set of preparers that are needed to be able to use
@@ -36,7 +37,17 @@
 var PrepareForBootImageConfigTest = android.GroupFixturePreparers(
 	android.PrepareForTestWithArchMutator,
 	android.PrepareForTestAccessingMakeVars,
+	PrepareForTestWithDexpreopt,
 	FixtureConfigureBootJars("com.android.art:core1", "com.android.art:core2", "platform:framework"),
+	dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:core1", "com.android.art:core2", "platform:extra1"),
+	android.FixtureAddTextFile("extra1/Android.bp", `
+		java_library {
+			name: "extra1",
+			srcs: ["extra1.java"],
+			installable: true,
+		}
+	`),
+	android.FixtureAddFile("extra1/extra1.java", nil),
 )
 
 var PrepareApexBootJarConfigs = FixtureConfigureApexBootJars(
@@ -218,15 +229,15 @@
 		symbolsDir:               "out/soong/dexpreopt_arm64/dex_artjars_unstripped",
 		installDir:               "apex/art_boot_images/javalib",
 		profileInstallPathInApex: "etc/boot-image.prof",
-		modules:                  android.CreateTestConfiguredJarList([]string{"com.android.art:core1", "com.android.art:core2"}),
-		dexPaths:                 []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar"},
-		dexPathsDeps:             []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar"},
+		modules:                  android.CreateTestConfiguredJarList([]string{"com.android.art:core1", "com.android.art:core2", "platform:extra1"}),
+		dexPaths:                 []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/extra1.jar"},
+		dexPathsDeps:             []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/extra1.jar"},
 		zip:                      "out/soong/dexpreopt_arm64/dex_artjars/art.zip",
 		variants: []*expectedVariant{
 			{
 				archType:          android.Arm64,
-				dexLocations:      []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
-				dexLocationsDeps:  []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
+				dexLocations:      []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
+				dexLocationsDeps:  []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
 				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
 				imagePathOnDevice: "/apex/art_boot_images/javalib/arm64/boot.art",
 				imagesDeps: []string{
@@ -236,6 +247,9 @@
 					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art",
 					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
 					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
+					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art",
+					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex",
 				},
 				installs: []normalizedInstall{
 					{
@@ -254,6 +268,14 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
 						to:   "/apex/art_boot_images/javalib/arm64/boot-core2.oat",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art",
+						to:   "/apex/art_boot_images/javalib/arm64/boot-extra1.art",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+						to:   "/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+					},
 				},
 				vdexInstalls: []normalizedInstall{
 					{
@@ -264,6 +286,10 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
 						to:   "/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex",
+						to:   "/apex/art_boot_images/javalib/arm64/boot-extra1.vdex",
+					},
 				},
 				unstrippedInstalls: []normalizedInstall{
 					{
@@ -274,13 +300,17 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
 						to:   "/apex/art_boot_images/javalib/arm64/boot-core2.oat",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+						to:   "/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+					},
 				},
 				licenseMetadataFile: expectedLicenseMetadataFile,
 			},
 			{
 				archType:          android.Arm,
-				dexLocations:      []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
-				dexLocationsDeps:  []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
+				dexLocations:      []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
+				dexLocationsDeps:  []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
 				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
 				imagePathOnDevice: "/apex/art_boot_images/javalib/arm/boot.art",
 				imagesDeps: []string{
@@ -290,6 +320,9 @@
 					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art",
 					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
 					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex",
+					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art",
+					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex",
 				},
 				installs: []normalizedInstall{
 					{
@@ -308,6 +341,14 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
 						to:   "/apex/art_boot_images/javalib/arm/boot-core2.oat",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art",
+						to:   "/apex/art_boot_images/javalib/arm/boot-extra1.art",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+						to:   "/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+					},
 				},
 				vdexInstalls: []normalizedInstall{
 					{
@@ -318,6 +359,10 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex",
 						to:   "/apex/art_boot_images/javalib/arm/boot-core2.vdex",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex",
+						to:   "/apex/art_boot_images/javalib/arm/boot-extra1.vdex",
+					},
 				},
 				unstrippedInstalls: []normalizedInstall{
 					{
@@ -328,13 +373,17 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
 						to:   "/apex/art_boot_images/javalib/arm/boot-core2.oat",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+						to:   "/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+					},
 				},
 				licenseMetadataFile: expectedLicenseMetadataFile,
 			},
 			{
 				archType:          android.X86_64,
-				dexLocations:      []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
-				dexLocationsDeps:  []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
+				dexLocations:      []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
+				dexLocationsDeps:  []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
 				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
 				imagePathOnDevice: "/apex/art_boot_images/javalib/x86_64/boot.art",
 				imagesDeps: []string{
@@ -344,6 +393,9 @@
 					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art",
 					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
 					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
+					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art",
+					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex",
 				},
 				installs: []normalizedInstall{
 					{
@@ -360,6 +412,13 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
 						to:   "/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art",
+						to:   "/apex/art_boot_images/javalib/x86_64/boot-extra1.art",
+					}, {
+						from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+						to:   "/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+					},
 				},
 				vdexInstalls: []normalizedInstall{
 					{
@@ -370,6 +429,10 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
 						to:   "/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex",
+						to:   "/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex",
+					},
 				},
 				unstrippedInstalls: []normalizedInstall{
 					{
@@ -380,13 +443,17 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
 						to:   "/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+						to:   "/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+					},
 				},
 				licenseMetadataFile: expectedLicenseMetadataFile,
 			},
 			{
 				archType:          android.X86,
-				dexLocations:      []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
-				dexLocationsDeps:  []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
+				dexLocations:      []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
+				dexLocationsDeps:  []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
 				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
 				imagePathOnDevice: "/apex/art_boot_images/javalib/x86/boot.art",
 				imagesDeps: []string{
@@ -396,6 +463,9 @@
 					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art",
 					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
 					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex",
+					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art",
+					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex",
 				},
 				installs: []normalizedInstall{
 					{
@@ -412,6 +482,13 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
 						to:   "/apex/art_boot_images/javalib/x86/boot-core2.oat",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art",
+						to:   "/apex/art_boot_images/javalib/x86/boot-extra1.art",
+					}, {
+						from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+						to:   "/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+					},
 				},
 				vdexInstalls: []normalizedInstall{
 					{
@@ -422,6 +499,10 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex",
 						to:   "/apex/art_boot_images/javalib/x86/boot-core2.vdex",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex",
+						to:   "/apex/art_boot_images/javalib/x86/boot-extra1.vdex",
+					},
 				},
 				unstrippedInstalls: []normalizedInstall{
 					{
@@ -432,6 +513,10 @@
 						from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
 						to:   "/apex/art_boot_images/javalib/x86/boot-core2.oat",
 					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+						to:   "/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+					},
 				},
 				licenseMetadataFile: expectedLicenseMetadataFile,
 			},
@@ -813,8 +898,8 @@
 			},
 		},
 		profileInstalls: []normalizedInstall{
+			{from: "out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof", to: "/system/etc/boot-image.prof"},
 			{from: "out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof", to: "/system/etc/boot-image.bprof"},
-			{from: "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/boot/boot.prof", to: "/system/etc/boot-image.prof"},
 		},
 		profileLicenseMetadataFile: expectedLicenseMetadataFile,
 	}
@@ -1202,10 +1287,10 @@
 DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS=/apex/com.android.art/javalib/core1.jar /apex/com.android.art/javalib/core2.jar /system/framework/framework.jar
 DEXPREOPT_BOOT_JARS_MODULES=com.android.art:core1:com.android.art:core2:platform:framework
 DEXPREOPT_GEN=out/host/linux-x86/bin/dexpreopt_gen
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art:/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art:/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art:/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art:/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art:/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art:/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art:/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art:/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art:/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art:/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art:/apex/art_boot_images/javalib/arm/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat:/apex/art_boot_images/javalib/arm/boot-extra1.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art:/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art:/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art:/apex/art_boot_images/javalib/arm64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat:/apex/art_boot_images/javalib/arm64/boot-extra1.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art:/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art:/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art:/apex/art_boot_images/javalib/x86/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat:/apex/art_boot_images/javalib/x86/boot-extra1.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art:/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art:/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art:/apex/art_boot_images/javalib/x86_64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat:/apex/art_boot_images/javalib/x86_64/boot-extra1.oat
 DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.art:/system/framework/arm/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.oat:/system/framework/arm/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.art:/system/framework/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.oat:/system/framework/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.art:/system/framework/arm/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.oat:/system/framework/arm/boot-framework.oat
 DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art:/system/framework/arm64/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.oat:/system/framework/arm64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.art:/system/framework/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.oat:/system/framework/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.art:/system/framework/arm64/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat
 DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.art:/system/framework/x86/boot.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.oat:/system/framework/x86/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.art:/system/framework/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.oat:/system/framework/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art:/system/framework/x86/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat
@@ -1214,10 +1299,10 @@
 DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_arm64=out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art:/system/framework/arm64/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.oat:/system/framework/arm64/boot-framework-foo.oat
 DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_host_x86=out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art:/system/framework/x86/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.oat:/system/framework/x86/boot-framework-foo.oat
 DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_host_x86_64=out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.art:/system/framework/x86_64/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.oat:/system/framework/x86_64/boot-framework-foo.oat
-DEXPREOPT_IMAGE_DEPS_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex
-DEXPREOPT_IMAGE_DEPS_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex
-DEXPREOPT_IMAGE_DEPS_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex
-DEXPREOPT_IMAGE_DEPS_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex
+DEXPREOPT_IMAGE_DEPS_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex
+DEXPREOPT_IMAGE_DEPS_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex
+DEXPREOPT_IMAGE_DEPS_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex
+DEXPREOPT_IMAGE_DEPS_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex
 DEXPREOPT_IMAGE_DEPS_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.vdex
 DEXPREOPT_IMAGE_DEPS_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.vdex
 DEXPREOPT_IMAGE_DEPS_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex
@@ -1230,14 +1315,14 @@
 DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm64=%[1]s
 DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86=%[1]s
 DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86_64=%[1]s
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86_64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
 DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEart=/apex/art_boot_images/javalib/boot.art
 DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEboot=/system/framework/boot.art
 DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEmainline=/system/framework/boot.art:/system/framework/boot-framework-foo.art
@@ -1245,12 +1330,12 @@
 DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTboot=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art
 DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTmainline=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art:out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/boot-framework-foo.art
 DEXPREOPT_IMAGE_NAMES=art boot mainline
-DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/boot/boot.prof:/system/etc/boot-image.prof
-DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat
+DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof:/system/etc/boot-image.prof out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof
+DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-extra1.oat:/apex/art_boot_images/javalib/arm/boot-extra1.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat:/apex/art_boot_images/javalib/arm64/boot-extra1.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat:/apex/art_boot_images/javalib/x86/boot-extra1.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat:/apex/art_boot_images/javalib/x86_64/boot-extra1.oat
 DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot.oat:/system/framework/arm/boot.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot-core2.oat:/system/framework/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot-framework.oat:/system/framework/arm/boot-framework.oat
 DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot.oat:/system/framework/arm64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-core2.oat:/system/framework/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat
 DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot.oat:/system/framework/x86/boot.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-core2.oat:/system/framework/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat
@@ -1259,10 +1344,10 @@
 DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_arm64=out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped/android/system/framework/arm64/boot-framework-foo.oat:/system/framework/arm64/boot-framework-foo.oat
 DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_host_x86=out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped/linux_glibc/system/framework/x86/boot-framework-foo.oat:/system/framework/x86/boot-framework-foo.oat
 DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_host_x86_64=out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped/linux_glibc/system/framework/x86_64/boot-framework-foo.oat:/system/framework/x86_64/boot-framework-foo.oat
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex:/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex:/apex/art_boot_images/javalib/arm/boot-core2.vdex
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex:/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex:/apex/art_boot_images/javalib/arm64/boot-core2.vdex
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex:/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex:/apex/art_boot_images/javalib/x86/boot-core2.vdex
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex:/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex:/apex/art_boot_images/javalib/x86_64/boot-core2.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex:/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex:/apex/art_boot_images/javalib/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex:/apex/art_boot_images/javalib/arm/boot-extra1.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex:/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex:/apex/art_boot_images/javalib/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex:/apex/art_boot_images/javalib/arm64/boot-extra1.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex:/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex:/apex/art_boot_images/javalib/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex:/apex/art_boot_images/javalib/x86/boot-extra1.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex:/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex:/apex/art_boot_images/javalib/x86_64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex:/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex
 DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.vdex:/system/framework/arm/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.vdex:/system/framework/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.vdex:/system/framework/arm/boot-framework.vdex
 DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.vdex:/system/framework/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.vdex:/system/framework/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.vdex:/system/framework/arm64/boot-framework.vdex
 DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.vdex:/system/framework/x86/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.vdex:/system/framework/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex:/system/framework/x86/boot-framework.vdex
diff --git a/java/java.go b/java/java.go
index 445eb61..011dc1c 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1877,8 +1877,10 @@
 		flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
 		flags.classpath = classpath(classPaths)
 
+		annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar")
+
 		TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
-			android.Paths{al.stubsSrcJar}, flags, android.Paths{})
+			android.Paths{al.stubsSrcJar}, annoSrcJar, flags, android.Paths{})
 	}
 
 	builder := android.NewRuleBuilder(pctx, ctx)
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 0d4db7c..a4bba48 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -123,15 +123,15 @@
 }
 
 func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
-	// Add dependencies on all the modules configured in the "art" boot image.
-	artImageConfig := genBootImageConfigs(ctx)[artBootImageName]
-	addDependenciesOntoBootImageModules(ctx, artImageConfig.modules, platformBootclasspathArtBootJarDepTag)
+	// Add dependencies on all the ART jars.
+	global := dexpreopt.GetGlobalConfig(ctx)
+	addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, platformBootclasspathArtBootJarDepTag)
 
-	// Add dependencies on all the non-updatable module configured in the "boot" boot image. That does
-	// not include modules configured in the "art" boot image.
+	// Add dependencies on all the non-updatable jars, which are on the platform or in non-updatable
+	// APEXes.
 	addDependenciesOntoBootImageModules(ctx, b.platformJars(ctx), platformBootclasspathBootJarDepTag)
 
-	// Add dependencies on all the apex jars.
+	// Add dependencies on all the updatable jars, except the ART jars.
 	apexJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
 	addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag)
 
@@ -186,7 +186,6 @@
 	bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
 	buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule)
 
-	b.generateBootImageBuildActions(ctx)
 	b.copyApexBootJarsForAppsDexpreopt(ctx, apexModules)
 }
 
@@ -218,7 +217,8 @@
 }
 
 func (b *platformBootclasspathModule) platformJars(ctx android.PathContext) android.ConfiguredJarList {
-	return defaultBootImageConfig(ctx).modules.RemoveList(artBootImageConfig(ctx).modules)
+	global := dexpreopt.GetGlobalConfig(ctx)
+	return global.BootJars.RemoveList(global.ArtApexJars)
 }
 
 // checkPlatformModules ensures that the non-updatable modules supplied are not part of an
@@ -399,78 +399,9 @@
 	ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", b.hiddenAPIFlagsCSV.String())
 }
 
-// generateBootImageBuildActions generates ninja rules related to the boot image creation.
-func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext) {
-	// Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
-	// GenerateSingletonBuildActions method as it cannot create it for itself.
-	dexpreopt.GetGlobalSoongConfig(ctx)
-
-	global := dexpreopt.GetGlobalConfig(ctx)
-	if !shouldBuildBootImages(ctx.Config(), global) {
-		return
-	}
-
-	frameworkBootImageConfig := defaultBootImageConfig(ctx)
-	bootFrameworkProfileRule(ctx, frameworkBootImageConfig)
-	b.generateBootImage(ctx, frameworkBootImageName)
-	b.generateBootImage(ctx, mainlineBootImageName)
-	dumpOatRules(ctx, frameworkBootImageConfig)
-}
-
-func (b *platformBootclasspathModule) generateBootImage(ctx android.ModuleContext, imageName string) {
-	imageConfig := genBootImageConfigs(ctx)[imageName]
-
-	modules := b.getModulesForImage(ctx, imageConfig)
-
-	// Copy module dex jars to their predefined locations.
-	bootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, modules)
-	copyBootJarsToPredefinedLocations(ctx, bootDexJarsByModule, imageConfig.dexPathsByModule)
-
-	// Build a profile for the image config and then use that to build the boot image.
-	profile := bootImageProfileRule(ctx, imageConfig)
-
-	// If dexpreopt of boot image jars should be skipped, generate only a profile.
-	global := dexpreopt.GetGlobalConfig(ctx)
-	if global.DisablePreoptBootImages {
-		return
-	}
-
-	// Build boot image files for the android variants.
-	androidBootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
-
-	// Zip the android variant boot image files up.
-	buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFiles.byArch)
-
-	// Build boot image files for the host variants. There are use directly by ART host side tests.
-	buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
-}
-
 // Copy apex module dex jars to their predefined locations. They will be used for dexpreopt for apps.
 func (b *platformBootclasspathModule) copyApexBootJarsForAppsDexpreopt(ctx android.ModuleContext, apexModules []android.Module) {
 	config := GetApexBootConfig(ctx)
 	apexBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, apexModules)
 	copyBootJarsToPredefinedLocations(ctx, apexBootDexJarsByModule, config.dexPathsByModule)
 }
-
-func (b *platformBootclasspathModule) getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig) []android.Module {
-	modules := make([]android.Module, 0, imageConfig.modules.Len())
-	for i := 0; i < imageConfig.modules.Len(); i++ {
-		found := false
-		for _, module := range b.configuredModules {
-			name := android.RemoveOptionalPrebuiltPrefix(module.Name())
-			if name == imageConfig.modules.Jar(i) {
-				modules = append(modules, module)
-				found = true
-				break
-			}
-		}
-		if !found && !ctx.Config().AllowMissingDependencies() {
-			ctx.ModuleErrorf(
-				"Boot image '%s' module '%s' not added as a dependency of platform_bootclasspath",
-				imageConfig.name,
-				imageConfig.modules.Jar(i))
-			return []android.Module{}
-		}
-	}
-	return modules
-}
diff --git a/scripts/unpack-prebuilt-apex.sh b/scripts/unpack-prebuilt-apex.sh
index 2a20e45..18f4da2 100755
--- a/scripts/unpack-prebuilt-apex.sh
+++ b/scripts/unpack-prebuilt-apex.sh
@@ -17,7 +17,7 @@
 # limitations under the License.
 
 # Tool to unpack an apex file and verify that the required files were extracted.
-if [ $# -lt 7 ]; then
+if [ $# -lt 6 ]; then
   echo "usage: $0 <deapaxer_path> <debugfs_path> <fsck.erofs_path> <apex file> <output_dir> <required_files>+" >&2
   exit 1
 fi
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index ac23aab..ee1b5db 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -145,8 +145,8 @@
 	preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("com.android.art", "art-bootclasspath-fragment")
 
 	// Check that source on its own configures the bootImageConfig correctly.
-	java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/meta_lic")
-	java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+	java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
+	java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
 
 	CheckSnapshot(t, result, "mysdk", "",
 		checkAndroidBpContents(`
@@ -213,24 +213,24 @@
 					java.ApexBootJarDexJarPaths...,
 				)...,
 			)
-			java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/art-bootclasspath-fragment/android_common_com.android.art/meta_lic")
-			java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+			java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
+			java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
 		}),
 
 		snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
 
 		// Check the behavior of the snapshot when the source is preferred.
 		snapshotTestChecker(checkSnapshotWithSourcePreferred, func(t *testing.T, result *android.TestResult) {
-			java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/meta_lic")
-			java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+			java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
+			java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
 		}),
 
 		snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
 
 		// Check the behavior of the snapshot when it is preferred.
 		snapshotTestChecker(checkSnapshotPreferredWithSource, func(t *testing.T, result *android.TestResult) {
-			java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/prebuilt_art-bootclasspath-fragment/android_common_com.android.art/meta_lic")
-			java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+			java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
+			java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
 		}),
 	)
 
diff --git a/tests/genrule_sandbox_test.py b/tests/genrule_sandbox_test.py
index a9f0c9b..0cebc2a 100755
--- a/tests/genrule_sandbox_test.py
+++ b/tests/genrule_sandbox_test.py
@@ -17,34 +17,37 @@
 import argparse
 import collections
 import json
-import os.path
+import os
 import subprocess
+import sys
 import tempfile
 
-SRC_ROOT_DIR = os.path.abspath(__file__ + "/../../../..")
+def get_top() -> str:
+  path = '.'
+  while not os.path.isfile(os.path.join(path, 'build/soong/tests/genrule_sandbox_test.py')):
+    if os.path.abspath(path) == '/':
+      sys.exit('Could not find android source tree root.')
+    path = os.path.join(path, '..')
+  return os.path.abspath(path)
 
-
-def _module_graph_path(out_dir):
-  return os.path.join(SRC_ROOT_DIR, out_dir, "soong", "module-actions.json")
-
-
-def _build_with_soong(targets, target_product, out_dir, extra_env={}):
+def _build_with_soong(targets, target_product, *, keep_going = False, extra_env={}):
   env = {
+      **os.environ,
       "TARGET_PRODUCT": target_product,
       "TARGET_BUILD_VARIANT": "userdebug",
   }
-  env.update(os.environ)
   env.update(extra_env)
   args = [
       "build/soong/soong_ui.bash",
       "--make-mode",
       "--skip-soong-tests",
   ]
+  if keep_going:
+    args.append("-k")
   args.extend(targets)
   try:
-    out = subprocess.check_output(
+    subprocess.check_output(
         args,
-        cwd=SRC_ROOT_DIR,
         env=env,
     )
   except subprocess.CalledProcessError as e:
@@ -55,14 +58,13 @@
 
 
 def _find_outputs_for_modules(modules, out_dir, target_product):
-  module_path = os.path.join(
-      SRC_ROOT_DIR, out_dir, "soong", "module-actions.json"
-  )
+  module_path = os.path.join(out_dir, "soong", "module-actions.json")
 
   if not os.path.exists(module_path):
-    _build_with_soong(["json-module-graph"], target_product, out_dir)
+    _build_with_soong(["json-module-graph"], target_product)
 
-  action_graph = json.load(open(_module_graph_path(out_dir)))
+  with open(module_path) as f:
+    action_graph = json.load(f)
 
   module_to_outs = collections.defaultdict(set)
   for mod in action_graph:
@@ -74,50 +76,15 @@
   return module_to_outs
 
 
-def _store_outputs_to_tmp(output_files):
-  try:
-    tempdir = tempfile.TemporaryDirectory()
-    for f in output_files:
-      out = subprocess.check_output(
-          ["cp", "--parents", f, tempdir.name],
-          cwd=SRC_ROOT_DIR,
-      )
-    return tempdir
-  except subprocess.CalledProcessError as e:
-    print(e)
-    print(e.stdout)
-    print(e.stderr)
-
-
-def _diff_outs(file1, file2, show_diff):
-  output = None
-  base_args = ["diff"]
-  if not show_diff:
-    base_args.append("--brief")
-  try:
-    args = base_args + [file1, file2]
-    output = subprocess.check_output(
-        args,
-        cwd=SRC_ROOT_DIR,
-    )
-  except subprocess.CalledProcessError as e:
-    if e.returncode == 1:
-      if show_diff:
-        return output
-      return True
-  return None
-
-
-def _compare_outputs(module_to_outs, tempdir, show_diff):
+def _compare_outputs(module_to_outs, tempdir) -> dict[str, list[str]]:
   different_modules = collections.defaultdict(list)
   for module, outs in module_to_outs.items():
     for out in outs:
-      output = None
-      diff = _diff_outs(os.path.join(tempdir.name, out), out, show_diff)
-      if diff:
-        different_modules[module].append(diff)
+      try:
+        subprocess.check_output(["diff", os.path.join(tempdir, out), out])
+      except subprocess.CalledProcessError as e:
+        different_modules[module].append(e.stdout)
 
-  tempdir.cleanup()
   return different_modules
 
 
@@ -138,53 +105,56 @@
       "--show-diff",
       "-d",
       action="store_true",
-      required=False,
       help="whether to display differing files",
   )
   parser.add_argument(
       "--output-paths-only",
       "-o",
       action="store_true",
-      required=False,
       help="Whether to only return the output paths per module",
   )
   args = parser.parse_args()
+  os.chdir(get_top())
 
   out_dir = os.environ.get("OUT_DIR", "out")
-  target_product = args.target_product
-  modules = set(args.modules)
 
-  module_to_outs = _find_outputs_for_modules(modules, out_dir, target_product)
+  print("finding output files for the modules...")
+  module_to_outs = _find_outputs_for_modules(set(args.modules), out_dir, args.target_product)
   if not module_to_outs:
-    print("No outputs found")
-    exit(1)
+    sys.exit("No outputs found")
 
   if args.output_paths_only:
     for m, o in module_to_outs.items():
       print(f"{m} outputs: {o}")
-    exit(0)
+    sys.exit(0)
 
-  all_outs = set()
-  for outs in module_to_outs.values():
-    all_outs.update(outs)
-  print("build without sandboxing")
-  _build_with_soong(list(all_outs), target_product, out_dir)
-  tempdir = _store_outputs_to_tmp(all_outs)
-  print("build with sandboxing")
-  _build_with_soong(
-      list(all_outs),
-      target_product,
-      out_dir,
-      extra_env={"GENRULE_SANDBOXING": "true"},
-  )
-  diffs = _compare_outputs(module_to_outs, tempdir, args.show_diff)
-  if len(diffs) == 0:
-    print("All modules are correct")
-  elif args.show_diff:
-    for m, d in diffs.items():
-      print(f"Module {m} has diffs {d}")
-  else:
-    print(f"Modules {list(diffs.keys())} have diffs")
+  all_outs = list(set.union(*module_to_outs.values()))
+
+  print("building without sandboxing...")
+  _build_with_soong(all_outs, args.target_product)
+  with tempfile.TemporaryDirectory() as tempdir:
+    for f in all_outs:
+      subprocess.check_call(["cp", "--parents", f, tempdir])
+
+    print("building with sandboxing...")
+    _build_with_soong(
+        all_outs,
+        args.target_product,
+        # We've verified these build without sandboxing already, so do the sandboxing build
+        # with keep_going = True so that we can find all the genrules that fail to build with
+        # sandboxing.
+        keep_going = True,
+        extra_env={"GENRULE_SANDBOXING": "true"},
+    )
+
+    diffs = _compare_outputs(module_to_outs, tempdir)
+    if len(diffs) == 0:
+      print("All modules are correct")
+    elif args.show_diff:
+      for m, d in diffs.items():
+        print(f"Module {m} has diffs {d}")
+    else:
+      print(f"Modules {list(diffs.keys())} have diffs")
 
 
 if __name__ == "__main__":
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 30a1d37..1241e89 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -111,6 +111,14 @@
     -I /system/lib64/android.hardware.security.rkp-V3-ndk.so \
     -I /system/lib64/android.hardware.security.sharedsecret-V1-ndk.so \
     -I /system/lib64/android.security.compat-ndk.so \
+    -I /system/lib64/libcuttlefish_allocd_utils.so \
+    -I /system/lib64/libcuttlefish_device_config_proto.so \
+    -I /system/lib64/libcuttlefish_device_config.so \
+    -I /system/lib64/libcuttlefish_fs.so \
+    -I /system/lib64/libcuttlefish_kernel_log_monitor_utils.so \
+    -I /system/lib64/libcuttlefish_utils.so \
+    -I /system/lib64/libfruit.so \
+    -I /system/lib64/libgflags.so \
     -I /system/lib64/libkeymaster4_1support.so \
     -I /system/lib64/libkeymaster4support.so \
     -I /system/lib64/libkeymint.so \
diff --git a/ui/metrics/bp2build_progress_metrics_proto/bp2build.proto b/ui/metrics/bp2build_progress_metrics_proto/bp2build.proto
index 4aee88b..5b44002 100644
--- a/ui/metrics/bp2build_progress_metrics_proto/bp2build.proto
+++ b/ui/metrics/bp2build_progress_metrics_proto/bp2build.proto
@@ -38,6 +38,9 @@
 
     // Total number of transitive dependencies.
     int32 num_deps = 5;
+
+    // Unconverted reasons from heuristics
+    repeated string unconverted_reasons_from_heuristics = 6;
   }
 
   // Modules that the transitive dependencies were identified for.
diff --git a/zip/cmd/main.go b/zip/cmd/main.go
index a2ccc20..5231fae 100644
--- a/zip/cmd/main.go
+++ b/zip/cmd/main.go
@@ -173,6 +173,7 @@
 	cpuProfile := flags.String("cpuprofile", "", "write cpu profile to file")
 	traceFile := flags.String("trace", "", "write trace to file")
 	sha256Checksum := flags.Bool("sha256", false, "add a zip header to each file containing its SHA256 digest")
+	doNotWrite := flags.Bool("n", false, "Nothing is written to disk -- all other work happens")
 
 	flags.Var(&rootPrefix{}, "P", "path prefix within the zip at which to place files")
 	flags.Var(&listFiles{}, "l", "file containing list of files to zip")
@@ -236,6 +237,7 @@
 		StoreSymlinks:            *symlinks,
 		IgnoreMissingFiles:       *ignoreMissingFiles,
 		Sha256Checksum:           *sha256Checksum,
+		DoNotWrite:               *doNotWrite,
 	})
 	if err != nil {
 		fmt.Fprintln(os.Stderr, "error:", err.Error())
diff --git a/zip/zip.go b/zip/zip.go
index 5e1a104..30a2ee7 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -282,6 +282,7 @@
 	StoreSymlinks            bool
 	IgnoreMissingFiles       bool
 	Sha256Checksum           bool
+	DoNotWrite               bool
 
 	Stderr     io.Writer
 	Filesystem pathtools.FileSystem
@@ -400,7 +401,9 @@
 
 	var zipErr error
 
-	if !args.WriteIfChanged {
+	if args.DoNotWrite {
+		out = io.Discard
+	} else if !args.WriteIfChanged {
 		f, err := os.Create(args.OutputFilePath)
 		if err != nil {
 			return err
@@ -421,7 +424,7 @@
 		return zipErr
 	}
 
-	if args.WriteIfChanged {
+	if args.WriteIfChanged && !args.DoNotWrite {
 		err := pathtools.WriteFileIfChanged(args.OutputFilePath, buf.Bytes(), 0666)
 		if err != nil {
 			return err