Merge "Support arch variations for export_system_include_dirs in cc_library_headers bp2build converter."
diff --git a/Android.bp b/Android.bp
index 9d5b07d..8f7f3e2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -47,101 +47,6 @@
 //
 
 toolchain_library {
-    name: "libatomic",
-    defaults: ["linux_bionic_supported"],
-    vendor_available: true,
-    product_available: true,
-    ramdisk_available: true,
-    vendor_ramdisk_available: true,
-    recovery_available: true,
-    native_bridge_supported: true,
-
-    arch: {
-        arm: {
-            src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/arm-linux-androideabi/lib/libatomic.a",
-        },
-        arm64: {
-            src: "prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/lib64/libatomic.a",
-        },
-        x86: {
-            src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/x86_64-linux-android/lib/libatomic.a",
-        },
-        x86_64: {
-            src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/x86_64-linux-android/lib64/libatomic.a",
-        },
-    },
-}
-
-toolchain_library {
-    name: "libgcc",
-    defaults: ["linux_bionic_supported"],
-    vendor_available: true,
-    product_available: true,
-    recovery_available: true,
-    native_bridge_supported: true,
-    apex_available: [
-        "//apex_available:platform",
-        "//apex_available:anyapex",
-    ],
-
-    arch: {
-        arm: {
-            src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a",
-        },
-        arm64: {
-            src: "prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/lib/gcc/aarch64-linux-android/4.9.x/libgcc.a",
-        },
-        x86: {
-            src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/32/libgcc.a",
-        },
-        x86_64: {
-            src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/libgcc.a",
-        },
-    },
-}
-
-toolchain_library {
-    name: "libgcc_stripped",
-    defaults: ["linux_bionic_supported"],
-    vendor_available: true,
-    product_available: true,
-    ramdisk_available: true,
-    vendor_ramdisk_available: true,
-    recovery_available: true,
-    native_bridge_supported: true,
-    sdk_version: "current",
-
-    arch: {
-        arm: {
-            src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a",
-            repack_objects_to_keep: [],
-            enabled: false,
-        },
-        arm64: {
-            src: "prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/lib/gcc/aarch64-linux-android/4.9.x/libgcc.a",
-            repack_objects_to_keep: [
-                "unwind-dw2.o",
-                "unwind-dw2-fde-dip.o",
-            ],
-        },
-        x86: {
-            src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/32/libgcc.a",
-            repack_objects_to_keep: [
-                "unwind-dw2.o",
-                "unwind-dw2-fde-dip.o",
-            ],
-        },
-        x86_64: {
-            src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/libgcc.a",
-            repack_objects_to_keep: [
-                "unwind-dw2.o",
-                "unwind-dw2-fde-dip.o",
-            ],
-        },
-    },
-}
-
-toolchain_library {
     name: "libwinpthread",
     host_supported: true,
     enabled: false,
@@ -159,26 +64,6 @@
     notice: ":mingw-libwinpthread-notice",
 }
 
-toolchain_library {
-    name: "libgcov",
-    defaults: ["linux_bionic_supported"],
-
-    arch: {
-        arm: {
-            src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x/libgcov.a",
-        },
-        arm64: {
-            src: "prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/lib/gcc/aarch64-linux-android/4.9.x/libgcov.a",
-        },
-        x86: {
-            src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/32/libgcov.a",
-        },
-        x86_64: {
-            src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/libgcov.a",
-        },
-    },
-}
-
 kernel_headers {
     name: "device_kernel_headers",
     vendor: true,
diff --git a/android/arch.go b/android/arch.go
index 3eff5d5..6826f3b 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -167,7 +167,8 @@
 	return archType
 }
 
-// ArchTypeList returns the 4 supported ArchTypes for arm, arm64, x86 and x86_64.
+// ArchTypeList returns the a slice copy of the 4 supported ArchTypes for arm,
+// arm64, x86 and x86_64.
 func ArchTypeList() []ArchType {
 	return append([]ArchType(nil), archTypeList...)
 }
@@ -266,7 +267,7 @@
 
 		DefaultDisabled: defDisabled,
 	}
-	OsTypeList = append(OsTypeList, os)
+	osTypeList = append(osTypeList, os)
 
 	if _, found := commonTargetMap[name]; found {
 		panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name))
