Merge changes I828b3e6b,I5d85ea8b

* changes:
  rust: Do not pass -C prefer-dynamic for cdylib
  rust: Include Soong module name as metadata
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 7449a3f..b2fe8da 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -52,40 +52,13 @@
 		return moduleNames
 	}
 
-	var postInstallCommands []string
-	for _, fi := range a.filesInfo {
-		if a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform() {
-			// TODO(jiyong): pathOnDevice should come from fi.module, not being calculated here
-			linkTarget := filepath.Join("/system", fi.Path())
-			linkPath := filepath.Join(a.installDir.ToMakePath().String(), apexName, fi.Path())
-			mkdirCmd := "mkdir -p " + filepath.Dir(linkPath)
-			linkCmd := "ln -s " + linkTarget + " " + linkPath
-			postInstallCommands = append(postInstallCommands, mkdirCmd, linkCmd)
-		}
-	}
-	postInstallCommands = append(postInstallCommands, a.compatSymlinks...)
-
 	for _, fi := range a.filesInfo {
 		if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
 			continue
 		}
 
-		linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform()
-
-		var moduleName string
-		if linkToSystemLib {
-			moduleName = fi.moduleName
-		} else {
-			moduleName = fi.moduleName + "." + apexName + a.suffix
-		}
-
-		if !android.InList(moduleName, moduleNames) {
-			moduleNames = append(moduleNames, moduleName)
-		}
-
-		if linkToSystemLib {
-			// No need to copy the file since it's linked to the system file
-			continue
+		if !android.InList(fi.moduleName, moduleNames) {
+			moduleNames = append(moduleNames, fi.moduleName)
 		}
 
 		fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
@@ -94,7 +67,7 @@
 		} else {
 			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
 		}
-		fmt.Fprintln(w, "LOCAL_MODULE :=", moduleName)
+		fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName)
 		// /apex/<apex_name>/{lib|framework|...}
 		pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir)
 		if apexType == flattenedApex {
@@ -178,9 +151,19 @@
 			fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk")
 		} else {
 			fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
-			// For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex
-			if a.primaryApexType && apexType == flattenedApex && fi.builtFile == a.manifestPbOut && len(postInstallCommands) > 0 {
-				fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(postInstallCommands, " && "))
+			if a.primaryApexType && fi.builtFile == a.manifestPbOut {
+				// Make apex_manifest.pb module for this APEX to override all other
+				// modules in the APEXes being overridden by this APEX
+				var patterns []string
+				for _, o := range a.overridableProperties.Overrides {
+					patterns = append(patterns, "%."+o+a.suffix)
+				}
+				fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(patterns, " "))
+
+				if len(a.compatSymlinks) > 0 {
+					// For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex
+					fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(a.compatSymlinks, " && "))
+				}
 			}
 			fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
 		}
@@ -243,8 +226,8 @@
 				if len(moduleNames) > 0 {
 					fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(moduleNames, " "))
 				}
-				if len(a.externalDeps) > 0 {
-					fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.externalDeps, " "))
+				if len(a.requiredDeps) > 0 {
+					fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.requiredDeps, " "))
 				}
 				a.writeRequiredModules(w)
 				var postInstallCommands []string
diff --git a/apex/apex.go b/apex/apex.go
index fb61a58..7d6b7f0 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -341,6 +341,8 @@
 	// Whether this APEX should support Android10. Default is false. If this is set true, then apex_manifest.json is bundled as well
 	// because Android10 requires legacy apex_manifest.json instead of apex_manifest.pb
 	Legacy_android10_support *bool
+
+	IsCoverageVariant bool `blueprint:"mutated"`
 }
 
 type apexTargetBundleProperties struct {
@@ -490,30 +492,6 @@
 	return af.builtFile != nil && af.builtFile.String() != ""
 }
 
