Merge "Update apex test to verify behavior"
diff --git a/aidl_library/Android.bp b/aidl_library/Android.bp
new file mode 100644
index 0000000..ec21504
--- /dev/null
+++ b/aidl_library/Android.bp
@@ -0,0 +1,32 @@
+// 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+    name: "soong-aidl-library",
+    pkgPath: "android/soong/aidl_library",
+    deps: [
+        "soong-android",
+    ],
+    srcs: [
+        "aidl_library.go",
+    ],
+    testSrcs: [
+        "aidl_library_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/aidl_library/aidl_library.go b/aidl_library/aidl_library.go
new file mode 100644
index 0000000..8a84e6b
--- /dev/null
+++ b/aidl_library/aidl_library.go
@@ -0,0 +1,174 @@
+// 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 aidl_library
+
+import (
+	"android/soong/android"
+	"android/soong/bazel"
+
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+)
+
+var PrepareForTestWithAidlLibrary = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+	registerAidlLibraryBuildComponents(ctx)
+})
+
+func init() {
+	registerAidlLibraryBuildComponents(android.InitRegistrationContext)
+}
+
+func registerAidlLibraryBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("aidl_library", AidlLibraryFactory)
+}
+
+type aidlLibraryProperties struct {
+	// srcs lists files that are included in this module for aidl compilation
+	Srcs []string `android:"path"`
+
+	// hdrs lists the headers that are imported by srcs but are not compiled by aidl to language binding code
+	// hdrs is provided to support Bazel migration. It is a no-op until
+	// we enable input sandbox in aidl compilation action
+	Hdrs []string `android:"path"`
+
+	// The prefix to strip from the paths of the .aidl files
+	// The remaining path is the package path of the aidl interface
+	Strip_import_prefix *string
+
+	// List of aidl files or aidl_library depended on by the module
+	Deps []string `android:"arch_variant"`
+}
+
+type AidlLibrary struct {
+	android.ModuleBase
+	android.BazelModuleBase
+	properties aidlLibraryProperties
+}
+
+type bazelAidlLibraryAttributes struct {
+	Srcs                bazel.LabelListAttribute
+	Hdrs                bazel.LabelListAttribute
+	Strip_import_prefix *string
+	Deps                bazel.LabelListAttribute
+}
+
+func (lib *AidlLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+	srcs := bazel.MakeLabelListAttribute(
+		android.BazelLabelForModuleSrc(
+			ctx,
+			lib.properties.Srcs,
+		),
+	)
+
+	hdrs := bazel.MakeLabelListAttribute(
+		android.BazelLabelForModuleSrc(
+			ctx,
+			lib.properties.Hdrs,
+		),
+	)
+
+	tags := []string{"apex_available=//apex_available:anyapex"}
+	deps := bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, lib.properties.Deps))
+
+	attrs := &bazelAidlLibraryAttributes{
+		Srcs:                srcs,
+		Hdrs:                hdrs,
+		Strip_import_prefix: lib.properties.Strip_import_prefix,
+		Deps:                deps,
+	}
+
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "aidl_library",
+		Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
+	}
+
+	ctx.CreateBazelTargetModule(
+		props,
+		android.CommonAttributes{
+			Name: lib.Name(),
+			Tags: bazel.MakeStringListAttribute(tags),
+		},
+		attrs,
+	)
+}
+
+type AidlLibraryInfo struct {
+	// The direct aidl files of the module
+	Srcs android.Paths
+	// The include dirs to the direct aidl files and those provided from aidl_library deps
+	IncludeDirs android.DepSet
+}
+
+// AidlLibraryProvider provides the srcs and the transitive include dirs
+var AidlLibraryProvider = blueprint.NewProvider(AidlLibraryInfo{})
+
+func (lib *AidlLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	includeDirsDepSetBuilder := android.NewDepSetBuilder(android.PREORDER)
+
+	if len(lib.properties.Srcs) == 0 && len(lib.properties.Hdrs) == 0 {
+		ctx.ModuleErrorf("at least srcs or hdrs prop must be non-empty")
+	}
+
+	srcs := android.PathsForModuleSrc(ctx, lib.properties.Srcs)
+	if lib.properties.Strip_import_prefix != nil {
+		srcs = android.PathsWithModuleSrcSubDir(
+			ctx,
+			srcs,
+			android.String(lib.properties.Strip_import_prefix))
+	}
+
+	includeDir := android.PathForModuleSrc(
+		ctx,
+		proptools.StringDefault(lib.properties.Strip_import_prefix, ""),
+	)
+
+	includeDirsDepSetBuilder.Direct(includeDir)
+
+	for _, dep := range ctx.GetDirectDepsWithTag(aidlLibraryTag) {
+		if ctx.OtherModuleHasProvider(dep, AidlLibraryProvider) {
+			info := ctx.OtherModuleProvider(dep, AidlLibraryProvider).(AidlLibraryInfo)
+			includeDirsDepSetBuilder.Transitive(&info.IncludeDirs)
+		}
+	}
+
+	// TODO(b/279960133) Propagate direct and transitive headers/srcs when aidl action sandboxes inputs
+	ctx.SetProvider(AidlLibraryProvider, AidlLibraryInfo{
+		Srcs:        srcs,
+		IncludeDirs: *includeDirsDepSetBuilder.Build(),
+	})
+}
+
+// aidl_library contains a list of .aidl files and the strip_import_prefix to
+// to strip from the paths of the .aidl files. The sub-path left-over after stripping
+// corresponds to the aidl package path the aidl interfaces are scoped in
+func AidlLibraryFactory() android.Module {
+	module := &AidlLibrary{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidModule(module)
+	android.InitBazelModule(module)
+	return module
+}
+
+type aidlDependencyTag struct {
+	blueprint.BaseDependencyTag
+}
+
+var aidlLibraryTag = aidlDependencyTag{}
+
+func (lib *AidlLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+	for _, dep := range lib.properties.Deps {
+		ctx.AddDependency(lib, aidlLibraryTag, dep)
+	}
+}
diff --git a/aidl_library/aidl_library_test.go b/aidl_library/aidl_library_test.go
new file mode 100644
index 0000000..d9b410a
--- /dev/null
+++ b/aidl_library/aidl_library_test.go
@@ -0,0 +1,122 @@
+// 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 aidl_library
+
+import (
+	"android/soong/android"
+	"testing"
+)
+
+func TestAidlLibrary(t *testing.T) {
+	t.Parallel()
+	ctx := android.GroupFixturePreparers(
+		PrepareForTestWithAidlLibrary,
+		android.MockFS{
+			"package_bar/Android.bp": []byte(`
+			aidl_library {
+					name: "bar",
+					srcs: ["x/y/Bar.aidl"],
+					strip_import_prefix: "x",
+				}
+			`),
+		}.AddToFixture(),
+		android.MockFS{
+			"package_foo/Android.bp": []byte(`
+			aidl_library {
+					name: "foo",
+					srcs: ["a/b/Foo.aidl"],
+					hdrs: ["Header.aidl"],
+					strip_import_prefix: "a",
+					deps: ["bar"],
+				}
+			`),
+		}.AddToFixture(),
+	).RunTest(t).TestContext
+
+	foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
+	actualInfo := ctx.ModuleProvider(foo, AidlLibraryProvider).(AidlLibraryInfo)
+
+	android.AssertArrayString(
+		t,
+		"aidl include dirs",
+		[]string{"package_foo/a", "package_bar/x"},
+		actualInfo.IncludeDirs.ToList().Strings(),
+	)
+
+	android.AssertPathsRelativeToTopEquals(
+		t,
+		"aidl srcs paths",
+		[]string{"package_foo/a/b/Foo.aidl"},
+		actualInfo.Srcs,
+	)
+}
+
+func TestAidlLibraryWithoutStripImportPrefix(t *testing.T) {
+	t.Parallel()
+	ctx := android.GroupFixturePreparers(
+		PrepareForTestWithAidlLibrary,
+		android.MockFS{
+			"package_bar/Android.bp": []byte(`
+			aidl_library {
+					name: "bar",
+					srcs: ["x/y/Bar.aidl"],
+				}
+			`),
+		}.AddToFixture(),
+		android.MockFS{
+			"package_foo/Android.bp": []byte(`
+			aidl_library {
+					name: "foo",
+					srcs: ["a/b/Foo.aidl"],
+					hdrs: ["Header.aidl"],
+					deps: ["bar"],
+				}
+			`),
+		}.AddToFixture(),
+	).RunTest(t).TestContext
+
+	foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
+	actualInfo := ctx.ModuleProvider(foo, AidlLibraryProvider).(AidlLibraryInfo)
+
+	android.AssertArrayString(
+		t,
+		"aidl include dirs",
+		[]string{"package_foo", "package_bar"},
+		actualInfo.IncludeDirs.ToList().Strings(),
+	)
+
+	android.AssertPathsRelativeToTopEquals(
+		t,
+		"aidl srcs paths",
+		[]string{"package_foo/a/b/Foo.aidl"},
+		actualInfo.Srcs,
+	)
+}
+
+func TestAidlLibraryWithNoSrcsHdrsDeps(t *testing.T) {
+	t.Parallel()
+	android.GroupFixturePreparers(
+		PrepareForTestWithAidlLibrary,
+		android.MockFS{
+			"package_bar/Android.bp": []byte(`
+			aidl_library {
+					name: "bar",
+				}
+			`),
+		}.AddToFixture(),
+	).
+		ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("at least srcs or hdrs prop must be non-empty")).
+		RunTest(t)
+}
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 71281a6..5b7f117 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -203,23 +203,24 @@
 		"frameworks/av/media/audioaidlconversion":            Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/codec2/components/aom":          Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/codecs":                         Bp2BuildDefaultTrueRecursively,
-		"frameworks/av/media/module/codecs":                  Bp2BuildDefaultTrueRecursively,
-		"frameworks/av/media/module/foundation":              Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/liberror":                       Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/libmediahelper":                 Bp2BuildDefaultTrue,
 		"frameworks/av/media/libshmem":                       Bp2BuildDefaultTrueRecursively,
+		"frameworks/av/media/module/codecs":                  Bp2BuildDefaultTrueRecursively,
+		"frameworks/av/media/module/foundation":              Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/module/minijail":                Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/services/minijail":                    Bp2BuildDefaultTrueRecursively,
 		"frameworks/base/libs/androidfw":                     Bp2BuildDefaultTrue,
 		"frameworks/base/media/tests/MediaDump":              Bp2BuildDefaultTrue,
-		"frameworks/base/services/tests/servicestests/aidl":  Bp2BuildDefaultTrue,
 		"frameworks/base/proto":                              Bp2BuildDefaultTrue,
+		"frameworks/base/services/tests/servicestests/aidl":  Bp2BuildDefaultTrue,
 		"frameworks/base/startop/apps/test":                  Bp2BuildDefaultTrue,
 		"frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
 		"frameworks/base/tools/aapt2":                        Bp2BuildDefaultTrue,
 		"frameworks/base/tools/codegen":                      Bp2BuildDefaultTrueRecursively,
 		"frameworks/base/tools/streaming_proto":              Bp2BuildDefaultTrueRecursively,
 		"frameworks/hardware/interfaces/stats/aidl":          Bp2BuildDefaultTrue,
+		"frameworks/libs/modules-utils/build":                Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/adbd_auth":                   Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/arect":                       Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/gui":                         Bp2BuildDefaultTrue,
@@ -1555,9 +1556,10 @@
 	// also be built - do not add them to this list.
 	StagingMixedBuildsEnabledList = []string{
 		// M13: media.swcodec launch
-		"com.android.media.swcodec",
-		"test_com.android.media.swcodec",
-		"libstagefright_foundation",
+		// TODO(b/282042844): reenable
+		// "com.android.media.swcodec",
+		// "test_com.android.media.swcodec",
+		// "libstagefright_foundation",
 	}
 
 	// These should be the libs that are included by the apexes in the ProdMixedBuildsEnabledList
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 5291eca..10cf60a 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -29,6 +29,7 @@
 	"android/soong/bazel/cquery"
 	"android/soong/shared"
 	"android/soong/starlark_fmt"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/metrics"
 
@@ -700,9 +701,6 @@
 		// We don't need to set --host_platforms because it's set in bazelrc files
 		// that the bazel shell script wrapper passes
 
-		// Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network.
-		"--experimental_repository_disable_download",
-
 		// Suppress noise
 		"--ui_event_filters=-INFO",
 		"--noshow_progress",
diff --git a/android/config.go b/android/config.go
index 9e94e05..acadb3f 100644
--- a/android/config.go
+++ b/android/config.go
@@ -183,6 +183,16 @@
 	return String(c.config.productVariables.DeviceMaxPageSizeSupported)
 }
 
+// The release version passed to aconfig, derived from RELEASE_VERSION
+func (c Config) ReleaseVersion() string {
+	return c.config.productVariables.ReleaseVersion
+}
+
+// The flag values files passed to aconfig, derived from RELEASE_VERSION
+func (c Config) ReleaseDeviceConfigValueSets() []string {
+	return c.config.productVariables.ReleaseDeviceConfigValueSets
+}
+
 // A DeviceConfig object represents the configuration for a particular device
 // being built. For now there will only be one of these, but in the future there
 // may be multiple devices being built.
diff --git a/android/variable.go b/android/variable.go
index bf66135..97171e7 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -473,6 +473,9 @@
 	ProductManufacturer string   `json:",omitempty"`
 	ProductBrand        string   `json:",omitempty"`
 	BuildVersionTags    []string `json:",omitempty"`
+
+	ReleaseVersion               string   `json:",omitempty"`
+	ReleaseDeviceConfigValueSets []string `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/apex/Android.bp b/apex/Android.bp
index 7ffca0e..61d7fb2 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -38,6 +38,7 @@
         "apex_test.go",
         "bootclasspath_fragment_test.go",
         "classpath_element_test.go",
+        "dexpreopt_bootjars_test.go",
         "metadata_test.go",
         "platform_bootclasspath_test.go",
         "systemserver_classpath_fragment_test.go",
diff --git a/apex/apex.go b/apex/apex.go
index 33ed111..ff7ee35 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -137,6 +137,10 @@
 	// List of filesystem images that are embedded inside this APEX bundle.
 	Filesystems []string
 
+	// The minimum SDK version that this APEX must support at minimum. This is usually set to
+	// the SDK version that the APEX was first introduced.
+	Min_sdk_version *string
+
 	// Whether this APEX is considered updatable or not. When set to true, this will enforce
 	// additional rules for making sure that the APEX is truly updatable. To be updatable,
 	// min_sdk_version should be set as well. This will also disable the size optimizations like
@@ -380,10 +384,6 @@
 
 	// Trim against a specific Dynamic Common Lib APEX
 	Trim_against *string
-
-	// The minimum SDK version that this APEX must support at minimum. This is usually set to
-	// the SDK version that the APEX was first introduced.
-	Min_sdk_version *string
 }
 
 type apexBundle struct {
@@ -404,7 +404,7 @@
 	///////////////////////////////////////////////////////////////////////////////////////////
 	// Inputs
 
-	// Keys for apex_paylaod.img
+	// Keys for apex_payload.img
 	publicKeyFile  android.Path
 	privateKeyFile android.Path
 
@@ -2287,16 +2287,13 @@
 				ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName)
 			}
 		case bcpfTag:
-			bcpfModule, ok := child.(*java.BootclasspathFragmentModule)
+			_, ok := child.(*java.BootclasspathFragmentModule)
 			if !ok {
 				ctx.PropertyErrorf("bootclasspath_fragments", "%q is not a bootclasspath_fragment module", depName)
 				return false
 			}
 
 			vctx.filesInfo = append(vctx.filesInfo, apexBootclasspathFragmentFiles(ctx, child)...)
-			for _, makeModuleName := range bcpfModule.BootImageDeviceInstallMakeModules() {
-				a.makeModulesToInstall = append(a.makeModulesToInstall, makeModuleName)
-			}
 			return true
 		case sscpfTag:
 			if _, ok := child.(*java.SystemServerClasspathModule); !ok {
@@ -2609,8 +2606,45 @@
 	ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
 	vctx.normalizeFileInfo(ctx)
 	if a.privateKeyFile == nil {
-		ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.overridableProperties.Key))
-		return
+		if ctx.Config().AllowMissingDependencies() {
+			// TODO(b/266099037): a better approach for slim manifests.
+			ctx.AddMissingDependencies([]string{String(a.overridableProperties.Key)})
+			// Create placeholder paths for later stages that expect to see those paths,
+			// though they won't be used.
+			var unusedPath = android.PathForModuleOut(ctx, "nonexistentprivatekey")
+			ctx.Build(pctx, android.BuildParams{
+				Rule:   android.ErrorRule,
+				Output: unusedPath,
+				Args: map[string]string{
+					"error": "Private key not available",
+				},
+			})
+			a.privateKeyFile = unusedPath
+		} else {
+			ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.overridableProperties.Key))
+			return
+		}
+	}
+
+	if a.publicKeyFile == nil {
+		if ctx.Config().AllowMissingDependencies() {
+			// TODO(b/266099037): a better approach for slim manifests.
+			ctx.AddMissingDependencies([]string{String(a.overridableProperties.Key)})
+			// Create placeholder paths for later stages that expect to see those paths,
+			// though they won't be used.
+			var unusedPath = android.PathForModuleOut(ctx, "nonexistentpublickey")
+			ctx.Build(pctx, android.BuildParams{
+				Rule:   android.ErrorRule,
+				Output: unusedPath,
+				Args: map[string]string{
+					"error": "Public key not available",
+				},
+			})
+			a.publicKeyFile = unusedPath
+		} else {
+			ctx.PropertyErrorf("key", "public_key for %q could not be found", String(a.overridableProperties.Key))
+			return
+		}
 	}
 
 	////////////////////////////////////////////////////////////////////////////////////////////
@@ -2662,19 +2696,6 @@
 	bootclasspathFragmentInfo := ctx.OtherModuleProvider(module, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
 	var filesToAdd []apexFile
 
-	// Add the boot image files, e.g. .art, .oat and .vdex files.
-	if bootclasspathFragmentInfo.ShouldInstallBootImageInApex() {
-		for arch, files := range bootclasspathFragmentInfo.AndroidBootImageFilesByArchType() {
-			dirInApex := filepath.Join("javalib", arch.String())
-			for _, f := range files {
-				androidMkModuleName := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
-				// TODO(b/177892522) - consider passing in the bootclasspath fragment module here instead of nil
-				af := newApexFile(ctx, f, androidMkModuleName, dirInApex, etc, nil)
-				filesToAdd = append(filesToAdd, af)
-			}
-		}
-	}
-
 	// Add classpaths.proto config.
 	if af := apexClasspathFragmentProtoFile(ctx, module); af != nil {
 		filesToAdd = append(filesToAdd, *af)
@@ -2951,7 +2972,7 @@
 	// Only override the minSdkVersion value on Apexes which already specify
 	// a min_sdk_version (it's optional for non-updatable apexes), and that its
 	// min_sdk_version value is lower than the one to override with.
-	minApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.overridableProperties.Min_sdk_version))
+	minApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version))
 	if minApiLevel.IsNone() {
 		return ""
 	}
@@ -3242,7 +3263,6 @@
 	//
 	m["com.android.appsearch"] = []string{
 		"icing-java-proto-lite",
-		"libprotobuf-java-lite",
 	}
 	//
 	// Module separator
@@ -3258,11 +3278,8 @@
 	// Module separator
 	//
 	m["com.android.extservices"] = []string{
-		"error_prone_annotations",
 		"ExtServices-core",
-		"ExtServices",
 		"libtextclassifier-java",
-		"libz_current",
 		"textclassifier-statsd",
 		"TextClassifierNotificationLibNoManifest",
 		"TextClassifierServiceLibNoManifest",
@@ -3280,8 +3297,6 @@
 		"android.hidl.memory@1.0",
 		"android.hidl.safe_union@1.0",
 		"libarect",
-		"libbuildversion",
-		"libmath",
 		"libprocpartition",
 	}
 	//
@@ -3311,15 +3326,12 @@
 	// Module separator
 	//
 	m["com.android.runtime"] = []string{
-		"bionic_libc_platform_headers",
-		"libarm-optimized-routines-math",
 		"libc_aeabi",
 		"libc_bionic",
 		"libc_bionic_ndk",
 		"libc_bootstrap",
 		"libc_common",
 		"libc_common_shared",
-		"libc_common_static",
 		"libc_dns",
 		"libc_dynamic_dispatch",
 		"libc_fortify",
@@ -3336,19 +3348,16 @@
 		"libc_openbsd_large_stack",
 		"libc_openbsd_ndk",
 		"libc_pthread",
-		"libc_static_dispatch",
 		"libc_syscalls",
 		"libc_tzcode",
 		"libc_unwind_static",
 		"libdebuggerd",
 		"libdebuggerd_common_headers",
 		"libdebuggerd_handler_core",
-		"libdebuggerd_handler_fallback",
 		"libdl_static",
 		"libjemalloc5",
 		"liblinker_main",
 		"liblinker_malloc",
-		"liblz4",
 		"liblzma",
 		"libprocinfo",
 		"libpropertyinfoparser",
@@ -3366,17 +3375,7 @@
 	m["com.android.tethering"] = []string{
 		"android.hardware.tetheroffload.config-V1.0-java",
 		"android.hardware.tetheroffload.control-V1.0-java",
-		"android.hidl.base-V1.0-java",
-		"libcgrouprc",
-		"libcgrouprc_format",
-		"libtetherutilsjni",
-		"libvndksupport",
 		"net-utils-framework-common",
-		"netd_aidl_interface-V3-java",
-		"netlink-client",
-		"networkstack-aidl-interfaces-java",
-		"tethering-aidl-interfaces-java",
-		"TetheringApiCurrentLib",
 	}
 	//
 	// Module separator
@@ -3396,48 +3395,22 @@
 		"android.hardware.wifi.supplicant-V1.1-java",
 		"android.hardware.wifi.supplicant-V1.2-java",
 		"android.hardware.wifi.supplicant-V1.3-java",
-		"android.hidl.base-V1.0-java",
-		"android.hidl.manager-V1.0-java",
-		"android.hidl.manager-V1.1-java",
-		"android.hidl.manager-V1.2-java",
 		"bouncycastle-unbundled",
-		"dnsresolver_aidl_interface-V2-java",
-		"error_prone_annotations",
-		"framework-wifi-pre-jarjar",
 		"framework-wifi-util-lib",
-		"ipmemorystore-aidl-interfaces-V3-java",
-		"ipmemorystore-aidl-interfaces-java",
 		"ksoap2",
 		"libnanohttpd",
-		"libwifi-jni",
-		"net-utils-services-common",
-		"netd_aidl_interface-V2-java",
-		"netd_aidl_interface-unstable-java",
-		"netd_event_listener_interface-java",
-		"netlink-client",
-		"networkstack-client",
-		"services.net",
 		"wifi-lite-protos",
 		"wifi-nano-protos",
 		"wifi-service-pre-jarjar",
-		"wifi-service-resources",
-	}
-	//
-	// Module separator
-	//
-	m["com.android.os.statsd"] = []string{
-		"libstatssocket",
 	}
 	//
 	// Module separator
 	//
 	m[android.AvailableToAnyApex] = []string{
-		"libclang_rt",
 		"libprofile-clang-extras",
 		"libprofile-clang-extras_ndk",
 		"libprofile-extras",
 		"libprofile-extras_ndk",
-		"libunwind",
 	}
 	return m
 }
@@ -3593,8 +3566,8 @@
 	// TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but
 	// given it's coming via config, we probably don't want to put it in here.
 	var minSdkVersion bazel.StringAttribute
-	if a.overridableProperties.Min_sdk_version != nil {
-		minSdkVersion.SetValue(*a.overridableProperties.Min_sdk_version)
+	if a.properties.Min_sdk_version != nil {
+		minSdkVersion.SetValue(*a.properties.Min_sdk_version)
 	}
 	if props, ok := productVariableProps[minSdkVersionPropName]; ok {
 		for c, p := range props {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ed5eb2e..c1d80a3 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -147,7 +147,7 @@
 	android.PrepareForTestWithAndroidBuildComponents,
 	bpf.PrepareForTestWithBpf,
 	cc.PrepareForTestWithCcBuildComponents,
-	java.PrepareForTestWithJavaDefaultModules,
+	java.PrepareForTestWithDexpreopt,
 	prebuilt_etc.PrepareForTestWithPrebuiltEtc,
 	rust.PrepareForTestWithRustDefaultModules,
 	sh.PrepareForTestWithShBuildComponents,
@@ -1499,6 +1499,10 @@
 			sanitize: {
 				never: true,
 			},
+			apex_available: [
+				"//apex_available:anyapex",
+				"//apex_available:platform",
+			],
 		}	`)
 	ctx := result.TestContext
 