@@ -280,7 +281,7 @@
 
 // osByName returns the OsType that has the given name, or NoOsType if none match.
 func osByName(name string) OsType {
-	for _, os := range OsTypeList {
+	for _, os := range osTypeList {
 		if os.Name == name {
 			return os
 		}
@@ -312,9 +313,9 @@
 }()
 
 var (
-	// OsTypeList contains a list of all the supported OsTypes, including ones not supported
+	// osTypeList contains a list of all the supported OsTypes, including ones not supported
 	// by the current build host or the target device.
-	OsTypeList []OsType
+	osTypeList []OsType
 	// commonTargetMap maps names of OsTypes to the corresponding common Target, i.e. the
 	// Target with the same OsType and the common ArchType.
 	commonTargetMap = make(map[string]Target)
@@ -347,6 +348,11 @@
 	CommonArch = Arch{ArchType: Common}
 )
 
+// OsTypeList returns a slice copy of the supported OsTypes.
+func OsTypeList() []OsType {
+	return append([]OsType(nil), osTypeList...)
+}
+
 // Target specifies the OS and architecture that a module is being compiled for.
 type Target struct {
 	// Os the OS that the module is being compiled for (e.g. "linux_glibc", "android").
@@ -448,7 +454,7 @@
 	// Collect a list of OSTypes supported by this module based on the HostOrDevice value
 	// passed to InitAndroidArchModule and the device_supported and host_supported properties.
 	var moduleOSList []OsType
-	for _, os := range OsTypeList {
+	for _, os := range osTypeList {
 		for _, t := range mctx.Config().Targets[os] {
 			if base.supportsTarget(t) {
 				moduleOSList = append(moduleOSList, os)
@@ -838,7 +844,7 @@
 			"Arm_on_x86_64",
 			"Native_bridge",
 		}
-		for _, os := range OsTypeList {
+		for _, os := range osTypeList {
 			// Add all the OSes.
 			targets = append(targets, os.Field)
 
@@ -1742,7 +1748,7 @@
 		}
 
 		// Iterate over the supported OS types
-		for _, os := range OsTypeList {
+		for _, os := range osTypeList {
 			// e.g android, linux_bionic
 			field := os.Field
 
diff --git a/android/bazel.go b/android/bazel.go
index a08da0e..b2170be 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -174,8 +174,6 @@
 		"liblinker_debuggerd_stub",      // ruperts@, cc_library_static, depends on //system/libbase
 		"libbionic_tests_headers_posix", // ruperts@, cc_library_static
 		"libc_dns",                      // ruperts@, cc_library_static
-		"note_memtag_heap_async",        // cparsons@, cc_library_static
-		"note_memtag_heap_sync",         // cparsons@, cc_library_static
 	}
 
 	// Used for quicker lookups
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 04b70d6..5b9d3bf 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -34,13 +34,6 @@
 	"android/soong/shared"
 )
 
-type CqueryRequestType int
-
-const (
-	getAllFiles CqueryRequestType = iota
-	getAllFilesAndCcObjectFiles
-)
-
 // Map key to describe bazel cquery requests.
 type cqueryKey struct {
 	label       string
@@ -481,7 +474,7 @@
     return id_string + ">>" + %s(target)
 `
 
-	for _, requestType := range cquery.RequestTypes {
+	for requestType, _ := range requestTypeToCqueryIdEntries {
 		labelMapName := requestType.Name() + "_Labels"
 		functionName := requestType.Name() + "_Fn"
 		labelRegistrationMapSection += fmt.Sprintf(mapDeclarationFormatString,
@@ -688,7 +681,7 @@
 	// Register bazel-owned build statements (obtained from the aquery invocation).
 	for index, buildStatement := range ctx.Config().BazelContext.BuildStatementsToRegister() {
 		if len(buildStatement.Command) < 1 {
-			panic(fmt.Sprintf("unhandled build statement: %s", buildStatement))
+			panic(fmt.Sprintf("unhandled build statement: %v", buildStatement))
 		}
 		rule := NewRuleBuilder(pctx, ctx)
 		cmd := rule.Command()
diff --git a/android/prebuilt.go b/android/prebuilt.go
index ebccaa7..2fc4782 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -82,6 +82,12 @@
 }
 
 func (p *Prebuilt) Name(name string) string {
+	return PrebuiltNameFromSource(name)
+}
+
+// PrebuiltNameFromSource returns the result of prepending the "prebuilt_" prefix to the supplied
+// name.
+func PrebuiltNameFromSource(name string) string {
 	return "prebuilt_" + name
 }
 
@@ -93,22 +99,24 @@
 	return proptools.Bool(p.properties.Prefer)
 }
 
-// The below source-related functions and the srcs, src fields are based on an assumption that
-// prebuilt modules have a static source property at the moment. Currently there is only one
-// exception, android_app_import, which chooses a source file depending on the product's DPI
-// preference configs. We'll want to add native support for dynamic source cases if we end up having
-// more modules like this.
-func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
-	if p.srcsSupplier != nil {
-		srcs := p.srcsSupplier(ctx, ctx.Module())
+// SingleSourcePathFromSupplier invokes the supplied supplier for the current module in the
+// supplied context to retrieve a list of file paths, ensures that the returned list of file paths
+// contains a single value and then assumes that is a module relative file path and converts it to
+// a Path accordingly.
+//
+// Any issues, such as nil supplier or not exactly one file path will be reported as errors on the
+// supplied context and this will return nil.
+func SingleSourcePathFromSupplier(ctx ModuleContext, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) Path {
+	if srcsSupplier != nil {
+		srcs := srcsSupplier(ctx, ctx.Module())
 
 		if len(srcs) == 0 {
-			ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file")
+			ctx.PropertyErrorf(srcsPropertyName, "missing prebuilt source file")
 			return nil
 		}
 
 		if len(srcs) > 1 {
-			ctx.PropertyErrorf(p.srcsPropertyName, "multiple prebuilt source files")
+			ctx.PropertyErrorf(srcsPropertyName, "multiple prebuilt source files")
 			return nil
 		}
 
@@ -122,6 +130,15 @@
 	}
 }
 
+// The below source-related functions and the srcs, src fields are based on an assumption that
+// prebuilt modules have a static source property at the moment. Currently there is only one
+// exception, android_app_import, which chooses a source file depending on the product's DPI
+// preference configs. We'll want to add native support for dynamic source cases if we end up having
+// more modules like this.
+func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
+	return SingleSourcePathFromSupplier(ctx, p.srcsSupplier, p.srcsPropertyName)
+}
+
 func (p *Prebuilt) UsePrebuilt() bool {
 	return p.properties.UsePrebuilt
 }
@@ -213,6 +230,26 @@
 	Prebuilt() *Prebuilt
 }
 
+// IsModulePreferred returns true if the given module is preferred.
+//
+// A source module is preferred if there is no corresponding prebuilt module or the prebuilt module
+// does not have "prefer: true".
+//
+// A prebuilt module is preferred if there is no corresponding source module or the prebuilt module
+// has "prefer: true".
+func IsModulePreferred(module Module) bool {
+	if module.IsReplacedByPrebuilt() {
+		// A source module that has been replaced by a prebuilt counterpart.
+		return false
+	}
+	if prebuilt, ok := module.(PrebuiltInterface); ok {
+		if p := prebuilt.Prebuilt(); p != nil {
+			return p.UsePrebuilt()
+		}
+	}
+	return true
+}
+
 func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
 	ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).Parallel()
 }
diff --git a/apex/apex.go b/apex/apex.go
index 9d06e1c..bad382a 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1049,6 +1049,16 @@
 	if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
 		apexBundleName := mctx.ModuleName()
 		mctx.CreateVariations(apexBundleName)
+		if strings.HasPrefix(apexBundleName, "com.android.art") {
+			// Create an alias from the platform variant. This is done to make
+			// test_for dependencies work for modules that are split by the APEX
+			// mutator, since test_for dependencies always go to the platform variant.
+			// This doesn't happen for normal APEXes that are disjunct, so only do
+			// this for the overlapping ART APEXes.
+			// TODO(b/183882457): Remove this if the test_for functionality is
+			// refactored to depend on the proper APEX variants instead of platform.
+			mctx.CreateAliasVariation("", apexBundleName)
+		}
 	} else if o, ok := mctx.Module().(*OverrideApex); ok {
 		apexBundleName := o.GetOverriddenModuleName()
 		if apexBundleName == "" {
@@ -1056,6 +1066,10 @@
 			return
 		}
 		mctx.CreateVariations(apexBundleName)
+		if strings.HasPrefix(apexBundleName, "com.android.art") {
+			// TODO(b/183882457): See note for CreateAliasVariation above.
+			mctx.CreateAliasVariation("", apexBundleName)
+		}
 	}
 }
 
@@ -2925,9 +2939,7 @@
 		"com.google.android.material_material",
 		"com.google.android.material_material-nodeps",
 
-		"libatomic",
 		"libclang_rt",
-		"libgcc_stripped",
 		"libprofile-clang-extras",
 		"libprofile-clang-extras_ndk",
 		"libprofile-extras",
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e47bd1e..bdff41e 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4316,6 +4316,14 @@
 	}
 }
 
+func TestPrebuiltMissingSrc(t *testing.T) {
+	testApexError(t, `module "myapex" variant "android_common".*: prebuilt_apex does not support "arm64_armv8-a"`, `
+		prebuilt_apex {
+			name: "myapex",
+		}
+	`)
+}
+
 func TestPrebuiltFilenameOverride(t *testing.T) {
 	ctx := testApex(t, `
 		prebuilt_apex {
@@ -6947,6 +6955,56 @@
 	ensureLinkedLibIs("myprivlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
 }
 
+func TestTestForForLibInOtherApex(t *testing.T) {
+	// This case is only allowed for known overlapping APEXes, i.e. the ART APEXes.
+	_ = testApex(t, `
+		apex {
+			name: "com.android.art",
+			key: "myapex.key",
+			native_shared_libs: ["mylib"],
+			updatable: false,
+		}
+
+		apex {
+			name: "com.android.art.debug",
+			key: "myapex.key",
+			native_shared_libs: ["mylib", "mytestlib"],
+			updatable: false,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			stubs: {
+				versions: ["1"],
+			},
+			apex_available: ["com.android.art", "com.android.art.debug"],
+		}
+
+		cc_library {
+			name: "mytestlib",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			shared_libs: ["mylib"],
+			stl: "none",
+			apex_available: ["com.android.art.debug"],
+			test_for: ["com.android.art"],
+		}
+	`,
+		android.MockFS{
+			"system/sepolicy/apex/com.android.art-file_contexts":       nil,
+			"system/sepolicy/apex/com.android.art.debug-file_contexts": nil,
+		}.AddToFixture())
+}
+
 // TODO(jungjw): Move this to proptools
 func intPtr(i int) *int {
 	return &i
diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go
index 574166a..aa0d9c4 100644
--- a/apex/boot_image_test.go
+++ b/apex/boot_image_test.go
@@ -305,6 +305,7 @@
 	`)
 
 	java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common", []string{
+		`com.android.art.apex.selector`,
 		`prebuilt_bar`,
 		`prebuilt_foo`,
 	})
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 46ce41f..1db13f9 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -49,35 +49,31 @@
 	Exported_java_libs []string
 }
 
+type SelectedApexProperties struct {
+	// The path to the apex selected for use by this module.
+	//
+	// Is tagged as `android:"path"` because it will usually contain a string of the form ":<module>"
+	// and is tagged as "`blueprint:"mutate"` because it is only initialized in a LoadHook not an
+	// Android.bp file.
+	Selected_apex *string `android:"path" blueprint:"mutated"`
+}
+
 type Deapexer struct {
 	android.ModuleBase
-	prebuilt android.Prebuilt
 
-	properties         DeapexerProperties
-	apexFileProperties ApexFileProperties
+	properties             DeapexerProperties
+	selectedApexProperties SelectedApexProperties
 
 	inputApex android.Path
 }
 
 func privateDeapexerFactory() android.Module {
 	module := &Deapexer{}
-	module.AddProperties(
-		&module.properties,
-		&module.apexFileProperties,
-	)
-	android.InitPrebuiltModuleWithSrcSupplier(module, module.apexFileProperties.prebuiltApexSelector, "src")
+	module.AddProperties(&module.properties, &module.selectedApexProperties)
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	return module
 }
 
-func (p *Deapexer) Prebuilt() *android.Prebuilt {
-	return &p.prebuilt
-}
-
-func (p *Deapexer) Name() string {
-	return p.prebuilt.Name(p.ModuleBase.Name())
-}
-
 func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) {
 	// Add dependencies from the java modules to which this exports files from the `.apex` file onto
 	// this module so that they can access the `DeapexerInfo` object that this provides.
@@ -88,7 +84,7 @@
 }
 
 func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	p.inputApex = p.Prebuilt().SingleSourcePath(ctx)
+	p.inputApex = android.OptionalPathForModuleSrc(ctx, p.selectedApexProperties.Selected_apex).Path()
 
 	// Create and remember the directory into which the .apex file's contents will be unpacked.
 	deapexerOutput := android.PathForModuleOut(ctx, "deapexer")
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 3280cd8..9d84281 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -91,11 +91,40 @@
 	return false
 }
 
+// prebuiltApexSelectorModule is a private module type that is only created by the prebuilt_apex
+// module. It selects the apex to use and makes it available for use by prebuilt_apex and the
+// deapexer.
+type prebuiltApexSelectorModule struct {
+	android.ModuleBase
+
+	apexFileProperties ApexFileProperties
+
+	inputApex android.Path
+}
+
+func privateApexSelectorModuleFactory() android.Module {
+	module := &prebuiltApexSelectorModule{}
+	module.AddProperties(
+		&module.apexFileProperties,
+	)
+	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	return module
+}
+
+func (p *prebuiltApexSelectorModule) Srcs() android.Paths {
+	return android.Paths{p.inputApex}
+}
+
+func (p *prebuiltApexSelectorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	p.inputApex = android.SingleSourcePathFromSupplier(ctx, p.apexFileProperties.prebuiltApexSelector, "src")
+}
+
 type Prebuilt struct {
 	android.ModuleBase
 	prebuiltCommon
 
-	properties PrebuiltProperties
+	properties             PrebuiltProperties
+	selectedApexProperties SelectedApexProperties
 
 	inputApex       android.Path
 	installDir      android.InstallPath
@@ -113,19 +142,19 @@
 	// This cannot be marked as `android:"arch_variant"` because the `prebuilt_apex` is only mutated
 	// for android_common. That is so that it will have the same arch variant as, and so be compatible
 	// with, the source `apex` module type that it replaces.
-	Src  *string
+	Src  *string `android:"path"`
 	Arch struct {
 		Arm struct {
-			Src *string
+			Src *string `android:"path"`
 		}
 		Arm64 struct {
-			Src *string
+			Src *string `android:"path"`
 		}
 		X86 struct {
-			Src *string
+			Src *string `android:"path"`
 		}
 		X86_64 struct {
-			Src *string
+			Src *string `android:"path"`
 		}
 	}
 }
@@ -152,14 +181,17 @@
 		src = String(p.Arch.X86.Src)
 	case android.X86_64:
 		src = String(p.Arch.X86_64.Src)
-	default:
-		ctx.OtherModuleErrorf(prebuilt, "prebuilt_apex does not support %q", multiTargets[0].Arch.String())
-		return nil
 	}
 	if src == "" {
 		src = String(p.Src)
 	}
 
+	if src == "" {
+		ctx.OtherModuleErrorf(prebuilt, "prebuilt_apex does not support %q", multiTargets[0].Arch.String())
+		// Drop through to return an empty string as the src (instead of nil) to avoid the prebuilt
+		// logic from reporting a more general, less useful message.
+	}
+
 	return []string{src}
 }
 
@@ -221,28 +253,77 @@
 // 3. The `deapexer` module adds a dependency from the modules that require the exported files onto
 //    itself so that they can retrieve the file paths to those files.
 //
+// It also creates a child module `selector` that is responsible for selecting the appropriate
+// input apex for both the prebuilt_apex and the deapexer. That is needed for a couple of reasons:
+// 1. To dedup the selection logic so it only runs in one module.
+// 2. To allow the deapexer to be wired up to a different source for the input apex, e.g. an
+//    `apex_set`.
+//
+//                     prebuilt_apex
+//                    /      |      \
+//                 /         |         \
+//              V            |            V
+//       selector  <---  deapexer  <---  exported java lib
+//
 func PrebuiltFactory() android.Module {
 	module := &Prebuilt{}
-	module.AddProperties(&module.properties)
-	android.InitPrebuiltModuleWithSrcSupplier(module, module.properties.prebuiltApexSelector, "src")
+	module.AddProperties(&module.properties, &module.selectedApexProperties)
+	android.InitSingleSourcePrebuiltModule(module, &module.selectedApexProperties, "Selected_apex")
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 
 	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
-		props := struct {
-			Name *string
-		}{
-			Name: proptools.StringPtr(module.BaseModuleName() + ".deapexer"),
+		baseModuleName := module.BaseModuleName()
+
+		apexSelectorModuleName := apexSelectorModuleName(baseModuleName)
+		createApexSelectorModule(ctx, apexSelectorModuleName, &module.properties.ApexFileProperties)
+
+		apexFileSource := ":" + apexSelectorModuleName
+		if len(module.properties.Exported_java_libs) != 0 {
+			createDeapexerModule(ctx, deapexerModuleName(baseModuleName), apexFileSource, &module.properties.DeapexerProperties)
 		}
-		ctx.CreateModule(privateDeapexerFactory,
-			&props,
-			&module.properties.ApexFileProperties,
-			&module.properties.DeapexerProperties,
-		)
+
+		// Add a source reference to retrieve the selected apex from the selector module.
+		module.selectedApexProperties.Selected_apex = proptools.StringPtr(apexFileSource)
 	})
 
 	return module
 }
 
+func createApexSelectorModule(ctx android.LoadHookContext, name string, apexFileProperties *ApexFileProperties) {
+	props := struct {
+		Name *string
+	}{
+		Name: proptools.StringPtr(name),
+	}
+
+	ctx.CreateModule(privateApexSelectorModuleFactory,
+		&props,
+		apexFileProperties,
+	)
+}
+
+func createDeapexerModule(ctx android.LoadHookContext, deapexerName string, apexFileSource string, deapexerProperties *DeapexerProperties) {
+	props := struct {
+		Name          *string
+		Selected_apex *string
+	}{
+		Name:          proptools.StringPtr(deapexerName),
+		Selected_apex: proptools.StringPtr(apexFileSource),
+	}
+	ctx.CreateModule(privateDeapexerFactory,
+		&props,
+		deapexerProperties,
+	)
+}
+
+func deapexerModuleName(baseModuleName string) string {
+	return baseModuleName + ".deapexer"
+}
+
+func apexSelectorModuleName(baseModuleName string) string {
+	return baseModuleName + ".apex.selector"
+}
+
 func prebuiltApexExportedModuleName(ctx android.BottomUpMutatorContext, name string) string {
 	// The prebuilt_apex should be depending on prebuilt modules but as this runs after
 	// prebuilt_rename the prebuilt module may or may not be using the prebuilt_ prefixed named. So,
@@ -250,7 +331,7 @@
 	// the unprefixed name is the one to use. If the unprefixed one turns out to be a source module
 	// and not a renamed prebuilt module then that will be detected and reported as an error when
 	// processing the dependency in ApexInfoMutator().
-	prebuiltName := "prebuilt_" + name
+	prebuiltName := android.PrebuiltNameFromSource(name)
 	if ctx.OtherModuleExists(prebuiltName) {
 		name = prebuiltName
 	}
@@ -375,7 +456,7 @@
 
 func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	// TODO(jungjw): Check the key validity.
-	p.inputApex = p.Prebuilt().SingleSourcePath(ctx)
+	p.inputApex = android.OptionalPathForModuleSrc(ctx, p.selectedApexProperties.Selected_apex).Path()
 	p.installDir = android.PathForModuleInstall(ctx, "apex")
 	p.installFilename = p.InstallFilename()
 	if !strings.HasSuffix(p.installFilename, imageApexSuffix) {
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index bd1ece1..affb5ce 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -14,11 +14,6 @@
 	CcObjectFiles []string
 }
 
-var RequestTypes []RequestType = []RequestType{
-	GetOutputFiles,
-	GetOutputFilesAndCcObjectFiles,
-}
-
 type RequestType interface {
 	// Name returns a string name for this request type. Such request type names must be unique,
 	// and must only consist of alphanumeric characters.
@@ -83,7 +78,17 @@
 	splitString := strings.Split(rawString, "|")
 	outputFilesString := splitString[0]
 	ccObjectsString := splitString[1]
-	outputFiles = strings.Split(outputFilesString, ", ")
-	ccObjects = strings.Split(ccObjectsString, ", ")
+	outputFiles = splitOrEmpty(outputFilesString, ", ")
+	ccObjects = splitOrEmpty(ccObjectsString, ", ")
 	return GetOutputFilesAndCcObjectFiles_Result{outputFiles, ccObjects}
 }
+
+// splitOrEmpty is a modification of strings.Split() that returns an empty list
+// if the given string is empty.
+func splitOrEmpty(s string, sep string) []string {
+	if len(s) < 1 {
+		return []string{}
+	} else {
+		return strings.Split(s, sep)
+	}
+}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 9d91ffa..74226ae 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -37,17 +37,6 @@
 	recovery_available: true,
 	native_bridge_supported: true,
 	src: "",
-}
-
-toolchain_library {
-	name: "libatomic",
-	defaults: ["linux_bionic_supported"],
-	vendor_available: true,
-	vendor_ramdisk_available: true,
-	product_available: true,
-	recovery_available: true,
-	native_bridge_supported: true,
-	src: "",
 }`
 )
 
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 7bf5fd3..467b0b2 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -37,17 +37,6 @@
 	recovery_available: true,
 	native_bridge_supported: true,
 	src: "",
-}
-
-toolchain_library {
-	name: "libatomic",
-	defaults: ["linux_bionic_supported"],
-	vendor_available: true,
-	vendor_ramdisk_available: true,
-	product_available: true,
-	recovery_available: true,
-	native_bridge_supported: true,
-	src: "",
 }`
 )
 
diff --git a/cc/cc.go b/cc/cc.go
index 0f9a556..1ce83a9 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1646,12 +1646,12 @@
 		c.hideApexVariantFromMake = true
 	}
 
+	c.makeLinkType = GetMakeLinkType(actx, c)
+
 	if c.maybeGenerateBazelActions(actx) {
 		return
 	}
 
-	c.makeLinkType = GetMakeLinkType(actx, c)
-
 	ctx := &moduleContext{
 		ModuleContext: actx,
 		moduleContextImpl: moduleContextImpl{
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 235232e..465283d 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2912,13 +2912,13 @@
 	// Check the shared version of lib2.
 	variant := "android_arm64_armv8-a_shared"
 	module := ctx.ModuleForTests("lib2", variant).Module().(*Module)
-	checkStaticLibs(t, []string{"lib1", "libc++demangle", "libclang_rt.builtins-aarch64-android", "libatomic"}, module)
+	checkStaticLibs(t, []string{"lib1", "libc++demangle", "libclang_rt.builtins-aarch64-android"}, module)
 
 	// Check the static version of lib2.
 	variant = "android_arm64_armv8-a_static"
 	module = ctx.ModuleForTests("lib2", variant).Module().(*Module)
 	// libc++_static is linked additionally.
-	checkStaticLibs(t, []string{"lib1", "libc++_static", "libc++demangle", "libclang_rt.builtins-aarch64-android", "libatomic"}, module)
+	checkStaticLibs(t, []string{"lib1", "libc++_static", "libc++demangle", "libclang_rt.builtins-aarch64-android"}, module)
 }
 
 var compilerFlagsTestCases = []struct {
diff --git a/cc/library.go b/cc/library.go
index 97c7ba1..b49f1e5 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -425,11 +425,14 @@
 	if !ok {
 		return ok
 	}
-	if len(outputPaths) != 1 {
+	if len(outputPaths) > 1 {
 		// TODO(cparsons): This is actually expected behavior for static libraries with no srcs.
 		// We should support this.
-		ctx.ModuleErrorf("expected exactly one output file for '%s', but got %s", label, objPaths)
+		ctx.ModuleErrorf("expected at most one output file for '%s', but got %s", label, objPaths)
 		return false
+	} else if len(outputPaths) == 0 {
+		handler.module.outputFile = android.OptionalPath{}
+		return true
 	}
 	outputFilePath := android.PathForBazelOut(ctx, outputPaths[0])
 	handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
@@ -453,7 +456,15 @@
 			Direct(outputFilePath).
 			Build(),
 	})
-	handler.module.outputFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, objPaths[0]))
+	if i, ok := handler.module.linker.(snapshotLibraryInterface); ok {
+		// Dependencies on this library will expect collectedSnapshotHeaders to
+		// be set, otherwise validation will fail. For now, set this to an empty
+		// list.
+		// TODO(cparsons): More closely mirror the collectHeadersForSnapshot
+		// implementation.
+		i.(*libraryDecorator).collectedSnapshotHeaders = android.Paths{}
+	}
+
 	return ok
 }
 
diff --git a/cc/linker.go b/cc/linker.go
index 21281d2..ae33356 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -321,10 +321,9 @@
 	}
 
 	if ctx.toolchain().Bionic() {
-		// libclang_rt.builtins and libatomic have to be last on the command line
+		// libclang_rt.builtins has to be last on the command line
 		if !Bool(linker.Properties.No_libcrt) {
 			deps.LateStaticLibs = append(deps.LateStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
-			deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
 		}
 
 		deps.SystemSharedLibs = linker.Properties.System_shared_libs
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index bbb8896..af05102 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -337,7 +337,8 @@
 		for _, name := range names {
 			snapshotMap[name] = name +
 				getSnapshotNameSuffix(snapshotSuffix+moduleSuffix,
-					s.baseSnapshot.version(), ctx.Arch().ArchType.Name)
+					s.baseSnapshot.version(),
+					ctx.DeviceConfig().Arches()[0].ArchType.String())
 		}
 		return snapshotMap
 	}
@@ -396,7 +397,7 @@
 	Target_arch string
 
 	// Suffix to be added to the module name when exporting to Android.mk, e.g. ".vendor".
-	Androidmk_suffix string
+	Androidmk_suffix string `blueprint:"mutated"`
 
 	// Suffix to be added to the module name, e.g., vendor_shared,
 	// recovery_shared, etc.
@@ -417,6 +418,7 @@
 // will be seen as "libbase.vendor_static.30.arm64" by Soong.
 type baseSnapshotDecorator struct {
 	baseProperties baseSnapshotDecoratorProperties
+	image          snapshotImage
 }
 
 func (p *baseSnapshotDecorator) Name(name string) string {
@@ -447,10 +449,21 @@
 	return p.baseProperties.Androidmk_suffix
 }
 
+func (p *baseSnapshotDecorator) setSnapshotAndroidMkSuffix(ctx android.ModuleContext) {
+	if ctx.OtherModuleDependencyVariantExists([]blueprint.Variation{
+		{Mutator: "image", Variation: android.CoreVariation},
+	}, ctx.Module().(*Module).BaseModuleName()) {
+		p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
+	} else {
+		p.baseProperties.Androidmk_suffix = ""
+	}
+}
+
 // Call this with a module suffix after creating a snapshot module, such as
 // vendorSnapshotSharedSuffix, recoverySnapshotBinarySuffix, etc.
-func (p *baseSnapshotDecorator) init(m *Module, snapshotSuffix, moduleSuffix string) {
-	p.baseProperties.ModuleSuffix = snapshotSuffix + moduleSuffix
+func (p *baseSnapshotDecorator) init(m *Module, image snapshotImage, moduleSuffix string) {
+	p.image = image
+	p.baseProperties.ModuleSuffix = image.moduleNameSuffix() + moduleSuffix
 	m.AddProperties(&p.baseProperties)
 	android.AddLoadHook(m, func(ctx android.LoadHookContext) {
 		vendorSnapshotLoadHook(ctx, p)
@@ -532,6 +545,8 @@
 // As snapshots are prebuilts, this just returns the prebuilt binary after doing things which are
 // done by normal library decorator, e.g. exporting flags.
 func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
+	p.setSnapshotAndroidMkSuffix(ctx)
+
 	if p.header() {
 		return p.libraryDecorator.link(ctx, flags, deps, objs)
 	}
@@ -614,7 +629,7 @@
 	}
 }
 
-func snapshotLibraryFactory(snapshotSuffix, moduleSuffix string) (*Module, *snapshotLibraryDecorator) {
+func snapshotLibraryFactory(image snapshotImage, moduleSuffix string) (*Module, *snapshotLibraryDecorator) {
 	module, library := NewLibrary(android.DeviceSupported)
 
 	module.stl = nil
@@ -637,7 +652,7 @@
 	module.linker = prebuilt
 	module.installer = prebuilt
 
-	prebuilt.init(module, snapshotSuffix, moduleSuffix)
+	prebuilt.init(module, image, moduleSuffix)
 	module.AddProperties(
 		&prebuilt.properties,
 		&prebuilt.sanitizerProperties,
@@ -651,7 +666,7 @@
 // overrides the vendor variant of the cc shared library with the same name, if BOARD_VNDK_VERSION
 // is set.
 func VendorSnapshotSharedFactory() android.Module {
-	module, prebuilt := snapshotLibraryFactory(vendorSnapshotImageSingleton.moduleNameSuffix(), snapshotSharedSuffix)
+	module, prebuilt := snapshotLibraryFactory(vendorSnapshotImageSingleton, snapshotSharedSuffix)
 	prebuilt.libraryDecorator.BuildOnlyShared()
 	return module.Init()
 }
@@ -661,7 +676,7 @@
 // overrides the recovery variant of the cc shared library with the same name, if BOARD_VNDK_VERSION
 // is set.
 func RecoverySnapshotSharedFactory() android.Module {
-	module, prebuilt := snapshotLibraryFactory(recoverySnapshotImageSingleton.moduleNameSuffix(), snapshotSharedSuffix)
+	module, prebuilt := snapshotLibraryFactory(recoverySnapshotImageSingleton, snapshotSharedSuffix)
 	prebuilt.libraryDecorator.BuildOnlyShared()
 	return module.Init()
 }
@@ -671,7 +686,7 @@
 // overrides the vendor variant of the cc static library with the same name, if BOARD_VNDK_VERSION
 // is set.
 func VendorSnapshotStaticFactory() android.Module {
-	module, prebuilt := snapshotLibraryFactory(vendorSnapshotImageSingleton.moduleNameSuffix(), snapshotStaticSuffix)
+	module, prebuilt := snapshotLibraryFactory(vendorSnapshotImageSingleton, snapshotStaticSuffix)
 	prebuilt.libraryDecorator.BuildOnlyStatic()
 	return module.Init()
 }
@@ -681,7 +696,7 @@
 // overrides the recovery variant of the cc static library with the same name, if BOARD_VNDK_VERSION
 // is set.
 func RecoverySnapshotStaticFactory() android.Module {
-	module, prebuilt := snapshotLibraryFactory(recoverySnapshotImageSingleton.moduleNameSuffix(), snapshotStaticSuffix)
+	module, prebuilt := snapshotLibraryFactory(recoverySnapshotImageSingleton, snapshotStaticSuffix)
 	prebuilt.libraryDecorator.BuildOnlyStatic()
 	return module.Init()
 }
@@ -691,7 +706,7 @@
 // overrides the vendor variant of the cc header library with the same name, if BOARD_VNDK_VERSION
 // is set.
 func VendorSnapshotHeaderFactory() android.Module {
-	module, prebuilt := snapshotLibraryFactory(vendorSnapshotImageSingleton.moduleNameSuffix(), snapshotHeaderSuffix)
+	module, prebuilt := snapshotLibraryFactory(vendorSnapshotImageSingleton, snapshotHeaderSuffix)
 	prebuilt.libraryDecorator.HeaderOnly()
 	return module.Init()
 }
@@ -701,7 +716,7 @@
 // overrides the recovery variant of the cc header library with the same name, if BOARD_VNDK_VERSION
 // is set.
 func RecoverySnapshotHeaderFactory() android.Module {
-	module, prebuilt := snapshotLibraryFactory(recoverySnapshotImageSingleton.moduleNameSuffix(), snapshotHeaderSuffix)
+	module, prebuilt := snapshotLibraryFactory(recoverySnapshotImageSingleton, snapshotHeaderSuffix)
 	prebuilt.libraryDecorator.HeaderOnly()
 	return module.Init()
 }
@@ -739,6 +754,8 @@
 // cc modules' link functions are to link compiled objects into final binaries.
 // As snapshots are prebuilts, this just returns the prebuilt binary
 func (p *snapshotBinaryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
+	p.setSnapshotAndroidMkSuffix(ctx)
+
 	if !p.matchesWithDevice(ctx.DeviceConfig()) {
 		return nil
 	}
@@ -767,17 +784,17 @@
 // development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_binary
 // overrides the vendor variant of the cc binary with the same name, if BOARD_VNDK_VERSION is set.
 func VendorSnapshotBinaryFactory() android.Module {
-	return snapshotBinaryFactory(vendorSnapshotImageSingleton.moduleNameSuffix(), snapshotBinarySuffix)
+	return snapshotBinaryFactory(vendorSnapshotImageSingleton, snapshotBinarySuffix)
 }
 
 // recovery_snapshot_binary is a special prebuilt executable binary which is auto-generated by
 // development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_binary
 // overrides the recovery variant of the cc binary with the same name, if BOARD_VNDK_VERSION is set.
 func RecoverySnapshotBinaryFactory() android.Module {
-	return snapshotBinaryFactory(recoverySnapshotImageSingleton.moduleNameSuffix(), snapshotBinarySuffix)
+	return snapshotBinaryFactory(recoverySnapshotImageSingleton, snapshotBinarySuffix)
 }
 
-func snapshotBinaryFactory(snapshotSuffix, moduleSuffix string) android.Module {
+func snapshotBinaryFactory(image snapshotImage, moduleSuffix string) android.Module {
 	module, binary := NewBinary(android.DeviceSupported)
 	binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
 	binary.baseLinker.Properties.Nocrt = BoolPtr(true)
@@ -796,7 +813,7 @@
 	module.stl = nil
 	module.linker = prebuilt
 
-	prebuilt.init(module, snapshotSuffix, moduleSuffix)
+	prebuilt.init(module, image, moduleSuffix)
 	module.AddProperties(&prebuilt.properties)
 	return module.Init()
 }
@@ -832,6 +849,8 @@
 // cc modules' link functions are to link compiled objects into final binaries.
 // As snapshots are prebuilts, this just returns the prebuilt binary
 func (p *snapshotObjectLinker) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
+	p.setSnapshotAndroidMkSuffix(ctx)
+
 	if !p.matchesWithDevice(ctx.DeviceConfig()) {
 		return nil
 	}
@@ -856,7 +875,7 @@
 	}
 	module.linker = prebuilt
 
-	prebuilt.init(module, vendorSnapshotImageSingleton.moduleNameSuffix(), snapshotObjectSuffix)
+	prebuilt.init(module, vendorSnapshotImageSingleton, snapshotObjectSuffix)
 	module.AddProperties(&prebuilt.properties)
 	return module.Init()
 }
@@ -874,7 +893,7 @@
 	}
 	module.linker = prebuilt
 
-	prebuilt.init(module, recoverySnapshotImageSingleton.moduleNameSuffix(), snapshotObjectSuffix)
+	prebuilt.init(module, recoverySnapshotImageSingleton, snapshotObjectSuffix)
 	module.AddProperties(&prebuilt.properties)
 	return module.Init()
 }
diff --git a/cc/testing.go b/cc/testing.go
index 6e35655..ff32bff 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -63,17 +63,6 @@
 func commonDefaultModules() string {
 	return `
 		toolchain_library {
-			name: "libatomic",
-			defaults: ["linux_bionic_supported"],
-			vendor_available: true,
-			vendor_ramdisk_available: true,
-			product_available: true,
-			recovery_available: true,
-			native_bridge_supported: true,
-			src: "",
-		}
-
-		toolchain_library {
 			name: "libcompiler_rt-extras",
 			vendor_available: true,
 			vendor_ramdisk_available: true,
@@ -200,29 +189,6 @@
 			srcs: [""],
 		}
 
-		toolchain_library {
-			name: "libgcc",
-			defaults: ["linux_bionic_supported"],
-			vendor_available: true,
-			product_available: true,
-			recovery_available: true,
-			src: "",
-			apex_available: [
-				"//apex_available:platform",
-				"//apex_available:anyapex",
-			],
-		}
-
-		toolchain_library {
-			name: "libgcc_stripped",
-			defaults: ["linux_bionic_supported"],
-			vendor_available: true,
-			product_available: true,
-			recovery_available: true,
-			sdk_version: "current",
-			src: "",
-		}
-
 		cc_library {
 			name: "libc",
 			defaults: ["linux_bionic_supported"],
@@ -398,16 +364,6 @@
 				"//apex_available:anyapex",
 			],
 		}
-		cc_library {
-			name: "libunwind_llvm",
-			no_libcrt: true,
-			nocrt: true,
-			system_shared_libs: [],
-			stl: "none",
-			vendor_available: true,
-			product_available: true,
-			recovery_available: true,
-		}
 
 		cc_defaults {
 			name: "crt_defaults",
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 4014fe0..3d31be4 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -238,7 +238,6 @@
 type snapshotJsonFlags struct {
 	ModuleName          string `json:",omitempty"`
 	RelativeInstallPath string `json:",omitempty"`
-	AndroidMkSuffix     string `json:",omitempty"`
 
 	// library flags
 	ExportedDirs       []string `json:",omitempty"`
@@ -352,7 +351,6 @@
 		} else {
 			prop.RelativeInstallPath = m.RelativeInstallPath()
 		}
-		prop.AndroidMkSuffix = m.Properties.SubName
 		prop.RuntimeLibs = m.Properties.SnapshotRuntimeLibs
 		prop.Required = m.RequiredModuleNames()
 		for _, path := range m.InitRc() {
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index 20cd031..8f77c28 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -271,7 +271,6 @@
 			enabled: true,
 		},
 		nocrt: true,
-		compile_multilib: "64",
 	}
 
 	cc_library {
@@ -281,7 +280,6 @@
 		no_libcrt: true,
 		stl: "none",
 		system_shared_libs: [],
-		compile_multilib: "64",
 	}
 
 	cc_library {
@@ -291,6 +289,25 @@
 		no_libcrt: true,
 		stl: "none",
 		system_shared_libs: [],
+	}
+
+	cc_library {
+		name: "lib32",
+		vendor: true,
+		nocrt: true,
+		no_libcrt: true,
+		stl: "none",
+		system_shared_libs: [],
+		compile_multilib: "32",
+	}
+
+	cc_library {
+		name: "lib64",
+		vendor: true,
+		nocrt: true,
+		no_libcrt: true,
+		stl: "none",
+		system_shared_libs: [],
 		compile_multilib: "64",
 	}
 
@@ -301,7 +318,16 @@
 		no_libcrt: true,
 		stl: "none",
 		system_shared_libs: [],
-		compile_multilib: "64",
+	}
+
+	cc_binary {
+		name: "bin32",
+		vendor: true,
+		nocrt: true,
+		no_libcrt: true,
+		stl: "none",
+		system_shared_libs: [],
+		compile_multilib: "32",
 	}
 `
 
@@ -320,6 +346,10 @@
 				srcs: ["libvndk.so"],
 				export_include_dirs: ["include/libvndk"],
 			},
+			arm: {
+				srcs: ["libvndk.so"],
+				export_include_dirs: ["include/libvndk"],
+			},
 		},
 	}
 
@@ -338,6 +368,28 @@
 				srcs: ["libvndk.so"],
 				export_include_dirs: ["include/libvndk"],
 			},
+			arm: {
+				srcs: ["libvndk.so"],
+				export_include_dirs: ["include/libvndk"],
+			},
+		},
+	}
+
+	// different arch snapshot which has to be ignored
+	vndk_prebuilt_shared {
+		name: "libvndk",
+		version: "28",
+		target_arch: "arm",
+		vendor_available: true,
+		product_available: true,
+		vndk: {
+			enabled: true,
+		},
+		arch: {
+			arm: {
+				srcs: ["libvndk.so"],
+				export_include_dirs: ["include/libvndk"],
+			},
 		},
 	}
 `
@@ -350,7 +402,6 @@
 		no_libcrt: true,
 		stl: "none",
 		system_shared_libs: [],
-		compile_multilib: "64",
 	}
 
 	cc_library_shared {
@@ -362,7 +413,14 @@
 		system_shared_libs: [],
 		shared_libs: ["libvndk", "libvendor_available"],
 		static_libs: ["libvendor", "libvendor_without_snapshot"],
-		compile_multilib: "64",
+		arch: {
+			arm64: {
+				shared_libs: ["lib64"],
+			},
+			arm: {
+				shared_libs: ["lib32"],
+			},
+		},
 		srcs: ["client.cpp"],
 	}
 
@@ -374,41 +432,69 @@
 		stl: "none",
 		system_shared_libs: [],
 		static_libs: ["libvndk"],
-		compile_multilib: "64",
 		srcs: ["bin.cpp"],
 	}
 
 	vendor_snapshot {
 		name: "vendor_snapshot",
-		compile_multilib: "first",
 		version: "28",
-		vndk_libs: [
-			"libvndk",
-		],
-		static_libs: [
-			"libvendor",
-			"libvendor_available",
-			"libvndk",
-		],
-		shared_libs: [
-			"libvendor",
-			"libvendor_available",
-		],
-		binaries: [
-			"bin",
-		],
+		arch: {
+			arm64: {
+				vndk_libs: [
+					"libvndk",
+				],
+				static_libs: [
+					"libvendor",
+					"libvendor_available",
+					"libvndk",
+					"lib64",
+				],
+				shared_libs: [
+					"libvendor",
+					"libvendor_available",
+					"lib64",
+				],
+				binaries: [
+					"bin",
+				],
+			},
+			arm: {
+				vndk_libs: [
+					"libvndk",
+				],
+				static_libs: [
+					"libvendor",
+					"libvendor_available",
+					"libvndk",
+					"lib32",
+				],
+				shared_libs: [
+					"libvendor",
+					"libvendor_available",
+					"lib32",
+				],
+				binaries: [
+					"bin32",
+				],
+			},
+		}
 	}
 
 	vendor_snapshot_static {
 		name: "libvndk",
 		version: "28",
 		target_arch: "arm64",
+		compile_multilib: "both",
 		vendor: true,
 		arch: {
 			arm64: {
 				src: "libvndk.a",
 				export_include_dirs: ["include/libvndk"],
 			},
+			arm: {
+				src: "libvndk.a",
+				export_include_dirs: ["include/libvndk"],
+			},
 		},
 	}
 
@@ -416,7 +502,7 @@
 		name: "libvendor",
 		version: "28",
 		target_arch: "arm64",
-		compile_multilib: "64",
+		compile_multilib: "both",
 		vendor: true,
 		shared_libs: [
 			"libvendor_without_snapshot",
@@ -428,6 +514,62 @@
 				src: "libvendor.so",
 				export_include_dirs: ["include/libvendor"],
 			},
+			arm: {
+				src: "libvendor.so",
+				export_include_dirs: ["include/libvendor"],
+			},
+		},
+	}
+
+	vendor_snapshot_static {
+		name: "lib32",
+		version: "28",
+		target_arch: "arm64",
+		compile_multilib: "32",
+		vendor: true,
+		arch: {
+			arm: {
+				src: "lib32.a",
+			},
+		},
+	}
+
+	vendor_snapshot_shared {
+		name: "lib32",
+		version: "28",
+		target_arch: "arm64",
+		compile_multilib: "32",
+		vendor: true,
+		arch: {
+			arm: {
+				src: "lib32.so",
+			},
+		},
+	}
+
+	vendor_snapshot_static {
+		name: "lib64",
+		version: "28",
+		target_arch: "arm64",
+		compile_multilib: "64",
+		vendor: true,
+		arch: {
+			arm64: {
+				src: "lib64.a",
+			},
+		},
+	}
+
+	vendor_snapshot_shared {
+		name: "lib64",
+		version: "28",
+		target_arch: "arm64",
+		compile_multilib: "64",
+		vendor: true,
+		arch: {
+			arm64: {
+				src: "lib64.so",
+			},
 		},
 	}
 
@@ -435,40 +577,53 @@
 		name: "libvendor",
 		version: "28",
 		target_arch: "arm64",
+		compile_multilib: "both",
 		vendor: true,
 		arch: {
 			arm64: {
 				src: "libvendor.a",
 				export_include_dirs: ["include/libvendor"],
 			},
+			arm: {
+				src: "libvendor.a",
+				export_include_dirs: ["include/libvendor"],
+			},
 		},
 	}
 
 	vendor_snapshot_shared {
 		name: "libvendor_available",
-		androidmk_suffix: ".vendor",
 		version: "28",
 		target_arch: "arm64",
+		compile_multilib: "both",
 		vendor: true,
 		arch: {
 			arm64: {
 				src: "libvendor_available.so",
 				export_include_dirs: ["include/libvendor"],
 			},
+			arm: {
+				src: "libvendor_available.so",
+				export_include_dirs: ["include/libvendor"],
+			},
 		},
 	}
 
 	vendor_snapshot_static {
 		name: "libvendor_available",
-		androidmk_suffix: ".vendor",
 		version: "28",
 		target_arch: "arm64",
+		compile_multilib: "both",
 		vendor: true,
 		arch: {
 			arm64: {
 				src: "libvendor_available.a",
 				export_include_dirs: ["include/libvendor"],
 			},
+			arm: {
+				src: "libvendor_available.so",
+				export_include_dirs: ["include/libvendor"],
+			},
 		},
 	}
 
@@ -476,6 +631,7 @@
 		name: "bin",
 		version: "28",
 		target_arch: "arm64",
+		compile_multilib: "64",
 		vendor: true,
 		arch: {
 			arm64: {
@@ -484,11 +640,39 @@
 		},
 	}
 
+	vendor_snapshot_binary {
+		name: "bin32",
+		version: "28",
+		target_arch: "arm64",
+		compile_multilib: "32",
+		vendor: true,
+		arch: {
+			arm: {
+				src: "bin32",
+			},
+		},
+	}
+
 	// old snapshot module which has to be ignored
 	vendor_snapshot_binary {
 		name: "bin",
 		version: "26",
 		target_arch: "arm64",
+		compile_multilib: "first",
+		vendor: true,
+		arch: {
+			arm64: {
+				src: "bin",
+			},
+		},
+	}
+
+	// different arch snapshot which has to be ignored
+	vendor_snapshot_binary {
+		name: "bin",
+		version: "28",
+		target_arch: "arm",
+		compile_multilib: "first",
 		vendor: true,
 		arch: {
 			arm64: {
@@ -504,6 +688,7 @@
 		"framework/Android.bp":         []byte(frameworkBp),
 		"vendor/Android.bp":            []byte(vendorProprietaryBp),
 		"vendor/bin":                   nil,
+		"vendor/bin32":                 nil,
 		"vendor/bin.cpp":               nil,
 		"vendor/client.cpp":            nil,
 		"vendor/include/libvndk/a.h":   nil,
@@ -511,6 +696,10 @@
 		"vendor/libvndk.a":             nil,
 		"vendor/libvendor.a":           nil,
 		"vendor/libvendor.so":          nil,
+		"vendor/lib32.a":               nil,
+		"vendor/lib32.so":              nil,
+		"vendor/lib64.a":               nil,
+		"vendor/lib64.so":              nil,
 		"vndk/Android.bp":              []byte(vndkBp),
 		"vndk/include/libvndk/a.h":     nil,
 		"vndk/libvndk.so":              nil,
@@ -531,6 +720,9 @@
 	staticVariant := "android_vendor.28_arm64_armv8-a_static"
 	binaryVariant := "android_vendor.28_arm64_armv8-a"
 
+	shared32Variant := "android_vendor.28_arm_armv7-a-neon_shared"
+	binary32Variant := "android_vendor.28_arm_armv7-a-neon"
+
 	// libclient uses libvndk.vndk.28.arm64, libvendor.vendor_static.28.arm64, libvendor_without_snapshot
 	libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"]
 	for _, includeFlags := range []string{
@@ -556,7 +748,7 @@
 	}
 
 	libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkSharedLibs
-	if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor"}; !reflect.DeepEqual(g, w) {
+	if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "lib64"}; !reflect.DeepEqual(g, w) {
 		t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g)
 	}
 
@@ -565,6 +757,11 @@
 		t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
 	}
 
+	libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs
+	if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "lib32"}; !reflect.DeepEqual(g, w) {
+		t.Errorf("wanted libclient32 AndroidMkSharedLibs %q, got %q", w, g)
+	}
+
 	// bin_without_snapshot uses libvndk.vendor_static.28.arm64
 	binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"]
 	if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivendor/include/libvndk") {
