Merge "Add ModuleInfoJSON to android_test_import and prebuilt_etc" into main
diff --git a/android/androidmk.go b/android/androidmk.go
index cf1589d..f2e1c10 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -892,13 +892,7 @@
 				}
 			}
 		} else {
-			mctx := &makeVarsContext{
-				SingletonContext: ctx.(SingletonContext),
-				config:           ctx.Config(),
-				pctx:             pctx,
-			}
-			switch x := mod.(type) {
-			case AndroidMkDataProvider:
+			if x, ok := mod.(AndroidMkDataProvider); ok {
 				data := x.AndroidMk()
 
 				if data.Include == "" {
@@ -915,7 +909,8 @@
 				if contribution := data.Entries.getDistContributions(mod); contribution != nil {
 					allDistContributions = append(allDistContributions, *contribution)
 				}
-			case AndroidMkEntriesProvider:
+			}
+			if x, ok := mod.(AndroidMkEntriesProvider); ok {
 				entriesList := x.AndroidMkEntries()
 				for _, entries := range entriesList {
 					entries.fillInEntries(ctx, mod)
@@ -929,7 +924,13 @@
 						allDistContributions = append(allDistContributions, *contribution)
 					}
 				}
-			case ModuleMakeVarsProvider:
+			}
+			if x, ok := mod.(ModuleMakeVarsProvider); ok {
+				mctx := &makeVarsContext{
+					SingletonContext: ctx.(SingletonContext),
+					config:           ctx.Config(),
+					pctx:             pctx,
+				}
 				if !x.Enabled(ctx) {
 					continue
 				}
@@ -937,15 +938,17 @@
 				if contribution := getMakeVarsDistContributions(mctx); contribution != nil {
 					allDistContributions = append(allDistContributions, *contribution)
 				}
-
-			case SingletonMakeVarsProvider:
+			}
+			if x, ok := mod.(SingletonMakeVarsProvider); ok {
+				mctx := &makeVarsContext{
+					SingletonContext: ctx.(SingletonContext),
+					config:           ctx.Config(),
+					pctx:             pctx,
+				}
 				x.MakeVars(mctx)
 				if contribution := getMakeVarsDistContributions(mctx); contribution != nil {
 					allDistContributions = append(allDistContributions, *contribution)
 				}
-
-			default:
-				// Not exported to make so no make variables to set.
 			}
 		}
 	}
diff --git a/android/apex.go b/android/apex.go
index 08c82eb..a5ccd52 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -105,6 +105,9 @@
 // thus wouldn't be merged.
 func (i ApexInfo) mergedName() string {
 	name := "apex" + strconv.Itoa(i.MinSdkVersion.FinalOrFutureInt())
+	if i.UsePlatformApis {
+		name += "_p"
+	}
 	return name
 }
 
@@ -613,25 +616,26 @@
 		apexInfos = allApexInfos.ApexInfos
 	}
 
-	// Shortcut
-	if len(apexInfos) == 0 {
-		return
-	}
-
-	// Do some validity checks.
-	// TODO(jiyong): is this the right place?
-	base.checkApexAvailableProperty(ctx)
-
-	if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
-		apexInfos, _ = mergeApexVariations(apexInfos)
-	}
-
 	if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() {
 		// Do not install the module for platform, but still allow it to output
 		// uninstallable AndroidMk entries in certain cases when they have side
 		// effects.  TODO(jiyong): move this routine to somewhere else
 		module.MakeUninstallable()
 	}
+
+	// Do some validity checks.
+	// TODO(jiyong): is this the right place?
+	base.checkApexAvailableProperty(ctx)
+
+	// Shortcut
+	if len(apexInfos) == 0 {
+		return
+	}
+
+	if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
+		apexInfos, _ = mergeApexVariations(apexInfos)
+	}
+
 	if !platformVariation {
 		var thisApexInfo ApexInfo
 
diff --git a/android/apex_test.go b/android/apex_test.go
index 78597b2..acc195d 100644
--- a/android/apex_test.go
+++ b/android/apex_test.go
@@ -193,7 +193,7 @@
 			},
 		},
 		{
-			name: "merge different UsePlatformApis but don't allow using platform api",
+			name: "don't merge different UsePlatformApis",
 			in: []ApexInfo{
 				{
 					ApexVariationName: "foo",
@@ -213,13 +213,20 @@
 				{
 					ApexVariationName: "apex10000",
 					MinSdkVersion:     FutureApiLevel,
-					InApexVariants:    []string{"foo", "bar"},
+					InApexVariants:    []string{"foo"},
+					ForPrebuiltApex:   NotForPrebuiltApex,
+				},
+				{
+					ApexVariationName: "apex10000_p",
+					MinSdkVersion:     FutureApiLevel,
+					UsePlatformApis:   true,
+					InApexVariants:    []string{"bar"},
 					ForPrebuiltApex:   NotForPrebuiltApex,
 				},
 			},
 			wantAliases: [][2]string{
 				{"foo", "apex10000"},
-				{"bar", "apex10000"},
+				{"bar", "apex10000_p"},
 			},
 		},
 		{
@@ -242,7 +249,7 @@
 			},
 			wantMerged: []ApexInfo{
 				{
-					ApexVariationName: "apex10000",
+					ApexVariationName: "apex10000_p",
 					MinSdkVersion:     FutureApiLevel,
 					UsePlatformApis:   true,
 					InApexVariants:    []string{"foo", "bar"},
@@ -250,8 +257,8 @@
 				},
 			},
 			wantAliases: [][2]string{
-				{"foo", "apex10000"},
-				{"bar", "apex10000"},
+				{"foo", "apex10000_p"},
+				{"bar", "apex10000_p"},
 			},
 		},
 	}
diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go
index dcf393d..35805a2 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -240,8 +240,8 @@
 		blueprint.RuleParams{
 			Command: `rm -rf $out && ` +
 				`${sqlite3} $out ".import --csv $in modules" && ` +
-				`([ -z "${make_metadata}" ] || ${sqlite3} $out ".import --csv ${make_metadata} make_metadata") && ` +
-				`([ -z "${make_modules}" ] || ${sqlite3} $out ".import --csv ${make_modules} make_modules")`,
+				`${sqlite3} $out ".import --csv ${make_metadata} make_metadata" && ` +
+				`${sqlite3} $out ".import --csv ${make_modules} make_modules"`,
 			CommandDeps: []string{"${sqlite3}"},
 		}, "make_metadata", "make_modules")
 )
@@ -311,29 +311,29 @@
 	modulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "soong-modules.csv")
 	WriteFileRuleVerbatim(ctx, modulesCsv, buffer.String())
 
-	var implicits []Path
-	args := make(map[string]string)
+	// Metadata generated in Make
+	makeMetadataCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-metadata.csv")
+	makeModulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-modules.csv")
 
-	if ctx.Config().KatiEnabled() {
-		// Metadata generated in Make
-		makeMetadataCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-metadata.csv")
-		makeModulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-modules.csv")
-		implicits = append(implicits, makeMetadataCsv, makeModulesCsv)
-		args["make_metadata"] = makeMetadataCsv.String()
-		args["make_modules"] = makeModulesCsv.String()
-	} else {
-		args["make_metadata"] = ""
-		args["make_modules"] = ""
+	if !ctx.Config().KatiEnabled() {
+		WriteFileRule(ctx, makeMetadataCsv, "installed_file,module_path,is_soong_module,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,static_libs,whole_static_libs,license_text")
+		WriteFileRule(ctx, makeModulesCsv, "name,module_path,module_class,module_type,static_libs,whole_static_libs,built_files,installed_files")
 	}
 
 	// Import metadata from Make and Soong to sqlite3 database
 	complianceMetadataDb := PathForOutput(ctx, "compliance-metadata", deviceProduct, "compliance-metadata.db")
 	ctx.Build(pctx, BuildParams{
-		Rule:      importCsv,
-		Input:     modulesCsv,
-		Implicits: implicits,
-		Output:    complianceMetadataDb,
-		Args:      args,
+		Rule:  importCsv,
+		Input: modulesCsv,
+		Implicits: []Path{
+			makeMetadataCsv,
+			makeModulesCsv,
+		},
+		Output: complianceMetadataDb,
+		Args: map[string]string{
+			"make_metadata": makeMetadataCsv.String(),
+			"make_modules":  makeModulesCsv.String(),
+		},
 	})
 
 	// Phony rule "compliance-metadata.db". "m compliance-metadata.db" to create the compliance metadata database.
diff --git a/android/module_test.go b/android/module_test.go
index 6e6d449..3b81ded 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -1110,3 +1110,14 @@
 			"Module .+ and Vintf_fragment .+ are installed to different partitions.")).
 		RunTestWithBp(t, bp)
 }
+
+func TestInvalidModuleName(t *testing.T) {
+	bp := `
+		deps {
+			name: "fo o",
+		}
+	`
+	prepareForModuleTests.
+		ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`should use a valid name`)).
+		RunTestWithBp(t, bp)
+}
diff --git a/apex/apex.go b/apex/apex.go
index a310671..fa796e5 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1032,9 +1032,9 @@
 	// be built for this apexBundle.
 
 	apexVariationName := mctx.ModuleName() // could be com.android.foo
-	if overridable, ok := mctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
+	if a.GetOverriddenBy() != "" {
 		// use the overridden name com.mycompany.android.foo
-		apexVariationName = overridable.GetOverriddenBy()
+		apexVariationName = a.GetOverriddenBy()
 	}
 
 	a.properties.ApexVariationName = apexVariationName
@@ -1202,8 +1202,6 @@
 			return []string{overridable.GetOverriddenBy()}
 		}
 		return []string{ai.ApexVariationName()}
-	} else if _, ok := ctx.Module().(*OverrideApex); ok {
-		return []string{ctx.ModuleName()}
 	}
 	return []string{""}
 }
@@ -1220,8 +1218,6 @@
 			return overridable.GetOverriddenBy()
 		}
 		return ai.ApexVariationName()
-	} else if _, ok := ctx.Module().(*OverrideApex); ok {
-		return ctx.Module().Name()
 	}
 
 	return ""
@@ -1663,6 +1659,10 @@
 // to the child modules. Returning false makes the visit to continue in the sibling or the parent
 // modules. This is used in check* functions below.
 func (a *apexBundle) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) {
+	apexVariationName := ctx.ModuleName()
+	if overrideName := a.GetOverriddenBy(); overrideName != "" {
+		apexVariationName = overrideName
+	}
 	ctx.WalkDeps(func(child, parent android.Module) bool {
 		am, ok := child.(android.ApexModule)
 		if !ok || !am.CanHaveApexVariants() {
@@ -1682,7 +1682,7 @@
 		}
 
 		ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
-		externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
+		externalDep := !android.InList(apexVariationName, ai.InApexVariants)
 
 		// Visit actually
 		return do(ctx, parent, am, externalDep)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index cd2df51..987cb69 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -20,7 +20,6 @@
 	"path/filepath"
 	"reflect"
 	"regexp"
-	"slices"
 	"sort"
 	"strconv"
 	"strings"
@@ -29,7 +28,6 @@
 	"android/soong/aconfig/codegen"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/bpmodify"
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
@@ -1249,12 +1247,12 @@
 
 	// Ensure that we are using non-stub variants of mylib2 and libfoo.shared_from_rust (because
 	// of the platform_apis: true)
-	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000_p").Rule("ld").Args["libFlags"]
 	ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
 	ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
 	ensureNotContains(t, mylibLdFlags, "libmylib2_rust/android_arm64_armv8-a_shared_current/unstripped/libmylib2_rust.so")
 	ensureContains(t, mylibLdFlags, "libmylib2_rust/android_arm64_armv8-a_shared/unstripped/libmylib2_rust.so")
-	rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
+	rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000_p").Rule("rustc").Args["linkFlags"]
 	ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
 	ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
 	ensureNotContains(t, rustDeps, "libmylib_rust.shared_from_rust/android_arm64_armv8-a_shared_current/unstripped/libmylib_rust.shared_from_rust.so")
@@ -5475,7 +5473,7 @@
 		checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
 			my-bootclasspath-fragment/index.csv
 			out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
-			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
+			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
 		`)
 	})
 
@@ -5548,7 +5546,7 @@
 		checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
 			my-bootclasspath-fragment/index.csv
 			out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
-			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
+			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
 		`)
 
 		myApex := ctx.ModuleForTests("myapex", "android_common_myapex").Module()
@@ -5743,7 +5741,7 @@
 		checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
 			my-bootclasspath-fragment/index.csv
 			out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
-			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
+			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
 		`)
 	})
 
@@ -5842,7 +5840,7 @@
 		checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
 			out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
 			out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/modular-hiddenapi/index.csv
-			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
+			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
 		`)
 	})
 