-// Path() returns path of this apex file relative to the APEX root
-func (af *apexFile) Path() string {
-	return filepath.Join(af.installDir, af.builtFile.Base())
-}
-
-// SymlinkPaths() returns paths of the symlinks (if any) relative to the APEX root
-func (af *apexFile) SymlinkPaths() []string {
-	var ret []string
-	for _, symlink := range af.symlinks {
-		ret = append(ret, filepath.Join(af.installDir, symlink))
-	}
-	return ret
-}
-
-func (af *apexFile) AvailableToPlatform() bool {
-	if af.module == nil {
-		return false
-	}
-	if am, ok := af.module.(android.ApexModule); ok {
-		return am.AvailableFor(android.AvailableToPlatform)
-	}
-	return false
-}
-
 type apexBundle struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
@@ -544,8 +522,13 @@
 	// list of files to be included in this apex
 	filesInfo []apexFile
 
-	// list of module names that this APEX is depending on
+	// list of module names that should be installed along with this APEX
+	requiredDeps []string
+
+	// list of module names that this APEX is depending on (to be shown via *-deps-info target)
 	externalDeps []string
+	// list of module names that this APEX is including (to be shown via *-deps-info target)
+	internalDeps []string
 
 	testApex        bool
 	vndkApex        bool
@@ -564,10 +547,6 @@
 	// Suffix of module name in Android.mk
 	// ".flattened", ".apex", ".zipapex", or ""
 	suffix string
-
-	// Whether to create symlink to the system file instead of having a file
-	// inside the apex or not
-	linkToSystemLib bool
 }
 
 func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
@@ -845,6 +824,10 @@
 	a.properties.HideFromMake = true
 }
 
+func (a *apexBundle) MarkAsCoverageVariant(coverage bool) {
+	a.properties.IsCoverageVariant = coverage
+}
+
 // TODO(jiyong) move apexFileFor* close to the apexFile type definition
 func apexFileForNativeLibrary(ctx android.BaseModuleContext, ccMod *cc.Module, handleSpecialLibs bool) apexFile {
 	// Decide the APEX-local directory by the multilib of the library
@@ -973,7 +956,7 @@
 			a.primaryApexType = true
 
 			if ctx.Config().InstallExtraFlattenedApexes() {
-				a.externalDeps = append(a.externalDeps, a.Name()+flattenedSuffix)
+				a.requiredDeps = append(a.requiredDeps, a.Name()+flattenedSuffix)
 			}
 		}
 	case zipApex:
@@ -1032,6 +1015,9 @@
 		depTag := ctx.OtherModuleDependencyTag(child)
 		depName := ctx.OtherModuleName(child)
 		if _, isDirectDep := parent.(*apexBundle); isDirectDep {
+			if depTag != keyTag && depTag != certificateTag {
+				a.internalDeps = append(a.internalDeps, depName)
+			}
 			switch depTag {
 			case sharedLibTag:
 				if cc, ok := child.(*cc.Module); ok {
@@ -1162,9 +1148,10 @@
 							//
 							// Always include if we are a host-apex however since those won't have any
 							// system libraries.
-							if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.Name(), a.externalDeps) {
-								a.externalDeps = append(a.externalDeps, cc.Name())
+							if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.Name(), a.requiredDeps) {
+								a.requiredDeps = append(a.requiredDeps, cc.Name())
 							}
+							a.externalDeps = append(a.externalDeps, depName)
 							requireNativeLibs = append(requireNativeLibs, cc.OutputFile().Path().Base())
 							// Don't track further
 							return false
@@ -1172,6 +1159,8 @@
 						af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs)
 						af.transitiveDep = true
 						filesInfo = append(filesInfo, af)
+						a.internalDeps = append(a.internalDeps, depName)
+						a.internalDeps = append(a.internalDeps, cc.AllStaticDeps()...)
 						return true // track transitive dependencies
 					}
 				} else if cc.IsTestPerSrcDepTag(depTag) {
@@ -1182,14 +1171,15 @@
 						// of the original test module (`depName`, shared by all `test_per_src`
 						// variations of that module).
 						af.moduleName = filepath.Base(af.builtFile.String())
-						// these are not considered transitive dep
-						af.transitiveDep = false
+						af.transitiveDep = true
 						filesInfo = append(filesInfo, af)
 						return true // track transitive dependencies
 					}
 				} else if java.IsJniDepTag(depTag) {
-					// Do nothing for JNI dep. JNI libraries are always embedded in APK-in-APEX.
+					a.externalDeps = append(a.externalDeps, depName)
 					return true
+				} else if java.IsStaticLibDepTag(depTag) {
+					a.internalDeps = append(a.internalDeps, depName)
 				} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
 					ctx.ModuleErrorf("unexpected tag %q for indirect dependency %q", depTag, depName)
 				}