@@ -582,6 +779,12 @@
 	// libvendor.so is installed by libvendor.vendor_shared.28.arm64
 	ctx.ModuleForTests("libvendor.vendor_shared.28.arm64", sharedVariant).Output("libvendor.so")
 
+	// lib64.so is installed by lib64.vendor_shared.28.arm64
+	ctx.ModuleForTests("lib64.vendor_shared.28.arm64", sharedVariant).Output("lib64.so")
+
+	// lib32.so is installed by lib32.vendor_shared.28.arm64
+	ctx.ModuleForTests("lib32.vendor_shared.28.arm64", shared32Variant).Output("lib32.so")
+
 	// libvendor_available.so is installed by libvendor_available.vendor_shared.28.arm64
 	ctx.ModuleForTests("libvendor_available.vendor_shared.28.arm64", sharedVariant).Output("libvendor_available.so")
 
@@ -591,6 +794,9 @@
 	// bin is installed by bin.vendor_binary.28.arm64
 	ctx.ModuleForTests("bin.vendor_binary.28.arm64", binaryVariant).Output("bin")
 
+	// bin32 is installed by bin32.vendor_binary.28.arm64
+	ctx.ModuleForTests("bin32.vendor_binary.28.arm64", binary32Variant).Output("bin32")
+
 	// bin_without_snapshot is installed by bin_without_snapshot
 	ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot")
 