@@ -5954,7 +5952,7 @@
 		checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
 			my-bootclasspath-fragment/index.csv
 			out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
-			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
+			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
 		`)
 	})
 
@@ -11302,7 +11300,7 @@
 		{
 			desc:                      "Source apex com.android.foo is selected, bootjar should come from source java library",
 			selectedApexContributions: "foo.source.contributions",
-			expectedBootJar:           "out/soong/.intermediates/foo-bootclasspath-fragment/android_common_apex10000/hiddenapi-modular/encoded/framework-foo.jar",
+			expectedBootJar:           "out/soong/.intermediates/foo-bootclasspath-fragment/android_common_com.android.foo/hiddenapi-modular/encoded/framework-foo.jar",
 		},
 		{
 			desc:                      "Prebuilt apex prebuilt_com.android.foo is selected, profile should come from .prof deapexed from the prebuilt",
@@ -11359,7 +11357,7 @@
 		variation := func(moduleName string) string {
 			ret := "android_common_com.android.foo"
 			if moduleName == "com.google.android.foo" {
-				ret = "android_common_com.google.android.foo_com.google.android.foo"
+				ret = "android_common_com.google.android.foo"
 			}
 			return ret
 		}
@@ -11874,7 +11872,7 @@
 		}
 	`)
 
-	java.CheckModuleHasDependency(t, res.TestContext, "myoverrideapex", "android_common_myoverrideapex_myoverrideapex", "foo")
+	java.CheckModuleHasDependency(t, res.TestContext, "myoverrideapex", "android_common_myoverrideapex", "foo")
 }
 
 func TestUpdatableApexMinSdkVersionCurrent(t *testing.T) {
@@ -12210,396 +12208,3 @@
 	fileList := android.ContentFromFileRuleForTests(t, result, partition.Output("fileList"))
 	android.AssertDeepEquals(t, "filesystem with apex", "apex/myapex.apex\n", fileList)
 }