@@ -1219,22 +1209,15 @@
 
 	// remove duplicates in filesInfo
 	removeDup := func(filesInfo []apexFile) []apexFile {
-		encountered := make(map[string]apexFile)
+		encountered := make(map[string]bool)
+		result := []apexFile{}
 		for _, f := range filesInfo {
 			dest := filepath.Join(f.installDir, f.builtFile.Base())
-			if e, ok := encountered[dest]; !ok {
-				encountered[dest] = f
-			} else {
-				// If a module is directly included and also transitively depended on
-				// consider it as directly included.
-				e.transitiveDep = e.transitiveDep && f.transitiveDep
-				encountered[dest] = e
+			if !encountered[dest] {
+				encountered[dest] = true
+				result = append(result, f)
 			}
 		}
-		var result []apexFile
-		for _, v := range encountered {
-			result = append(result, v)
-		}
 		return result
 	}
 	filesInfo = removeDup(filesInfo)
@@ -1256,6 +1239,12 @@
 		}
 	}
 
+	// prepend the name of this APEX to the module names. These names will be the names of
+	// modules that will be defined if the APEX is flattened.
+	for i := range filesInfo {
+		filesInfo[i].moduleName = filesInfo[i].moduleName + "." + a.Name() + a.suffix
+	}
+
 	a.installDir = android.PathForModuleInstall(ctx, "apex")
 	a.filesInfo = filesInfo
 
@@ -1275,14 +1264,6 @@
 			return
 		}
 	}
-	// Optimization. If we are building bundled APEX, for the files that are gathered due to the
-	// transitive dependencies, don't place them inside the APEX, but place a symlink pointing
-	// the same library in the system partition, thus effectively sharing the same libraries
-	// across the APEX boundary. For unbundled APEX, all the gathered files are actually placed
-	// in the APEX.
-	a.linkToSystemLib = !ctx.Config().UnbundledBuild() &&
-		a.installable() &&
-		!proptools.Bool(a.properties.Use_vendor)
 
 	// prepare apex_manifest.json
 	a.buildManifest(ctx, provideNativeLibs, requireNativeLibs)
@@ -1295,6 +1276,8 @@
 	}
 
 	a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
+
+	a.buildApexDependencyInfo(ctx)
 }
 
 func newApexBundle() *apexBundle {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 01549bb..b37674f 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -91,10 +91,6 @@
 	config.TestProductVariables.Binder32bit = proptools.BoolPtr(true)
 }
 
-func withUnbundledBuild(fs map[string][]byte, config android.Config) {
-	config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
-}
-
 func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
 	android.ClearApexDependency()
 
@@ -223,6 +219,7 @@
 		"apex_manifest.json":                                  nil,
 		"AndroidManifest.xml":                                 nil,
 		"system/sepolicy/apex/myapex-file_contexts":           nil,
+		"system/sepolicy/apex/myapex2-file_contexts":          nil,
 		"system/sepolicy/apex/otherapex-file_contexts":        nil,
 		"system/sepolicy/apex/commonapex-file_contexts":       nil,
 		"system/sepolicy/apex/com.android.vndk-file_contexts": nil,