diff --git a/java/app.go b/java/app.go
index dcb3bc6..04406e7 100755
--- a/java/app.go
+++ b/java/app.go
@@ -380,7 +380,11 @@
 }
 
 func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
-	a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis)
+	usePlatformAPI := proptools.Bool(a.Module.deviceProperties.Platform_apis)
+	if ctx.Module().(android.SdkContext).SdkVersion().Kind == android.SdkModule {
+		usePlatformAPI = true
+	}
+	a.aapt.usesNonSdkApis = usePlatformAPI
 
 	// Ask manifest_fixer to add or update the application element indicating this app has no code.
 	a.aapt.hasNoCode = !a.hasCode(ctx)
diff --git a/java/boot_jars.go b/java/boot_jars.go
index ac8107b..1fb3deb 100644
--- a/java/boot_jars.go
+++ b/java/boot_jars.go
@@ -56,16 +56,7 @@
 	if !module.Enabled() {
 		return false
 	}
-	if module.IsReplacedByPrebuilt() {
-		// A source module that has been replaced by a prebuilt counterpart.
-		return false
-	}
-	if prebuilt, ok := module.(android.PrebuiltInterface); ok {
-		if p := prebuilt.Prebuilt(); p != nil {
-			return p.UsePrebuilt()
-		}
-	}
-	return true
+	return android.IsModulePreferred(module)
 }
 
 func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 6ad4ff3..7e9477b 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -186,17 +186,6 @@
 	// We do not have prebuilts of the core platform api yet
 	corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
 