@@ -1547,6 +1551,10 @@
 			sanitize: {
 				never: true,
 			},
+			apex_available: [
+				"//apex_available:anyapex",
+				"//apex_available:platform",
+			],
 		}
 		`)
 	ctx := result.TestContext
@@ -8445,8 +8453,8 @@
 		testNoUpdatableJarsInBootImage(t, "", preparer, fragments...)
 	})
 
-	t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
-		err := `module "some-art-lib" from updatable apexes \["com.android.art.debug"\] is not allowed in the framework boot image`
+	t.Run("updatable jar from ART apex in the platform bootclasspath => error", func(t *testing.T) {
+		err := `module "some-art-lib" from updatable apexes \["com.android.art.debug"\] is not allowed in the platform bootclasspath`
 		// Update the dexpreopt BootJars directly.
 		preparer := android.GroupFixturePreparers(
 			prepareSetBootJars("com.android.art.debug:some-art-lib"),
@@ -8469,8 +8477,8 @@
 		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
-	t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) {
-		err := `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the framework boot image`
+	t.Run("updatable jar from some other apex in the platform bootclasspath => error", func(t *testing.T) {
+		err := `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the platform bootclasspath`
 		preparer := android.GroupFixturePreparers(
 			java.FixtureConfigureBootJars("some-updatable-apex:some-updatable-apex-lib"),
 			java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib"),
@@ -8478,7 +8486,7 @@
 		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
-	t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) {
+	t.Run("non-updatable jar from some other apex in the platform bootclasspath => ok", func(t *testing.T) {
 		preparer := java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib")
 		fragment := java.ApexVariantReference{
 			Apex:   proptools.StringPtr("some-non-updatable-apex"),
@@ -8493,7 +8501,7 @@
 		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
-	t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) {
+	t.Run("nonexistent jar in the platform bootclasspath => error", func(t *testing.T) {
 		err := `"platform-bootclasspath" depends on undefined module "nonexistent"`
 		preparer := java.FixtureConfigureBootJars("platform:nonexistent")
 		testNoUpdatableJarsInBootImage(t, err, preparer)
@@ -8506,7 +8514,7 @@
 		testNoUpdatableJarsInBootImage(t, err, preparer)
 	})
 
-	t.Run("platform jar in the framework boot image => ok", func(t *testing.T) {
+	t.Run("platform jar in the platform bootclasspath => ok", func(t *testing.T) {
 		preparer := android.GroupFixturePreparers(
 			java.FixtureConfigureBootJars("platform:some-platform-lib"),
 			java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib"),
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 3e55ccc..1b52886 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -115,20 +115,7 @@
 
 	// Make sure that the art-bootclasspath-fragment is using the correct configuration.
 	checkBootclasspathFragment(t, result, "art-bootclasspath-fragment", "android_common_apex10000",
-		"com.android.art:baz,com.android.art:quuz", `
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-quuz.art
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-quuz.oat
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-quuz.vdex
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-quuz.art
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-quuz.oat
-dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-quuz.vdex
-`)
+		"com.android.art:baz,com.android.art:quuz")
 }
 
 func TestBootclasspathFragments_FragmentDependency(t *testing.T) {
@@ -261,7 +248,7 @@
 	checkAPIScopeStubs("other", otherInfo, java.CorePlatformHiddenAPIScope)
 }
 
-func checkBootclasspathFragment(t *testing.T, result *android.TestResult, moduleName, variantName string, expectedConfiguredModules string, expectedBootclasspathFragmentFiles string) {
+func checkBootclasspathFragment(t *testing.T, result *android.TestResult, moduleName, variantName string, expectedConfiguredModules string) {
 	t.Helper()
 
 	bootclasspathFragment := result.ModuleForTests(moduleName, variantName).Module().(*java.BootclasspathFragmentModule)
@@ -269,19 +256,6 @@
 	bootclasspathFragmentInfo := result.ModuleProvider(bootclasspathFragment, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
 	modules := bootclasspathFragmentInfo.Modules()
 	android.AssertStringEquals(t, "invalid modules for "+moduleName, expectedConfiguredModules, modules.String())
-
-	// Get a list of all the paths in the boot image sorted by arch type.
-	allPaths := []string{}
-	bootImageFilesByArchType := bootclasspathFragmentInfo.AndroidBootImageFilesByArchType()
-	for _, archType := range android.ArchTypeList() {
-		if paths, ok := bootImageFilesByArchType[archType]; ok {
-			for _, path := range paths {
-				allPaths = append(allPaths, android.NormalizePathForTesting(path))
-			}
-		}
-	}
-
-	android.AssertTrimmedStringEquals(t, "invalid paths for "+moduleName, expectedBootclasspathFragmentFiles, strings.Join(allPaths, "\n"))
 }
 
 func TestBootclasspathFragmentInArtApex(t *testing.T) {
@@ -420,18 +394,6 @@
 		ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
 			"etc/boot-image.prof",
 			"etc/classpaths/bootclasspath.pb",
-			"javalib/arm/boot.art",
-			"javalib/arm/boot.oat",
-			"javalib/arm/boot.vdex",
-			"javalib/arm/boot-bar.art",
-			"javalib/arm/boot-bar.oat",
-			"javalib/arm/boot-bar.vdex",
-			"javalib/arm64/boot.art",
-			"javalib/arm64/boot.oat",
-			"javalib/arm64/boot.vdex",
-			"javalib/arm64/boot-bar.art",
-			"javalib/arm64/boot-bar.oat",
-			"javalib/arm64/boot-bar.vdex",
 			"javalib/bar.jar",
 			"javalib/foo.jar",
 		})
@@ -441,62 +403,12 @@
 			`mybootclasspathfragment`,
 		})
 
-		// The boot images are installed in the APEX by Soong, so there shouldn't be any dexpreopt-related Make modules.
-		ensureDoesNotContainRequiredDeps(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
-			"mybootclasspathfragment-dexpreopt-arm64-boot.art",
-			"mybootclasspathfragment-dexpreopt-arm64-boot.oat",
-			"mybootclasspathfragment-dexpreopt-arm64-boot.vdex",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.art",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.oat",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.vdex",
-			"mybootclasspathfragment-dexpreopt-arm-boot.art",
-			"mybootclasspathfragment-dexpreopt-arm-boot.oat",
-			"mybootclasspathfragment-dexpreopt-arm-boot.vdex",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.art",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.oat",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.vdex",
-		})
-
 		// Make sure that the source bootclasspath_fragment copies its dex files to the predefined
 		// locations for the art image.
 		module := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
 		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
 	})
 
-	t.Run("boot image files from source no boot image in apex", func(t *testing.T) {
-		result := android.GroupFixturePreparers(
-			commonPreparer,
-
-			// 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"),
-			addSource("foo", "bar"),
-			java.FixtureSetBootImageInstallDirOnDevice("art", "system/framework"),
-		).RunTest(t)
-
-		ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
-			"etc/boot-image.prof",
-			"etc/classpaths/bootclasspath.pb",
-			"javalib/bar.jar",
-			"javalib/foo.jar",
-		})
-
-		ensureContainsRequiredDeps(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
-			"mybootclasspathfragment-dexpreopt-arm64-boot.art",
-			"mybootclasspathfragment-dexpreopt-arm64-boot.oat",
-			"mybootclasspathfragment-dexpreopt-arm64-boot.vdex",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.art",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.oat",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.vdex",
-			"mybootclasspathfragment-dexpreopt-arm-boot.art",
-			"mybootclasspathfragment-dexpreopt-arm-boot.oat",
-			"mybootclasspathfragment-dexpreopt-arm-boot.vdex",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.art",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.oat",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.vdex",
-		})
-	})
-
 	t.Run("generate boot image profile even if dexpreopt is disabled", func(t *testing.T) {
 		result := android.GroupFixturePreparers(
 			commonPreparer,
@@ -552,18 +464,6 @@
 
 		ensureExactDeapexedContents(t, result.TestContext, "com.android.art", "android_common", []string{
 			"etc/boot-image.prof",
-			"javalib/arm/boot.art",
-			"javalib/arm/boot.oat",
-			"javalib/arm/boot.vdex",
-			"javalib/arm/boot-bar.art",
-			"javalib/arm/boot-bar.oat",
-			"javalib/arm/boot-bar.vdex",
-			"javalib/arm64/boot.art",
-			"javalib/arm64/boot.oat",
-			"javalib/arm64/boot.vdex",
-			"javalib/arm64/boot-bar.art",
-			"javalib/arm64/boot-bar.oat",
-			"javalib/arm64/boot-bar.vdex",
 			"javalib/bar.jar",
 			"javalib/foo.jar",
 		})
@@ -574,65 +474,12 @@
 			`prebuilt_com.android.art`,
 		})
 
-		// The boot images are installed in the APEX by Soong, so there shouldn't be any dexpreopt-related Make modules.
-		ensureDoesNotContainRequiredDeps(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
-			"mybootclasspathfragment-dexpreopt-arm64-boot.art",
-			"mybootclasspathfragment-dexpreopt-arm64-boot.oat",
-			"mybootclasspathfragment-dexpreopt-arm64-boot.vdex",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.art",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.oat",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.vdex",
-			"mybootclasspathfragment-dexpreopt-arm-boot.art",
-			"mybootclasspathfragment-dexpreopt-arm-boot.oat",
-			"mybootclasspathfragment-dexpreopt-arm-boot.vdex",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.art",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.oat",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.vdex",
-		})
-
 		// Make sure that the prebuilt bootclasspath_fragment copies its dex files to the predefined
 		// locations for the art image.
 		module := result.ModuleForTests("prebuilt_mybootclasspathfragment", "android_common_com.android.art")
 		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
 	})
 
-	t.Run("boot image files from preferred prebuilt no boot image in apex", func(t *testing.T) {
-		result := android.GroupFixturePreparers(
-			commonPreparer,
-
-			// 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"),
-			addSource("foo", "bar"),
-
-			// Make sure that a preferred prebuilt with consistent contents doesn't affect the apex.
-			addPrebuilt(true, "foo", "bar"),
-
-			java.FixtureSetBootImageInstallDirOnDevice("art", "system/framework"),
-		).RunTest(t)
-
-		ensureExactDeapexedContents(t, result.TestContext, "com.android.art", "android_common", []string{
-			"etc/boot-image.prof",
-			"javalib/bar.jar",
-			"javalib/foo.jar",
-		})
-
-		ensureContainsRequiredDeps(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
-			"mybootclasspathfragment-dexpreopt-arm64-boot.art",
-			"mybootclasspathfragment-dexpreopt-arm64-boot.oat",
-			"mybootclasspathfragment-dexpreopt-arm64-boot.vdex",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.art",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.oat",
-			"mybootclasspathfragment-dexpreopt-arm64-boot-bar.vdex",
-			"mybootclasspathfragment-dexpreopt-arm-boot.art",
-			"mybootclasspathfragment-dexpreopt-arm-boot.oat",
-			"mybootclasspathfragment-dexpreopt-arm-boot.vdex",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.art",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.oat",
-			"mybootclasspathfragment-dexpreopt-arm-boot-bar.vdex",
-		})
-	})
-
 	t.Run("source with inconsistency between config and contents", func(t *testing.T) {
 		android.GroupFixturePreparers(
 			commonPreparer,
@@ -782,10 +629,6 @@
 
 		module := result.ModuleForTests("mybootclasspathfragment", "android_common_com.android.art")
 		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
-
-		// Check that the right deapexer module was chosen for a boot image.
-		param := module.Output("out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art")
-		android.AssertStringDoesContain(t, "didn't find the expected deapexer in the input path", param.Input.String(), "/com.android.art.deapexer")
 	})
 
 	t.Run("enabled alternative APEX", func(t *testing.T) {
@@ -1250,7 +1093,7 @@
 func TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		prepareForTestWithBootclasspathFragment,
-		java.PrepareForTestWithJavaDefaultModules,
+		java.PrepareForTestWithDexpreopt,
 		prepareForTestWithArtApex,
 		prepareForTestWithMyapex,
 		// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
new file mode 100644
index 0000000..bba8bb6
--- /dev/null
+++ b/apex/dexpreopt_bootjars_test.go
@@ -0,0 +1,254 @@
+// Copyright 2019 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 apex
+
+import (
+	"fmt"
+	"path/filepath"
+	"sort"
+	"testing"
+
+	"android/soong/android"
+	"android/soong/java"
+)
+
+func testDexpreoptBoot(t *testing.T, ruleFile string, expectedInputs, expectedOutputs []string, preferPrebuilt bool) {
+	bp := `
+		// Platform.
+
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			api_packages: ["foo"],
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["b.java"],
+			installable: true,
+			system_ext_specific: true,
+		}
+
+		dex_import {
+			name: "baz",
+			jars: ["a.jar"],
+		}
+
+		platform_bootclasspath {
+			name: "platform-bootclasspath",
+			fragments: [
+				{
+					apex: "com.android.art",
+					module: "art-bootclasspath-fragment",
+				},
+			],
+		}
+
+		// Source ART APEX.
+
+		java_library {
+			name: "core-oj",
+			srcs: ["core-oj.java"],
+			installable: true,
+			apex_available: [
+				"com.android.art",
+			],
+		}
+
+		bootclasspath_fragment {
+			name: "art-bootclasspath-fragment",
+			image_name: "art",
+			contents: ["core-oj"],
+			apex_available: [
+				"com.android.art",
+			],
+			hidden_api: {
+				split_packages: ["*"],
+			},
+		}
+
+		apex_key {
+			name: "com.android.art.key",
+			public_key: "com.android.art.avbpubkey",
+			private_key: "com.android.art.pem",
+		}
+
+		apex {
+			name: "com.android.art",
+			key: "com.android.art.key",
+			bootclasspath_fragments: ["art-bootclasspath-fragment"],
+			updatable: false,
+		}
+
+		// Prebuilt ART APEX.
+
+		java_import {
+			name: "core-oj",
+			prefer: %[1]t,
+			jars: ["core-oj.jar"],
+			apex_available: [
+				"com.android.art",
+			],
+		}
+
+		prebuilt_bootclasspath_fragment {
+			name: "art-bootclasspath-fragment",
+			prefer: %[1]t,
+			image_name: "art",
+			contents: ["core-oj"],
+			hidden_api: {
+				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+				metadata: "my-bootclasspath-fragment/metadata.csv",
+				index: "my-bootclasspath-fragment/index.csv",
+				stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+				all_flags: "my-bootclasspath-fragment/all-flags.csv",
+			},
+			apex_available: [
+				"com.android.art",
+			],
+		}
+
+		prebuilt_apex {
+			name: "com.android.art",
+			prefer: %[1]t,
+			apex_name: "com.android.art",
+			src: "com.android.art-arm.apex",
+			exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+		}
+	`
+
+	result := android.GroupFixturePreparers(
+		java.PrepareForTestWithDexpreopt,
+		java.PrepareForTestWithJavaSdkLibraryFiles,
+		java.FixtureWithLastReleaseApis("foo"),
+		java.FixtureConfigureBootJars("com.android.art:core-oj", "platform:foo", "system_ext:bar", "platform:baz"),
+		PrepareForTestWithApexBuildComponents,
+		prepareForTestWithArtApex,
+	).RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt))
+
+	platformBootclasspath := result.ModuleForTests("platform-bootclasspath", "android_common")
+	rule := platformBootclasspath.Output(ruleFile)
+
+	inputs := rule.Implicits.Strings()
+	sort.Strings(inputs)
+	sort.Strings(expectedInputs)
+
+	outputs := append(android.WritablePaths{rule.Output}, rule.ImplicitOutputs...).Strings()
+	sort.Strings(outputs)
+	sort.Strings(expectedOutputs)
+
+	android.AssertStringPathsRelativeToTopEquals(t, "inputs", result.Config, expectedInputs, inputs)
+
+	android.AssertStringPathsRelativeToTopEquals(t, "outputs", result.Config, expectedOutputs, outputs)
+}
+
+func TestDexpreoptBootJarsWithSourceArtApex(t *testing.T) {
+	ruleFile := "boot.art"
+
+	expectedInputs := []string{
+		"out/soong/dexpreopt_arm64/dex_bootjars_input/core-oj.jar",
+		"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/dexpreopt_arm64/dex_artjars/boot.prof",
+		"out/soong/dexpreopt_arm64/dex_bootjars/boot.prof",
+	}
+
+	expectedOutputs := []string{
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.invocation",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-foo.art",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-bar.art",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-baz.art",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-foo.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-bar.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-baz.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.vdex",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-foo.vdex",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-bar.vdex",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-baz.vdex",
+		"out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-foo.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-bar.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-baz.oat",
+	}
+
+	testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs, false)
+}
+
+// The only difference is that the ART profile should be deapexed from the prebuilt APEX. Other
+// inputs and outputs should be the same as above.
+func TestDexpreoptBootJarsWithPrebuiltArtApex(t *testing.T) {
+	ruleFile := "boot.art"
+
+	expectedInputs := []string{
+		"out/soong/dexpreopt_arm64/dex_bootjars_input/core-oj.jar",
+		"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/com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
+		"out/soong/dexpreopt_arm64/dex_bootjars/boot.prof",
+	}
+
+	expectedOutputs := []string{
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.invocation",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-foo.art",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-bar.art",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-baz.art",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-foo.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-bar.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-baz.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.vdex",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-foo.vdex",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-bar.vdex",
+		"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-baz.vdex",
+		"out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-foo.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-bar.oat",
+		"out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-baz.oat",
+	}
+
+	testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs, true)
+}
+
+// Changes to the boot.zip structure may break the ART APK scanner.
+func TestDexpreoptBootZip(t *testing.T) {
+	ruleFile := "boot.zip"
+
+	ctx := android.PathContextForTesting(android.TestArchConfig("", nil, "", nil))
+	expectedInputs := []string{}
+	for _, target := range ctx.Config().Targets[android.Android] {
+		for _, ext := range []string{".art", ".oat", ".vdex"} {
+			for _, suffix := range []string{"", "-foo", "-bar", "-baz"} {
+				expectedInputs = append(expectedInputs,
+					filepath.Join(
+						"out/soong/dexpreopt_arm64/dex_bootjars",
+						target.Os.String(),
+						"system/framework",
+						target.Arch.ArchType.String(),
+						"boot"+suffix+ext))
+			}
+		}
+	}
+
+	expectedOutputs := []string{
+		"out/soong/dexpreopt_arm64/dex_bootjars/boot.zip",
+	}
+
+	testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs, false)
+}
diff --git a/apex/metadata_test.go b/apex/metadata_test.go
index f6ead42..fed5bea 100644
--- a/apex/metadata_test.go
+++ b/apex/metadata_test.go
@@ -27,7 +27,7 @@
 func TestModulesSingleton(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		PrepareForTestWithApexMultitreeSingleton,
-		java.PrepareForTestWithDexpreopt,
+		java.PrepareForTestWithJavaDefaultModules,
 		PrepareForTestWithApexBuildComponents,
 		java.FixtureConfigureApexBootJars("myapex:foo"),
 		java.PrepareForTestWithJavaSdkLibraryFiles,
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 4b48da8..05bb136 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -20,6 +20,7 @@
 	"testing"
 
 	"android/soong/android"
+	"android/soong/dexpreopt"
 	"android/soong/java"
 
 	"github.com/google/blueprint"
@@ -30,7 +31,7 @@
 // apexes.
 
 var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers(
-	java.PrepareForTestWithDexpreopt,
+	java.PrepareForTestWithJavaDefaultModules,
 	PrepareForTestWithApexBuildComponents,
 )
 
@@ -249,6 +250,8 @@
 		java.FixtureConfigureApexBootJars("myapex:bar"),
 		java.PrepareForTestWithJavaSdkLibraryFiles,
 		java.FixtureWithLastReleaseApis("foo"),
+		java.PrepareForTestWithDexpreopt,
+		dexpreopt.FixtureDisableDexpreoptBootImages(false),
 	).RunTestWithBp(t, `
 		apex {
 			name: "com.android.art",
@@ -539,9 +542,6 @@
 		// Not a prebuilt as no prebuilt existed when it was added.
 		"platform:legacy.core.platform.api.stubs",
 
-		// Needed for generating the boot image.
-		"platform:dex2oatd",
-
 		// The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
 		// modules when available as it does not know which one will be preferred.
 		"myapex:foo",
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 31cecf1..0d83830 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -199,14 +199,11 @@
 				p.apexFilesForAndroidMk = append(p.apexFilesForAndroidMk, af)
 			}
 		} else if tag == exportedBootclasspathFragmentTag {
-			bcpfModule, ok := child.(*java.PrebuiltBootclasspathFragmentModule)
+			_, ok := child.(*java.PrebuiltBootclasspathFragmentModule)
 			if !ok {
 				ctx.PropertyErrorf("exported_bootclasspath_fragments", "%q is not a prebuilt_bootclasspath_fragment module", name)
 				return false
 			}
-			for _, makeModuleName := range bcpfModule.BootImageDeviceInstallMakeModules() {
-				p.requiredModuleNames = append(p.requiredModuleNames, makeModuleName)
-			}
 			// Visit the children of the bootclasspath_fragment.
 			return true
 		} else if tag == exportedSystemserverclasspathFragmentTag {
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index b6635c4..9ec3a40 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -19,6 +19,7 @@
         "testing.go",
     ],
     deps: [
+        "soong-aidl-library",
         "soong-android",
         "soong-android-allowlists",
         "soong-android-soongconfig",
@@ -37,6 +38,7 @@
     ],
     testSrcs: [
         "aar_conversion_test.go",
+        "aidl_library_conversion_test.go",
         "android_app_certificate_conversion_test.go",
         "android_app_conversion_test.go",
         "apex_conversion_test.go",
diff --git a/bp2build/aidl_library_conversion_test.go b/bp2build/aidl_library_conversion_test.go
new file mode 100644
index 0000000..0522da4
--- /dev/null
+++ b/bp2build/aidl_library_conversion_test.go
@@ -0,0 +1,119 @@
+// 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"
+
+	"android/soong/aidl_library"
+	"android/soong/android"
+)
+
+func runAidlLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	(&tc).ModuleTypeUnderTest = "aidl_library"
+	(&tc).ModuleTypeUnderTestFactory = aidl_library.AidlLibraryFactory
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
+}
+
+func TestAidlLibrary(t *testing.T) {
+	testcases := []struct {
+		name               string
+		bp                 string
+		expectedBazelAttrs AttrNameToString
+	}{
+		{
+			name: "aidl_library with strip_import_prefix",
+			bp: `
+	aidl_library {
+		name: "foo",
+		srcs: ["aidl/foo.aidl"],
+		hdrs: ["aidl/header.aidl"],
+		strip_import_prefix: "aidl",
+	}`,
+			expectedBazelAttrs: AttrNameToString{
+				"srcs":                `["aidl/foo.aidl"]`,
+				"hdrs":                `["aidl/header.aidl"]`,
+				"strip_import_prefix": `"aidl"`,
+				"tags":                `["apex_available=//apex_available:anyapex"]`,
+			},
+		},
+		{
+			name: "aidl_library without strip_import_prefix",
+			bp: `
+	aidl_library {
+		name: "foo",
+		srcs: ["aidl/foo.aidl"],
+		hdrs: ["aidl/header.aidl"],
+	}`,
+			expectedBazelAttrs: AttrNameToString{
+				"srcs": `["aidl/foo.aidl"]`,
+				"hdrs": `["aidl/header.aidl"]`,
+				"tags": `["apex_available=//apex_available:anyapex"]`,
+			},
+		},
+	}
+
+	for _, test := range testcases {
+		t.Run(test.name, func(t *testing.T) {
+			expectedBazelTargets := []string{
+				MakeBazelTargetNoRestrictions("aidl_library", "foo", test.expectedBazelAttrs),
+			}
+			runAidlLibraryTestCase(t, Bp2buildTestCase{
+				Description:          test.name,
+				Blueprint:            test.bp,
+				ExpectedBazelTargets: expectedBazelTargets,
+			})
+		})
+	}
+}
+
+func TestAidlLibraryWithDeps(t *testing.T) {
+	bp := `
+	aidl_library {
+		name: "bar",
+		srcs: ["Bar.aidl"],
+		hdrs: ["aidl/BarHeader.aidl"],
+	}
+	aidl_library {
+		name: "foo",
+		srcs: ["aidl/Foo.aidl"],
+		hdrs: ["aidl/FooHeader.aidl"],
+		strip_import_prefix: "aidl",
+		deps: ["bar"],
+	}`
+
+	t.Run("aidl_library with deps", func(t *testing.T) {
+		expectedBazelTargets := []string{
+			MakeBazelTargetNoRestrictions("aidl_library", "bar", AttrNameToString{
+				"srcs": `["Bar.aidl"]`,
+				"hdrs": `["aidl/BarHeader.aidl"]`,
+				"tags": `["apex_available=//apex_available:anyapex"]`,
+			}),
+			MakeBazelTargetNoRestrictions("aidl_library", "foo", AttrNameToString{
+				"srcs":                `["aidl/Foo.aidl"]`,
+				"hdrs":                `["aidl/FooHeader.aidl"]`,
+				"strip_import_prefix": `"aidl"`,
+				"deps":                `[":bar"]`,
+				"tags":                `["apex_available=//apex_available:anyapex"]`,
+			}),
+		}
+		runAidlLibraryTestCase(t, Bp2buildTestCase{
+			Description:          "aidl_library with deps",
+			Blueprint:            bp,
+			ExpectedBazelTargets: expectedBazelTargets,
+		})
+	})
+}
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 89eac8a..6ec3703 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -644,10 +644,7 @@
 		targets: []testBazelTarget{
 			{"cc_binary", "foo", AttrNameToString{
 				"features": `select({
-        "//build/bazel/platforms/arch:arm": [
-            "arm_isa_arm",
-            "-arm_isa_thumb",
-        ],
+        "//build/bazel/platforms/arch:arm": ["arm_isa_arm"],
         "//conditions:default": [],
     })`,
 				"local_includes": `["."]`,
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 1b681ef..8c090d8 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -18,6 +18,7 @@
 	"fmt"
 	"testing"
 
+	"android/soong/aidl_library"
 	"android/soong/android"
 	"android/soong/cc"
 )
@@ -63,6 +64,7 @@
 	ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
 	ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory)
 	ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
+	ctx.RegisterModuleType("aidl_library", aidl_library.AidlLibraryFactory)
 }
 
 func TestCcLibrarySimple(t *testing.T) {
@@ -3219,10 +3221,7 @@
 `,
 		ExpectedBazelTargets: makeCcLibraryTargets("foo", AttrNameToString{
 			"features": `select({
-        "//build/bazel/platforms/arch:arm": [
-            "arm_isa_arm",
-            "-arm_isa_thumb",
-        ],
+        "//build/bazel/platforms/arch:arm": ["arm_isa_arm"],
         "//conditions:default": [],
     })`,
 			"local_includes": `["."]`,
@@ -3315,6 +3314,46 @@
 	})
 }
 
+func TestCcLibraryWithAidlLibrary(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library with aidl_library",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+aidl_library {
+    name: "A_aidl",
+    srcs: ["aidl/A.aidl"],
+	hdrs: ["aidl/Header.aidl"],
+	strip_import_prefix: "aidl",
+}
+cc_library {
+	name: "foo",
+	aidl: {
+		libs: ["A_aidl"],
+	}
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("aidl_library", "A_aidl", AttrNameToString{
+				"srcs":                `["aidl/A.aidl"]`,
+				"hdrs":                `["aidl/Header.aidl"]`,
+				"strip_import_prefix": `"aidl"`,
+				"tags":                `["apex_available=//apex_available:anyapex"]`,
+			}),
+			MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+				"deps": `[":A_aidl"]`,
+			}),
+			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+				"implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+				"local_includes":                    `["."]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+				"local_includes":                    `["."]`,
+			}),
+		},
+	})
+}
+
 func TestCcLibraryWithAidlSrcs(t *testing.T) {
 	runCcLibraryTestCase(t, Bp2buildTestCase{
 		Description:                "cc_library with aidl srcs",
@@ -3397,37 +3436,77 @@
 }
 
 func TestCcLibraryWithExportAidlHeaders(t *testing.T) {
-	runCcLibraryTestCase(t, Bp2buildTestCase{
-		Description:                "cc_library with export aidl headers",
-		ModuleTypeUnderTest:        "cc_library",
-		ModuleTypeUnderTestFactory: cc.LibraryFactory,
-		Blueprint: `
-cc_library {
-    name: "foo",
-    srcs: [
-        "Foo.aidl",
-    ],
-    aidl: {
-        export_aidl_headers: true,
-    }
-}`,
-		ExpectedBazelTargets: []string{
-			MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
-				"srcs": `["Foo.aidl"]`,
-			}),
-			MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
-				"deps": `[":foo_aidl_library"]`,
-			}),
-			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
-				"whole_archive_deps": `[":foo_cc_aidl_library"]`,
-				"local_includes":     `["."]`,
-			}),
-			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"whole_archive_deps": `[":foo_cc_aidl_library"]`,
-				"local_includes":     `["."]`,
-			}),
+	t.Parallel()
+
+	expectedBazelTargets := []string{
+		MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+			"deps": `[":foo_aidl_library"]`,
+		}),
+		MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+			"whole_archive_deps": `[":foo_cc_aidl_library"]`,
+			"local_includes":     `["."]`,
+		}),
+		MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+			"whole_archive_deps": `[":foo_cc_aidl_library"]`,
+			"local_includes":     `["."]`,
+		}),
+	}
+	testCases := []struct {
+		description          string
+		bp                   string
+		expectedBazelTargets []string
+	}{
+		{
+			description: "cc_library with aidl srcs and aidl.export_aidl_headers set",
+			bp: `
+			cc_library {
+				name: "foo",
+				srcs: [
+					"Foo.aidl",
+				],
+				aidl: {
+					export_aidl_headers: true,
+				}
+			}`,
+			expectedBazelTargets: append(
+				expectedBazelTargets,
+				MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
+					"srcs": `["Foo.aidl"]`,
+				})),
 		},