@@ -524,6 +521,12 @@
 	}
 	ensureListContains(t, noticeInputs, "NOTICE")
 	ensureListContains(t, noticeInputs, "custom_notice")
+
+	depsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("myapex-deps-info.txt").Args["content"], "\\n")
+	ensureListContains(t, depsInfo, "internal myjar")
+	ensureListContains(t, depsInfo, "internal mylib")
+	ensureListContains(t, depsInfo, "internal mylib2")
+	ensureListContains(t, depsInfo, "internal myotherjar")
 }
 
 func TestDefaults(t *testing.T) {
@@ -744,13 +747,13 @@
 func TestApexWithExplicitStubsDependency(t *testing.T) {
 	ctx, _ := testApex(t, `
 		apex {
-			name: "myapex",
-			key: "myapex.key",
+			name: "myapex2",
+			key: "myapex2.key",
 			native_shared_libs: ["mylib"],
 		}
 
 		apex_key {
-			name: "myapex.key",
+			name: "myapex2.key",
 			public_key: "testkey.avbpubkey",
 			private_key: "testkey.pem",
 		}
@@ -783,7 +786,7 @@
 
 	`)
 
-	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
+	apexRule := ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Rule("apexRule")
 	copyCmds := apexRule.Args["copy_commands"]
 
 	// Ensure that direct non-stubs dep is always included
@@ -795,7 +798,7 @@
 	// Ensure that dependency of stubs is not included
 	ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
 
-	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
+	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex2").Rule("ld").Args["libFlags"]
 
 	// Ensure that mylib is linking with version 10 of libfoo
 	ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10/libfoo.so")
@@ -806,6 +809,12 @@
 
 	// Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
 	ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
+
+	depsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("myapex2-deps-info.txt").Args["content"], "\\n")
+	ensureListContains(t, depsInfo, "internal mylib")
+	ensureListContains(t, depsInfo, "external libfoo")
+	ensureListNotContains(t, depsInfo, "internal libfoo")
+	ensureListNotContains(t, depsInfo, "external mylib")
 }
 
 func TestApexWithRuntimeLibsDependency(t *testing.T) {
@@ -1535,68 +1544,46 @@
 	ensureContains(t, cFlags, "-Imy_include")
 }
 
-type fileInApex struct {
-	path   string // path in apex
-	isLink bool
-}
-
-func getFiles(t *testing.T, ctx *android.TestContext, moduleName string) []fileInApex {
+func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName string, files []string) {
 	t.Helper()
 	apexRule := ctx.ModuleForTests(moduleName, "android_common_"+moduleName+"_image").Rule("apexRule")
 	copyCmds := apexRule.Args["copy_commands"]
 	imageApexDir := "/image.apex/"
-	var ret []fileInApex
+	var failed bool
+	var surplus []string
+	filesMatched := make(map[string]bool)
+	addContent := func(content string) {
+		for _, expected := range files {
+			if matched, _ := path.Match(expected, content); matched {
+				filesMatched[expected] = true
+				return
+			}
+		}
+		surplus = append(surplus, content)
+	}
 	for _, cmd := range strings.Split(copyCmds, "&&") {
 		cmd = strings.TrimSpace(cmd)
 		if cmd == "" {
 			continue
 		}
 		terms := strings.Split(cmd, " ")
-		var dst string
-		var isLink bool
 		switch terms[0] {
 		case "mkdir":
 		case "cp":
 			if len(terms) != 3 {
 				t.Fatal("copyCmds contains invalid cp command", cmd)
 			}
-			dst = terms[2]
-			isLink = false
-		case "ln":
-			if len(terms) != 3 && len(terms) != 4 {
-				// ln LINK TARGET or ln -s LINK TARGET
-				t.Fatal("copyCmds contains invalid ln command", cmd)
-			}
-			dst = terms[len(terms)-1]
-			isLink = true
-		default:
-			t.Fatalf("copyCmds should contain mkdir/cp commands only: %q", cmd)
-		}
-		if dst != "" {
+			dst := terms[2]
 			index := strings.Index(dst, imageApexDir)
 			if index == -1 {
 				t.Fatal("copyCmds should copy a file to image.apex/", cmd)
 			}
 			dstFile := dst[index+len(imageApexDir):]
-			ret = append(ret, fileInApex{path: dstFile, isLink: isLink})
+			addContent(dstFile)
+		default:
+			t.Fatalf("copyCmds should contain mkdir/cp commands only: %q", cmd)
 		}
 	}
-	return ret
-}
-
-func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName string, files []string) {
-	var failed bool
-	var surplus []string
-	filesMatched := make(map[string]bool)
-	for _, file := range getFiles(t, ctx, moduleName) {
-		for _, expected := range files {
-			if matched, _ := path.Match(expected, file.path); matched {
-				filesMatched[expected] = true
-				return
-			}
-		}
-		surplus = append(surplus, file.path)
-	}
 
 	if len(surplus) > 0 {
 		sort.Strings(surplus)
@@ -2678,7 +2665,7 @@
 		config.TestProductVariables.InstallExtraFlattenedApexes = proptools.BoolPtr(true)
 	})
 	ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	ensureListContains(t, ab.externalDeps, "myapex.flattened")