-	// Add the android.test.base to the set of stubs only if the android.test.base module is on
-	// the boot jars list as the runtime will only enforce hiddenapi access against modules on
-	// that list.
-	if inList("android.test.base", ctx.Config().BootJars()) {
-		if ctx.Config().AlwaysUsePrebuiltSdks() {
-			publicStubModules = append(publicStubModules, "sdk_public_current_android.test.base")
-		} else {
-			publicStubModules = append(publicStubModules, "android.test.base.stubs")
-		}
-	}
-
 	// Allow products to define their own stubs for custom product jars that apps can use.
 	publicStubModules = append(publicStubModules, ctx.Config().ProductHiddenAPIStubs()...)
 	systemStubModules = append(systemStubModules, ctx.Config().ProductHiddenAPIStubsSystem()...)
@@ -369,20 +358,20 @@
 		FlagWithInput("--csv ", stubFlags).
 		Inputs(flagsCSV).
 		FlagWithInput("--unsupported ",
-			android.PathForSource(ctx, "frameworks/base/config/hiddenapi-unsupported.txt")).
+			android.PathForSource(ctx, "frameworks/base/boot/hiddenapi/hiddenapi-unsupported.txt")).
 		FlagWithInput("--unsupported ", combinedRemovedApis).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed").
 		FlagWithInput("--max-target-r ",
-			android.PathForSource(ctx, "frameworks/base/config/hiddenapi-max-target-r-loprio.txt")).FlagWithArg("--tag ", "lo-prio").
+			android.PathForSource(ctx, "frameworks/base/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt")).FlagWithArg("--tag ", "lo-prio").
 		FlagWithInput("--max-target-q ",
-			android.PathForSource(ctx, "frameworks/base/config/hiddenapi-max-target-q.txt")).
+			android.PathForSource(ctx, "frameworks/base/boot/hiddenapi/hiddenapi-max-target-q.txt")).
 		FlagWithInput("--max-target-p ",
-			android.PathForSource(ctx, "frameworks/base/config/hiddenapi-max-target-p.txt")).
+			android.PathForSource(ctx, "frameworks/base/boot/hiddenapi/hiddenapi-max-target-p.txt")).
 		FlagWithInput("--max-target-o ", android.PathForSource(
-			ctx, "frameworks/base/config/hiddenapi-max-target-o.txt")).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio").
+			ctx, "frameworks/base/boot/hiddenapi/hiddenapi-max-target-o.txt")).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio").
 		FlagWithInput("--blocked ",
-			android.PathForSource(ctx, "frameworks/base/config/hiddenapi-force-blocked.txt")).
+			android.PathForSource(ctx, "frameworks/base/boot/hiddenapi/hiddenapi-force-blocked.txt")).
 		FlagWithInput("--unsupported ", android.PathForSource(
-			ctx, "frameworks/base/config/hiddenapi-unsupported-packages.txt")).Flag("--packages ").
+			ctx, "frameworks/base/boot/hiddenapi/hiddenapi-unsupported-packages.txt")).Flag("--packages ").
 		FlagWithOutput("--output ", tempPath)
 
 	commitChangeForRestat(rule, tempPath, outputPath)