-	})
+		{
+			description: "cc_library with aidl.libs and aidl.export_aidl_headers set",
+			bp: `
+			aidl_library {
+				name: "foo_aidl_library",
+				srcs: ["Foo.aidl"],
+			}
+			cc_library {
+				name: "foo",
+				aidl: {
+					libs: ["foo_aidl_library"],
+					export_aidl_headers: true,
+				}
+			}`,
+			expectedBazelTargets: append(
+				expectedBazelTargets,
+				MakeBazelTargetNoRestrictions("aidl_library", "foo_aidl_library", AttrNameToString{
+					"srcs": `["Foo.aidl"]`,
+					"tags": `["apex_available=//apex_available:anyapex"]`,
+				}),
+			),
+		},
+	}
+
+	for _, testCase := range testCases {
+		runCcLibraryTestCase(t, Bp2buildTestCase{
+			Description:                "cc_library with export aidl headers",
+			ModuleTypeUnderTest:        "cc_library",
+			ModuleTypeUnderTestFactory: cc.LibraryFactory,
+			Blueprint:                  testCase.bp,
+			ExpectedBazelTargets:       testCase.expectedBazelTargets,
+		})
+	}
 }
 
 func TestCcLibraryWithTargetApex(t *testing.T) {
@@ -4519,3 +4598,59 @@
 	},
 	)
 }