+	ensureListContains(t, ab.requiredDeps, "myapex.flattened")
 	mk := android.AndroidMkDataForTest(t, config, "", ab)
 	var builder strings.Builder
 	mk.Custom(&builder, ab.Name(), "TARGET_", "", mk)
@@ -3391,90 +3378,6 @@
 	ensureContains(t, androidMk, "LOCAL_TARGET_REQUIRED_MODULES += e f\n")
 }
 
-func TestSymlinksFromApexToSystem(t *testing.T) {
-	bp := `
-		apex {
-			name: "myapex",
-			key: "myapex.key",
-			native_shared_libs: ["mylib"],
-			java_libs: ["myjar"],
-		}
-
-		apex_key {
-			name: "myapex.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-
-		cc_library {
-			name: "mylib",
-			srcs: ["mylib.cpp"],
-			shared_libs: ["myotherlib"],
-			system_shared_libs: [],
-			stl: "none",
-		}
-
-		cc_library {
-			name: "myotherlib",
-			srcs: ["mylib.cpp"],
-			system_shared_libs: [],
-			stl: "none",
-		}
-
-		java_library {
-			name: "myjar",
-			srcs: ["foo/bar/MyClass.java"],
-			sdk_version: "none",
-			system_modules: "none",
-			libs: ["myotherjar"],
-			compile_dex: true,
-		}
-
-		java_library {
-			name: "myotherjar",
-			srcs: ["foo/bar/MyClass.java"],
-			sdk_version: "none",
-			system_modules: "none",
-		}
-	`
-
-	ensureRealfileExists := func(t *testing.T, files []fileInApex, file string) {
-		for _, f := range files {
-			if f.path == file {
-				if f.isLink {
-					t.Errorf("%q is not a real file", file)
-				}
-				return
-			}
-		}
-		t.Errorf("%q is not found", file)
-	}
-
-	ensureSymlinkExists := func(t *testing.T, files []fileInApex, file string) {
-		for _, f := range files {
-			if f.path == file {
-				if !f.isLink {
-					t.Errorf("%q is not a symlink", file)
-				}
-				return
-			}
-		}
-		t.Errorf("%q is not found", file)
-	}
-
-	ctx, _ := testApex(t, bp, withUnbundledBuild)
-	files := getFiles(t, ctx, "myapex")
-	ensureRealfileExists(t, files, "javalib/myjar.jar")
-	ensureRealfileExists(t, files, "lib64/mylib.so")
-	ensureRealfileExists(t, files, "lib64/myotherlib.so")
-
-	ctx, _ = testApex(t, bp)
-	files = getFiles(t, ctx, "myapex")
-	ensureRealfileExists(t, files, "javalib/myjar.jar")
-	ensureRealfileExists(t, files, "lib64/mylib.so")
-	ensureSymlinkExists(t, files, "lib64/myotherlib.so") // this is symlink
-}
-
 func TestMain(m *testing.M) {
 	run := func() int {
 		setUp()
diff --git a/apex/builder.go b/apex/builder.go
index e16df02..2f1e453 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -245,41 +245,36 @@
 
 	apexType := a.properties.ApexType
 	suffix := apexType.suffix()
-	var implicitInputs []android.Path
 	unsignedOutputFile := android.PathForModuleOut(ctx, a.Name()+suffix+".unsigned")
 
-	// TODO(jiyong): construct the copy rules using RuleBuilder
-	var copyCommands []string
-	for _, fi := range a.filesInfo {
-		destPath := android.PathForModuleOut(ctx, "image"+suffix, fi.Path()).String()
-		copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(destPath))
-		if a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform() {
-			// TODO(jiyong): pathOnDevice should come from fi.module, not being calculated here
-			pathOnDevice := filepath.Join("/system", fi.Path())
-			copyCommands = append(copyCommands, "ln -s "+pathOnDevice+" "+destPath)
-		} else {
-			copyCommands = append(copyCommands, "cp "+fi.builtFile.String()+" "+destPath)
-			implicitInputs = append(implicitInputs, fi.builtFile)
-		}
-		// create additional symlinks pointing the file inside the APEX
-		for _, symlinkPath := range fi.SymlinkPaths() {
-			symlinkDest := android.PathForModuleOut(ctx, "image"+suffix, symlinkPath).String()
-			copyCommands = append(copyCommands, "ln -s "+filepath.Base(destPath)+" "+symlinkDest)
-		}
+	filesToCopy := []android.Path{}
+	for _, f := range a.filesInfo {
+		filesToCopy = append(filesToCopy, f.builtFile)
 	}
 
-	// TODO(jiyong): use RuleBuilder
-	var emitCommands []string
-	imageContentFile := android.PathForModuleOut(ctx, "content.txt")
+	copyCommands := []string{}
+	emitCommands := []string{}
+	imageContentFile := android.PathForModuleOut(ctx, a.Name()+"-content.txt")
 	emitCommands = append(emitCommands, "echo ./apex_manifest.pb >> "+imageContentFile.String())
 	if proptools.Bool(a.properties.Legacy_android10_support) {
 		emitCommands = append(emitCommands, "echo ./apex_manifest.json >> "+imageContentFile.String())
 	}
-	for _, fi := range a.filesInfo {
-		emitCommands = append(emitCommands, "echo './"+fi.Path()+"' >> "+imageContentFile.String())
+	for i, src := range filesToCopy {
+		dest := filepath.Join(a.filesInfo[i].installDir, src.Base())
+		emitCommands = append(emitCommands, "echo './"+dest+"' >> "+imageContentFile.String())
+		dest_path := filepath.Join(android.PathForModuleOut(ctx, "image"+suffix).String(), dest)
+		copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path))
+		copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path)
+		for _, sym := range a.filesInfo[i].symlinks {
+			symlinkDest := filepath.Join(filepath.Dir(dest_path), sym)
+			copyCommands = append(copyCommands, "ln -s "+filepath.Base(dest)+" "+symlinkDest)
+		}
 	}
 	emitCommands = append(emitCommands, "sort -o "+imageContentFile.String()+" "+imageContentFile.String())
 