diff --git a/java/lint.go b/java/lint.go
index 475e8dc..30843dc 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -347,7 +347,7 @@
 
 	cmd := rule.Command()
 
-	cmd.Flag("JAVA_OPTS=-Xmx3072m").
+	cmd.Flag(`JAVA_OPTS="-Xmx3072m --add-opens java.base/java.util=ALL-UNNAMED"`).
 		FlagWithArg("ANDROID_SDK_HOME=", lintPaths.homeDir.String()).
 		FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
 		FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath)
@@ -392,6 +392,9 @@
 
 	rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
 
+	// The HTML output contains a date, remove it to make the output deterministic.
+	rule.Command().Text(`sed -i.tmp -e 's|Check performed at .*\(</nav>\)|\1|'`).Output(html)
+
 	rule.Build("lint", "lint")
 
 	l.outputs = lintOutputs{
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index 0786b7c..2de05b0 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -76,3 +76,5 @@
 
 # TODO(b/158390965): remove this when lint doesn't crash
 --disable_check HardcodedDebugMode
+
+--warning_check QueryAllPackagesPermission
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index c3d13ae..edfa146 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -232,15 +232,7 @@
 		}
 	}
 
-	// A prebuilt module should only be used when it is preferred.
-	if pi, ok := module.(android.PrebuiltInterface); ok {
-		if p := pi.Prebuilt(); p != nil {
-			return p.UsePrebuilt()
-		}
-	}
-
-	// Otherwise, a module should only be used if it has not been replaced by a prebuilt.
-	return !module.IsReplacedByPrebuilt()
+	return android.IsModulePreferred(module)
 }
 
 func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 37b8d9f..eb9ba9b 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1945,11 +1945,11 @@
 		}
 
 		// Add dependencies to the prebuilt stubs library