+
+func TestCcLibraryYaccConversion(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library is built from .y/.yy files",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: soongCcLibraryPreamble + `cc_library {
+    name: "a",
+    srcs: [
+	"a.cpp",
+	"a.yy",
+    ],
+    shared_libs: ["sharedlib"],
+    static_libs: ["staticlib"],
+    yacc: {
+	    flags: ["someYaccFlag"],
+	    gen_location_hh: true,
+	    gen_position_hh: true,
+	},
+}
+cc_library_static {
+	name: "staticlib",
+	bazel_module: { bp2build_available: false },
+}
+cc_library {
+	name: "sharedlib",
+	bazel_module: { bp2build_available: false },
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_yacc_static_library", "a_yacc", AttrNameToString{
+				"src":                         `"a.yy"`,
+				"implementation_deps":         `[":staticlib"]`,
+				"implementation_dynamic_deps": `[":sharedlib"]`,
+				"flags":                       `["someYaccFlag"]`,
+				"gen_location_hh":             "True",
+				"gen_position_hh":             "True",
+				"local_includes":              `["."]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
+				"srcs":                              `["a.cpp"]`,
+				"implementation_deps":               `[":staticlib"]`,
+				"implementation_dynamic_deps":       `[":sharedlib"]`,
+				"implementation_whole_archive_deps": `[":a_yacc"]`,
+				"local_includes":                    `["."]`,
+			}),
+			MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
+				"srcs":                              `["a.cpp"]`,
+				"implementation_deps":               `[":staticlib"]`,
+				"implementation_dynamic_deps":       `[":sharedlib"]`,
+				"implementation_whole_archive_deps": `[":a_yacc"]`,
+				"local_includes":                    `["."]`,
+			}),
+		},
+	})
+}
diff --git a/cc/Android.bp b/cc/Android.bp
index be2cc5a..f49dc1a 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -9,6 +9,7 @@
         "blueprint",
         "blueprint-pathtools",
         "soong",
+        "soong-aidl-library",
         "soong-android",
         "soong-bazel",
         "soong-cc-config",
@@ -22,7 +23,6 @@
     srcs: [
         "afdo.go",
         "fdo_profile.go",
-
         "androidmk.go",
         "api_level.go",
         "bp2build.go",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index cf5f74d..1980ab9 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -38,6 +38,7 @@
 	protoSrcPartition   = "proto"
 	aidlSrcPartition    = "aidl"
 	syspropSrcPartition = "sysprop"
+	yaccSrcPartition    = "yacc"
 
 	stubsSuffix = "_stub_libs_current"
 )
@@ -154,6 +155,7 @@
 		// know the language of these sources until the genrule is executed.
 		cppSrcPartition:     bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
 		syspropSrcPartition: bazel.LabelPartition{Extensions: []string{".sysprop"}},
+		yaccSrcPartition:    bazel.LabelPartition{Extensions: []string{".y", "yy"}},
 	}
 
 	return bazel.PartitionLabelListAttribute(ctx, &srcs, labels)
@@ -404,6 +406,12 @@
 	// Sysprop sources
 	syspropSrcs bazel.LabelListAttribute
 
+	// Yacc sources
+	yaccSrc               *bazel.LabelAttribute
+	yaccFlags             bazel.StringListAttribute
+	yaccGenLocationHeader bazel.BoolAttribute
+	yaccGenPositionHeader bazel.BoolAttribute
+
 	hdrs bazel.LabelListAttribute
 
 	rtti bazel.BoolAttribute
@@ -492,7 +500,7 @@
 
 	instructionSet := proptools.StringDefault(props.Instruction_set, "")
 	if instructionSet == "arm" {
-		ca.features.SetSelectValue(axis, config, []string{"arm_isa_arm", "-arm_isa_thumb"})
+		ca.features.SetSelectValue(axis, config, []string{"arm_isa_arm"})
 	} else if instructionSet != "" && instructionSet != "thumb" {
 		ctx.ModuleErrorf("Unknown value for instruction_set: %s", instructionSet)
 	}
@@ -566,6 +574,12 @@
 	ca.asmSrcs = partitionedSrcs[asmSrcPartition]
 	ca.lSrcs = partitionedSrcs[lSrcPartition]
 	ca.llSrcs = partitionedSrcs[llSrcPartition]
+	if yacc := partitionedSrcs[yaccSrcPartition]; !yacc.IsEmpty() {
+		if len(yacc.Value.Includes) > 1 {
+			ctx.PropertyErrorf("srcs", "Found multiple yacc (.y/.yy) files in library")
+		}
+		ca.yaccSrc = bazel.MakeLabelAttribute(yacc.Value.Includes[0].Label)
+	}
 	ca.syspropSrcs = partitionedSrcs[syspropSrcPartition]
 
 	ca.absoluteIncludes.DeduplicateAxesFromBase()
@@ -728,6 +742,8 @@
 	compilerAttrs := compilerAttributes{}
 	linkerAttrs := linkerAttributes{}
 
+	var aidlLibs bazel.LabelList
+
 	// Iterate through these axes in a deterministic order. This is required
 	// because processing certain dependencies may result in concatenating
 	// elements along other axes. (For example, processing NoConfig may result
@@ -742,7 +758,13 @@
 				if baseCompilerProps.Lex != nil {
 					compilerAttrs.lexopts.SetSelectValue(axis, cfg, baseCompilerProps.Lex.Flags)
 				}
+				if baseCompilerProps.Yacc != nil {
+					compilerAttrs.yaccFlags.SetSelectValue(axis, cfg, baseCompilerProps.Yacc.Flags)
+					compilerAttrs.yaccGenLocationHeader.SetSelectValue(axis, cfg, baseCompilerProps.Yacc.Gen_location_hh)
+					compilerAttrs.yaccGenPositionHeader.SetSelectValue(axis, cfg, baseCompilerProps.Yacc.Gen_position_hh)
+				}
 				(&compilerAttrs).bp2buildForAxisAndConfig(ctx, axis, cfg, baseCompilerProps)
+				aidlLibs.Append(android.BazelLabelForModuleDeps(ctx, baseCompilerProps.Aidl.Libs))
 			}
 
 			var exportHdrs []string
@@ -815,7 +837,14 @@
 	(&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib)
 	(&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib)
 
-	aidlDep := bp2buildCcAidlLibrary(ctx, module, compilerAttrs.aidlSrcs, linkerAttrs)
+	aidlDep := bp2buildCcAidlLibrary(
+		ctx, module,
+		compilerAttrs.aidlSrcs,
+		bazel.LabelListAttribute{
+			Value: aidlLibs,
+		},
+		linkerAttrs,
+	)
 	if aidlDep != nil {
 		if lib, ok := module.linker.(*libraryDecorator); ok {
 			if proptools.Bool(lib.Properties.Aidl.Export_aidl_headers) {
@@ -826,6 +855,12 @@
 		}
 	}
 
+	// Create a cc_yacc_static_library if srcs contains .y/.yy files
+	// This internal target will produce an .a file that will be statically linked to the parent library
+	if yaccDep := bp2buildCcYaccLibrary(ctx, compilerAttrs, linkerAttrs); yaccDep != nil {
+		(&linkerAttrs).implementationWholeArchiveDeps.Add(yaccDep)
+	}
+
 	convertedLSrcs := bp2BuildLex(ctx, module.Name(), compilerAttrs)
 	(&compilerAttrs).srcs.Add(&convertedLSrcs.srcName)
 	(&compilerAttrs).cSrcs.Add(&convertedLSrcs.cSrcName)
@@ -864,6 +899,48 @@
 	}
 }
 
+type ccYaccLibraryAttributes struct {
+	Src                         bazel.LabelAttribute
+	Flags                       bazel.StringListAttribute
+	Gen_location_hh             bazel.BoolAttribute
+	Gen_position_hh             bazel.BoolAttribute
+	Local_includes              bazel.StringListAttribute
+	Implementation_deps         bazel.LabelListAttribute
+	Implementation_dynamic_deps bazel.LabelListAttribute
+}
+
+func bp2buildCcYaccLibrary(ctx android.Bp2buildMutatorContext, ca compilerAttributes, la linkerAttributes) *bazel.LabelAttribute {
+	if ca.yaccSrc == nil {
+		return nil
+	}
+	yaccLibraryLabel := ctx.Module().Name() + "_yacc"
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "cc_yacc_static_library",
+			Bzl_load_location: "//build/bazel/rules/cc:cc_yacc_library.bzl",
+		},
+		android.CommonAttributes{
+			Name: yaccLibraryLabel,
+		},
+		&ccYaccLibraryAttributes{
+			Src:                         *ca.yaccSrc,
+			Flags:                       ca.yaccFlags,
+			Gen_location_hh:             ca.yaccGenLocationHeader,
+			Gen_position_hh:             ca.yaccGenPositionHeader,
+			Local_includes:              ca.localIncludes,
+			Implementation_deps:         la.implementationDeps,
+			Implementation_dynamic_deps: la.implementationDynamicDeps,
+		},
+	)
+
+	yaccLibrary := &bazel.LabelAttribute{
+		Value: &bazel.Label{
+			Label: ":" + yaccLibraryLabel,
+		},
+	}
+	return yaccLibrary
+}
+
 // As a workaround for b/261657184, we are manually adding the default value
 // of system_dynamic_deps for the linux_musl os.
 // TODO: Solve this properly
@@ -912,11 +989,15 @@
 func bp2buildCcAidlLibrary(
 	ctx android.Bp2buildMutatorContext,
 	m *Module,
-	aidlLabelList bazel.LabelListAttribute,
+	aidlSrcs bazel.LabelListAttribute,
+	aidlLibs bazel.LabelListAttribute,
 	linkerAttrs linkerAttributes,
 ) *bazel.LabelAttribute {
-	if !aidlLabelList.IsEmpty() {
-		aidlLibs, aidlSrcs := aidlLabelList.Partition(func(src bazel.Label) bool {
+	var aidlLibsFromSrcs, aidlFiles bazel.LabelListAttribute
+	apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
+
+	if !aidlSrcs.IsEmpty() {
+		aidlLibsFromSrcs, aidlFiles = aidlSrcs.Partition(func(src bazel.Label) bool {
 			if fg, ok := android.ToFileGroupAsLibrary(ctx, src.OriginalModuleName); ok &&
 				fg.ShouldConvertToAidlLibrary(ctx) {
 				return true
@@ -924,57 +1005,61 @@
 			return false
 		})
 
-		apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
-		sdkAttrs := bp2BuildParseSdkAttributes(m)
-
-		if !aidlSrcs.IsEmpty() {
+		if !aidlFiles.IsEmpty() {
 			aidlLibName := m.Name() + "_aidl_library"
 			ctx.CreateBazelTargetModule(
 				bazel.BazelTargetModuleProperties{
 					Rule_class:        "aidl_library",
 					Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
 				},
-				android.CommonAttributes{Name: aidlLibName},
-				&aidlLibraryAttributes{
-					Srcs: aidlSrcs,
+				android.CommonAttributes{
+					Name: aidlLibName,
 					Tags: apexAvailableTags,
 				},
-			)
-			aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
-		}
-
-		if !aidlLibs.IsEmpty() {
-			ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
-			// Since parent cc_library already has these dependencies, we can add them as implementation
-			// deps so that they don't re-export
-			implementationDeps := linkerAttrs.deps.Clone()
-			implementationDeps.Append(linkerAttrs.implementationDeps)
-			implementationDynamicDeps := linkerAttrs.dynamicDeps.Clone()
-			implementationDynamicDeps.Append(linkerAttrs.implementationDynamicDeps)
-
-			ctx.CreateBazelTargetModule(
-				bazel.BazelTargetModuleProperties{
-					Rule_class:        "cc_aidl_library",
-					Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
-				},
-				android.CommonAttributes{Name: ccAidlLibrarylabel},
-				&ccAidlLibraryAttributes{
-					Deps:                        aidlLibs,
-					Implementation_deps:         *implementationDeps,
-					Implementation_dynamic_deps: *implementationDynamicDeps,
-					Tags:                        apexAvailableTags,
-					sdkAttributes:               sdkAttrs,
+				&aidlLibraryAttributes{
+					Srcs: aidlFiles,
 				},
 			)
-			label := &bazel.LabelAttribute{
-				Value: &bazel.Label{
-					Label: ":" + ccAidlLibrarylabel,
-				},
-			}
-			return label
+			aidlLibsFromSrcs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
 		}
 	}
 
+	allAidlLibs := aidlLibs.Clone()
+	allAidlLibs.Append(aidlLibsFromSrcs)
+
+	if !allAidlLibs.IsEmpty() {
+		ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
+		// Since parent cc_library already has these dependencies, we can add them as implementation
+		// deps so that they don't re-export
+		implementationDeps := linkerAttrs.deps.Clone()
+		implementationDeps.Append(linkerAttrs.implementationDeps)
+		implementationDynamicDeps := linkerAttrs.dynamicDeps.Clone()
+		implementationDynamicDeps.Append(linkerAttrs.implementationDynamicDeps)
+
+		sdkAttrs := bp2BuildParseSdkAttributes(m)
+
+		ctx.CreateBazelTargetModule(
+			bazel.BazelTargetModuleProperties{
+				Rule_class:        "cc_aidl_library",
+				Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
+			},
+			android.CommonAttributes{Name: ccAidlLibrarylabel},
+			&ccAidlLibraryAttributes{
+				Deps:                        *allAidlLibs,
+				Implementation_deps:         *implementationDeps,
+				Implementation_dynamic_deps: *implementationDynamicDeps,
+				Tags:                        apexAvailableTags,
+				sdkAttributes:               sdkAttrs,
+			},
+		)
+		label := &bazel.LabelAttribute{
+			Value: &bazel.Label{
+				Label: ":" + ccAidlLibrarylabel,
+			},
+		}
+		return label
+	}
+
 	return nil
 }
 
diff --git a/cc/builder.go b/cc/builder.go
index fef00d4..f5e0dcc 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -125,6 +125,14 @@
 		},
 		"objcopyCmd", "prefix")
 
+	// Rule to run objcopy --remove-section=.llvm_addrsig on a partially linked object
+	noAddrSig = pctx.AndroidStaticRule("noAddrSig",
+		blueprint.RuleParams{
+			Command:     "rm -f ${out} && $objcopyCmd --remove-section=.llvm_addrsig ${in} ${out}",
+			CommandDeps: []string{"$objcopyCmd"},
+		},
+		"objcopyCmd")
+
 	_ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
 	_ = pctx.SourcePathVariable("xzCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/xz")
 	_ = pctx.SourcePathVariable("createMiniDebugInfo", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/create_minidebuginfo")
@@ -1008,6 +1016,21 @@
 	})
 }
 
+// Generate a rule for running objcopy --remove-section=.llvm_addrsig on a partially linked object
+func transformObjectNoAddrSig(ctx android.ModuleContext, inputFile android.Path, outputFile android.WritablePath) {
+	objcopyCmd := "${config.ClangBin}/llvm-objcopy"
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        noAddrSig,
+		Description: "remove addrsig " + outputFile.Base(),
+		Output:      outputFile,
+		Input:       inputFile,
+		Args: map[string]string{
+			"objcopyCmd": objcopyCmd,
+		},
+	})
+}
+
 // Registers a build statement to invoke `strip` (to discard symbols and data from object files).
 func transformStrip(ctx android.ModuleContext, inputFile android.Path,
 	outputFile android.WritablePath, flags StripFlags) {
diff --git a/cc/cc.go b/cc/cc.go
index 7237686..f4b5655 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -27,6 +27,7 @@
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
+	"android/soong/aidl_library"
 	"android/soong/android"
 	"android/soong/bazel/cquery"
 	"android/soong/cc/config"
@@ -110,6 +111,9 @@
 	// Used by DepsMutator to pass system_shared_libs information to check_elf_file.py.
 	SystemSharedLibs []string
 
+	// Used by DepMutator to pass aidl_library modules to aidl compiler
+	AidlLibs []string
+
 	// If true, statically link the unwinder into native libraries/binaries.
 	StaticUnwinderIfLegacy bool
 
@@ -182,6 +186,9 @@
 	// For Darwin builds, the path to the second architecture's output that should
 	// be combined with this architectures's output into a FAT MachO file.
 	DarwinSecondArchOutput android.OptionalPath
+
+	// Paths to direct srcs and transitive include dirs from direct aidl_library deps
+	AidlLibraryInfos []aidl_library.AidlLibraryInfo
 }
 
 // LocalOrGlobalFlags contains flags that need to have values set globally by the build system or locally by the module
@@ -765,6 +772,7 @@
 	stubImplDepTag        = dependencyTag{name: "stub_impl"}
 	JniFuzzLibTag         = dependencyTag{name: "jni_fuzz_lib_tag"}
 	FdoProfileTag         = dependencyTag{name: "fdo_profile"}
+	aidlLibraryTag        = dependencyTag{name: "aidl_library"}
 )
 
 func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
@@ -2751,6 +2759,14 @@
 		}
 	}
 
+	if len(deps.AidlLibs) > 0 {
+		actx.AddDependency(
+			c,
+			aidlLibraryTag,
+			deps.AidlLibs...,
+		)
+	}
+
 	updateImportedLibraryDependency(ctx)
 }
 
@@ -3055,6 +3071,17 @@
 			return
 		}
 
+		if depTag == aidlLibraryTag {
+			if ctx.OtherModuleHasProvider(dep, aidl_library.AidlLibraryProvider) {
+				depPaths.AidlLibraryInfos = append(
+					depPaths.AidlLibraryInfos,
+					ctx.OtherModuleProvider(
+						dep,
+						aidl_library.AidlLibraryProvider).(aidl_library.AidlLibraryInfo),
+				)
+			}
+		}
+
 		ccDep, ok := dep.(LinkableInterface)
 		if !ok {
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index f9e661f..d3d55e8 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -24,6 +24,7 @@
 	"strings"
 	"testing"
 
+	"android/soong/aidl_library"
 	"android/soong/android"
 	"android/soong/bazel/cquery"
 )
@@ -4418,9 +4419,65 @@
 	}
 }
 
+func TestAidlLibraryWithHeader(t *testing.T) {
+	t.Parallel()
+	ctx := android.GroupFixturePreparers(
+		prepareForCcTest,
+		aidl_library.PrepareForTestWithAidlLibrary,
+		android.MockFS{
+			"package_bar/Android.bp": []byte(`
+			aidl_library {
+				name: "bar",
+				srcs: ["x/y/Bar.aidl"],
+				strip_import_prefix: "x",
+			}
+			`)}.AddToFixture(),
+		android.MockFS{
+			"package_foo/Android.bp": []byte(`
+			aidl_library {
+				name: "foo",
+				srcs: ["a/b/Foo.aidl"],
+				strip_import_prefix: "a",
+				deps: ["bar"],
+			}
+			cc_library {
+				name: "libfoo",
+				aidl: {
+					libs: ["foo"],
+				}
+			}
+			`),
+		}.AddToFixture(),
+	).RunTest(t).TestContext
+
+	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
+	manifest := android.RuleBuilderSboxProtoForTests(t, libfoo.Output("aidl.sbox.textproto"))
+	aidlCommand := manifest.Commands[0].GetCommand()
+
+	expectedAidlFlags := "-Ipackage_foo/a -Ipackage_bar/x"
+	if !strings.Contains(aidlCommand, expectedAidlFlags) {
+		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlags)
+	}
+
+	outputs := strings.Join(libfoo.AllOutputs(), " ")
+
+	android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl/b/BpFoo.h")
+	android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl/b/BnFoo.h")
+	android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl/b/Foo.h")
+	android.AssertStringDoesContain(t, "aidl-generated cpp", outputs, "b/Foo.cpp")
+	// Confirm that the aidl header doesn't get compiled to cpp and h files
+	android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl/y/BpBar.h")
+	android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl/y/BnBar.h")
+	android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl/y/Bar.h")
+	android.AssertStringDoesNotContain(t, "aidl-generated cpp", outputs, "y/Bar.cpp")
+}
+
 func TestAidlFlagsPassedToTheAidlCompiler(t *testing.T) {
 	t.Parallel()
-	ctx := testCc(t, `
+	ctx := android.GroupFixturePreparers(
+		prepareForCcTest,
+		aidl_library.PrepareForTestWithAidlLibrary,
+	).RunTestWithBp(t, `
 		cc_library {
 			name: "libfoo",
 			srcs: ["a/Foo.aidl"],
@@ -4705,7 +4762,15 @@
 	})
 
 	t.Run("ensure only aidl headers are exported", func(t *testing.T) {
-		ctx := testCc(t, genRuleModules+`
+		ctx := android.GroupFixturePreparers(
+			prepareForCcTest,
+			aidl_library.PrepareForTestWithAidlLibrary,
+		).RunTestWithBp(t, `
+		aidl_library {
+			name: "libfoo_aidl",
+			srcs: ["x/y/Bar.aidl"],
+			strip_import_prefix: "x",
+		}
 		cc_library_shared {
 			name: "libfoo",
 			srcs: [
@@ -4714,10 +4779,11 @@
 				"a.proto",
 			],
 			aidl: {
+				libs: ["libfoo_aidl"],
 				export_aidl_headers: true,
 			}
 		}
-		`)
+		`).TestContext
 		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
 		checkIncludeDirs(t, ctx, foo,
 			expectedIncludeDirs(`
@@ -4728,11 +4794,17 @@
 				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
 				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
 				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/Bar.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/BnBar.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/BpBar.h
 			`),
 			expectedOrderOnlyDeps(`
 				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
 				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
 				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/Bar.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/BnBar.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/BpBar.h
 			`),
 		)
 	})
diff --git a/cc/compiler.go b/cc/compiler.go
index 88985b6..5da745e 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -120,6 +120,9 @@
 	Lex  *LexProperties
 
 	Aidl struct {
+		// List of aidl_library modules
+		Libs []string
+
 		// list of directories that will be added to the aidl include paths.
 		Include_dirs []string
 
@@ -272,6 +275,7 @@
 	deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...)
 	deps.GeneratedSources = removeListFromList(deps.GeneratedSources, compiler.Properties.Exclude_generated_sources)
 	deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...)
+	deps.AidlLibs = append(deps.AidlLibs, compiler.Properties.Aidl.Libs...)
 
 	android.ProtoDeps(ctx, &compiler.Proto)
 	if compiler.hasSrcExt(".proto") {
@@ -561,7 +565,7 @@
 			"-I"+android.PathForModuleGen(ctx, "yacc", ctx.ModuleDir()).String())
 	}
 
-	if compiler.hasSrcExt(".aidl") {
+	if compiler.hasAidl(deps) {
 		flags.aidlFlags = append(flags.aidlFlags, compiler.Properties.Aidl.Flags...)
 		if len(compiler.Properties.Aidl.Local_include_dirs) > 0 {
 			localAidlIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Aidl.Local_include_dirs)
@@ -572,6 +576,14 @@
 			flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(rootAidlIncludeDirs))
 		}
 
+		var rootAidlIncludeDirs android.Paths
+		for _, aidlLibraryInfo := range deps.AidlLibraryInfos {
+			rootAidlIncludeDirs = append(rootAidlIncludeDirs, aidlLibraryInfo.IncludeDirs.ToList()...)
+		}
+		if len(rootAidlIncludeDirs) > 0 {
+			flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(rootAidlIncludeDirs))
+		}
+
 		if proptools.BoolDefault(compiler.Properties.Aidl.Generate_traces, true) {
 			flags.aidlFlags = append(flags.aidlFlags, "-t")
 		}
@@ -660,6 +672,10 @@
 	return nil
 }
 
+func (compiler *baseCompiler) hasAidl(deps PathDeps) bool {
+	return len(deps.AidlLibraryInfos) > 0 || compiler.hasSrcExt(".aidl")
+}
+
 func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
 	pathDeps := deps.GeneratedDeps
 	pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
@@ -668,7 +684,7 @@
 
 	srcs := append(android.Paths(nil), compiler.srcsBeforeGen...)
 
-	srcs, genDeps, info := genSources(ctx, srcs, buildFlags)
+	srcs, genDeps, info := genSources(ctx, deps.AidlLibraryInfos, srcs, buildFlags)
 	pathDeps = append(pathDeps, genDeps...)
 
 	compiler.pathDeps = pathDeps
diff --git a/cc/config/global.go b/cc/config/global.go
index 530b79a..e5ce48e 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -111,9 +111,6 @@
 
 		// Turn off FMA which got enabled by default in clang-r445002 (http://b/218805949)
 		"-ffp-contract=off",
-
-		// Turn off stack protector check for noreturn calls. (http://b/264965700)
-		"-mllvm -disable-check-noreturn-call",
 	}
 
 	commonGlobalConlyflags = []string{}
@@ -150,9 +147,6 @@
 	commonGlobalLldflags = []string{
 		"-fuse-ld=lld",
 		"-Wl,--icf=safe",
-
-		// Turn off stack protector check for noreturn calls. (http://b/264965700)
-		"-Wl,-mllvm,-disable-check-noreturn-call",
 	}
 
 	deviceGlobalCppflags = []string{
diff --git a/cc/gen.go b/cc/gen.go
index dfbb177..dbb9560 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -18,7 +18,9 @@
 	"path/filepath"
 	"strings"
 
+	"android/soong/aidl_library"
 	"android/soong/bazel"
+
 	"github.com/google/blueprint"
 
 	"android/soong/android"
@@ -124,11 +126,6 @@
 	headerBn := outDir.Join(ctx, aidlPackage, "Bn"+shortName+".h")
 	headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h")
 
-	baseDir := strings.TrimSuffix(aidlFile.String(), aidlFile.Rel())
-	if baseDir != "" {
-		aidlFlags += " -I" + baseDir
-	}
-
 	cmd := rule.Command()
 	cmd.BuiltTool("aidl-cpp").
 		FlagWithDepFile("-d", depFile).
@@ -282,7 +279,10 @@
 	syspropOrderOnlyDeps android.Paths
 }
 
-func genSources(ctx android.ModuleContext, srcFiles android.Paths,
+func genSources(
+	ctx android.ModuleContext,
+	aidlLibraryInfos []aidl_library.AidlLibraryInfo,
+	srcFiles android.Paths,
 	buildFlags builderFlags) (android.Paths, android.Paths, generatedSourceInfo) {
 
 	var info generatedSourceInfo
@@ -330,7 +330,8 @@
 				aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"),
 					android.PathForModuleGen(ctx, "aidl.sbox.textproto"))
 			}
-			cppFile, aidlHeaders := genAidl(ctx, aidlRule, srcFile, buildFlags.aidlFlags)
+			baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel())
+			cppFile, aidlHeaders := genAidl(ctx, aidlRule, srcFile, buildFlags.aidlFlags+" -I"+baseDir)
 			srcFiles[i] = cppFile
 
 			info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...)
@@ -352,6 +353,24 @@
 		}
 	}
 
+	for _, aidlLibraryInfo := range aidlLibraryInfos {
+		for _, aidlSrc := range aidlLibraryInfo.Srcs {
+			if aidlRule == nil {
+				// TODO(b/279960133): Sandbox inputs to ensure aidl headers are explicitly specified
+				aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"),
+					android.PathForModuleGen(ctx, "aidl.sbox.textproto"))
+			}
+			cppFile, aidlHeaders := genAidl(ctx, aidlRule, aidlSrc, buildFlags.aidlFlags)
+
+			srcFiles = append(srcFiles, cppFile)
+			info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...)
+			// Use the generated headers as order only deps to ensure that they are up to date when
+			// needed.
+			// TODO: Reduce the size of the ninja file by using one order only dep for the whole rule
+			info.aidlOrderOnlyDeps = append(info.aidlOrderOnlyDeps, aidlHeaders...)
+		}
+	}
+
 	if aidlRule != nil {
 		aidlRule.Build("aidl", "gen aidl")
 	}
diff --git a/cc/library.go b/cc/library.go
index 13b333a..ad4688f 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -2114,7 +2114,7 @@
 
 	// Optionally export aidl headers.
 	if Bool(library.Properties.Aidl.Export_aidl_headers) {
-		if library.baseCompiler.hasSrcExt(".aidl") {
+		if library.baseCompiler.hasAidl(deps) {
 			dir := android.PathForModuleGen(ctx, "aidl")
 			library.reexportDirs(dir)
 
diff --git a/cc/object.go b/cc/object.go
index 5d61872..ca14845 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -309,6 +309,8 @@
 			})
 		}
 	} else {
+		outputAddrSig := android.PathForModuleOut(ctx, "addrsig", outputName)
+
 		if String(object.Properties.Prefix_symbols) != "" {
 			input := android.PathForModuleOut(ctx, "unprefixed", outputName)
 			transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input,
@@ -316,7 +318,12 @@
 			output = input
 		}
 
-		transformObjsToObj(ctx, objs.objFiles, builderFlags, output, flags.LdFlagsDeps)
+		transformObjsToObj(ctx, objs.objFiles, builderFlags, outputAddrSig, flags.LdFlagsDeps)
+
+		// ld -r reorders symbols and invalidates the .llvm_addrsig section, which then causes warnings
+		// if the resulting object is used with ld --icf=safe.  Strip the .llvm_addrsig section to
+		// prevent the warnings.
+		transformObjectNoAddrSig(ctx, outputAddrSig, output)
 	}
 
 	ctx.CheckbuildFile(outputFile)
diff --git a/cc/testing.go b/cc/testing.go
index ced0929..d346739 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -82,6 +82,10 @@
 			sanitize: {
 				never: true,
 			},
+			apex_available: [
+				"//apex_available:anyapex",
+				"//apex_available:platform",
+			],
 		}
 
 		cc_prebuilt_library_static {
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 5de2326..cf6c1c7 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -133,6 +133,10 @@
 	ninjaDeps = append(ninjaDeps, writeBuildGlobsNinjaFile(ctx)...)
 
 	writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
+
+	if ctx.Config().IsEnvTrue("SOONG_GENERATES_NINJA_HINT") {
+		writeNinjaHint(ctx)
+	}
 	return cmdlineArgs.OutFile
 }
 
@@ -455,6 +459,9 @@
 		// The actual output (build.ninja) was written in the RunBlueprint() call
 		// above
 		writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
+		if ctx.Config().IsEnvTrue("SOONG_GENERATES_NINJA_HINT") {
+			writeNinjaHint(ctx)
+		}
 		return cmdlineArgs.OutFile
 	}
 }
@@ -535,15 +542,18 @@
 		} else {
 			finalOutputFile = runSoongOnlyBuild(ctx, extraNinjaDeps)
 		}
-		if ctx.Config().IsEnvTrue("SOONG_GENERATES_NINJA_HINT") {
-			writeNinjaHint(ctx)
-		}
 		writeMetrics(configuration, ctx.EventHandler, metricsDir)
 	}
-	writeUsedEnvironmentFile(configuration, finalOutputFile)
+	writeUsedEnvironmentFile(configuration)
+
+	// Touch the output file so that it's the newest file created by soong_build.
+	// This is necessary because, if soong_build generated any files which
+	// are ninja inputs to the main output file, then ninja would superfluously
+	// rebuild this output file on the next build invocation.
+	touch(shared.JoinPath(topDir, finalOutputFile))
 }
 
-func writeUsedEnvironmentFile(configuration android.Config, finalOutputFile string) {
+func writeUsedEnvironmentFile(configuration android.Config) {
 	if usedEnvFile == "" {
 		return
 	}
@@ -562,11 +572,6 @@
 	}
 	err = os.WriteFile(path, data, 0666)
 	maybeQuit(err, "error writing used environment file '%s'", usedEnvFile)
-
-	// Touch the output file so that it's not older than the file we just
-	// wrote. We can't write the environment file earlier because one an access
-	// new environment variables while writing it.
-	touch(shared.JoinPath(topDir, finalOutputFile))
 }
 
 func touch(path string) {
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 1c6aaad..eea41e6 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -92,13 +92,12 @@
 		stdio:       stdio,
 		run:         runMake,
 	}, {
-		flag:        "--upload-metrics-only",
-		description: "upload metrics without building anything",
+		flag:        "--finalize-bazel-metrics",
+		description: "finalize b metrics and upload",
 		config:      build.UploadOnlyConfig,
 		stdio:       stdio,
-		// Upload-only mode mostly skips to the metrics-uploading phase of soong_ui.
-		// However, this invocation marks the true "end of the build", and thus we
-		// need to update the total runtime of the build to include this upload step.
+		// Finalize-bazel-metrics mode updates metrics files and calls the metrics
+		// uploader. This marks the end of a b invocation.
 		run: finalizeBazelMetrics,
 	},
 }
diff --git a/device_config/Android.bp b/device_config/Android.bp
new file mode 100644
index 0000000..360b389
--- /dev/null
+++ b/device_config/Android.bp
@@ -0,0 +1,30 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+    name: "soong-device_config",
+    pkgPath: "android/soong/device_config",
+    deps: [
+        "blueprint",
+        "blueprint-pathtools",
+        "sbox_proto",
+        "soong",
+        "soong-android",
+        "soong-bazel",
+        "soong-shared",
+    ],
+    srcs: [
+        "device_config_definitions.go",
+        "device_config_values.go",
+        "device_config_value_set.go",
+        "init.go",
+        //"testing.go"
+    ],
+    /*
+    testSrcs: [
+        "device_config_test.go",
+    ],
+    */
+    pluginFor: ["soong_build"],
+}
diff --git a/device_config/device_config_definitions.go b/device_config/device_config_definitions.go
new file mode 100644
index 0000000..c565766
--- /dev/null
+++ b/device_config/device_config_definitions.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 device_config
+
+import (
+	"android/soong/android"
+	"fmt"
+	"github.com/google/blueprint"
+	"strings"
+)
+
+type DefinitionsModule struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	// Properties for "device_config_definitions"
+	properties struct {
+		// aconfig files, relative to this Android.bp file
+		Srcs []string `android:"path"`
+
+		// Release config flag namespace
+		Namespace string
+
+		// Values from TARGET_RELEASE / RELEASE_DEVICE_CONFIG_VALUE_SETS
+		Values []string `blueprint:"mutated"`
+	}
+
+	intermediatePath android.WritablePath
+	srcJarPath       android.WritablePath
+}
+
+func DefinitionsFactory() android.Module {
+	module := &DefinitionsModule{}
+
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	module.AddProperties(&module.properties)
+	// TODO: bp2build
+	//android.InitBazelModule(module)
+
+	return module
+}
+
+type implicitValuesTagType struct {
+	blueprint.BaseDependencyTag
+}
+
+var implicitValuesTag = implicitValuesTagType{}
+
+func (module *DefinitionsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// Validate Properties
+	if len(module.properties.Srcs) == 0 {
+		ctx.PropertyErrorf("srcs", "missing source files")
+		return
+	}
+	if len(module.properties.Namespace) == 0 {
+		ctx.PropertyErrorf("namespace", "missing namespace property")
+	}
+
+	// Add a dependency on the device_config_value_sets defined in
+	// RELEASE_DEVICE_CONFIG_VALUE_SETS, and add any device_config_values that
+	// match our namespace.
+	valuesFromConfig := ctx.Config().ReleaseDeviceConfigValueSets()
+	ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...)
+}
+
+func (module *DefinitionsModule) OutputFiles(tag string) (android.Paths, error) {
+	switch tag {
+	case ".srcjar":
+		return []android.Path{module.srcJarPath}, nil
+	case "":
+		// The default output of this module is the intermediates format, which is
+		// not installable and in a private format that no other rules can handle
+		// correctly.
+		return []android.Path{module.intermediatePath}, nil
+	default:
+		return nil, fmt.Errorf("unsupported device_config_definitions module reference tag %q", tag)
+	}
+}
+
+func joinAndPrefix(prefix string, values []string) string {
+	var sb strings.Builder
+	for _, v := range values {
+		sb.WriteString(prefix)
+		sb.WriteString(v)
+	}
+	return sb.String()
+}
+
+func (module *DefinitionsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	// Get the values that came from the global RELEASE_DEVICE_CONFIG_VALUE_SETS flag
+	ctx.VisitDirectDeps(func(dep android.Module) {
+		if !ctx.OtherModuleHasProvider(dep, valueSetProviderKey) {
+			// Other modules get injected as dependencies too, for example the license modules
+			return
+		}
+		depData := ctx.OtherModuleProvider(dep, valueSetProviderKey).(valueSetProviderData)
+		valuesFiles, ok := depData.AvailableNamespaces[module.properties.Namespace]
+		if ok {
+			for _, path := range valuesFiles {
+				module.properties.Values = append(module.properties.Values, path.String())
+			}
+		}
+	})
+
+	// Intermediate format
+	inputFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
+	module.intermediatePath = android.PathForModuleOut(ctx, "intermediate.json")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        aconfigRule,
+		Inputs:      inputFiles,
+		Output:      module.intermediatePath,
+		Description: "device_config_definitions",
+		Args: map[string]string{
+			"release_version": ctx.Config().ReleaseVersion(),
+			"namespace":       module.properties.Namespace,
+			"values":          joinAndPrefix(" --values ", module.properties.Values),
+		},
+	})
+
+	// Generated java inside a srcjar
+	module.srcJarPath = android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        srcJarRule,
+		Input:       module.intermediatePath,
+		Output:      module.srcJarPath,
+		Description: "device_config.srcjar",
+	})
+
+	// TODO: C++
+
+	// Phony target for debugging convenience
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   blueprint.Phony,
+		Output: android.PathForPhony(ctx, ctx.ModuleName()),
+		Inputs: []android.Path{module.srcJarPath}, // TODO: C++
+	})
+}
diff --git a/device_config/device_config_test.go b/device_config/device_config_test.go
new file mode 100644
index 0000000..91a06a7
--- /dev/null
+++ b/device_config/device_config_test.go
@@ -0,0 +1,61 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package device_config
+
+import (
+	"os"
+	"testing"
+
+	"android/soong/android"
+	"android/soong/java"
+)
+
+func TestMain(m *testing.M) {
+	os.Exit(m.Run())
+}
+
+func test(t *testing.T, bp string) *android.TestResult {
+	t.Helper()
+
+	mockFS := android.MockFS{
+		"config.aconfig": nil,
+	}
+
+	result := android.GroupFixturePreparers(
+		java.PrepareForTestWithJavaDefaultModules,
+		PrepareForTestWithSyspropBuildComponents,
+		// TODO: Consider values files, although maybe in its own test
+		// android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+		//	variables.ReleaseConfigValuesBasePaths = ...
+		//})
+		mockFS.AddToFixture(),
+		android.FixtureWithRootAndroidBp(bp),
+	).RunTest(t)
+
+	return result
+}
+
+func TestOutputs(t *testing.T) {
+	/*result := */ test(t, `
+        device_config {
+            name: "my_device_config",
+            srcs: ["config.aconfig"],
+        }
+	`)
+
+	// TODO: Make sure it exports a .srcjar, which is used by java libraries
+	// TODO: Make sure it exports an intermediates file
+	// TODO: Make sure the intermediates file is propagated to the Android.mk file
+}
diff --git a/device_config/device_config_value_set.go b/device_config/device_config_value_set.go
new file mode 100644
index 0000000..e406d20
--- /dev/null
+++ b/device_config/device_config_value_set.go
@@ -0,0 +1,92 @@
+// 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 device_config
+
+import (
+	"android/soong/android"
+	"github.com/google/blueprint"
+)
+
+// Properties for "device_config_value_set"
+type ValueSetModule struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties struct {
+		// device_config_values modules
+		Values []string
+	}
+}
+
+func ValueSetFactory() android.Module {
+	module := &ValueSetModule{}
+
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	module.AddProperties(&module.properties)
+	// TODO: bp2build
+	//android.InitBazelModule(module)
+
+	return module
+}
+
+// Dependency tag for values property
+type valueSetType struct {
+	blueprint.BaseDependencyTag
+}
+
+var valueSetTag = valueSetType{}
+
+// Provider published by device_config_value_set
+type valueSetProviderData struct {
+	// The namespace of each of the
+	// (map of namespace --> device_config_module)
+	AvailableNamespaces map[string]android.Paths
+}
+
+var valueSetProviderKey = blueprint.NewProvider(valueSetProviderData{})
+
+func (module *ValueSetModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+	deps := ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...)
+	for _, dep := range deps {
+		_, ok := dep.(*ValuesModule)
+		if !ok {
+			ctx.PropertyErrorf("values", "values must be a device_config_values module")
+			return
+		}
+	}
+}
+
+func (module *ValueSetModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	// Accumulate the namespaces of the values modules listed, and set that as an
+	// valueSetProviderKey provider that device_config modules can read and use
+	// to append values to their aconfig actions.
+	namespaces := make(map[string]android.Paths)
+	ctx.VisitDirectDeps(func(dep android.Module) {
+		if !ctx.OtherModuleHasProvider(dep, valuesProviderKey) {
+			// Other modules get injected as dependencies too, for example the license modules
+			return
+		}
+		depData := ctx.OtherModuleProvider(dep, valuesProviderKey).(valuesProviderData)
+
+		srcs := make([]android.Path, len(depData.Values))
+		copy(srcs, depData.Values)
+		namespaces[depData.Namespace] = srcs
+
+	})
+	ctx.SetProvider(valueSetProviderKey, valueSetProviderData{
+		AvailableNamespaces: namespaces,
+	})
+}
diff --git a/device_config/device_config_values.go b/device_config/device_config_values.go
new file mode 100644
index 0000000..110f12a
--- /dev/null
+++ b/device_config/device_config_values.go
@@ -0,0 +1,70 @@
+// 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 device_config
+
+import (
+	"android/soong/android"
+	"github.com/google/blueprint"
+)
+
+// Properties for "device_config_value"
+type ValuesModule struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties struct {
+		// aconfig files, relative to this Android.bp file
+		Srcs []string `android:"path"`
+
+		// Release config flag namespace
+		Namespace string
+	}
+}
+
+func ValuesFactory() android.Module {
+	module := &ValuesModule{}
+
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	module.AddProperties(&module.properties)
+	// TODO: bp2build
+	//android.InitBazelModule(module)
+
+	return module
+}
+
+// Provider published by device_config_value_set
+type valuesProviderData struct {
+	// The namespace that this values module values
+	Namespace string
+
+	// The values aconfig files, relative to the root of the tree
+	Values android.Paths
+}
+
+var valuesProviderKey = blueprint.NewProvider(valuesProviderData{})
+
+func (module *ValuesModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if len(module.properties.Namespace) == 0 {
+		ctx.PropertyErrorf("namespace", "missing namespace property")
+	}
+
+	// Provide the our source files list to the device_config_value_set as a list of files
+	providerData := valuesProviderData{
+		Namespace: module.properties.Namespace,
+		Values:    android.PathsForModuleSrc(ctx, module.properties.Srcs),
+	}
+	ctx.SetProvider(valuesProviderKey, providerData)
+}
diff --git a/device_config/init.go b/device_config/init.go
new file mode 100644
index 0000000..0a4645b
--- /dev/null
+++ b/device_config/init.go
@@ -0,0 +1,70 @@
+// 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 device_config
+
+import (
+	"android/soong/android"
+	"github.com/google/blueprint"
+)
+
+var (
+	pctx = android.NewPackageContext("android/soong/device_config")
+
+	// For device_config_definitions: Generate cache file
+	// TODO: Restat
+	aconfigRule = pctx.AndroidStaticRule("aconfig",
+		blueprint.RuleParams{
+			Command: `${aconfig} create-cache` +
+				` --namespace ${namespace}` +
+				` --declarations ${in}` +
+				` ${values}` +
+				` --cache ${out}.tmp` +
+				` && ( if cmp -s ${out}.tmp ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
+			//				` --build-id ${release_version}` +
+			CommandDeps: []string{
+				"${aconfig}",
+			},
+			Restat: true,
+		}, "release_version", "namespace", "values")
+
+	// For device_config_definitions: Generate java file
+	srcJarRule = pctx.AndroidStaticRule("aconfig_srcjar",
+		blueprint.RuleParams{
+			Command: `rm -rf ${out}.tmp` +
+				` && mkdir -p ${out}.tmp` +
+				` && ${aconfig} create-java-lib` +
+				`    --cache ${in}` +
+				`    --out ${out}.tmp` +
+				` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
+				` && rm -rf ${out}.tmp`,
+			CommandDeps: []string{
+				"$aconfig",
+				"$soong_zip",
+			},
+			Restat: true,
+		})
+)
+
+func init() {
+	registerBuildComponents(android.InitRegistrationContext)
+}
+
+func registerBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("device_config_definitions", DefinitionsFactory)
+	ctx.RegisterModuleType("device_config_values", ValuesFactory)
+	ctx.RegisterModuleType("device_config_value_set", ValueSetFactory)
+	pctx.HostBinToolVariable("aconfig", "aconfig")
+	pctx.HostBinToolVariable("soong_zip", "soong_zip")
+}
diff --git a/device_config/testing.go b/device_config/testing.go
new file mode 100644
index 0000000..f054476
--- /dev/null
+++ b/device_config/testing.go
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package device_config
+
+import "android/soong/android"
+
+var PrepareForTestWithSyspropBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents)
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 6817dce..3e1bbde 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -652,9 +652,7 @@
 		prop := snapshot.SnapshotJsonFlags{}
 		propOut := snapshotLibOut + ".json"
 		prop.InitBaseSnapshotProps(m)
-		if m.subdirProperties.Relative_install_path != nil {
-			prop.RelativeInstallPath = *m.subdirProperties.Relative_install_path
-		}
+		prop.RelativeInstallPath = m.SubDir()
 
 		if m.properties.Filename != nil {
 			prop.Filename = *m.properties.Filename
diff --git a/java/Android.bp b/java/Android.bp
index 27a0a38..4af2a14 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -87,7 +87,6 @@
         "device_host_converter_test.go",
         "dex_test.go",
         "dexpreopt_test.go",
-        "dexpreopt_bootjars_test.go",
         "dexpreopt_config_test.go",
         "droiddoc_test.go",
         "droidstubs_test.go",
diff --git a/java/app_test.go b/java/app_test.go
index daff94c..8a69a03 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -443,9 +443,9 @@
 	inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits
 	var crtbeginFound, crtendFound bool
 	expectedCrtBegin := ctx.ModuleForTests("crtbegin_so",
-		"android_arm64_armv8-a_sdk_29").Rule("partialLd").Output
+		"android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output
 	expectedCrtEnd := ctx.ModuleForTests("crtend_so",
-		"android_arm64_armv8-a_sdk_29").Rule("partialLd").Output
+		"android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output
 	implicits := []string{}
 	for _, input := range inputs {
 		implicits = append(implicits, input.String())
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 6ccf5a3..108fdd4 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -241,10 +241,8 @@
 	// Collect the module directory for IDE info in java/jdeps.go.
 	modulePaths []string
 
-	// Installs for on-device boot image files. This list has entries only if the installs should be
-	// handled by Make (e.g., the boot image should be installed on the system partition, rather than
-	// in the APEX).
-	bootImageDeviceInstalls []dexpreopterInstall
+	// Path to the boot image profile.
+	profilePath android.Path
 }
 
 // commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt
@@ -264,16 +262,16 @@
 	// 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
 }
 
 var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil)
 
-// bootImageFilesByArch is a map from android.ArchType to the paths to the boot image files.
-//
-// The paths include the .art, .oat and .vdex files, one for each of the modules from which the boot
-// image is created.
-type bootImageFilesByArch map[android.ArchType]android.Paths
-
 func bootclasspathFragmentFactory() android.Module {
 	m := &BootclasspathFragmentModule{}
 	m.AddProperties(&m.properties, &m.sourceOnlyProperties)
@@ -395,12 +393,6 @@
 	// set image_name: "art".
 	modules android.ConfiguredJarList
 
-	// Map from arch type to the boot image files.
-	bootImageFilesByArch bootImageFilesByArch
-
-	// True if the boot image should be installed in the APEX.
-	shouldInstallBootImageInApex bool
-
 	// Map from the base module name (without prebuilt_ prefix) of a fragment's contents module to the
 	// hidden API encoded dex jar path.
 	contentModuleDexJarPaths bootDexJarByModule
@@ -417,18 +409,6 @@
 	return i.modules
 }
 
-// Get a map from ArchType to the associated boot image's contents for Android.
-//
-// Extension boot images only return their own files, not the files of the boot images they extend.
-func (i BootclasspathFragmentApexContentInfo) AndroidBootImageFilesByArchType() bootImageFilesByArch {
-	return i.bootImageFilesByArch
-}
-
-// Return true if the boot image should be installed in the APEX.
-func (i *BootclasspathFragmentApexContentInfo) ShouldInstallBootImageInApex() bool {
-	return i.shouldInstallBootImageInApex
-}
-
 // DexBootJarPathForContentModule returns the path to the dex boot jar for specified module.
 //
 // The dex boot jar is one which has had hidden API encoding performed on it.
@@ -557,6 +537,7 @@
 		// 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
@@ -566,25 +547,6 @@
 			// Copy the dex jars of this fragment's content modules to their predefined locations.
 			copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
 		}
-
-		for _, variant := range bootImageFiles.variants {
-			archType := variant.config.target.Arch.ArchType
-			arch := archType.String()
-			for _, install := range variant.deviceInstalls {
-				// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
-				installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
-				installBase := filepath.Base(install.To)
-				installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir)
-
-				b.bootImageDeviceInstalls = append(b.bootImageDeviceInstalls, dexpreopterInstall{
-					name:                arch + "-" + installBase,
-					moduleName:          b.Name(),
-					outputPathOnHost:    install.From,
-					installDirOnDevice:  installPath,
-					installFileOnDevice: installBase,
-				})
-			}
-		}
 	}
 
 	// A prebuilt fragment cannot contribute to an apex.
@@ -643,12 +605,8 @@
 			info.profilePathOnHost = bootImageFiles.profile
 			info.profileInstallPathInApex = imageConfig.profileInstallPathInApex
 		}
-
-		info.shouldInstallBootImageInApex = imageConfig.shouldInstallInApex()
 	}
 
-	info.bootImageFilesByArch = bootImageFiles.byArch
-
 	// Make the apex content info available for other modules.
 	ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info)
 }
@@ -960,19 +918,15 @@
 			},
 		},
 	}}
-	for _, install := range b.bootImageDeviceInstalls {
-		entriesList = append(entriesList, install.ToMakeEntries())
-	}
 	return entriesList
 }
 
-// Returns the names of all Make modules that handle the installation of the boot image.
-func (b *BootclasspathFragmentModule) BootImageDeviceInstallMakeModules() []string {
-	var makeModules []string
-	for _, install := range b.bootImageDeviceInstalls {
-		makeModules = append(makeModules, install.FullModuleName())
-	}
-	return makeModules
+func (b *BootclasspathFragmentModule) getImageName() *string {
+	return b.properties.Image_name
+}
+
+func (b *BootclasspathFragmentModule) getProfilePath() android.Path {
+	return b.profilePath
 }
 
 // Collect information for opening IDE project files in java/jdeps.go.
@@ -1262,59 +1216,25 @@
 	// built without a profile as the prebuilt modules do not provide a profile.
 	buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
 
-	if imageConfig.shouldInstallInApex() {
-		// If the boot image files for the android variants are in the prebuilt apex, we must use those
-		// rather than building new ones because those boot image files are going to be used on device.
-		files := bootImageFilesByArch{}
-		bootImageFiles := bootImageOutputs{
-			byArch:  files,
-			profile: profile,
-		}
-		for _, variant := range imageConfig.apexVariants() {
-			arch := variant.target.Arch.ArchType
-			bootImageFiles.variants = append(bootImageFiles.variants, bootImageVariantOutputs{
-				variant,
-				// No device installs needed when installed in APEX.
-				nil,
-			})
-			for _, toPath := range variant.imagesDeps {
-				apexRelativePath := apexRootRelativePathToBootImageFile(arch, toPath.Base())
-				// Get the path to the file that the deapexer extracted from the prebuilt apex file.
-				fromPath := di.PrebuiltExportPath(apexRelativePath)
-
-				// Return the toPath as the calling code expects the paths in the returned map to be the
-				// paths predefined in the bootImageConfig.
-				files[arch] = append(files[arch], toPath)
-
-				// Copy the file to the predefined location.
-				ctx.Build(pctx, android.BuildParams{
-					Rule:   android.Cp,
-					Input:  fromPath,
-					Output: toPath,
-				})
-			}
-		}
-		return bootImageFiles
-	} else {
-		if profile == nil && imageConfig.isProfileGuided() {
-			ctx.ModuleErrorf("Unable to produce boot image files: neither boot image files nor profiles exists 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)
+	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
+}
+
+func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path {
+	return b.profilePath
 }
 
 var _ commonBootclasspathFragment = (*PrebuiltBootclasspathFragmentModule)(nil)
 
-// createBootImageTag creates the tag to uniquely identify the boot image file among all of the
-// files that a module requires from the prebuilt .apex file.
-func createBootImageTag(arch android.ArchType, baseName string) string {
-	tag := fmt.Sprintf(".bootimage-%s-%s", arch, baseName)
-	return tag
-}
-
 // RequiredFilesFromPrebuiltApex returns the list of all files the prebuilt_bootclasspath_fragment
 // requires from a prebuilt .apex file.
 //
@@ -1328,25 +1248,11 @@
 			// Add the boot image profile.
 			files = append(files, imageConfig.profileInstallPathInApex)
 		}
-		if imageConfig.shouldInstallInApex() {
-			// Add the boot image files, e.g. .art, .oat and .vdex files.
-			for _, variant := range imageConfig.apexVariants() {
-				arch := variant.target.Arch.ArchType
-				for _, path := range variant.imagesDeps.Paths() {
-					base := path.Base()
-					files = append(files, apexRootRelativePathToBootImageFile(arch, base))
-				}
-			}
-		}
 		return files
 	}
 	return nil
 }
 
-func apexRootRelativePathToBootImageFile(arch android.ArchType, base string) string {
-	return filepath.Join("javalib", arch.String(), base)
-}
-
 var _ android.RequiredFilesFromPrebuiltApex = (*PrebuiltBootclasspathFragmentModule)(nil)
 
 func prebuiltBootclasspathFragmentFactory() android.Module {
diff --git a/java/dex.go b/java/dex.go
index f7c1361..7e7da00 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -161,7 +161,7 @@
 		"$r8Template": &remoteexec.REParams{
 			Labels:          map[string]string{"type": "compile", "compiler": "r8"},
 			Inputs:          []string{"$implicits", "${config.R8Jar}"},
-			OutputFiles:     []string{"${outUsage}"},
+			OutputFiles:     []string{"${outUsage}", "${outConfig}", "${outDict}"},
 			ExecStrategy:    "${config.RER8ExecStrategy}",
 			ToolchainInputs: []string{"${config.JavaCmd}"},
 			Platform:        map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
@@ -399,13 +399,16 @@
 			args["implicits"] = strings.Join(r8Deps.Strings(), ",")
 		}
 		ctx.Build(pctx, android.BuildParams{
-			Rule:            rule,
-			Description:     "r8",
-			Output:          javalibJar,
-			ImplicitOutputs: android.WritablePaths{proguardDictionary, proguardUsageZip},
-			Input:           dexParams.classesJar,
-			Implicits:       r8Deps,
-			Args:            args,
+			Rule:        rule,
+			Description: "r8",
+			Output:      javalibJar,
+			ImplicitOutputs: android.WritablePaths{
+				proguardDictionary,
+				proguardUsageZip,
+				proguardConfiguration},
+			Input:     dexParams.classesJar,
+			Implicits: r8Deps,
+			Args:      args,
 		})
 	} else {
 		d8Flags, d8Deps := d8Flags(dexParams.flags)
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 8e79674..f477f40 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -250,11 +250,12 @@
 	// Output directory for the image files with debug symbols.
 	symbolsDir android.OutputPath
 
-	// Subdirectory where the image files are installed.
-	installDirOnHost string
-
-	// Subdirectory where the image files on device are installed.
-	installDirOnDevice string
+	// The relative location where the image files are installed. On host, the location is relative to
+	// $ANDROID_PRODUCT_OUT.
+	//
+	// Only the configs that are built by platform_bootclasspath are installable on device. On device,
+	// 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.
@@ -294,6 +295,11 @@
 
 	// 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
 }
 
 // Target-dependent description of a boot image.
@@ -421,11 +427,6 @@
 	return variants
 }
 
-// Returns true if the boot image should be installed in the APEX.
-func (image *bootImageConfig) shouldInstallInApex() bool {
-	return strings.HasPrefix(image.installDirOnDevice, "apex/")
-}
-
 // Return boot image locations (as a list of symbolic paths).
 //
 // The image "location" is a symbolic path that, with multiarchitecture support, doesn't really
@@ -596,6 +597,12 @@
 	buildBootImageForOsType(ctx, image, profile, ctx.Config().BuildOS)
 }
 
+// bootImageFilesByArch is a map from android.ArchType to the paths to the boot image files.
+//
+// The paths include the .art, .oat and .vdex files, one for each of the modules from which the boot
+// image is created.
+type bootImageFilesByArch map[android.ArchType]android.Paths
+
 // bootImageOutputs encapsulates information about boot images that were created/obtained by
 // commonBootclasspathFragment.produceBootImageFiles.
 type bootImageOutputs struct {
@@ -656,8 +663,7 @@
 }
 
 type bootImageVariantOutputs struct {
-	config         *bootImageVariant
-	deviceInstalls android.RuleBuilderInstalls
+	config *bootImageVariant
 }
 
 // Generate boot image build rules for a specific target.
@@ -668,9 +674,9 @@
 
 	arch := image.target.Arch.ArchType
 	os := image.target.Os.String() // We need to distinguish host-x86 and device-x86.
-	symbolsDir := image.symbolsDir.Join(ctx, os, image.installDirOnHost, arch.String())
+	symbolsDir := image.symbolsDir.Join(ctx, os, image.installDir, arch.String())
 	symbolsFile := symbolsDir.Join(ctx, image.stem+".oat")
-	outputDir := image.dir.Join(ctx, os, image.installDirOnHost, arch.String())
+	outputDir := image.dir.Join(ctx, os, image.installDir, arch.String())
 	outputPath := outputDir.Join(ctx, image.stem+".oat")
 	oatLocation := dexpreopt.PathToLocation(outputPath, arch)
 	imagePath := outputPath.ReplaceExtension(ctx, "art")
@@ -710,6 +716,34 @@
 		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 _, 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"
 	dirtyImagePath := android.ExistentPathForSource(ctx, dirtyImageFile)
 	if dirtyImagePath.Valid() {
@@ -796,11 +830,10 @@
 
 	cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape(failureMessage))
 
-	installDir := filepath.Join("/", image.installDirOnHost, arch.String())
+	installDir := filepath.Dir(image.imagePathOnDevice)
 
 	var vdexInstalls android.RuleBuilderInstalls
 	var unstrippedInstalls android.RuleBuilderInstalls
-	var deviceInstalls android.RuleBuilderInstalls
 
 	for _, artOrOat := range image.moduleFiles(ctx, outputDir, ".art", ".oat") {
 		cmd.ImplicitOutput(artOrOat)
@@ -826,14 +859,6 @@
 			android.RuleBuilderInstall{unstrippedOat, filepath.Join(installDir, unstrippedOat.Base())})
 	}
 
-	if image.installDirOnHost != image.installDirOnDevice && !image.shouldInstallInApex() && !ctx.Config().UnbundledBuild() {
-		installDirOnDevice := filepath.Join("/", image.installDirOnDevice, arch.String())
-		for _, file := range image.moduleFiles(ctx, outputDir, ".art", ".oat", ".vdex") {
-			deviceInstalls = append(deviceInstalls,
-				android.RuleBuilderInstall{file, filepath.Join(installDirOnDevice, file.Base())})
-		}
-	}
-
 	rule.Build(image.name+"JarsDexpreopt_"+image.target.String(), "dexpreopt "+image.name+" jars "+arch.String())
 
 	// save output and installed files for makevars
@@ -849,7 +874,6 @@
 
 	return bootImageVariantOutputs{
 		image,
-		deviceInstalls,
 	}
 }
 
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
deleted file mode 100644
index 9083808..0000000
--- a/java/dexpreopt_bootjars_test.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2019 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 java
-
-import (
-	"path/filepath"
-	"sort"
-	"testing"
-
-	"android/soong/android"
-)
-
-func testDexpreoptBoot(t *testing.T, ruleFile string, expectedInputs, expectedOutputs []string) {
-	bp := `
-		java_sdk_library {
-			name: "foo",
-			srcs: ["a.java"],
-			api_packages: ["foo"],
-		}
-
-		java_library {
-			name: "bar",
-			srcs: ["b.java"],
-			installable: true,
-			system_ext_specific: true,
-		}
-
-		dex_import {
-			name: "baz",
-			jars: ["a.jar"],
-		}
-
-		platform_bootclasspath {
-			name: "platform-bootclasspath",
-		}
-	`
-
-	result := android.GroupFixturePreparers(
-		prepareForJavaTest,
-		PrepareForTestWithJavaSdkLibraryFiles,
-		FixtureWithLastReleaseApis("foo"),
-		FixtureConfigureBootJars("platform:foo", "system_ext:bar", "platform:baz"),
-	).RunTestWithBp(t, bp)
-
-	platformBootclasspath := result.ModuleForTests("platform-bootclasspath", "android_common")
-	rule := platformBootclasspath.Output(ruleFile)
-
-	for i := range expectedInputs {
-		expectedInputs[i] = filepath.Join("out/soong/dexpreopt_arm64", expectedInputs[i])
-	}
-
-	for i := range expectedOutputs {
-		expectedOutputs[i] = filepath.Join("out/soong/dexpreopt_arm64", expectedOutputs[i])
-	}
-
-	inputs := rule.Implicits.Strings()
-	sort.Strings(inputs)
-	sort.Strings(expectedInputs)
-
-	outputs := append(android.WritablePaths{rule.Output}, rule.ImplicitOutputs...).Strings()
-	sort.Strings(outputs)
-	sort.Strings(expectedOutputs)
-
-	android.AssertStringPathsRelativeToTopEquals(t, "inputs", result.Config, expectedInputs, inputs)
-
-	android.AssertStringPathsRelativeToTopEquals(t, "outputs", result.Config, expectedOutputs, outputs)
-}
-
-func TestDexpreoptBootJars(t *testing.T) {
-	ruleFile := "boot-foo.art"
-
-	expectedInputs := []string{
-		"dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
-		"dex_bootjars_input/foo.jar",
-		"dex_bootjars_input/bar.jar",
-		"dex_bootjars_input/baz.jar",
-	}
-
-	expectedOutputs := []string{
-		"dex_bootjars/android/system/framework/arm64/boot.invocation",
-		"dex_bootjars/android/system/framework/arm64/boot-foo.art",
-		"dex_bootjars/android/system/framework/arm64/boot-bar.art",
-		"dex_bootjars/android/system/framework/arm64/boot-baz.art",
-		"dex_bootjars/android/system/framework/arm64/boot-foo.oat",
-		"dex_bootjars/android/system/framework/arm64/boot-bar.oat",
-		"dex_bootjars/android/system/framework/arm64/boot-baz.oat",
-		"dex_bootjars/android/system/framework/arm64/boot-foo.vdex",
-		"dex_bootjars/android/system/framework/arm64/boot-bar.vdex",
-		"dex_bootjars/android/system/framework/arm64/boot-baz.vdex",
-		"dex_bootjars_unstripped/android/system/framework/arm64/boot-foo.oat",
-		"dex_bootjars_unstripped/android/system/framework/arm64/boot-bar.oat",
-		"dex_bootjars_unstripped/android/system/framework/arm64/boot-baz.oat",
-	}
-
-	testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs)
-}
-
-// Changes to the boot.zip structure may break the ART APK scanner.
-func TestDexpreoptBootZip(t *testing.T) {
-	ruleFile := "boot.zip"
-
-	ctx := android.PathContextForTesting(android.TestArchConfig("", nil, "", nil))
-	expectedInputs := []string{}
-	for _, target := range ctx.Config().Targets[android.Android] {
-		for _, ext := range []string{".art", ".oat", ".vdex"} {
-			for _, jar := range []string{"foo", "bar", "baz"} {
-				expectedInputs = append(expectedInputs,
-					filepath.Join("dex_bootjars", target.Os.String(), "system/framework", target.Arch.ArchType.String(), "boot-"+jar+ext))
-			}
-		}
-	}
-
-	expectedOutputs := []string{
-		"dex_bootjars/boot.zip",
-	}
-
-	testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs)
-}
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 8f732cf..9100e87 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -53,7 +53,7 @@
 		global := dexpreopt.GetGlobalConfig(ctx)
 
 		artModules := global.ArtApexJars
-		frameworkModules := global.BootJars.RemoveList(artModules)
+		frameworkModules := global.BootJars // This includes `artModules`.
 		mainlineBcpModules := global.ApexBootJars
 		frameworkSubdir := "system/framework"
 
@@ -62,8 +62,7 @@
 		artCfg := bootImageConfig{
 			name:                     artBootImageName,
 			stem:                     bootImageStem,
-			installDirOnHost:         "apex/art_boot_images/javalib",
-			installDirOnDevice:       frameworkSubdir,
+			installDir:               "apex/art_boot_images/javalib",
 			profileInstallPathInApex: "etc/boot-image.prof",
 			modules:                  artModules,
 			preloadedClassesFile:     "art/build/boot/preloaded-classes",
@@ -74,26 +73,24 @@
 		// Framework config for the boot image extension.
 		// It includes framework libraries and depends on the ART config.
 		frameworkCfg := bootImageConfig{
-			extends:              &artCfg,
 			name:                 frameworkBootImageName,
 			stem:                 bootImageStem,
-			installDirOnHost:     frameworkSubdir,
-			installDirOnDevice:   frameworkSubdir,
+			installDir:           frameworkSubdir,
 			modules:              frameworkModules,
 			preloadedClassesFile: "frameworks/base/config/preloaded-classes",
 			compilerFilter:       "speed-profile",
 			singleImage:          false,
+			profileImports:       []*bootImageConfig{&artCfg},
 		}
 
 		mainlineCfg := bootImageConfig{
-			extends:            &frameworkCfg,
-			name:               mainlineBootImageName,
-			stem:               bootImageStem,
-			installDirOnHost:   frameworkSubdir,
-			installDirOnDevice: frameworkSubdir,
-			modules:            mainlineBcpModules,
-			compilerFilter:     "verify",
-			singleImage:        true,
+			extends:        &frameworkCfg,
+			name:           mainlineBootImageName,
+			stem:           bootImageStem,
+			installDir:     frameworkSubdir,
+			modules:        mainlineBcpModules,
+			compilerFilter: "verify",
+			singleImage:    true,
 		}
 
 		return map[string]*bootImageConfig{
@@ -132,12 +129,12 @@
 			// Create target-specific variants.
 			for _, target := range targets {
 				arch := target.Arch.ArchType
-				imageDir := c.dir.Join(ctx, target.Os.String(), c.installDirOnHost, arch.String())
+				imageDir := c.dir.Join(ctx, target.Os.String(), c.installDir, arch.String())
 				variant := &bootImageVariant{
 					bootImageConfig:   c,
 					target:            target,
 					imagePathOnHost:   imageDir.Join(ctx, imageName),
-					imagePathOnDevice: filepath.Join("/", c.installDirOnDevice, arch.String(), imageName),
+					imagePathOnDevice: filepath.Join("/", c.installDir, arch.String(), imageName),
 					imagesDeps:        c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
 					dexLocations:      c.modules.DevicePaths(ctx.Config(), target.Os),
 				}
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
index 6b98ca5..6f3aa2b 100644
--- a/java/dexpreopt_config_testing.go
+++ b/java/dexpreopt_config_testing.go
@@ -147,8 +147,7 @@
 	stem                     string
 	dir                      string
 	symbolsDir               string
-	installDirOnDevice       string
-	installDirOnHost         string
+	installDir               string
 	profileInstallPathInApex string
 	modules                  android.ConfiguredJarList
 	dexPaths                 []string
@@ -209,8 +208,7 @@
 		stem:                     "boot",
 		dir:                      "out/soong/dexpreopt_arm64/dex_artjars",
 		symbolsDir:               "out/soong/dexpreopt_arm64/dex_artjars_unstripped",
-		installDirOnDevice:       "system/framework",
-		installDirOnHost:         "apex/art_boot_images/javalib",
+		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"},
@@ -222,7 +220,7 @@
 				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"},
 				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
-				imagePathOnDevice: "/system/framework/arm64/boot.art",
+				imagePathOnDevice: "/apex/art_boot_images/javalib/arm64/boot.art",
 				imagesDeps: []string{
 					"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",
@@ -276,7 +274,7 @@
 				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"},
 				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
-				imagePathOnDevice: "/system/framework/arm/boot.art",
+				imagePathOnDevice: "/apex/art_boot_images/javalib/arm/boot.art",
 				imagesDeps: []string{
 					"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",
@@ -330,7 +328,7 @@
 				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"},
 				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
-				imagePathOnDevice: "/system/framework/x86_64/boot.art",
+				imagePathOnDevice: "/apex/art_boot_images/javalib/x86_64/boot.art",
 				imagesDeps: []string{
 					"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",
@@ -382,7 +380,7 @@
 				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"},
 				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
-				imagePathOnDevice: "/system/framework/x86/boot.art",
+				imagePathOnDevice: "/apex/art_boot_images/javalib/x86/boot.art",
 				imagesDeps: []string{
 					"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",
@@ -462,40 +460,68 @@
 		stem:                     "boot",
 		dir:                      "out/soong/dexpreopt_arm64/dex_bootjars",
 		symbolsDir:               "out/soong/dexpreopt_arm64/dex_bootjars_unstripped",
-		installDirOnDevice:       "system/framework",
-		installDirOnHost:         "system/framework",
+		installDir:               "system/framework",
 		profileInstallPathInApex: "",
-		modules:                  android.CreateTestConfiguredJarList([]string{"platform:framework"}),
-		dexPaths:                 []string{"out/soong/dexpreopt_arm64/dex_bootjars_input/framework.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_bootjars_input/framework.jar"},
-		zip:                      "out/soong/dexpreopt_arm64/dex_bootjars/boot.zip",
+		modules: android.CreateTestConfiguredJarList([]string{
+			"com.android.art:core1",
+			"com.android.art:core2",
+			"platform:framework",
+		}),
+		dexPaths: []string{
+			"out/soong/dexpreopt_arm64/dex_bootjars_input/core1.jar",
+			"out/soong/dexpreopt_arm64/dex_bootjars_input/core2.jar",
+			"out/soong/dexpreopt_arm64/dex_bootjars_input/framework.jar",
+		},
+		dexPathsDeps: []string{
+			"out/soong/dexpreopt_arm64/dex_bootjars_input/core1.jar",
+			"out/soong/dexpreopt_arm64/dex_bootjars_input/core2.jar",
+			"out/soong/dexpreopt_arm64/dex_bootjars_input/framework.jar",
+		},
+		zip: "out/soong/dexpreopt_arm64/dex_bootjars/boot.zip",
 		variants: []*expectedVariant{
 			{
-				archType:     android.Arm64,
-				dexLocations: []string{"/system/framework/framework.jar"},
+				archType: android.Arm64,
+				dexLocations: []string{
+					"/apex/com.android.art/javalib/core1.jar",
+					"/apex/com.android.art/javalib/core2.jar",
+					"/system/framework/framework.jar",
+				},
 				dexLocationsDeps: []string{
 					"/apex/com.android.art/javalib/core1.jar",
 					"/apex/com.android.art/javalib/core2.jar",
 					"/system/framework/framework.jar",
 				},
-				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.art",
-				imagePathOnDevice: "/system/framework/arm64/boot-framework.art",
+				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art",
+				imagePathOnDevice: "/system/framework/arm64/boot.art",
 				imagesDeps: []string{
+					"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",
 				},
-				baseImages: []string{"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art"},
-				baseImagesDeps: []string{
-					"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",
-				},
 				installs: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art",
+						to:   "/system/framework/arm64/boot.art",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.oat",
+						to:   "/system/framework/arm64/boot.oat",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.art",
+						to:   "/system/framework/arm64/boot-core2.art",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.oat",
+						to:   "/system/framework/arm64/boot-core2.oat",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.art",
 						to:   "/system/framework/arm64/boot-framework.art",
 					},
@@ -506,12 +532,28 @@
 				},
 				vdexInstalls: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.vdex",
+						to:   "/system/framework/arm64/boot.vdex",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.vdex",
+						to:   "/system/framework/arm64/boot-core2.vdex",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.vdex",
 						to:   "/system/framework/arm64/boot-framework.vdex",
 					},
 				},
 				unstrippedInstalls: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot.oat",
+						to:   "/system/framework/arm64/boot.oat",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-core2.oat",
+						to:   "/system/framework/arm64/boot-core2.oat",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-framework.oat",
 						to:   "/system/framework/arm64/boot-framework.oat",
 					},
@@ -519,31 +561,48 @@
 				licenseMetadataFile: expectedLicenseMetadataFile,
 			},
 			{
-				archType:     android.Arm,
-				dexLocations: []string{"/system/framework/framework.jar"},
+				archType: android.Arm,
+				dexLocations: []string{
+					"/apex/com.android.art/javalib/core1.jar",
+					"/apex/com.android.art/javalib/core2.jar",
+					"/system/framework/framework.jar",
+				},
 				dexLocationsDeps: []string{
 					"/apex/com.android.art/javalib/core1.jar",
 					"/apex/com.android.art/javalib/core2.jar",
 					"/system/framework/framework.jar",
 				},
-				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.art",
-				imagePathOnDevice: "/system/framework/arm/boot-framework.art",
+				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.art",
+				imagePathOnDevice: "/system/framework/arm/boot.art",
 				imagesDeps: []string{
+					"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",
 				},
-				baseImages: []string{"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art"},
-				baseImagesDeps: []string{
-					"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",
-				},
 				installs: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.art",
+						to:   "/system/framework/arm/boot.art",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.oat",
+						to:   "/system/framework/arm/boot.oat",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.art",
+						to:   "/system/framework/arm/boot-core2.art",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.oat",
+						to:   "/system/framework/arm/boot-core2.oat",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.art",
 						to:   "/system/framework/arm/boot-framework.art",
 					},
@@ -554,12 +613,28 @@
 				},
 				vdexInstalls: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.vdex",
+						to:   "/system/framework/arm/boot.vdex",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.vdex",
+						to:   "/system/framework/arm/boot-core2.vdex",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.vdex",
 						to:   "/system/framework/arm/boot-framework.vdex",
 					},
 				},
 				unstrippedInstalls: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot.oat",
+						to:   "/system/framework/arm/boot.oat",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot-core2.oat",
+						to:   "/system/framework/arm/boot-core2.oat",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot-framework.oat",
 						to:   "/system/framework/arm/boot-framework.oat",
 					},
@@ -567,31 +642,48 @@
 				licenseMetadataFile: expectedLicenseMetadataFile,
 			},
 			{
-				archType:     android.X86_64,
-				dexLocations: []string{"host/linux-x86/system/framework/framework.jar"},
+				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",
+					"host/linux-x86/system/framework/framework.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/framework.jar",
 				},
-				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art",
-				imagePathOnDevice: "/system/framework/x86_64/boot-framework.art",
+				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.art",
+				imagePathOnDevice: "/system/framework/x86_64/boot.art",
 				imagesDeps: []string{
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.art",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.oat",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.vdex",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.art",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.oat",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.vdex",
 					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art",
 					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat",
 					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex",
 				},
-				baseImages: []string{"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art"},
-				baseImagesDeps: []string{
-					"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",
-				},
 				installs: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.art",
+						to:   "/system/framework/x86_64/boot.art",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.oat",
+						to:   "/system/framework/x86_64/boot.oat",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.art",
+						to:   "/system/framework/x86_64/boot-core2.art",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.oat",
+						to:   "/system/framework/x86_64/boot-core2.oat",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art",
 						to:   "/system/framework/x86_64/boot-framework.art",
 					},
@@ -602,12 +694,28 @@
 				},
 				vdexInstalls: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.vdex",
+						to:   "/system/framework/x86_64/boot.vdex",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.vdex",
+						to:   "/system/framework/x86_64/boot-core2.vdex",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex",
 						to:   "/system/framework/x86_64/boot-framework.vdex",
 					},
 				},
 				unstrippedInstalls: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot.oat",
+						to:   "/system/framework/x86_64/boot.oat",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot-core2.oat",
+						to:   "/system/framework/x86_64/boot-core2.oat",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot-framework.oat",
 						to:   "/system/framework/x86_64/boot-framework.oat",
 					},
@@ -615,31 +723,48 @@
 				licenseMetadataFile: expectedLicenseMetadataFile,
 			},
 			{
-				archType:     android.X86,
-				dexLocations: []string{"host/linux-x86/system/framework/framework.jar"},
+				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",
+					"host/linux-x86/system/framework/framework.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/framework.jar",
 				},
-				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art",
-				imagePathOnDevice: "/system/framework/x86/boot-framework.art",
+				imagePathOnHost:   "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.art",
+				imagePathOnDevice: "/system/framework/x86/boot.art",
 				imagesDeps: []string{
+					"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",
 				},
-				baseImages: []string{"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art"},
-				baseImagesDeps: []string{
-					"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",
-				},
 				installs: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.art",
+						to:   "/system/framework/x86/boot.art",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.oat",
+						to:   "/system/framework/x86/boot.oat",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.art",
+						to:   "/system/framework/x86/boot-core2.art",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.oat",
+						to:   "/system/framework/x86/boot-core2.oat",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art",
 						to:   "/system/framework/x86/boot-framework.art",
 					},
@@ -650,12 +775,28 @@
 				},
 				vdexInstalls: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.vdex",
+						to:   "/system/framework/x86/boot.vdex",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.vdex",
+						to:   "/system/framework/x86/boot-core2.vdex",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex",
 						to:   "/system/framework/x86/boot-framework.vdex",
 					},
 				},
 				unstrippedInstalls: []normalizedInstall{
 					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot.oat",
+						to:   "/system/framework/x86/boot.oat",
+					},
+					{
+						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-core2.oat",
+						to:   "/system/framework/x86/boot-core2.oat",
+					},
+					{
 						from: "out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-framework.oat",
 						to:   "/system/framework/x86/boot-framework.oat",
 					},
@@ -693,8 +834,7 @@
 		stem:                     "boot",
 		dir:                      "out/soong/dexpreopt_arm64/dex_mainlinejars",
 		symbolsDir:               "out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped",
-		installDirOnDevice:       "system/framework",
-		installDirOnHost:         "system/framework",
+		installDir:               "system/framework",
 		profileInstallPathInApex: "",
 		modules: android.CreateTestConfiguredJarList([]string{
 			"com.android.foo:framework-foo",
@@ -705,8 +845,8 @@
 			"out/soong/dexpreopt_arm64/dex_mainlinejars_input/framework-bar.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_bootjars_input/core1.jar",
+			"out/soong/dexpreopt_arm64/dex_bootjars_input/core2.jar",
 			"out/soong/dexpreopt_arm64/dex_bootjars_input/framework.jar",
 			"out/soong/dexpreopt_arm64/dex_mainlinejars_input/framework-foo.jar",
 			"out/soong/dexpreopt_arm64/dex_mainlinejars_input/framework-bar.jar",
@@ -734,16 +874,15 @@
 					"out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.vdex",
 				},
 				baseImages: []string{
-					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
-					"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.art",
+					"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art",
 				},
 				baseImagesDeps: []string{
-					"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_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",
@@ -793,16 +932,15 @@
 					"out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.vdex",
 				},
 				baseImages: []string{
-					"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
-					"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.art",
+					"out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.art",
 				},
 				baseImagesDeps: []string{
-					"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_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",
@@ -852,16 +990,15 @@
 					"out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.vdex",
 				},
 				baseImages: []string{
-					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
-					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.art",
 				},
 				baseImagesDeps: []string{
-					"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_bootjars/linux_glibc/system/framework/x86_64/boot.art",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.oat",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.vdex",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.art",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.oat",
+					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.vdex",
 					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art",
 					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat",
 					"out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex",
@@ -911,16 +1048,15 @@
 					"out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.vdex",
 				},
 				baseImages: []string{
-					"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
-					"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.art",
 				},
 				baseImagesDeps: []string{
-					"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_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",
@@ -999,8 +1135,7 @@
 	android.AssertStringEquals(t, "stem", expected.stem, imageConfig.stem)
 	android.AssertPathRelativeToTopEquals(t, "dir", expected.dir, imageConfig.dir)
 	android.AssertPathRelativeToTopEquals(t, "symbolsDir", expected.symbolsDir, imageConfig.symbolsDir)
-	android.AssertStringEquals(t, "installDirOnDevice", expected.installDirOnDevice, imageConfig.installDirOnDevice)
-	android.AssertStringEquals(t, "installDirOnHost", expected.installDirOnHost, imageConfig.installDirOnHost)
+	android.AssertStringEquals(t, "installDir", expected.installDir, imageConfig.installDir)
 	android.AssertStringEquals(t, "profileInstallPathInApex", expected.profileInstallPathInApex, imageConfig.profileInstallPathInApex)
 	android.AssertDeepEquals(t, "modules", expected.modules, imageConfig.modules)
 	android.AssertPathsRelativeToTopEquals(t, "dexPaths", expected.dexPaths, imageConfig.dexPaths.Paths())
@@ -1056,18 +1191,18 @@
 		fmt.Fprintf(out, "%s=%s\n", v.Name(), android.StringRelativeToTop(result.Config, v.Value()))
 	}
 	format := `
-DEXPREOPT_BOOTCLASSPATH_DEX_FILES=out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar out/soong/dexpreopt_arm64/dex_bootjars_input/framework.jar
+DEXPREOPT_BOOTCLASSPATH_DEX_FILES=out/soong/dexpreopt_arm64/dex_bootjars_input/core1.jar out/soong/dexpreopt_arm64/dex_bootjars_input/core2.jar out/soong/dexpreopt_arm64/dex_bootjars_input/framework.jar
 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=platform:framework
+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_boot_arm=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-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-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
-DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86_64=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art:/system/framework/x86_64/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat:/system/framework/x86_64/boot-framework.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
+DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86_64=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.art:/system/framework/x86_64/boot.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.oat:/system/framework/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.art:/system/framework/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.oat:/system/framework/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art:/system/framework/x86_64/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat:/system/framework/x86_64/boot-framework.oat
 DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_arm=out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.art:/system/framework/arm/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.oat:/system/framework/arm/boot-framework-foo.oat
 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
@@ -1076,10 +1211,10 @@
 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_boot_arm=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-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-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
-DEXPREOPT_IMAGE_DEPS_boot_host_x86_64=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.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
+DEXPREOPT_IMAGE_DEPS_boot_host_x86_64=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex
 DEXPREOPT_IMAGE_DEPS_mainline_arm=out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.oat out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.vdex
 DEXPREOPT_IMAGE_DEPS_mainline_arm64=out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.oat out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.vdex
 DEXPREOPT_IMAGE_DEPS_mainline_host_x86=out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.oat out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.vdex
@@ -1096,12 +1231,12 @@
 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_LOCATIONS_ON_DEVICEart=/system/framework/boot.art
-DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEboot=/system/framework/boot.art:/system/framework/boot-framework.art
-DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEmainline=/system/framework/boot.art:/system/framework/boot-framework.art:/system/framework/boot-framework-foo.art
+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
 DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTart=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/boot.art
-DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTboot=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/boot.art:out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot-framework.art
-DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTmainline=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/boot.art:out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot-framework.art:out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/boot-framework-foo.art
+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/dexpreopt_arm64/dex_bootjars/boot.prof:/system/etc/boot-image.prof
 DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
@@ -1109,10 +1244,10 @@
 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_UNSTRIPPED_BUILT_INSTALLED_boot_arm=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-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-framework.oat:/system/framework/x86/boot-framework.oat
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86_64=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot-framework.oat:/system/framework/x86_64/boot-framework.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
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86_64=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot.oat:/system/framework/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot-core2.oat:/system/framework/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot-framework.oat:/system/framework/x86_64/boot-framework.oat
 DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_arm=out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped/android/system/framework/arm/boot-framework-foo.oat:/system/framework/arm/boot-framework-foo.oat
 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
@@ -1121,10 +1256,10 @@
 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_boot_arm=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-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-framework.vdex:/system/framework/x86/boot-framework.vdex
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86_64=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex:/system/framework/x86_64/boot-framework.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
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86_64=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.vdex:/system/framework/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-core2.vdex:/system/framework/x86_64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex:/system/framework/x86_64/boot-framework.vdex
 DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_mainline_arm=out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.vdex:/system/framework/arm/boot-framework-foo.vdex
 DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_mainline_arm64=out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.vdex:/system/framework/arm64/boot-framework-foo.vdex
 DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_mainline_host_x86=out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.vdex:/system/framework/x86/boot-framework-foo.vdex
@@ -1136,10 +1271,10 @@
 DEXPREOPT_IMAGE_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art
 DEXPREOPT_IMAGE_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art
 DEXPREOPT_IMAGE_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art
-DEXPREOPT_IMAGE_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.art
-DEXPREOPT_IMAGE_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.art
-DEXPREOPT_IMAGE_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art
-DEXPREOPT_IMAGE_boot_host_x86_64=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art
+DEXPREOPT_IMAGE_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.art
+DEXPREOPT_IMAGE_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art
+DEXPREOPT_IMAGE_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.art
+DEXPREOPT_IMAGE_boot_host_x86_64=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86_64/boot.art
 DEXPREOPT_IMAGE_mainline_arm=out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.art
 DEXPREOPT_IMAGE_mainline_arm64=out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art
 DEXPREOPT_IMAGE_mainline_host_x86=out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index f91ac5c..fedd564 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -212,7 +212,7 @@
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
 			preparers := android.GroupFixturePreparers(
-				PrepareForTestWithJavaDefaultModules,
+				PrepareForTestWithDexpreopt,
 				PrepareForTestWithFakeApexMutator,
 				dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"),
 			)
@@ -257,7 +257,7 @@
 
 	preparers := android.GroupFixturePreparers(
 		cc.PrepareForTestWithCcDefaultModules,
-		PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd,
+		PrepareForTestWithDexpreoptWithoutFakeDex2oatd,
 		dexpreopt.PrepareForTestByEnablingDexpreopt)
 
 	testDex2oatToolDep := func(sourceEnabled, prebuiltEnabled, prebuiltPreferred bool,
@@ -299,7 +299,7 @@
 
 func TestDexpreoptBuiltInstalledForApex(t *testing.T) {
 	preparers := android.GroupFixturePreparers(
-		PrepareForTestWithJavaDefaultModules,
+		PrepareForTestWithDexpreopt,
 		PrepareForTestWithFakeApexMutator,
 		dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"),
 	)
@@ -386,7 +386,7 @@
 
 func TestAndroidMkEntriesForApex(t *testing.T) {
 	preparers := android.GroupFixturePreparers(
-		PrepareForTestWithJavaDefaultModules,
+		PrepareForTestWithDexpreopt,
 		PrepareForTestWithFakeApexMutator,
 		dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"),
 	)
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 75b7bb7..ef792f9 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -39,7 +39,9 @@
 `)
 
 var hiddenApiFixtureFactory = android.GroupFixturePreparers(
-	prepareForJavaTest, PrepareForTestWithHiddenApiBuildComponents)
+	PrepareForTestWithJavaDefaultModules,
+	PrepareForTestWithHiddenApiBuildComponents,
+)
 
 func TestHiddenAPISingleton(t *testing.T) {
 	result := android.GroupFixturePreparers(
diff --git a/java/java_test.go b/java/java_test.go
index 553b762..2a4913e 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -46,12 +46,11 @@
 	// Get the CC build components but not default modules.
 	cc.PrepareForTestWithCcBuildComponents,
 	// Include all the default java modules.
-	PrepareForTestWithJavaDefaultModules,
+	PrepareForTestWithDexpreopt,
 	PrepareForTestWithOverlayBuildComponents,
 	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
 		ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
 	}),
-	PrepareForTestWithDexpreopt,
 )
 
 func TestMain(m *testing.M) {
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index d5779f7..07fb92c 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -129,8 +129,7 @@
 
 	// 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.
-	bootImageConfig := defaultBootImageConfig(ctx)
-	addDependenciesOntoBootImageModules(ctx, bootImageConfig.modules, platformBootclasspathBootJarDepTag)
+	addDependenciesOntoBootImageModules(ctx, b.platformJars(ctx), platformBootclasspathBootJarDepTag)
 
 	// Add dependencies on all the apex jars.
 	apexJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
@@ -187,7 +186,8 @@
 	bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
 	buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule)
 
-	b.generateBootImageBuildActions(ctx, platformModules, apexModules)
+	b.generateBootImageBuildActions(ctx)
+	b.copyApexBootJarsForAppsDexpreopt(ctx, apexModules)
 }
 
 // Generate classpaths.proto config
@@ -200,7 +200,7 @@
 
 func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
 	// Include all non APEX jars
-	jars := defaultBootImageConfig(ctx).modules
+	jars := b.platformJars(ctx)
 
 	// Include jars from APEXes that don't populate their classpath proto config.
 	remainingJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
@@ -217,6 +217,10 @@
 	return jars
 }
 
+func (b *platformBootclasspathModule) platformJars(ctx android.PathContext) android.ConfiguredJarList {
+	return defaultBootImageConfig(ctx).modules.RemoveList(artBootImageConfig(ctx).modules)
+}
+
 // checkPlatformModules ensures that the non-updatable modules supplied are not part of an
 // apex module.
 func (b *platformBootclasspathModule) checkPlatformModules(ctx android.ModuleContext, modules []android.Module) {
@@ -226,7 +230,7 @@
 		fromUpdatableApex := apexInfo.Updatable
 		if fromUpdatableApex {
 			// error: this jar is part of an updatable apex
-			ctx.ModuleErrorf("module %q from updatable apexes %q is not allowed in the framework boot image", ctx.OtherModuleName(m), apexInfo.InApexVariants)
+			ctx.ModuleErrorf("module %q from updatable apexes %q is not allowed in the platform bootclasspath", ctx.OtherModuleName(m), apexInfo.InApexVariants)
 		} else {
 			// ok: this jar is part of the platform or a non-updatable apex
 		}
@@ -396,7 +400,7 @@
 }
 
 // generateBootImageBuildActions generates ninja rules related to the boot image creation.
-func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext, platformModules, apexModules []android.Module) {
+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)
@@ -408,15 +412,16 @@
 
 	frameworkBootImageConfig := defaultBootImageConfig(ctx)
 	bootFrameworkProfileRule(ctx, frameworkBootImageConfig)
-	b.generateBootImage(ctx, frameworkBootImageName, platformModules)
-	b.generateBootImage(ctx, mainlineBootImageName, apexModules)
-	b.copyApexBootJarsForAppsDexpreopt(ctx, apexModules)
+	b.generateBootImage(ctx, frameworkBootImageName)
+	b.generateBootImage(ctx, mainlineBootImageName)
 	dumpOatRules(ctx, frameworkBootImageConfig)
 }
 
-func (b *platformBootclasspathModule) generateBootImage(ctx android.ModuleContext, imageName string, modules []android.Module) {
+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)
@@ -446,3 +451,26 @@
 	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/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index 10c9187..ff2da4b 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -18,14 +18,12 @@
 	"testing"
 
 	"android/soong/android"
-	"android/soong/dexpreopt"
 )
 
 // Contains some simple tests for platform_bootclasspath.
 
 var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers(
 	PrepareForTestWithJavaDefaultModules,
-	dexpreopt.PrepareForTestByEnablingDexpreopt,
 )
 
 func TestPlatformBootclasspath(t *testing.T) {
diff --git a/java/testing.go b/java/testing.go
index f68e12f..6671bf0 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -80,9 +80,7 @@
 	}.AddToFixture(),
 )
 
-// Test fixture preparer that will define all default java modules except the
-// fake_tool_binary for dex2oatd.
-var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixturePreparers(
+var prepareForTestWithJavaDefaultModulesBase = android.GroupFixturePreparers(
 	// Make sure that all the module types used in the defaults are registered.
 	PrepareForTestWithJavaBuildComponents,
 	prepareForTestWithFrameworkDeps,
@@ -92,13 +90,21 @@
 
 // Test fixture preparer that will define default java modules, e.g. standard prebuilt modules.
 var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers(
-	PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd,
-	dexpreopt.PrepareForTestWithFakeDex2oatd,
+	prepareForTestWithJavaDefaultModulesBase,
+	dexpreopt.FixtureDisableDexpreoptBootImages(true),
+	dexpreopt.FixtureDisableDexpreopt(true),
 )
 
 // Provides everything needed by dexpreopt.
 var PrepareForTestWithDexpreopt = android.GroupFixturePreparers(
-	PrepareForTestWithJavaDefaultModules,
+	prepareForTestWithJavaDefaultModulesBase,
+	dexpreopt.PrepareForTestWithFakeDex2oatd,
+	dexpreopt.PrepareForTestByEnablingDexpreopt,
+)
+
+// Provides everything needed by dexpreopt except the fake_tool_binary for dex2oatd.
+var PrepareForTestWithDexpreoptWithoutFakeDex2oatd = android.GroupFixturePreparers(
+	prepareForTestWithJavaDefaultModulesBase,
 	dexpreopt.PrepareForTestByEnablingDexpreopt,
 )
 
@@ -604,9 +610,9 @@
 	})
 }
 
-// Sets the value of `installDirOnDevice` of the boot image config with the given name.
+// Sets the value of `installDir` of the boot image config with the given name.
 func FixtureSetBootImageInstallDirOnDevice(name string, installDir string) android.FixturePreparer {
 	return FixtureModifyBootImageConfig(name, func(config *bootImageConfig) {
-		config.installDirOnDevice = installDir
+		config.installDir = installDir
 	})
 }
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 13fa81e..96645b0 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@
 	defaultBindgenFlags = []string{""}
 
 	// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
-	bindgenClangVersion = "clang-r487747"
+	bindgenClangVersion = "clang-r487747c"
 
 	_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
 		if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
diff --git a/rust/config/global.go b/rust/config/global.go
index 2d1f0c1..748bb3d 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
 var pctx = android.NewPackageContext("android/soong/rust/config")
 
 var (
-	RustDefaultVersion = "1.68.0"
+	RustDefaultVersion = "1.69.0"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2021"
 	Stdlibs            = []string{
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 0d6496d..bef82d6 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -74,7 +74,7 @@
 func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
-		java.PrepareForTestWithJavaDefaultModules,
+		java.PrepareForTestWithDexpreopt,
 		prepareForSdkTestWithApex,
 
 		// Some additional files needed for the art apex.
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index fda5ca0..5935247 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -885,4 +885,37 @@
   fi
 }
 
+# This test verifies that adding a new glob to a blueprint file only
+# causes build.ninja to be regenerated on the *next* build, and *not*
+# the build after. (This is a regression test for a bug where globs
+# resulted in two successive regenerations.)
+function test_new_glob_incrementality {
+  setup
+
+  run_soong nothing
+  local -r mtime1=$(stat -c "%y" out/soong/build.ninja)
+
+  mkdir -p globdefpkg/
+  cat > globdefpkg/Android.bp <<'EOF'
+filegroup {
+  name: "fg_with_glob",
+  srcs: ["*.txt"],
+}
+EOF
+
+  run_soong nothing
+  local -r mtime2=$(stat -c "%y" out/soong/build.ninja)
+
+  if [[ "$mtime1" == "$mtime2" ]]; then
+    fail "Ninja file was not regenerated, despite a new bp file"
+  fi
+
+  run_soong nothing
+  local -r mtime3=$(stat -c "%y" out/soong/build.ninja)
+
+  if [[ "$mtime2" != "$mtime3" ]]; then
+    fail "Ninja file was regenerated despite no previous bp changes"
+  fi
+}
+
 scan_and_run_tests
diff --git a/ui/build/config.go b/ui/build/config.go
index 8ec9680..6b6ce71 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -316,8 +316,9 @@
 
 func NewConfig(ctx Context, args ...string) Config {
 	ret := &configImpl{
-		environ:       OsEnvironment(),
-		sandboxConfig: &SandboxConfig{},
+		environ:               OsEnvironment(),
+		sandboxConfig:         &SandboxConfig{},
+		ninjaWeightListSource: HINT_FROM_SOONG,
 	}
 
 	// Default matching ninja
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index b83b5cb..efe7478 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -150,7 +150,6 @@
 	"PRODUCT_INCLUDE_TAGS",
 	"PRODUCT_SOURCE_ROOT_DIRS",
 	"TARGET_PRODUCT",
-	"TARGET_RELEASE",
 	"TARGET_BUILD_VARIANT",
 	"TARGET_BUILD_APPS",
 	"TARGET_BUILD_UNBUNDLED",