+	implicitInputs := append(android.Paths(nil), filesToCopy...)
+	implicitInputs = append(implicitInputs, a.manifestPbOut)
+
 	if a.properties.Whitelisted_files != nil {
 		ctx.Build(pctx, android.BuildParams{
 			Rule:        emitApexContentRule,
@@ -401,7 +396,6 @@
 			optFlags = append(optFlags, "--do_not_check_keyname")
 		}
 
-		implicitInputs = append(implicitInputs, a.manifestPbOut)
 		if proptools.Bool(a.properties.Legacy_android10_support) {
 			implicitInputs = append(implicitInputs, a.manifestJsonOut)
 			optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
@@ -519,7 +513,7 @@
 	if a.installable() {
 		// For flattened APEX, do nothing but make sure that APEX manifest and apex_pubkey are also copied along
 		// with other ordinary files.
-		a.filesInfo = append(a.filesInfo, newApexFile(ctx, a.manifestPbOut, "apex_manifest.pb", ".", etc, nil))
+		a.filesInfo = append(a.filesInfo, newApexFile(ctx, a.manifestPbOut, "apex_manifest.pb."+a.Name()+a.suffix, ".", etc, nil))
 
 		// rename to apex_pubkey
 		copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
@@ -528,7 +522,7 @@
 			Input:  a.public_key_file,
 			Output: copiedPubkey,
 		})
-		a.filesInfo = append(a.filesInfo, newApexFile(ctx, copiedPubkey, "apex_pubkey", ".", etc, nil))
+		a.filesInfo = append(a.filesInfo, newApexFile(ctx, copiedPubkey, "apex_pubkey."+a.Name()+a.suffix, ".", etc, nil))
 
 		if a.properties.ApexType == flattenedApex {
 			apexName := proptools.StringDefault(a.properties.Apex_name, a.Name())
@@ -560,3 +554,51 @@
 	}
 	return ""
 }
+
+func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) {
+	if !a.primaryApexType {
+		return
+	}
+
+	if a.properties.IsCoverageVariant {
+		// Otherwise, we will have duplicated rules for coverage and
+		// non-coverage variants of the same APEX
+		return
+	}
+
+	if ctx.Host() {
+		// No need to generate dependency info for host variant
+		return
+	}
+
+	internalDeps := a.internalDeps
+	externalDeps := a.externalDeps
+
+	internalDeps = android.SortedUniqueStrings(internalDeps)
+	externalDeps = android.SortedUniqueStrings(externalDeps)
+	externalDeps = android.RemoveListFromList(externalDeps, internalDeps)
+
+	var content strings.Builder
+	for _, name := range internalDeps {
+		fmt.Fprintf(&content, "internal %s\\n", name)
+	}
+	for _, name := range externalDeps {
+		fmt.Fprintf(&content, "external %s\\n", name)
+	}
+
+	depsInfoFile := android.PathForOutput(ctx, a.Name()+"-deps-info.txt")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.WriteFile,
+		Description: "Dependency Info",
+		Output:      depsInfoFile,
+		Args: map[string]string{
+			"content": content.String(),
+		},
+	})
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   android.Phony,
+		Output: android.PathForPhony(ctx, a.Name()+"-deps-info"),
+		Inputs: []android.Path{depsInfoFile},
+	})
+}
diff --git a/cc/cc.go b/cc/cc.go
index 04f0351..d1b97b4 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -398,6 +398,13 @@
 	return ok && ccDepTag.Shared
 }
 