-		ctx.AddVariationDependencies(nil, apiScope.stubsTag, "prebuilt_"+module.stubsLibraryModuleName(apiScope))
+		ctx.AddVariationDependencies(nil, apiScope.stubsTag, android.PrebuiltNameFromSource(module.stubsLibraryModuleName(apiScope)))
 
 		if len(scopeProperties.Stub_srcs) > 0 {
 			// Add dependencies to the prebuilt stubs source library
-			ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, "prebuilt_"+module.stubsSourceModuleName(apiScope))
+			ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, android.PrebuiltNameFromSource(module.stubsSourceModuleName(apiScope)))
 		}
 	}
 }
diff --git a/java/system_modules.go b/java/system_modules.go
index 8c69051..320a2bb 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -236,7 +236,7 @@
 // modules.
 func (system *systemModulesImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
 	for _, lib := range system.properties.Libs {
-		ctx.AddVariationDependencies(nil, systemModulesLibsTag, "prebuilt_"+lib)
+		ctx.AddVariationDependencies(nil, systemModulesLibsTag, android.PrebuiltNameFromSource(lib))
 	}
 }
 
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 0f9a17d..b0e6967 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -50,7 +50,7 @@
 	}
 
 	ret := android.AndroidMkEntries{
-		OutputFile: mod.outputFile,
+		OutputFile: mod.unstrippedOutputFile,
 		Include:    "$(BUILD_SYSTEM)/soong_rust_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
 			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
diff --git a/rust/compiler.go b/rust/compiler.go
index 41b7371..2e85f5a 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -272,6 +272,10 @@
 	return false
 }
 