-
-func TestApexVerifyNativeImplementationLibs(t *testing.T) {
-	t.Parallel()
-
-	extractDepenencyPathFromErrors := func(errs []error) []string {
-		i := slices.IndexFunc(errs, func(err error) bool {
-			return strings.Contains(err.Error(), "dependency path:")
-		})
-		if i < 0 {
-			return nil
-		}
-		var dependencyPath []string
-		for _, err := range errs[i+1:] {
-			s := err.Error()
-			lastSpace := strings.LastIndexByte(s, ' ')
-			if lastSpace >= 0 {
-				dependencyPath = append(dependencyPath, s[lastSpace+1:])
-			}
-		}
-		return dependencyPath
-	}
-
-	checkErrors := func(wantDependencyPath []string) func(t *testing.T, result *android.TestResult) {
-		return func(t *testing.T, result *android.TestResult) {
-			t.Helper()
-			if len(result.Errs) == 0 {
-				t.Fatalf("expected errors")
-			}
-			t.Log("found errors:")
-			for _, err := range result.Errs {
-				t.Log(err)
-			}
-			if g, w := result.Errs[0].Error(), "library in apex transitively linked against implementation library"; !strings.Contains(g, w) {
-				t.Fatalf("expected error %q, got %q", w, g)
-			}
-			dependencyPath := extractDepenencyPathFromErrors(result.Errs)
-			if g, w := dependencyPath, wantDependencyPath; !slices.Equal(g, w) {
-				t.Errorf("expected dependency path %q, got %q", w, g)
-			}
-		}
-	}
-
-	addToSharedLibs := func(module, lib string) func(bp *bpmodify.Blueprint) {
-		return func(bp *bpmodify.Blueprint) {
-			m := bp.ModulesByName(module)
-			props, err := m.GetOrCreateProperty(bpmodify.List, "shared_libs")
-			if err != nil {
-				panic(err)
-			}
-			props.AddStringToList(lib)
-		}
-	}
-
-	bpTemplate := `
-	apex {
-		name: "myapex",
-		key: "myapex.key",
-		native_shared_libs: ["mylib"],
-		rust_dyn_libs: ["libmyrust"],
-		binaries: ["mybin", "myrustbin"],
-		jni_libs: ["libjni"],
-		apps: ["myapp"],
-		updatable: false,
-	}
-
-	apex {
-		name: "otherapex",
-		key: "myapex.key",
-		native_shared_libs: ["libotherapex"],
-		updatable: false,
-	}
-
-	apex_key {
-		name: "myapex.key",
-		public_key: "testkey.avbpubkey",
-		private_key: "testkey.pem",
-	}
-
-	cc_library {
-		name: "mylib",
-		srcs: ["foo.cpp"],
-		apex_available: ["myapex"],
-	}
-
-	cc_binary {
-		name: "mybin",
-		srcs: ["foo.cpp"],
-		apex_available: ["myapex"],
-	}
-
-	rust_library {
-		name: "libmyrust",
-		crate_name: "myrust",
-		srcs: ["src/lib.rs"],
-		rustlibs: ["libmyrust_transitive_dylib"],
-		rlibs: ["libmyrust_transitive_rlib"],
-		apex_available: ["myapex"],
-	}
-
-	rust_library{
-		name: "libmyrust_transitive_dylib",
-		crate_name: "myrust_transitive_dylib",
-		srcs: ["src/lib.rs"],
-		apex_available: ["myapex"],
-	}
-
-	rust_library {
-		name: "libmyrust_transitive_rlib",
-		crate_name: "myrust_transitive_rlib",
-		srcs: ["src/lib.rs"],
-		apex_available: ["myapex"],
-	}
-
-	rust_binary {
-		name: "myrustbin",
-		srcs: ["src/main.rs"],
-		apex_available: ["myapex"],
-	}
-
-	cc_library {
-		name: "libbar",
-		sdk_version: "current",
-		srcs: ["bar.cpp"],
-		apex_available: ["myapex"],
-		stl: "none",
-	}
-
-	android_app {
-		name: "myapp",
-		jni_libs: ["libembeddedjni"],
-		use_embedded_native_libs: true,
-		sdk_version: "current",
-		apex_available: ["myapex"],
-	}
-
-	cc_library {
-		name: "libembeddedjni",
-		sdk_version: "current",
-		srcs: ["bar.cpp"],
-		apex_available: ["myapex"],
-		stl: "none",
-	}
-
-	cc_library {
-		name: "libjni",
-		sdk_version: "current",
-		srcs: ["bar.cpp"],
-		apex_available: ["myapex"],
-		stl: "none",
-	}
-
-	cc_library {
-		name: "libotherapex",
-		sdk_version: "current",
-		srcs: ["otherapex.cpp"],
-		apex_available: ["otherapex"],
-		stubs: {
-			symbol_file: "libotherapex.map.txt",
-			versions: ["1", "2", "3"],
-		},
-		stl: "none",
-	}
-
-	cc_library {
-		name: "libplatform",
-		sdk_version: "current",
-		srcs: ["libplatform.cpp"],
-		stubs: {
-			symbol_file: "libplatform.map.txt",
-			versions: ["1", "2", "3"],
-		},
-		stl: "none",
-		system_shared_libs: [],
-	}
-	`
-
-	testCases := []struct {
-		name           string
-		bpModifier     func(bp *bpmodify.Blueprint)
-		dependencyPath []string
-	}{
-		{
-			name:           "library dependency in other apex",
-			bpModifier:     addToSharedLibs("mylib", "libotherapex#impl"),
-			dependencyPath: []string{"myapex", "mylib", "libotherapex"},
-		},
-		{
-			name: "transitive library dependency in other apex",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("mylib", "libbar")(bp)
-				addToSharedLibs("libbar", "libotherapex#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "mylib", "libbar", "libotherapex"},
-		},
-		{
-			name:           "library dependency in platform",
-			bpModifier:     addToSharedLibs("mylib", "libplatform#impl"),
-			dependencyPath: []string{"myapex", "mylib", "libplatform"},
-		},
-		{
-			name:           "jni library dependency in other apex",
-			bpModifier:     addToSharedLibs("libjni", "libotherapex#impl"),
-			dependencyPath: []string{"myapex", "libjni", "libotherapex"},
-		},
-		{
-			name: "transitive jni library dependency in other apex",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("libjni", "libbar")(bp)
-				addToSharedLibs("libbar", "libotherapex#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "libjni", "libbar", "libotherapex"},
-		},
-		{
-			name:           "jni library dependency in platform",
-			bpModifier:     addToSharedLibs("libjni", "libplatform#impl"),
-			dependencyPath: []string{"myapex", "libjni", "libplatform"},
-		},
-		{
-			name: "transitive jni library dependency in platform",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("libjni", "libbar")(bp)
-				addToSharedLibs("libbar", "libplatform#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "libjni", "libbar", "libplatform"},
-		},
-		{
-			name:           "app jni library dependency in other apex",
-			bpModifier:     addToSharedLibs("libembeddedjni", "libotherapex#impl"),
-			dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libotherapex"},
-		},
-		{
-			name: "transitive app jni library dependency in other apex",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("libembeddedjni", "libbar")(bp)
-				addToSharedLibs("libbar", "libotherapex#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libbar", "libotherapex"},
-		},
-		{
-			name:           "app jni library dependency in platform",
-			bpModifier:     addToSharedLibs("libembeddedjni", "libplatform#impl"),
-			dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libplatform"},
-		},
-		{
-			name: "transitive app jni library dependency in platform",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("libembeddedjni", "libbar")(bp)
-				addToSharedLibs("libbar", "libplatform#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libbar", "libplatform"},
-		},
-		{
-			name:           "binary dependency in other apex",
-			bpModifier:     addToSharedLibs("mybin", "libotherapex#impl"),
-			dependencyPath: []string{"myapex", "mybin", "libotherapex"},
-		},
-		{
-			name: "transitive binary dependency in other apex",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("mybin", "libbar")(bp)
-				addToSharedLibs("libbar", "libotherapex#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "mybin", "libbar", "libotherapex"},
-		},
-		{
-			name:           "binary dependency in platform",
-			bpModifier:     addToSharedLibs("mybin", "libplatform#impl"),
-			dependencyPath: []string{"myapex", "mybin", "libplatform"},
-		},
-		{
-			name: "transitive binary dependency in platform",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("mybin", "libbar")(bp)
-				addToSharedLibs("libbar", "libplatform#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "mybin", "libbar", "libplatform"},
-		},
-
-		{
-			name:           "rust library dependency in other apex",
-			bpModifier:     addToSharedLibs("libmyrust", "libotherapex#impl"),
-			dependencyPath: []string{"myapex", "libmyrust", "libotherapex"},
-		},
-		{
-			name: "transitive rust library dependency in other apex",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("libmyrust", "libbar")(bp)
-				addToSharedLibs("libbar", "libotherapex#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "libmyrust", "libbar", "libotherapex"},
-		},
-		{
-			name:           "rust library dependency in platform",
-			bpModifier:     addToSharedLibs("libmyrust", "libplatform#impl"),
-			dependencyPath: []string{"myapex", "libmyrust", "libplatform"},
-		},
-		{
-			name: "transitive rust library dependency in platform",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("libmyrust", "libbar")(bp)
-				addToSharedLibs("libbar", "libplatform#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "libmyrust", "libbar", "libplatform"},
-		},
-		{
-			name: "transitive rust library dylib dependency in other apex",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("libmyrust_transitive_dylib", "libotherapex#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "libmyrust", "libmyrust_transitive_dylib", "libotherapex"},
-		},
-		{
-			name: "transitive rust library dylib dependency in platform",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("libmyrust_transitive_dylib", "libplatform#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "libmyrust", "libmyrust_transitive_dylib", "libplatform"},
-		},
-		{
-			name: "transitive rust library rlib dependency in other apex",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("libmyrust_transitive_rlib", "libotherapex#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "libmyrust", "libmyrust_transitive_rlib", "libotherapex"},
-		},
-		{
-			name: "transitive rust library rlib dependency in platform",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("libmyrust_transitive_rlib", "libplatform#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "libmyrust", "libmyrust_transitive_rlib", "libplatform"},
-		},
-		{
-			name:           "rust binary dependency in other apex",
-			bpModifier:     addToSharedLibs("myrustbin", "libotherapex#impl"),
-			dependencyPath: []string{"myapex", "myrustbin", "libotherapex"},
-		},
-		{
-			name: "transitive rust binary dependency in other apex",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("myrustbin", "libbar")(bp)
-				addToSharedLibs("libbar", "libotherapex#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "myrustbin", "libbar", "libotherapex"},
-		},
-		{
-			name:           "rust binary dependency in platform",
-			bpModifier:     addToSharedLibs("myrustbin", "libplatform#impl"),
-			dependencyPath: []string{"myapex", "myrustbin", "libplatform"},
-		},
-		{
-			name: "transitive rust binary dependency in platform",
-			bpModifier: func(bp *bpmodify.Blueprint) {
-				addToSharedLibs("myrustbin", "libbar")(bp)
-				addToSharedLibs("libbar", "libplatform#impl")(bp)
-			},
-			dependencyPath: []string{"myapex", "myrustbin", "libbar", "libplatform"},
-		},
-	}
-
-	for _, testCase := range testCases {
-		t.Run(testCase.name, func(t *testing.T) {
-			t.Parallel()
-			bp, err := bpmodify.NewBlueprint("", []byte(bpTemplate))
-			if err != nil {
-				t.Fatal(err)
-			}
-			if testCase.bpModifier != nil {
-				func() {
-					defer func() {
-						if r := recover(); r != nil {
-							t.Fatalf("panic in bpModifier: %v", r)
-						}
-					}()
-					testCase.bpModifier(bp)
-				}()
-			}
-			android.GroupFixturePreparers(
-				android.PrepareForTestWithAndroidBuildComponents,
-				cc.PrepareForTestWithCcBuildComponents,
-				java.PrepareForTestWithDexpreopt,
-				rust.PrepareForTestWithRustDefaultModules,
-				PrepareForTestWithApexBuildComponents,
-				prepareForTestWithMyapex,
-				prepareForTestWithOtherapex,
-				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
-					variables.BuildId = proptools.StringPtr("TEST.BUILD_ID")
-				}),
-			).ExtendWithErrorHandler(android.FixtureCustomErrorHandler(checkErrors(testCase.dependencyPath))).
-				RunTestWithBp(t, bp.String())
-		})
-	}
-}
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index d0bff62..c7674b5 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -242,6 +242,7 @@
 					apex_available: [
 						"com.android.art",
 					],
+					min_sdk_version: "33",
 				}
 			`, content)
 		}
@@ -711,7 +712,7 @@
 	copyCommands := apexRule.Args["copy_commands"]
 
 	// Make sure that the fragment provides the hidden API encoded dex jars to the APEX.
-	fragment := result.Module("mybootclasspathfragment", "android_common_apex10000")
+	fragment := result.Module("mybootclasspathfragment", "android_common_myapex")
 
 	info, _ := android.OtherModuleProvider(result, fragment, java.BootclasspathFragmentApexContentInfoProvider)
 
@@ -727,8 +728,8 @@
 		android.AssertStringDoesContain(t, name+" apex copy command", copyCommands, expectedCopyCommand)
 	}
 
-	checkFragmentExportedDexJar("foo", "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/hiddenapi-modular/encoded/foo.jar")
-	checkFragmentExportedDexJar("bar", "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/hiddenapi-modular/encoded/bar.jar")
+	checkFragmentExportedDexJar("foo", "out/soong/.intermediates/mybootclasspathfragment/android_common_myapex/hiddenapi-modular/encoded/foo.jar")
+	checkFragmentExportedDexJar("bar", "out/soong/.intermediates/mybootclasspathfragment/android_common_myapex/hiddenapi-modular/encoded/bar.jar")
 }
 
 func getDexJarPath(result *android.TestResult, name string) string {
@@ -859,7 +860,7 @@
 		}
 	`)
 
-	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
 		"all_apex_contributions",
 		"art-bootclasspath-fragment",
 		"bar",
@@ -874,7 +875,7 @@
 	quuzModuleLibStubs := getDexJarPath(result, "quuz.stubs.exportable.module_lib")
 
 	// Make sure that the fragment uses the quuz stub dex jars when generating the hidden API flags.
-	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_myapex")
 
 	rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
 	command := rule.RuleParams.Command
@@ -1032,7 +1033,7 @@
 		}
 	`)
 
-	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
 		"all_apex_contributions",
 		"android-non-updatable.stubs",
 		"android-non-updatable.stubs.module_lib",
@@ -1051,7 +1052,7 @@
 
 	// Make sure that the fragment uses the android-non-updatable modules when generating the hidden
 	// API flags.
-	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_myapex")
 
 	rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
 	command := rule.RuleParams.Command
@@ -1206,7 +1207,7 @@
 		}
 	`)
 
-	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
 		"all_apex_contributions",
 		"android-non-updatable.stubs",
 		"android-non-updatable.stubs.system",
@@ -1222,7 +1223,7 @@
 
 	// Make sure that the fragment uses the android-non-updatable modules when generating the hidden
 	// API flags.
-	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_myapex")
 
 	rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
 	command := rule.RuleParams.Command
@@ -1361,7 +1362,7 @@
 		}
 	`)
 
-	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
 		"all_apex_contributions",
 		"art-bootclasspath-fragment",
 		"bar",
@@ -1380,7 +1381,7 @@
 
 	// Make sure that the fragment uses the android-non-updatable modules when generating the hidden
 	// API flags.
-	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_myapex")
 
 	rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
 	command := rule.RuleParams.Command
@@ -1463,7 +1464,7 @@
 		}
 	`)
 
-	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_myapex")
 	classPathProtoContent := android.ContentFromFileRuleForTests(t, result.TestContext, fragment.Output("bootclasspath.pb.textproto"))
 	// foo
 	ensureContains(t, classPathProtoContent, `jars {
diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go
index f367174..55f1475 100644
--- a/apex/classpath_element_test.go
+++ b/apex/classpath_element_test.go
@@ -198,11 +198,11 @@
 
 	result := preparer.RunTest(t)
 
-	artFragment := result.Module("art-bootclasspath-fragment", "android_common_apex10000")
+	artFragment := result.Module("art-bootclasspath-fragment", "android_common_com.android.art")
 	artBaz := result.Module("baz", "android_common_apex10000")
 	artQuuz := result.Module("quuz", "android_common_apex10000")
 
-	myFragment := result.Module("mybootclasspath-fragment", "android_common_apex10000")
+	myFragment := result.Module("mybootclasspath-fragment", "android_common_myapex")
 	myBar := result.Module("bar", "android_common_apex10000")
 
 	other := result.Module("othersdklibrary", "android_common_apex10000")
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index b51bb36..6fa1fe2 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -176,7 +176,7 @@
 		"out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar",
 		"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
 		"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
-		"out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof",
+		"out/soong/.intermediates/art-bootclasspath-fragment/android_common_com.android.art/art-bootclasspath-fragment/boot.prof",
 		"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
 		"out/soong/dexpreopt/uffd_gc_flag.txt",
 	}
@@ -396,7 +396,7 @@
 		{
 			desc:                         "Source apex com.android.art is selected, profile should come from source java library",
 			selectedArtApexContributions: "art.source.contributions",
-			expectedProfile:              "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof",
+			expectedProfile:              "out/soong/.intermediates/art-bootclasspath-fragment/android_common_com.android.art/art-bootclasspath-fragment/boot.prof",
 		},
 		{
 			desc:                         "Prebuilt apex prebuilt_com.android.art is selected, profile should come from .prof deapexed from the prebuilt",
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index c13d599..8b5fce9 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -165,12 +165,12 @@
 		android.AssertPathsRelativeToTopEquals(t, message, expected, info.FlagsFilesByCategory[category])
 	}
 
-	android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
-	android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
-	android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/index.csv"}, info.IndexPaths)
+	android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
+	android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
+	android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/index.csv"}, info.IndexPaths)
 
-	android.AssertArrayString(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/filtered-stub-flags.csv:out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
-	android.AssertArrayString(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/filtered-flags.csv:out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
+	android.AssertArrayString(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv:out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
+	android.AssertArrayString(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv:out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
 }
 
 // TestPlatformBootclasspath_LegacyPrebuiltFragment verifies that the
diff --git a/cc/builder.go b/cc/builder.go
index c94a674..16f006d 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -974,13 +974,18 @@
 func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
 	baseName string, exportedIncludeDirs []string, symbolFile android.OptionalPath,
 	excludedSymbolVersions, excludedSymbolTags, includedSymbolTags []string,
-	api string) android.Path {
+	api string, commonGlobalIncludes bool) android.Path {
 
 	outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
 
 	implicits := android.Paths{soFile}
 	symbolFilterStr := "-so " + soFile.String()
 	exportedHeaderFlags := android.JoinWithPrefix(exportedIncludeDirs, "-I")
+	// If this library does not export any include directory, do not append the flags
+	// so that the ABI tool dumps everything without filtering by the include directories.
+	if commonGlobalIncludes && len(exportedIncludeDirs) > 0 {
+		exportedHeaderFlags += " ${config.CommonGlobalIncludes}"
+	}
 
 	if symbolFile.Valid() {
 		implicits = append(implicits, symbolFile.Path())
diff --git a/cc/cc.go b/cc/cc.go
index 0279928..ad6468d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -839,6 +839,7 @@
 
 	reexportFlags       bool
 	explicitlyVersioned bool
+	explicitlyImpl      bool
 	dataLib             bool
 	ndk                 bool
 
@@ -934,6 +935,11 @@
 	llndkHeaderLibTag     = dependencyTag{name: "llndk_header_lib"}
 )
 
+func IsExplicitImplSharedDepTag(depTag blueprint.DependencyTag) bool {
+	ccLibDepTag, ok := depTag.(libraryDependencyTag)
+	return ok && ccLibDepTag.shared() && ccLibDepTag.explicitlyImpl
+}
+
 func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
 	ccLibDepTag, ok := depTag.(libraryDependencyTag)
 	return ok && ccLibDepTag.shared()
@@ -2699,6 +2705,9 @@
 		variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
 		if tag, ok := depTag.(libraryDependencyTag); ok {
 			tag.explicitlyVersioned = true
+			if version == "" {
+				tag.explicitlyImpl = true
+			}
 			// depTag is an interface that contains a concrete non-pointer struct.  That makes the local
 			// tag variable a copy of the contents of depTag, and updating it doesn't change depTag.  Reassign
 			// the modified copy to depTag.
@@ -4074,7 +4083,7 @@
 
 func (c *Module) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
 	if c.HasStubsVariants() {
-		if IsSharedDepTag(depTag) {
+		if IsSharedDepTag(depTag) && !IsExplicitImplSharedDepTag(depTag) {
 			// dynamic dep to a stubs lib crosses APEX boundary
 			return false
 		}
diff --git a/cc/compiler.go b/cc/compiler.go
index 3730bbe..949603e 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -324,6 +324,10 @@
 	getNamedMapForConfig(ctx.Config(), key).Store(module, true)
 }
 
+func requiresGlobalIncludes(ctx ModuleContext) bool {
+	return !(ctx.useSdk() || ctx.InVendorOrProduct()) || ctx.Host()
+}
+
 func useGnuExtensions(gnuExtensions *bool) bool {
 	return proptools.BoolDefault(gnuExtensions, true)
 }
@@ -452,7 +456,7 @@
 		flags.Local.YasmFlags = append(flags.Local.YasmFlags, "-I"+modulePath)
 	}
 
-	if !(ctx.useSdk() || ctx.InVendorOrProduct()) || ctx.Host() {
+	if requiresGlobalIncludes(ctx) {
 		flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
 			"${config.CommonGlobalIncludes}",
 			tc.IncludeFlags())
diff --git a/cc/library.go b/cc/library.go
index 950ea91..789190c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -630,10 +630,17 @@
 	}
 	if library.sabi.shouldCreateSourceAbiDump() {
 		dirs := library.exportedIncludeDirsForAbiCheck(ctx)
-		flags.SAbiFlags = make([]string, 0, len(dirs))
+		flags.SAbiFlags = make([]string, 0, len(dirs)+1)
 		for _, dir := range dirs {
 			flags.SAbiFlags = append(flags.SAbiFlags, "-I"+dir)
 		}
+		// If this library does not export any include directory, do not append the flags
+		// so that the ABI tool dumps everything without filtering by the include directories.
+		// requiresGlobalIncludes returns whether this library can include CommonGlobalIncludes.
+		// If the library cannot include them, it cannot export them.
+		if len(dirs) > 0 && requiresGlobalIncludes(ctx) {
+			flags.SAbiFlags = append(flags.SAbiFlags, "${config.CommonGlobalIncludes}")
+		}
 		totalLength := len(srcs) + len(deps.GeneratedSources) +
 			len(sharedSrcs) + len(staticSrcs)
 		if totalLength > 0 {
@@ -1362,13 +1369,15 @@
 	deps PathDeps, sAbiDumpFiles android.Paths, soFile android.Path, libFileName string,
 	excludeSymbolVersions, excludeSymbolTags []string,
 	sdkVersionForVendorApiLevel string) android.Path {
+	// Though LLNDK is implemented in system, the callers in vendor cannot include CommonGlobalIncludes,
+	// so commonGlobalIncludes is false.
 	return transformDumpToLinkedDump(ctx,
 		sAbiDumpFiles, soFile, libFileName+".llndk",
 		library.llndkIncludeDirsForAbiCheck(ctx, deps),
 		android.OptionalPathForModuleSrc(ctx, library.Properties.Llndk.Symbol_file),
 		append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...),
 		append([]string{"platform-only"}, excludeSymbolTags...),
-		[]string{"llndk"}, sdkVersionForVendorApiLevel)
+		[]string{"llndk"}, sdkVersionForVendorApiLevel, false /* commonGlobalIncludes */)
 }
 
 func (library *libraryDecorator) linkApexSAbiDumpFiles(ctx ModuleContext,
@@ -1381,7 +1390,7 @@
 		android.OptionalPathForModuleSrc(ctx, library.Properties.Stubs.Symbol_file),
 		append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...),
 		append([]string{"platform-only"}, excludeSymbolTags...),
-		[]string{"apex", "systemapi"}, sdkVersion)
+		[]string{"apex", "systemapi"}, sdkVersion, requiresGlobalIncludes(ctx))
 }
 
 func getRefAbiDumpFile(ctx android.ModuleInstallPathContext,
@@ -1524,7 +1533,7 @@
 			android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)),
 			headerAbiChecker.Exclude_symbol_versions,
 			headerAbiChecker.Exclude_symbol_tags,
-			[]string{} /* includeSymbolTags */, currSdkVersion)
+			[]string{} /* includeSymbolTags */, currSdkVersion, requiresGlobalIncludes(ctx))
 
 		var llndkDump, apexVariantDump android.Path
 		tags := classifySourceAbiDump(ctx.Module().(*Module))
diff --git a/cc/strip.go b/cc/strip.go
index 36c0c48..a950df8 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -23,10 +23,8 @@
 // StripProperties defines the type of stripping applied to the module.
 type StripProperties struct {
 	Strip struct {
-		// none forces all stripping to be disabled.
-		// Device modules default to stripping enabled leaving mini debuginfo.
-		// Host modules default to stripping disabled, but can be enabled by setting any other
-		// strip boolean property.
+		// Device and host modules default to stripping enabled leaving mini debuginfo.
+		// This can be disabled by setting none to true.
 		None *bool `android:"arch_variant"`
 
 		// all forces stripping everything, including the mini debug info.
diff --git a/cc/testing.go b/cc/testing.go
index 14a6b7a..c9d362d 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -193,7 +193,7 @@
 			},
 			apex_available: [
 				"//apex_available:platform",
-				"myapex"
+				"//apex_available:anyapex",
 			],
 			llndk: {
 				symbol_file: "libm.map.txt",
@@ -253,7 +253,7 @@
 			},
 			apex_available: [
 				"//apex_available:platform",
-				"myapex"
+				"//apex_available:anyapex",
 			],
 			llndk: {
 				symbol_file: "libdl.map.txt",
diff --git a/filesystem/android_device_product_out.go b/filesystem/android_device_product_out.go
index 1175c42..6ac89ad 100644
--- a/filesystem/android_device_product_out.go
+++ b/filesystem/android_device_product_out.go
@@ -36,6 +36,7 @@
 	filesystemInfos := a.getFsInfos(ctx)
 
 	var deps android.Paths
+	var depsNoImg android.Paths // subset of deps without any img files. used for sbom creation.
 
 	for _, partition := range android.SortedKeys(filesystemInfos) {
 		info := filesystemInfos[partition]
@@ -86,6 +87,7 @@
 				ctx.Phony(info.ModuleName, fip.FullInstallPath)
 				ctx.Phony(partition, fip.FullInstallPath)
 				deps = append(deps, fip.FullInstallPath)
+				depsNoImg = append(depsNoImg, fip.FullInstallPath)
 				ctx.Phony("sync_"+partition, fip.FullInstallPath)
 				ctx.Phony("sync", fip.FullInstallPath)
 			}
@@ -94,6 +96,8 @@
 		deps = append(deps, imgInstallPath)
 	}
 
+	a.createComplianceMetadataTimestamp(ctx, depsNoImg)
+
 	// List all individual files to be copied to PRODUCT_OUT here
 	if a.deviceProps.Bootloader != nil {
 		bootloaderInstallPath := android.PathForModuleInPartitionInstall(ctx, "", "bootloader")
@@ -173,9 +177,31 @@
 		Implicits: deps,
 	})
 
+	emptyFile := android.PathForModuleOut(ctx, "empty_file")
+	android.WriteFileRule(ctx, emptyFile, "")
+
+	// TODO: We don't have these tests building in soong yet. Add phonies for them so that CI builds
+	// that try to build them don't error out.
+	ctx.Phony("continuous_instrumentation_tests", emptyFile)
+	ctx.Phony("continuous_native_tests", emptyFile)
+	ctx.Phony("device-tests", emptyFile)
+	ctx.Phony("device-platinum-tests", emptyFile)
+	ctx.Phony("platform_tests", emptyFile)
+
 	return copyToProductOutTimestamp
 }
 
+// createComplianceMetadataTimestampForSoongOnly creates a timestamp file in m --soong-only
+// this timestamp file depends on installed files of the main `android_device`.
+// Any changes to installed files of the main `android_device` will retrigger SBOM generation
+func (a *androidDevice) createComplianceMetadataTimestamp(ctx android.ModuleContext, installedFiles android.Paths) {
+	ctx.Build(pctx, android.BuildParams{
+		Rule:      android.Touch,
+		Implicits: installedFiles,
+		Output:    android.PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "installed_files.stamp"),
+	})
+}
+
 // Returns a mapping from partition type -> FilesystemInfo. This includes filesystems that are
 // nested inside of other partitions, such as the partitions inside super.img, or ramdisk inside
 // of boot.
diff --git a/java/androidmk.go b/java/androidmk.go
index f069e75..4305360 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -552,8 +552,6 @@
 			func(w io.Writer, name, prefix, moduleDir string) {
 				if dstubs.apiLintTimestamp != nil {
 					if dstubs.apiLintReport != nil {
-						fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n", dstubs.Name()+"-api-lint",
-							dstubs.apiLintReport.String(), "apilint/"+dstubs.Name()+"-lint-report.txt")
 						fmt.Fprintf(w, "$(call declare-0p-target,%s)\n", dstubs.apiLintReport.String())
 					}
 				}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 8fb8ba9..f6d6cad 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -290,6 +290,10 @@
 	return m
 }
 
+func (m *BootclasspathFragmentModule) UniqueApexVariations() bool {
+	return true
+}
+
 func (m *BootclasspathFragmentModule) bootclasspathFragmentPropertyCheck(ctx android.ModuleContext) {
 	contents := m.properties.Contents.GetOrDefault(ctx, nil)
 	if len(contents) == 0 {
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 497facb..093cc87 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -566,6 +566,9 @@
 				// The prebuilt might have been renamed by prebuilt_rename mutator if the source module does not exist.
 				// Remove the prebuilt_ prefix.
 				ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, android.RemoveOptionalPrebuiltPrefix(selected))
+			} else {
+				// Couldn't find a dependency, do it again to report an error.
+				ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, selected)
 			}
 		}
 	}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 22f4d98..c8f798a 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -1524,6 +1524,18 @@
 	}
 )
 
+func (d *Droidstubs) MakeVars(ctx android.MakeVarsModuleContext) {
+	if d.apiLintTimestamp != nil {
+		if d.apiLintReport != nil {
+			ctx.DistForGoalsWithFilename(
+				[]string{fmt.Sprintf("%s-api-lint", d.Name()), "droidcore"},
+				d.apiLintReport,
+				fmt.Sprintf("apilint/%s-lint-report.txt", d.Name()),
+			)
+		}
+	}
+}
+
 func StubsDefaultsFactory() android.Module {
 	module := &DocDefaults{}
 
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 152eb1e..86062d4 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -15,6 +15,8 @@
 package java
 
 import (
+	"github.com/google/blueprint"
+
 	"android/soong/android"
 	"android/soong/dexpreopt"
 )
@@ -33,9 +35,18 @@
 	platformBootclasspathArtBootJarDepTag  = bootclasspathDependencyTag{name: "art-boot-jar"}
 	platformBootclasspathBootJarDepTag     = bootclasspathDependencyTag{name: "platform-boot-jar"}
 	platformBootclasspathApexBootJarDepTag = bootclasspathDependencyTag{name: "apex-boot-jar"}
-	platformBootclasspathImplLibDepTag     = dependencyTag{name: "impl-lib-tag"}
 )
 
+type platformBootclasspathImplLibDepTagType struct {
+	blueprint.BaseDependencyTag
+}
+
+func (p platformBootclasspathImplLibDepTagType) ExcludeFromVisibilityEnforcement() {}
+
+var platformBootclasspathImplLibDepTag platformBootclasspathImplLibDepTagType
+
+var _ android.ExcludeFromVisibilityEnforcementTag = platformBootclasspathImplLibDepTag
+
 type platformBootclasspathModule struct {
 	android.ModuleBase
 	ClasspathFragmentBase
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 3176ad9..f3074ed 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -58,6 +58,10 @@
 	return m
 }
 
+func (m *platformSystemServerClasspathModule) UniqueApexVariations() bool {
+	return true
+}
+
 func (p *platformSystemServerClasspathModule) AndroidMkEntries() (entries []android.AndroidMkEntries) {
 	return p.classpathFragmentBase().androidMkEntries()
 }
@@ -115,6 +119,9 @@
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
 }
+func (m *SystemServerClasspathModule) UniqueApexVariations() bool {
+	return true
+}
 
 func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	if len(s.properties.Contents.GetOrDefault(ctx, nil)) == 0 && len(s.properties.Standalone_contents.GetOrDefault(ctx, nil)) == 0 {
diff --git a/python/binary.go b/python/binary.go
index a3acb34..4d6e118 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -23,6 +23,7 @@
 
 	"android/soong/android"
 	"android/soong/cc"
+
 	"github.com/google/blueprint"
 )
 
@@ -143,8 +144,7 @@
 	}
 	srcsZips = append(srcsZips, depsSrcsZips...)
 	p.installSource = registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
-		p.getHostInterpreterName(ctx, p.properties.Actual_version),
-		main, p.getStem(ctx), srcsZips)
+		"python3", main, p.getStem(ctx), srcsZips)
 
 	var sharedLibs []string
 	// if embedded launcher is enabled, we need to collect the shared library dependencies of the
@@ -205,23 +205,6 @@
 	return BoolDefault(b.binaryProperties.Autorun, true)
 }
 
-// get host interpreter name.
-func (p *PythonBinaryModule) getHostInterpreterName(ctx android.ModuleContext,
-	actualVersion string) string {
-	var interp string
-	switch actualVersion {
-	case pyVersion2:
-		interp = "python2.7"
-	case pyVersion3:
-		interp = "python3"
-	default:
-		panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.",
-			actualVersion, ctx.ModuleName()))
-	}
-
-	return interp
-}
-
 // find main program path within runfiles tree.
 func (p *PythonBinaryModule) getPyMainFile(ctx android.ModuleContext,
 	srcsPathMappings []pathMapping) string {
diff --git a/python/defaults.go b/python/defaults.go
index 3dc5bc4..b5ee2bc 100644
--- a/python/defaults.go
+++ b/python/defaults.go
@@ -18,10 +18,6 @@
 	"android/soong/android"
 )
 
-func init() {
-	android.RegisterModuleType("python_defaults", DefaultsFactory)
-}
-
 type Defaults struct {
 	android.ModuleBase
 	android.DefaultsModuleBase
diff --git a/python/library.go b/python/library.go
index 7cdb80b..c197028 100644
--- a/python/library.go
+++ b/python/library.go
@@ -27,6 +27,7 @@
 func registerPythonLibraryComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("python_library_host", PythonLibraryHostFactory)
 	ctx.RegisterModuleType("python_library", PythonLibraryFactory)
+	ctx.RegisterModuleType("python_defaults", DefaultsFactory)
 }
 
 func PythonLibraryHostFactory() android.Module {
diff --git a/python/python.go b/python/python.go
index 09af62e..10c11ad 100644
--- a/python/python.go
+++ b/python/python.go
@@ -23,6 +23,7 @@
 	"strings"
 
 	"android/soong/cc"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
@@ -39,19 +40,6 @@
 
 var PythonLibraryInfoProvider = blueprint.NewProvider[PythonLibraryInfo]()
 
-func init() {
-	registerPythonMutators(android.InitRegistrationContext)
-}
-
-func registerPythonMutators(ctx android.RegistrationContext) {
-	ctx.PreDepsMutators(RegisterPythonPreDepsMutators)
-}
-
-// Exported to support other packages using Python modules in tests.
-func RegisterPythonPreDepsMutators(ctx android.RegisterMutatorsContext) {
-	ctx.Transition("python_version", &versionSplitTransitionMutator{})
-}
-
 // the version-specific properties that apply to python modules.
 type VersionProperties struct {
 	// whether the module is required to be built with this version.
@@ -127,18 +115,14 @@
 		Py3 VersionProperties `android:"arch_variant"`
 	} `android:"arch_variant"`
 
-	// the actual version each module uses after variations created.
-	// this property name is hidden from users' perspectives, and soong will populate it during
-	// runtime.
-	Actual_version string `blueprint:"mutated"`
-
-	// whether the module is required to be built with actual_version.
-	// this is set by the python version mutator based on version-specific properties
+	// This enabled property is to accept the collapsed enabled property from the VersionProperties.
+	// It is unused now, as all builds should be python3.
 	Enabled *bool `blueprint:"mutated"`
 
-	// whether the binary is required to be built with embedded launcher for this actual_version.
-	// this is set by the python version mutator based on version-specific properties
-	Embedded_launcher *bool `blueprint:"mutated"`
+	// whether the binary is required to be built with an embedded python interpreter, defaults to
+	// true. This allows taking the resulting binary outside of the build and running it on machines
+	// that don't have python installed or may have an older version of python.
+	Embedded_launcher *bool
 }
 
 // Used to store files of current module after expanding dependencies
@@ -252,8 +236,6 @@
 	pathComponentRegexp      = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_-]*$`)
 	pyExt                    = ".py"
 	protoExt                 = ".proto"
-	pyVersion2               = "PY2"
-	pyVersion3               = "PY3"
 	internalPath             = "internal"
 )
 
@@ -261,71 +243,6 @@
 	getBaseProperties() *BaseProperties
 }
 
-type versionSplitTransitionMutator struct{}
-
-func (versionSplitTransitionMutator) Split(ctx android.BaseModuleContext) []string {
-	if base, ok := ctx.Module().(basePropertiesProvider); ok {
-		props := base.getBaseProperties()
-		var variants []string
-		// PY3 is first so that we alias the PY3 variant rather than PY2 if both
-		// are available
-		if proptools.BoolDefault(props.Version.Py3.Enabled, true) {
-			variants = append(variants, pyVersion3)
-		}
-		if proptools.BoolDefault(props.Version.Py2.Enabled, false) {
-			if ctx.ModuleName() != "py2-cmd" &&
-				ctx.ModuleName() != "py2-stdlib" {
-				ctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3.")
-			}
-			variants = append(variants, pyVersion2)
-		}
-		return variants
-	}
-	return []string{""}
-}
-
-func (versionSplitTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
-	return ""
-}
-
-func (versionSplitTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
-	if incomingVariation != "" {
-		return incomingVariation
-	}
-	if base, ok := ctx.Module().(basePropertiesProvider); ok {
-		props := base.getBaseProperties()
-		if proptools.BoolDefault(props.Version.Py3.Enabled, true) {
-			return pyVersion3
-		} else {
-			return pyVersion2
-		}
-	}
-
-	return ""
-}
-
-func (versionSplitTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
-	if variation == "" {
-		return
-	}
-	if base, ok := ctx.Module().(basePropertiesProvider); ok {
-		props := base.getBaseProperties()
-		props.Actual_version = variation
-
-		var versionProps *VersionProperties
-		if variation == pyVersion3 {
-			versionProps = &props.Version.Py3
-		} else if variation == pyVersion2 {
-			versionProps = &props.Version.Py2
-		}
-
-		err := proptools.AppendMatchingProperties([]interface{}{props}, versionProps, nil)
-		if err != nil {
-			panic(err)
-		}
-	}
-}
-
 func anyHasExt(paths []string, ext string) bool {
 	for _, p := range paths {
 		if filepath.Ext(p) == ext {
@@ -345,19 +262,26 @@
 //   - if required, specifies launcher and adds launcher dependencies,
 //   - applies python version mutations to Python dependencies
 func (p *PythonLibraryModule) DepsMutator(ctx android.BottomUpMutatorContext) {
-	android.ProtoDeps(ctx, &p.protoProperties)
+	// Flatten the version.py3 props down into the main property struct. Leftover from when
+	// there was both python2 and 3 in the build, and properties could be different between them.
+	if base, ok := ctx.Module().(basePropertiesProvider); ok {
+		props := base.getBaseProperties()
 
-	versionVariation := []blueprint.Variation{
-		{"python_version", p.properties.Actual_version},
+		err := proptools.AppendMatchingProperties([]interface{}{props}, &props.Version.Py3, nil)
+		if err != nil {
+			panic(err)
+		}
 	}
 
+	android.ProtoDeps(ctx, &p.protoProperties)
+
 	// If sources contain a proto file, add dependency on libprotobuf-python
 	if p.anySrcHasExt(ctx, protoExt) && p.Name() != "libprotobuf-python" {
-		ctx.AddVariationDependencies(versionVariation, pythonLibTag, "libprotobuf-python")
+		ctx.AddDependency(ctx.Module(), pythonLibTag, "libprotobuf-python")
 	}
 
 	// Add python library dependencies for this python version variation
-	ctx.AddVariationDependencies(versionVariation, pythonLibTag, android.LastUniqueStrings(p.properties.Libs)...)
+	ctx.AddDependency(ctx.Module(), pythonLibTag, android.LastUniqueStrings(p.properties.Libs)...)
 
 	// Emulate the data property for java_data but with the arch variation overridden to "common"
 	// so that it can point to java modules.
@@ -394,55 +318,38 @@
 		launcherSharedLibDeps = append(launcherSharedLibDeps, "libc_musl")
 	}
 
-	switch p.properties.Actual_version {
-	case pyVersion2:
-		stdLib = "py2-stdlib"
-
-		launcherModule = "py2-launcher"
-		if autorun {
-			launcherModule = "py2-launcher-autorun"
-		}
-
-		launcherSharedLibDeps = append(launcherSharedLibDeps, "libc++")
-	case pyVersion3:
-		var prebuiltStdLib bool
-		if targetForDeps.Os.Bionic() {
-			prebuiltStdLib = false
-		} else if ctx.Config().VendorConfig("cpython3").Bool("force_build_host") {
-			prebuiltStdLib = false
-		} else {
-			prebuiltStdLib = true
-		}
-
-		if prebuiltStdLib {
-			stdLib = "py3-stdlib-prebuilt"
-		} else {
-			stdLib = "py3-stdlib"
-		}
-
-		launcherModule = "py3-launcher"
-		if autorun {
-			launcherModule = "py3-launcher-autorun"
-		}
-		if ctx.Config().HostStaticBinaries() && targetForDeps.Os == android.LinuxMusl {
-			launcherModule += "-static"
-		}
-		if ctx.Device() {
-			launcherSharedLibDeps = append(launcherSharedLibDeps, "liblog")
-		}
-	default:
-		panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",
-			p.properties.Actual_version, ctx.ModuleName()))
+	var prebuiltStdLib bool
+	if targetForDeps.Os.Bionic() {
+		prebuiltStdLib = false
+	} else if ctx.Config().VendorConfig("cpython3").Bool("force_build_host") {
+		prebuiltStdLib = false
+	} else {
+		prebuiltStdLib = true
 	}
+
+	if prebuiltStdLib {
+		stdLib = "py3-stdlib-prebuilt"
+	} else {
+		stdLib = "py3-stdlib"
+	}
+
+	launcherModule = "py3-launcher"
+	if autorun {
+		launcherModule = "py3-launcher-autorun"
+	}
+	if ctx.Config().HostStaticBinaries() && targetForDeps.Os == android.LinuxMusl {
+		launcherModule += "-static"
+	}
+	if ctx.Device() {
+		launcherSharedLibDeps = append(launcherSharedLibDeps, "liblog")
+	}
+
 	targetVariations := targetForDeps.Variations()
 	if ctx.ModuleName() != stdLib {
-		stdLibVariations := make([]blueprint.Variation, 0, len(targetVariations)+1)
-		stdLibVariations = append(stdLibVariations, blueprint.Variation{Mutator: "python_version", Variation: p.properties.Actual_version})
-		stdLibVariations = append(stdLibVariations, targetVariations...)
 		// Using AddFarVariationDependencies for all of these because they can be for a different
 		// platform, like if the python module itself was being compiled for device, we may want
 		// the python interpreter built for host so that we can precompile python sources.
-		ctx.AddFarVariationDependencies(stdLibVariations, stdLibTag, stdLib)
+		ctx.AddFarVariationDependencies(targetVariations, stdLibTag, stdLib)
 	}
 	ctx.AddFarVariationDependencies(targetVariations, launcherTag, launcherModule)
 	ctx.AddFarVariationDependencies(targetVariations, launcherSharedLibTag, launcherSharedLibDeps...)
@@ -450,6 +357,9 @@
 
 // GenerateAndroidBuildActions performs build actions common to all Python modules
 func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if proptools.BoolDefault(p.properties.Version.Py2.Enabled, false) {
+		ctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3.")
+	}
 	expandedSrcs := android.PathsForModuleSrcExcludes(ctx, p.properties.Srcs, p.properties.Exclude_srcs)
 	// Keep before any early returns.
 	android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
diff --git a/python/python_test.go b/python/python_test.go
index 6a6bd1d..0e97626 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -36,10 +36,8 @@
 }
 
 var (
-	buildNamePrefix = "soong_python_test"
-	// We allow maching almost anything before the actual variant so that the os/arch variant
-	// is matched.
-	moduleVariantErrTemplate = `%s: module %q variant "[a-zA-Z0-9_]*%s": `
+	buildNamePrefix          = "soong_python_test"
+	moduleVariantErrTemplate = `%s: module %q variant "[a-zA-Z0-9_]*": `
 	pkgPathErrTemplate       = moduleVariantErrTemplate +
 		"pkg_path: %q must be a relative path contained in par file."
 	badIdentifierErrTemplate = moduleVariantErrTemplate +
@@ -48,9 +46,8 @@
 		"found two files to be placed at the same location within zip %q." +
 		" First file: in module %s at path %q." +
 		" Second file: in module %s at path %q."
-	noSrcFileErr      = moduleVariantErrTemplate + "doesn't have any source files!"
-	badSrcFileExtErr  = moduleVariantErrTemplate + "srcs: found non (.py|.proto) file: %q!"
-	badDataFileExtErr = moduleVariantErrTemplate + "data: found (.py) file: %q!"
+	badSrcFileExtErr  = moduleVariantErrTemplate + `srcs: found non \(.py\|.proto\) file: %q!`
+	badDataFileExtErr = moduleVariantErrTemplate + `data: found \(.py\) file: %q!`
 	bpFile            = "Android.bp"
 
 	data = []struct {
@@ -61,20 +58,6 @@
 		expectedBinaries []pyModule
 	}{
 		{
-			desc: "module without any src files",
-			mockFiles: map[string][]byte{
-				filepath.Join("dir", bpFile): []byte(
-					`python_library_host {
-						name: "lib1",
-					}`,
-				),
-			},
-			errors: []string{
-				fmt.Sprintf(noSrcFileErr,
-					"dir/Android.bp:1:1", "lib1", "PY3"),
-			},
-		},
-		{
 			desc: "module with bad src file ext",
 			mockFiles: map[string][]byte{
 				filepath.Join("dir", bpFile): []byte(
@@ -89,7 +72,7 @@
 			},
 			errors: []string{
 				fmt.Sprintf(badSrcFileExtErr,
-					"dir/Android.bp:3:11", "lib1", "PY3", "dir/file1.exe"),
+					"dir/Android.bp:3:11", "lib1", "dir/file1.exe"),
 			},
 		},
 		{
@@ -111,7 +94,7 @@
 			},
 			errors: []string{
 				fmt.Sprintf(badDataFileExtErr,
-					"dir/Android.bp:6:11", "lib1", "PY3", "dir/file2.py"),
+					"dir/Android.bp:6:11", "lib1", "dir/file2.py"),
 			},
 		},
 		{
@@ -146,9 +129,9 @@
 			},
 			errors: []string{
 				fmt.Sprintf(pkgPathErrTemplate,
-					"dir/Android.bp:11:15", "lib2", "PY3", "a/c/../../../"),
+					"dir/Android.bp:11:15", "lib2", "a/c/../../../"),
 				fmt.Sprintf(pkgPathErrTemplate,
-					"dir/Android.bp:19:15", "lib3", "PY3", "/a/c/../../"),
+					"dir/Android.bp:19:15", "lib3", "/a/c/../../"),
 			},
 		},
 		{
@@ -171,11 +154,11 @@
 			},
 			errors: []string{
 				fmt.Sprintf(badIdentifierErrTemplate, "dir/Android.bp:4:11",
-					"lib1", "PY3", "a/b/c/-e/f/file1.py", "-e"),
+					"lib1", "a/b/c/-e/f/file1.py", "-e"),
 				fmt.Sprintf(badIdentifierErrTemplate, "dir/Android.bp:4:11",
-					"lib1", "PY3", "a/b/c/.file1.py", ".file1"),
+					"lib1", "a/b/c/.file1.py", ".file1"),
 				fmt.Sprintf(badIdentifierErrTemplate, "dir/Android.bp:4:11",
-					"lib1", "PY3", "a/b/c/123/file1.py", "123"),
+					"lib1", "a/b/c/123/file1.py", "123"),
 			},
 		},
 		{
@@ -219,115 +202,15 @@
 			},
 			errors: []string{
 				fmt.Sprintf(dupRunfileErrTemplate, "dir/Android.bp:20:6",
-					"bin", "PY3", "a/b/c/file1.py", "bin", "dir/file1.py",
+					"bin", "a/b/c/file1.py", "bin", "dir/file1.py",
 					"lib1", "dir/c/file1.py"),
 			},
 		},
