Merge changes from topic "dangling_build_metadata_files" into main

* changes:
  Introduce an environment var to run "Test for dangling rules"
  Add build_* meta files to allowlist in Dangling rules check
diff --git a/android/apex.go b/android/apex.go
index 08c82eb..c2f73a9 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
 }
 
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..1e1f4bc 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -240,10 +240,22 @@
 		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")
+
+	buildMakeMetadataCsv = pctx.AndroidStaticRule("buildMakeMetadataCsv",
+		blueprint.RuleParams{
+			Command: `rm -rf $out && ` +
+				`echo "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" > $out`,
+		})
+
+	buildMakeModulesCsv = pctx.AndroidStaticRule("buildMakeModulesCsv",
+		blueprint.RuleParams{
+			Command: `rm -rf $out && ` +
+				`echo "name,module_path,module_class,module_type,static_libs,whole_static_libs,built_files,installed_files" > $out`,
+		})
 )
 
 func complianceMetadataSingletonFactory() Singleton {
@@ -311,29 +323,35 @@
 	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() {
+		ctx.Build(pctx, BuildParams{
+			Rule:   buildMakeMetadataCsv,
+			Output: makeMetadataCsv,
+		})
+		ctx.Build(pctx, BuildParams{
+			Rule:   buildMakeModulesCsv,
+			Output: makeModulesCsv,
+		})
 	}
 
 	// 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/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/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/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/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/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/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
 		}