+func IsStaticDepTag(depTag blueprint.DependencyTag) bool {
+	ccDepTag, ok := depTag.(DependencyTag)
+	return ok && (ccDepTag == staticExportDepTag ||
+		ccDepTag == lateStaticDepTag ||
+		ccDepTag == wholeStaticDepTag)
+}
+
 func IsRuntimeDepTag(depTag blueprint.DependencyTag) bool {
 	ccDepTag, ok := depTag.(DependencyTag)
 	return ok && ccDepTag == runtimeDepTag
@@ -463,6 +470,9 @@
 	makeLinkType string
 	// Kythe (source file indexer) paths for this compilation module
 	kytheFiles android.Paths
+
+	// name of the modules that are direct or indirect static deps of this module
+	allStaticDeps []string
 }
 
 func (c *Module) Toc() android.OptionalPath {
@@ -1258,6 +1268,15 @@
 	return results
 }
 
+func gatherTransitiveStaticDeps(staticDeps []LinkableInterface) []string {
+	var ret []string
+	for _, dep := range staticDeps {
+		ret = append(ret, dep.Module().Name())
+		ret = append(ret, dep.AllStaticDeps()...)
+	}
+	return android.FirstUniqueStrings(ret)
+}
+
 func (c *Module) IsTestPerSrcAllTestsVariation() bool {
 	test, ok := c.linker.(testPerSrc)
 	return ok && test.isAllTestsVariation()
@@ -2328,6 +2347,8 @@
 		c.sabi.Properties.ReexportedIncludes = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludes)
 	}
 