+func (compiler *baseCompiler) strippedOutputFilePath() android.OptionalPath {
+	return compiler.strippedOutputFile
+}
+
 func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
 	deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...)
 	deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...)
@@ -337,10 +341,7 @@
 }
 
 func (compiler *baseCompiler) install(ctx ModuleContext) {
-	path := ctx.RustModule().outputFile
-	if compiler.strippedOutputFile.Valid() {
-		path = compiler.strippedOutputFile
-	}
+	path := ctx.RustModule().OutputFile()
 	compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path())
 }
 
diff --git a/rust/rust.go b/rust/rust.go
index f0d0e36..566ad37 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -114,7 +114,10 @@
 	sourceProvider   SourceProvider
 	subAndroidMkOnce map[SubAndroidMkProvider]bool
 
-	outputFile android.OptionalPath
+	// Unstripped output. This is usually used when this module is linked to another module
+	// as a library. The stripped output which is used for installation can be found via
+	// compiler.strippedOutputFile if it exists.
+	unstrippedOutputFile android.OptionalPath
 
 	hideApexVariantFromMake bool
 }
@@ -163,8 +166,8 @@
 		if mod.sourceProvider != nil && (mod.compiler == nil || mod.compiler.Disabled()) {
 			return mod.sourceProvider.Srcs(), nil
 		} else {
-			if mod.outputFile.Valid() {
-				return android.Paths{mod.outputFile.Path()}, nil
+			if mod.OutputFile().Valid() {
+				return android.Paths{mod.OutputFile().Path()}, nil
 			}
 			return android.Paths{}, nil
 		}
@@ -346,6 +349,8 @@
 
 	stdLinkage(ctx *depsContext) RustLinkage
 	isDependencyRoot() bool
+
+	strippedOutputFilePath() android.OptionalPath
 }
 
 type exportedFlagsProducer interface {
@@ -523,7 +528,10 @@
 }
 
 func (mod *Module) OutputFile() android.OptionalPath {
-	return mod.outputFile
+	if mod.compiler != nil && mod.compiler.strippedOutputFilePath().Valid() {
+		return mod.compiler.strippedOutputFilePath()
+	}
+	return mod.unstrippedOutputFile
 }
 
 func (mod *Module) CoverageFiles() android.Paths {
@@ -540,7 +548,7 @@
 		return false
 	}
 
-	return mod.outputFile.Valid() && !mod.Properties.PreventInstall
+	return mod.OutputFile().Valid() && !mod.Properties.PreventInstall
 }
 
 var _ cc.LinkableInterface = (*Module)(nil)
@@ -721,9 +729,9 @@
 
 	if mod.compiler != nil && !mod.compiler.Disabled() {
 		mod.compiler.initialize(ctx)
-		outputFile := mod.compiler.compile(ctx, flags, deps)
+		unstrippedOutputFile := mod.compiler.compile(ctx, flags, deps)
 
-		mod.outputFile = android.OptionalPathForPath(outputFile)
+		mod.unstrippedOutputFile = android.OptionalPathForPath(unstrippedOutputFile)
 
 		apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
 		if mod.installable(apexInfo) {
@@ -882,7 +890,7 @@
 			}
 
 			if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
-				linkFile := rustDep.outputFile
+				linkFile := rustDep.unstrippedOutputFile
 				if !linkFile.Valid() {
 					ctx.ModuleErrorf("Invalid output file when adding dep %q to %q",
 						depName, ctx.ModuleName())
@@ -978,15 +986,15 @@
 
 	var rlibDepFiles RustLibraries
 	for _, dep := range directRlibDeps {
-		rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.outputFile.Path(), CrateName: dep.CrateName()})
+		rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.unstrippedOutputFile.Path(), CrateName: dep.CrateName()})
 	}
 	var dylibDepFiles RustLibraries
 	for _, dep := range directDylibDeps {
-		dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.outputFile.Path(), CrateName: dep.CrateName()})
+		dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.unstrippedOutputFile.Path(), CrateName: dep.CrateName()})
 	}
 	var procMacroDepFiles RustLibraries
 	for _, dep := range directProcMacroDeps {
-		procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.outputFile.Path(), CrateName: dep.CrateName()})
+		procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.unstrippedOutputFile.Path(), CrateName: dep.CrateName()})
 	}
 
 	var staticLibDepFiles android.Paths
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 9e8a602..c54b2bc 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -254,3 +254,22 @@
         "linker_config_proto",
     ],
 }
+
+python_binary_host {
+    name: "conv_classpaths_proto",
+    srcs: [
+        "conv_classpaths_proto.py",
+    ],
+    version: {
+        py2: {
+            enabled: false,
+        },
+        py3: {
+            enabled: true,
+            embedded_launcher: true,
+        },
+    },
+    libs: [
+        "classpaths_proto_python",
+    ],
+}
diff --git a/scripts/conv_classpaths_proto.py b/scripts/conv_classpaths_proto.py
new file mode 100644
index 0000000..f49fbbb
--- /dev/null
+++ b/scripts/conv_classpaths_proto.py
@@ -0,0 +1,76 @@
+#  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.
+
+import argparse
+
+import classpaths_pb2
+
+import google.protobuf.json_format as json_format
+import google.protobuf.text_format as text_format
+
+
+def encode(args):
+    pb = classpaths_pb2.ExportedClasspathsJars()
+    if args.format == 'json':
+        json_format.Parse(args.input.read(), pb)
+    else:
+        text_format.Parse(args.input.read(), pb)
+    args.output.write(pb.SerializeToString())
+    args.input.close()
+    args.output.close()
+
+
+def decode(args):
+    pb = classpaths_pb2.ExportedClasspathsJars()
+    pb.ParseFromString(args.input.read())
+    if args.format == 'json':
+        args.output.write(json_format.MessageToJson(pb))
+    else:
+        args.output.write(text_format.MessageToString(pb).encode('utf_8'))
+    args.input.close()
+    args.output.close()
+
+
+def main():
+    parser = argparse.ArgumentParser('Convert classpaths.proto messages between binary and '
+                                     'human-readable formats.')
+    parser.add_argument('-f', '--format', default='textproto',
+                        help='human-readable format, either json or text(proto), '
+                             'defaults to textproto')
+    parser.add_argument('-i', '--input',
+                        nargs='?', type=argparse.FileType('rb'), default=sys.stdin.buffer)
+    parser.add_argument('-o', '--output',
+                        nargs='?', type=argparse.FileType('wb'),
+                        default=sys.stdout.buffer)
+
+    subparsers = parser.add_subparsers()
+
+    parser_encode = subparsers.add_parser('encode',
+                                          help='convert classpaths protobuf message from '
+                                               'JSON to binary format',
+                                          parents=[parser], add_help=False)
+
+    parser_encode.set_defaults(func=encode)
+
+    parser_decode = subparsers.add_parser('decode',
+                                          help='print classpaths config in JSON format',
+                                          parents=[parser], add_help=False)
+    parser_decode.set_defaults(func=decode)
+
+    args = parser.parse_args()
+    args.func(args)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/sdk/update.go b/sdk/update.go
index 828c7b6..522a888 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -1350,7 +1350,7 @@
 // Compute the list of possible os types that this sdk could support.
 func (s *sdk) getPossibleOsTypes() []android.OsType {
 	var osTypes []android.OsType
-	for _, osType := range android.OsTypeList {
+	for _, osType := range android.OsTypeList() {
 		if s.DeviceSupported() {
 			if osType.Class == android.Device && osType != android.Fuchsia {
 				osTypes = append(osTypes, osType)