-		{
-			desc: "module for testing dependencies",
-			mockFiles: map[string][]byte{
-				filepath.Join("dir", bpFile): []byte(
-					`python_defaults {
-						name: "default_lib",
-						srcs: [
-							"default.py",
-						],
-						version: {
-							py2: {
-								enabled: true,
-								srcs: [
-									"default_py2.py",
-								],
-							},
-							py3: {
-								enabled: false,
-								srcs: [
-									"default_py3.py",
-								],
-							},
-						},
-					}
-
-					python_library_host {
-						name: "lib5",
-						pkg_path: "a/b/",
-						srcs: [
-							"file1.py",
-						],
-						version: {
-							py2: {
-								enabled: true,
-							},
-							py3: {
-								enabled: true,
-							},
-						},
-					}
-
-					python_library_host {
-						name: "lib6",
-						pkg_path: "c/d/",
-						srcs: [
-							"file2.py",
-						],
-						libs: [
-							"lib5",
-						],
-					}
-
-					python_binary_host {
-						name: "bin",
-						defaults: ["default_lib"],
-						pkg_path: "e/",
-						srcs: [
-							"bin.py",
-						],
-						libs: [
-							"lib5",
-						],
-						version: {
-							py3: {
-								enabled: true,
-								srcs: [
-									"file4.py",
-								],
-								libs: [
-									"lib6",
-								],
-							},
-						},
-					}`,
-				),
-				filepath.Join("dir", "default.py"):     nil,
-				filepath.Join("dir", "default_py2.py"): nil,
-				filepath.Join("dir", "default_py3.py"): nil,
-				filepath.Join("dir", "file1.py"):       nil,
-				filepath.Join("dir", "file2.py"):       nil,
-				filepath.Join("dir", "bin.py"):         nil,
-				filepath.Join("dir", "file4.py"):       nil,
-			},
-			expectedBinaries: []pyModule{
-				{
-					name:          "bin",
-					actualVersion: "PY3",
-					pyRunfiles: []string{
-						"e/default.py",
-						"e/bin.py",
-						"e/default_py3.py",
-						"e/file4.py",
-					},
-					srcsZip: "out/soong/.intermediates/dir/bin/PY3/bin.py.srcszip",
-				},
-			},
-		},
 	}
 )
 
 func TestPythonModule(t *testing.T) {
 	for _, d := range data {
-		if d.desc != "module with duplicate runfile path" {
-			continue
-		}
 		d.mockFiles[filepath.Join("common", bpFile)] = []byte(`
 python_library {
   name: "py3-stdlib",
@@ -416,10 +299,6 @@
 	for i, bp := range testCases {
 		ctx := android.GroupFixturePreparers(
 			PrepareForTestWithPythonBuildComponents,
-			android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
-
-				ctx.RegisterModuleType("python_defaults", DefaultsFactory)
-			}),
 			android.PrepareForTestWithAllowMissingDependencies).
 			ExtendWithErrorHandler(android.FixtureIgnoreErrors).
 			RunTestWithBp(t, bp)
diff --git a/python/testing.go b/python/testing.go
index ce1a5ab..fe53ee5 100644
--- a/python/testing.go
+++ b/python/testing.go
@@ -20,5 +20,4 @@
 	android.FixtureRegisterWithContext(registerPythonBinaryComponents),
 	android.FixtureRegisterWithContext(registerPythonLibraryComponents),
 	android.FixtureRegisterWithContext(registerPythonTestComponents),
-	android.FixtureRegisterWithContext(registerPythonMutators),
 )
diff --git a/rust/coverage.go b/rust/coverage.go
index ae95e46..798b21d 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -16,12 +16,12 @@
 
 import (
 	"android/soong/android"
+
 	"github.com/google/blueprint"
 
 	"android/soong/cc"
 )
 
-var CovLibraryName = "libprofile-clang-extras"
 var ProfilerBuiltins = "libprofiler_builtins.rust_sysroot"
 
 // Add '%c' to default specifier after we resolve http://b/210012154
@@ -38,12 +38,20 @@
 	return []interface{}{&cov.Properties}
 }
 
+func getClangProfileLibraryName(ctx ModuleContextIntf) string {
+	if ctx.RustModule().UseSdk() {
+		return "libprofile-clang-extras_ndk"
+	} else {
+		return "libprofile-clang-extras"
+	}
+}
+
 func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps {
 	if cov.Properties.NeedCoverageVariant {
 		if ctx.Device() {
 			ctx.AddVariationDependencies([]blueprint.Variation{
 				{Mutator: "link", Variation: "static"},
-			}, cc.CoverageDepTag, CovLibraryName)
+			}, cc.CoverageDepTag, getClangProfileLibraryName(ctx))
 		}
 
 		// no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
@@ -66,7 +74,7 @@
 		flags.RustFlags = append(flags.RustFlags,
 			"-C instrument-coverage", "-g")
 		if ctx.Device() {
-			m := ctx.GetDirectDepProxyWithTag(CovLibraryName, cc.CoverageDepTag)
+			m := ctx.GetDirectDepProxyWithTag(getClangProfileLibraryName(ctx), cc.CoverageDepTag)
 			coverage := android.OtherModuleProviderOrDefault(ctx, m, cc.LinkableInfoProvider)
 			flags.LinkFlags = append(flags.LinkFlags,
 				profileInstrFlag, "-g", coverage.OutputFile.Path().String(), "-Wl,--wrap,open")
diff --git a/rust/rust.go b/rust/rust.go
index f4fda22..81c33e6 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -2129,7 +2129,7 @@
 	}
 
 	if mod.HasStubsVariants() {
-		if cc.IsSharedDepTag(depTag) {
+		if cc.IsSharedDepTag(depTag) && !cc.IsExplicitImplSharedDepTag(depTag) {
 			// dynamic dep to a stubs lib crosses APEX boundary
 			return false
 		}
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 34e11f0..ad315bf 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -73,6 +73,7 @@
 }
 
 func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		java.PrepareForTestWithDexpreopt,
@@ -514,7 +515,9 @@
 }
 
 func TestSnapshotWithBootClasspathFragment_Contents(t *testing.T) {
+	t.Parallel()
 	t.Run("added-directly", func(t *testing.T) {
+		t.Parallel()
 		testSnapshotWithBootClasspathFragment_Contents(t, `
 			sdk {
 				name: "mysdk",
@@ -566,6 +569,7 @@
 .intermediates/mycoreplatform.stubs.source/android_common/exportable/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
 `
 	t.Run("added-via-apex", func(t *testing.T) {
+		t.Parallel()
 		testSnapshotWithBootClasspathFragment_Contents(t, `
 			sdk {
 				name: "mysdk",
@@ -575,6 +579,7 @@
 	})
 
 	t.Run("added-directly-and-indirectly", func(t *testing.T) {
+		t.Parallel()
 		testSnapshotWithBootClasspathFragment_Contents(t, `
 			sdk {
 				name: "mysdk",
@@ -599,6 +604,7 @@
 // TestSnapshotWithBootClasspathFragment_Fragments makes sure that the fragments property of a
 // bootclasspath_fragment is correctly output to the sdk snapshot.
 func TestSnapshotWithBootClasspathFragment_Fragments(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		java.PrepareForTestWithJavaDefaultModules,
@@ -734,6 +740,7 @@
 
 // Test that bootclasspath_fragment works with sdk.
 func TestBasicSdkWithBootclasspathFragment(t *testing.T) {
+	t.Parallel()
 	android.GroupFixturePreparers(
 		prepareForSdkTestWithApex,
 		prepareForSdkTestWithJava,
@@ -752,6 +759,13 @@
 			bootclasspath_fragments: ["mybootclasspathfragment"],
 		}
 
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			min_sdk_version: "1",
+			bootclasspath_fragments: ["mybootclasspathfragment"],
+		}
+
 		bootclasspath_fragment {
 			name: "mybootclasspathfragment",
 			image_name: "art",
@@ -794,7 +808,7 @@
 		java_import {
 			name: "mybootlib",
 			visibility: ["//visibility:public"],
-			apex_available: ["com.android.art"],
+			apex_available: ["myapex"],
 			jars: ["java/mybootlib.jar"],
 		}
 	`),
@@ -802,6 +816,7 @@
 }
 
 func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		java.PrepareForTestWithJavaDefaultModules,
@@ -1127,7 +1142,9 @@
 }
 
 func TestSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T) {
+	t.Parallel()
 	t.Run("target S build", func(t *testing.T) {
+		t.Parallel()
 		expectedSnapshot := `
 // This is auto-generated. DO NOT EDIT.
 
@@ -1184,6 +1201,7 @@
 	})
 
 	t.Run("target-Tiramisu-build", func(t *testing.T) {
+		t.Parallel()
 		expectedSnapshot := `
 // This is auto-generated. DO NOT EDIT.
 
@@ -1268,6 +1286,7 @@
 }
 
 func TestSnapshotWithEmptyBootClasspathFragment(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		java.PrepareForTestWithJavaDefaultModules,
diff --git a/sdk/bp_test.go b/sdk/bp_test.go
index c620ac2..d3eaafe 100644
--- a/sdk/bp_test.go
+++ b/sdk/bp_test.go
@@ -73,6 +73,7 @@
 }
 
 func TestAddPropertySimple(t *testing.T) {
+	t.Parallel()
 	set := newPropertySet()
 	for name, val := range map[string]interface{}{
 		"x":   "taxi",
@@ -91,14 +92,17 @@
 }
 
 func TestAddPropertySubset(t *testing.T) {
+	t.Parallel()
 	getFixtureMap := map[string]func() interface{}{
 		"property set":    propertySetFixture,
 		"property struct": propertyStructFixture,
 	}
 
 	t.Run("add new subset", func(t *testing.T) {
+		t.Parallel()
 		for name, getFixture := range getFixtureMap {
 			t.Run(name, func(t *testing.T) {
+				t.Parallel()
 				set := propertySetFixture().(*bpPropertySet)
 				set.AddProperty("new", getFixture())
 				checkPropertySetFixture(t, set, true)
@@ -108,8 +112,10 @@
 	})
 
 	t.Run("merge existing subset", func(t *testing.T) {
+		t.Parallel()
 		for name, getFixture := range getFixtureMap {
 			t.Run(name, func(t *testing.T) {
+				t.Parallel()
 				set := newPropertySet()
 				subset := set.AddPropertySet("sub")
 				subset.AddProperty("flag", false)
@@ -123,12 +129,14 @@
 	})
 
 	t.Run("add conflicting subset", func(t *testing.T) {
+		t.Parallel()
 		set := propertySetFixture().(*bpPropertySet)
 		android.AssertPanicMessageContains(t, "adding x again should panic", `Property "x" already exists in property set`,
 			func() { set.AddProperty("x", propertySetFixture()) })
 	})
 
 	t.Run("add non-pointer struct", func(t *testing.T) {
+		t.Parallel()
 		set := propertySetFixture().(*bpPropertySet)
 		str := propertyStructFixture().(*propertyStruct)
 		android.AssertPanicMessageContains(t, "adding a non-pointer struct should panic", "Value is a struct, not a pointer to one:",
@@ -137,6 +145,7 @@
 }
 
 func TestAddPropertySetNew(t *testing.T) {
+	t.Parallel()
 	set := newPropertySet()
 	subset := set.AddPropertySet("sub")
 	subset.AddProperty("new", "d^^b")
@@ -144,6 +153,7 @@
 }
 
 func TestAddPropertySetExisting(t *testing.T) {
+	t.Parallel()
 	set := propertySetFixture().(*bpPropertySet)
 	subset := set.AddPropertySet("sub")
 	subset.AddProperty("new", "d^^b")
@@ -176,6 +186,7 @@
 }
 
 func TestTransformRemoveProperty(t *testing.T) {
+	t.Parallel()
 	set := newPropertySet()
 	set.AddProperty("name", "name")
 	set.AddProperty("fred", "12")
@@ -188,6 +199,7 @@
 }
 
 func TestTransformRemovePropertySet(t *testing.T) {
+	t.Parallel()
 	set := newPropertySet()
 	set.AddProperty("name", "name")
 	set.AddPropertySet("fred")
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 25839b8..5bac67d 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -58,6 +58,7 @@
 // Contains tests for SDK members provided by the cc package.
 
 func TestSingleDeviceOsAssumption(t *testing.T) {
+	t.Parallel()
 	// Mock a module with DeviceSupported() == true.
 	s := &sdk{}
 	android.InitAndroidArchModule(s, android.DeviceSupported, android.MultilibCommon)
@@ -72,6 +73,7 @@
 }
 
 func TestSdkIsCompileMultilibBoth(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -102,6 +104,7 @@
 }
 
 func TestSdkCompileMultilibOverride(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -161,6 +164,7 @@
 
 // Make sure the sdk can use host specific cc libraries static/shared and both.
 func TestHostSdkWithCc(t *testing.T) {
+	t.Parallel()
 	testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -184,6 +188,7 @@
 
 // Make sure the sdk can use cc libraries static/shared and both.
 func TestSdkWithCc(t *testing.T) {
+	t.Parallel()
 	testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -214,6 +219,7 @@
 }
 
 func TestSnapshotWithObject(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -268,6 +274,7 @@
 }
 
 func TestSnapshotWithCcDuplicateHeaders(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -305,6 +312,7 @@
 }
 
 func TestSnapshotWithCcExportGeneratedHeaders(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -393,6 +401,7 @@
 // handling is tested with the sanitize clauses (but note there's a lot of
 // built-in logic in sanitize.go that can affect those flags).
 func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -475,6 +484,7 @@
 }
 
 func TestSnapshotWithCcBinary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "mymodule_exports",
@@ -523,6 +533,7 @@
 }
 
 func TestMultipleHostOsTypesSnapshotWithCcBinary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "myexports",
@@ -604,6 +615,7 @@
 }
 
 func TestSnapshotWithSingleHostOsType(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTest,
 		ccTestFs.AddToFixture(),
@@ -721,6 +733,7 @@
 // Test that we support the necessary flags for the linker binary, which is
 // special in several ways.
 func TestSnapshotWithCcStaticNocrtBinary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "mymodule_exports",
@@ -785,19 +798,26 @@
 }
 
 func TestSnapshotWithCcSharedLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
 			native_shared_libs: ["mynativelib"],
 		}
 
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			min_sdk_version: "1",
+		}
+
 		cc_library_shared {
 			name: "mynativelib",
 			srcs: [
 				"Test.cpp",
 				"aidl/foo/bar/Test.aidl",
 			],
-			apex_available: ["apex1", "apex2"],
+			apex_available: ["myapex"],
 			export_include_dirs: ["myinclude"],
 			aidl: {
 				export_aidl_headers: true,
@@ -807,6 +827,18 @@
 	`)
 
 	CheckSnapshot(t, result, "mysdk", "",
+		snapshotTestPreparer(checkSnapshotWithoutSource,
+			android.FixtureMergeMockFs(android.MockFS{
+				"myapex/Android.bp": []byte(`
+				apex {
+					name: "myapex",
+					key: "myapex.key",
+					min_sdk_version: "1",
+				}
+				`),
+				"myapex/apex_manifest.json": nil,
+			}),
+		),
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -819,10 +851,7 @@
     name: "mynativelib",
     prefer: false,
     visibility: ["//visibility:public"],
-    apex_available: [
-        "apex1",
-        "apex2",
-    ],
+    apex_available: ["myapex"],
     stl: "none",
     compile_multilib: "both",
     export_include_dirs: ["include/myinclude"],
@@ -856,6 +885,7 @@
 }
 
 func TestSnapshotWithCcSharedLibrarySharedLibs(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -1005,6 +1035,7 @@
 }
 
 func TestHostSnapshotWithCcSharedLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -1085,6 +1116,7 @@
 }
 
 func TestMultipleHostOsTypesSnapshotWithCcSharedLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -1168,6 +1200,7 @@
 }
 
 func TestSnapshotWithCcStaticLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "myexports",
@@ -1232,6 +1265,7 @@
 }
 
 func TestHostSnapshotWithCcStaticLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "myexports",
@@ -1307,6 +1341,7 @@
 }
 
 func TestSnapshotWithCcLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "myexports",
@@ -1376,6 +1411,7 @@
 }
 
 func TestSnapshotSameLibraryWithNativeLibsAndNativeSharedLib(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			host_supported: true,
@@ -1477,6 +1513,7 @@
 }
 
 func TestSnapshotSameLibraryWithAndroidNativeLibsAndHostNativeSharedLib(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			host_supported: true,
@@ -1578,6 +1615,7 @@
 }
 
 func TestSnapshotSameLibraryWithNativeStaticLibsAndNativeSharedLib(t *testing.T) {
+	t.Parallel()
 	testSdkError(t, "Incompatible member types", `
 		module_exports {
 			host_supported: true,
@@ -1609,6 +1647,7 @@
 }
 
 func TestHostSnapshotWithMultiLib64(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "myexports",
@@ -1682,6 +1721,7 @@
 }
 
 func TestSnapshotWithCcHeadersLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -1721,6 +1761,7 @@
 }
 
 func TestSnapshotWithCcHeadersLibraryAndNativeBridgeSupport(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		cc.PrepareForTestWithCcDefaultModules,
 		PrepareForTestWithSdkBuildComponents,
@@ -1778,6 +1819,7 @@
 // module that has different output files for a native bridge target requests the native bridge
 // variants are copied into the sdk snapshot that it reports an error.
 func TestSnapshotWithCcHeadersLibrary_DetectsNativeBridgeSpecificProperties(t *testing.T) {
+	t.Parallel()
 	android.GroupFixturePreparers(
 		cc.PrepareForTestWithCcDefaultModules,
 		PrepareForTestWithSdkBuildComponents,
@@ -1814,6 +1856,7 @@
 }
 
 func TestSnapshotWithCcHeadersLibraryAndImageVariants(t *testing.T) {
+	t.Parallel()
 	testImageVariant := func(t *testing.T, property, trait string) {
 		result := android.GroupFixturePreparers(
 			cc.PrepareForTestWithCcDefaultModules,
@@ -1877,6 +1920,7 @@
 }
 
 func TestHostSnapshotWithCcHeadersLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -1933,6 +1977,7 @@
 }
 
 func TestDeviceAndHostSnapshotWithCcHeadersLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2002,6 +2047,7 @@
 }
 
 func TestSystemSharedLibPropagation(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2162,6 +2208,7 @@
 }
 
 func TestStubsLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2223,6 +2270,7 @@
 }
 
 func TestDeviceAndHostSnapshotWithStubsLibrary(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2299,6 +2347,7 @@
 }
 
 func TestUniqueHostSoname(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2364,6 +2413,7 @@
 }
 
 func TestNoSanitizerMembers(t *testing.T) {
+	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
diff --git a/sdk/compat_config_sdk_test.go b/sdk/compat_config_sdk_test.go
index 75b5229..1737b3a 100644
--- a/sdk/compat_config_sdk_test.go
+++ b/sdk/compat_config_sdk_test.go
@@ -76,6 +76,7 @@
 }
 
 func TestSnapshotWithCompatConfig(t *testing.T) {
+	t.Parallel()
 	testSnapshotWithCompatConfig(t, `
 		sdk {
 			name: "mysdk",
@@ -85,6 +86,7 @@
 }
 
 func TestSnapshotWithCompatConfig_Apex(t *testing.T) {
+	t.Parallel()
 	testSnapshotWithCompatConfig(t, `
 		apex {
 			name: "myapex",
diff --git a/sdk/exports_test.go b/sdk/exports_test.go
index 9d0a242..5a7ce84 100644
--- a/sdk/exports_test.go
+++ b/sdk/exports_test.go
@@ -20,6 +20,7 @@
 
 // Ensure that module_exports generates a module_exports_snapshot module.
 func TestModuleExportsSnapshot(t *testing.T) {
+	t.Parallel()
 	packageBp := `
 		module_exports {
 			name: "myexports",
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 4db163c..1e545ce 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -51,6 +51,7 @@
 // Contains tests for SDK members provided by the java package.
 
 func TestSdkDependsOnSourceEvenWhenPrebuiltPreferred(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -77,6 +78,7 @@
 }
 
 func TestSnapshotWithJavaHeaderLibrary(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		android.FixtureAddFile("aidl/foo/bar/Test.aidl", nil),
@@ -126,6 +128,7 @@
 }
 
 func TestHostSnapshotWithJavaHeaderLibrary(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		android.FixtureAddFile("aidl/foo/bar/Test.aidl", nil),
@@ -178,6 +181,7 @@
 }
 
 func TestDeviceAndHostSnapshotWithJavaHeaderLibrary(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -228,6 +232,7 @@
 }
 
 func TestSnapshotWithJavaImplLibrary(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		android.FixtureAddFile("aidl/foo/bar/Test.aidl", nil),
@@ -277,6 +282,7 @@
 }
 
 func TestSnapshotWithJavaBootLibrary(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		android.FixtureAddFile("aidl", nil),
@@ -328,6 +334,7 @@
 }
 
 func TestSnapshotWithJavaBootLibrary_UpdatableMedia(t *testing.T) {
+	t.Parallel()
 	runTest := func(t *testing.T, targetBuildRelease, expectedJarPath, expectedCopyRule string) {
 		result := android.GroupFixturePreparers(
 			prepareForSdkTestWithJava,
@@ -385,6 +392,7 @@
 }
 
 func TestSnapshotWithJavaLibrary_MinSdkVersion(t *testing.T) {
+	t.Parallel()
 	runTest := func(t *testing.T, targetBuildRelease, minSdkVersion, expectedMinSdkVersion string) {
 		result := android.GroupFixturePreparers(
 			prepareForSdkTestWithJava,
@@ -457,6 +465,7 @@
 }
 
 func TestSnapshotWithJavaSystemserverLibrary(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		android.FixtureAddFile("aidl", nil),
@@ -509,6 +518,7 @@
 }
 
 func TestHostSnapshotWithJavaImplLibrary(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		android.FixtureAddFile("aidl/foo/bar/Test.aidl", nil),
@@ -561,6 +571,7 @@
 }
 
 func TestSnapshotWithJavaTest(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
 		module_exports {
 			name: "myexports",
@@ -603,6 +614,7 @@
 }
 
 func TestHostSnapshotWithJavaTest(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
 		module_exports {
 			name: "myexports",
@@ -650,6 +662,7 @@
 }
 
 func TestSnapshotWithJavaSystemModules(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		java.PrepareForTestWithJavaDefaultModules,
@@ -853,6 +866,7 @@
 }
 
 func TestHostSnapshotWithJavaSystemModules(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -911,6 +925,7 @@
 }
 
 func TestDeviceAndHostSnapshotWithOsSpecificMembers(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
 		module_exports {
 			name: "myexports",
@@ -1004,6 +1019,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -1081,6 +1097,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_DistStem(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -1136,6 +1153,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_UseSrcJar(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJavaSdkLibrary,
 		android.FixtureMergeEnv(map[string]string{
@@ -1192,6 +1210,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_AnnotationsZip(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -1246,6 +1265,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_AnnotationsZip_PreT(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJavaSdkLibrary,
 		android.FixtureMergeEnv(map[string]string{
@@ -1303,6 +1323,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_CompileDex(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJavaSdkLibrary,
 		android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
@@ -1385,6 +1406,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_SdkVersion_None(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -1435,6 +1457,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -1488,6 +1511,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_ApiScopes(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -1555,6 +1579,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_ModuleLib(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -1636,6 +1661,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_SystemServer(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -1703,6 +1729,7 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_DoctagFiles(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJavaSdkLibrary,
 		android.FixtureAddFile("docs/known_doctags", nil),
diff --git a/sdk/license_sdk_test.go b/sdk/license_sdk_test.go
index 754f019..eb8112b 100644
--- a/sdk/license_sdk_test.go
+++ b/sdk/license_sdk_test.go
@@ -21,6 +21,7 @@
 )
 
 func TestSnapshotWithPackageDefaultLicense(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		android.PrepareForTestWithLicenses,
diff --git a/sdk/member_trait_test.go b/sdk/member_trait_test.go
index 673d6fb..9b41e9b 100644
--- a/sdk/member_trait_test.go
+++ b/sdk/member_trait_test.go
@@ -116,6 +116,7 @@
 }
 
 func TestBasicTrait_WithoutTrait(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		android.FixtureWithRootAndroidBp(`
@@ -154,6 +155,7 @@
 }
 
 func TestBasicTrait_MultipleTraits(t *testing.T) {
+	t.Parallel()
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		android.FixtureWithRootAndroidBp(`
@@ -262,6 +264,7 @@
 }
 
 func TestTraitUnsupportedByMemberType(t *testing.T) {
+	t.Parallel()
 	android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
 		android.FixtureWithRootAndroidBp(`
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 2532a25..b525eb8 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -40,6 +40,7 @@
 // Ensure that prebuilt modules have the same effective visibility as the source
 // modules.
 func TestSnapshotVisibility(t *testing.T) {
+	t.Parallel()
 	packageBp := `
 		package {
 			default_visibility: ["//other/foo"],
@@ -160,6 +161,7 @@
 }
 
 func TestSdkInstall(t *testing.T) {
+	t.Parallel()
 	sdk := `
 		sdk {
 			name: "mysdk",
@@ -326,6 +328,7 @@
 
 // Ensure that sdk snapshot related environment variables work correctly.
 func TestSnapshot_EnvConfiguration(t *testing.T) {
+	t.Parallel()
 	bp := `
 		sdk {
 			name: "mysdk",
@@ -352,6 +355,7 @@
 	}
 
 	t.Run("no env variables", func(t *testing.T) {
+		t.Parallel()
 		result := preparer.RunTest(t)
 
 		checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip")
@@ -377,6 +381,7 @@
 	})
 
 	t.Run("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE=S", func(t *testing.T) {
+		t.Parallel()
 		result := android.GroupFixturePreparers(
 			prepareForSdkTestWithJava,
 			java.PrepareForTestWithJavaDefaultModules,
@@ -468,6 +473,7 @@
 	})
 
 	t.Run("test replacing exportable module", func(t *testing.T) {
+		t.Parallel()
 		result := android.GroupFixturePreparers(
 			prepareForSdkTestWithJava,
 			java.PrepareForTestWithJavaDefaultModules,
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index fd6c4e7..7ebdcd4 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -87,10 +87,23 @@
 
 	CheckSnapshot(t, result, "mysdk", "",
 		checkAndroidBpContents(expectedSdkSnapshot),
+		snapshotTestPreparer(checkSnapshotWithoutSource,
+			android.FixtureMergeMockFs(android.MockFS{
+				"myapex/Android.bp": []byte(`
+				apex {
+					name: "myapex",
+					key: "myapex.key",
+					min_sdk_version: "1",
+				}
+				`),
+				"myapex/apex_manifest.json": nil,
+			}),
+		),
 	)
 }
 
 func TestSnapshotWithPartialSystemServerClasspathFragment(t *testing.T) {
+	t.Parallel()
 	commonSdk := `
 		apex {
 			name: "myapex",
@@ -185,6 +198,7 @@
 }
 
 func TestSnapshotWithEmptySystemServerClasspathFragment(t *testing.T) {
+	t.Parallel()
 	commonSdk := `
 		apex {
 			name: "myapex",
@@ -231,6 +245,7 @@
 }
 
 func TestSnapshotWithSystemServerClasspathFragment(t *testing.T) {
+	t.Parallel()
 
 	commonSdk := `
 sdk {
@@ -298,6 +313,7 @@
 `
 
 	t.Run("target-s", func(t *testing.T) {
+		t.Parallel()
 		testSnapshotWithSystemServerClasspathFragment(t, commonSdk, "S", `
 // This is auto-generated. DO NOT EDIT.
 
@@ -319,6 +335,7 @@
 	})
 
 	t.Run("target-t", func(t *testing.T) {
+		t.Parallel()
 		testSnapshotWithSystemServerClasspathFragment(t, commonSdk, "Tiramisu", `
 // This is auto-generated. DO NOT EDIT.
 
@@ -361,6 +378,7 @@
 	})
 
 	t.Run("target-u", func(t *testing.T) {
+		t.Parallel()
 		testSnapshotWithSystemServerClasspathFragment(t, commonSdk, "UpsideDownCake", `
 // This is auto-generated. DO NOT EDIT.
 
@@ -409,10 +427,12 @@
 	})
 
 	t.Run("added-directly", func(t *testing.T) {
+		t.Parallel()
 		testSnapshotWithSystemServerClasspathFragment(t, commonSdk, `latest`, expectedLatestSnapshot)
 	})
 
 	t.Run("added-via-apex", func(t *testing.T) {
+		t.Parallel()
 		testSnapshotWithSystemServerClasspathFragment(t, `
 			sdk {
 				name: "mysdk",
diff --git a/sdk/testing.go b/sdk/testing.go
index 21d457c..f5518c4 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -128,12 +128,11 @@
 // generated, etc.
 func getSdkSnapshotBuildInfo(t *testing.T, result *android.TestResult, sdk *sdk) *snapshotBuildInfo {
 	info := &snapshotBuildInfo{
-		t:                          t,
-		r:                          result,
-		androidBpContents:          sdk.GetAndroidBpContentsForTests(),
-		infoContents:               sdk.GetInfoContentsForTests(),
-		snapshotTestCustomizations: map[snapshotTest]*snapshotTestCustomization{},
-		targetBuildRelease:         sdk.builderForTests.targetBuildRelease,
+		t:                  t,
+		r:                  result,
+		androidBpContents:  sdk.GetAndroidBpContentsForTests(),
+		infoContents:       sdk.GetInfoContentsForTests(),
+		targetBuildRelease: sdk.builderForTests.targetBuildRelease,
 	}
 
 	buildParams := sdk.BuildParamsForTests()
@@ -293,6 +292,7 @@
 	}
 
 	t.Run("snapshot without source", func(t *testing.T) {
+		t.Parallel()
 		// Remove the source Android.bp file to make sure it works without.
 		removeSourceAndroidBp := android.FixtureModifyMockFS(func(fs android.MockFS) {
 			delete(fs, "Android.bp")
@@ -302,10 +302,12 @@
 	})
 
 	t.Run("snapshot with source preferred", func(t *testing.T) {
+		t.Parallel()
 		runSnapshotTestWithCheckers(t, checkSnapshotWithSourcePreferred, android.NullFixturePreparer)
 	})
 
 	t.Run("snapshot preferred with source", func(t *testing.T) {
+		t.Parallel()
 		// Replace the snapshot/Android.bp file with one where "prefer: false," has been replaced with
 		// "prefer: true,"
 		preferPrebuilts := android.FixtureModifyMockFS(func(fs android.MockFS) {
@@ -469,19 +471,40 @@
 	targetBuildRelease *buildRelease
 
 	// The test specific customizations for each snapshot test.
-	snapshotTestCustomizations map[snapshotTest]*snapshotTestCustomization
+	snapshotTestCustomizations snapshotTestCustomizationSet
+}
+
+type snapshotTestCustomizationSet struct {
+	snapshotWithoutSource       *snapshotTestCustomization
+	snapshotWithSourcePreferred *snapshotTestCustomization
+	snapshotPreferredWithSource *snapshotTestCustomization
+}
+
+func (s *snapshotTestCustomizationSet) customization(snapshotTest snapshotTest) **snapshotTestCustomization {
+	var customization **snapshotTestCustomization
+	switch snapshotTest {
+	case checkSnapshotWithoutSource:
+
+		customization = &s.snapshotWithoutSource
+	case checkSnapshotWithSourcePreferred:
+		customization = &s.snapshotWithSourcePreferred
+	case checkSnapshotPreferredWithSource:
+		customization = &s.snapshotPreferredWithSource
+	default:
+		panic(fmt.Errorf("unsupported snapshotTest %v", snapshotTest))
+	}
+	return customization
 }
 
 // snapshotTestCustomization gets the test specific customization for the specified snapshotTest.
 //
 // If no customization was created previously then it creates a default customization.
 func (i *snapshotBuildInfo) snapshotTestCustomization(snapshotTest snapshotTest) *snapshotTestCustomization {
-	customization := i.snapshotTestCustomizations[snapshotTest]
-	if customization == nil {
-		customization = &snapshotTestCustomization{
+	customization := i.snapshotTestCustomizations.customization(snapshotTest)
+	if *customization == nil {
+		*customization = &snapshotTestCustomization{
 			errorHandler: android.FixtureExpectsNoErrors,
 		}
-		i.snapshotTestCustomizations[snapshotTest] = customization
 	}
-	return customization
+	return *customization
 }
diff --git a/ui/build/build.go b/ui/build/build.go
index ea86782..95d7831 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -427,6 +427,9 @@
 	if config.Checkbuild() {
 		what |= RunBuildTests
 	}
+	if value, ok := config.environ.Get("RUN_BUILD_TESTS"); ok && value == "true" {
+		what |= RunBuildTests
+	}
 	if !config.SkipConfig() {
 		what |= RunProductConfig
 	} else {
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 7a2fd16..87bec93 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -76,8 +76,10 @@
 	// treated as an source file.
 	dexpreoptConfigFilePath := filepath.Join(outDir, "soong", "dexpreopt.config")
 
-	// out/build_date.txt is considered a "source file"
+	// out/build_(date|hostname|number).txt is considered a "source file"
 	buildDatetimeFilePath := filepath.Join(outDir, "build_date.txt")
+	buildHostnameFilePath := filepath.Join(outDir, "soong", "build_hostname.txt")
+	buildNumberFilePath := filepath.Join(outDir, "soong", "build_number.txt")
 
 	// release-config files are generated from the initial lunch or Kati phase
 	// before running soong and ninja.
@@ -102,6 +104,8 @@
 			line == extraVariablesFilePath ||
 			line == dexpreoptConfigFilePath ||
 			line == buildDatetimeFilePath ||
+			line == buildHostnameFilePath ||
+			line == buildNumberFilePath ||
 			strings.HasPrefix(line, releaseConfigDir) ||
 			buildFingerPrintFilePattern.MatchString(line) {
 			// Leaf node is in one of Soong's bootstrap directories, which do not have