+	c.allStaticDeps = gatherTransitiveStaticDeps(directStaticDeps)
+
 	return depPaths
 }
 
@@ -2481,6 +2502,10 @@
 	return false
 }
 
+func (c *Module) AllStaticDeps() []string {
+	return c.allStaticDeps
+}
+
 func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
 	if c.linker != nil {
 		if library, ok := c.linker.(*libraryDecorator); ok {
diff --git a/cc/coverage.go b/cc/coverage.go
index c03a568..b6451ee 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -163,6 +163,7 @@
 	IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool
 	PreventInstall()
 	HideFromMake()
+	MarkAsCoverageVariant(bool)
 }
 
 func coverageMutator(mctx android.BottomUpMutatorContext) {
@@ -191,6 +192,7 @@
 		// module which are split into "" and "cov" variants. e.g. when cc_test refers
 		// to an APEX via 'data' property.
 		m := mctx.CreateVariations("", "cov")
+		m[0].(Coverage).MarkAsCoverageVariant(true)
 		m[0].(Coverage).PreventInstall()
 		m[0].(Coverage).HideFromMake()
 	}
diff --git a/cc/linkable.go b/cc/linkable.go
index 815d405..106092b 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -51,6 +51,8 @@
 	ToolchainLibrary() bool
 	NdkPrebuiltStl() bool
 	StubDecorator() bool
+
+	AllStaticDeps() []string
 }
 
 type DependencyTag struct {
diff --git a/java/app.go b/java/app.go
index 05fa505..a6b3408 100755
--- a/java/app.go
+++ b/java/app.go
@@ -752,6 +752,7 @@
 
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
+	android.InitApexModule(module)
 	return module
 }
 
diff --git a/java/java.go b/java/java.go
index a546cd5..4c6a5a5 100644
--- a/java/java.go
+++ b/java/java.go
@@ -500,6 +500,14 @@
 	usesLibTag            = dependencyTag{name: "uses-library"}
 )
 
+func IsLibDepTag(depTag blueprint.DependencyTag) bool {
+	return depTag == libTag
+}
+
+func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool {
+	return depTag == staticLibTag
+}
+
 type sdkDep struct {
 	useModule, useFiles, useDefaultLibs, invalidVersion bool
 
@@ -619,12 +627,9 @@
 			}
 
 			linkType, _ := j.getLinkType(ctx.ModuleName())
-			if linkType == javaSystem {
+			// only platform modules can use internal props
+			if linkType != javaPlatform {
 				ret[idx] = stub
-			} else if linkType != javaPlatform {
-				ctx.PropertyErrorf("sdk_version",
-					"can't link against sysprop_library %q from a module using public or core API",
-					lib)
 			}
 		}
 
diff --git a/rust/rust.go b/rust/rust.go
index 0eab8d2..14513fb 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -346,6 +346,11 @@
 	return nil
 }
 
+func (mod *Module) AllStaticDeps() []string {
+	// TODO(jiyong): do this for rust?
+	return nil
+}
+
 func (mod *Module) Module() android.Module {
 	return mod
 }
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index ee6e9dc..bfe662d 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -87,7 +87,6 @@
 	"java":     Allowed,
 	"javap":    Allowed,
 	"lsof":     Allowed,
-	"m4":       Log,
 	"openssl":  Allowed,
 	"patch":    Allowed,
 	"pstree":   Allowed,