Merge "<apex_name>-deps-info correctly tracks dependencies"
diff --git a/apex/apex.go b/apex/apex.go
index a2acb01e..df29c27 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1461,6 +1461,12 @@
 	return false
 }
 
+type depInfo struct {
+	to         string
+	from       []string
+	isExternal bool
+}
+
 type apexBundle struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
@@ -1494,10 +1500,8 @@
 	// 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
+	depInfos map[string]depInfo
 
 	testApex        bool
 	vndkApex        bool
@@ -1978,6 +1982,31 @@
 	})
 }
 
+// Collects the list of module names that directly or indirectly contributes to the payload of this APEX
+func (a *apexBundle) collectDepsInfo(ctx android.ModuleContext) {
+	a.depInfos = make(map[string]depInfo)
+	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+		if from.Name() == to.Name() {
+			// This can happen for cc.reuseObjTag. We are not interested in tracking this.
+			return
+		}
+
+		if info, exists := a.depInfos[to.Name()]; exists {
+			if !android.InList(from.Name(), info.from) {
+				info.from = append(info.from, from.Name())
+			}
+			info.isExternal = info.isExternal && externalDep
+			a.depInfos[to.Name()] = info
+		} else {
+			a.depInfos[to.Name()] = depInfo{
+				to:         to.Name(),
+				from:       []string{from.Name()},
+				isExternal: externalDep,
+			}
+		}
+	})
+}
+
 func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
 	switch a.properties.ApexType {
@@ -2015,6 +2044,8 @@
 
 	a.checkApexAvailability(ctx)
 
+	a.collectDepsInfo(ctx)
+
 	handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
 
 	// native lib dependencies
@@ -2046,13 +2077,11 @@
 	})
 
 	var filesInfo []apexFile
+	// TODO(jiyong) do this using walkPayloadDeps
 	ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
 		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 c, ok := child.(*cc.Module); ok {
@@ -2189,7 +2218,6 @@
 							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
@@ -2197,8 +2225,6 @@
 						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) {
@@ -2215,10 +2241,7 @@
 						return true // track transitive dependencies
 					}
 				} else if java.IsJniDepTag(depTag) {
-					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)
 				}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 508bde6..b128400 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -549,10 +549,11 @@
 	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")
+	ensureListContains(t, depsInfo, "myjar <- myapex")
+	ensureListContains(t, depsInfo, "mylib <- myapex")
+	ensureListContains(t, depsInfo, "mylib2 <- mylib")
+	ensureListContains(t, depsInfo, "myotherjar <- myjar")
+	ensureListContains(t, depsInfo, "mysharedjar (external) <- myjar")
 }
 
 func TestDefaults(t *testing.T) {
@@ -796,6 +797,7 @@
 			name: "mylib",
 			srcs: ["mylib.cpp"],
 			shared_libs: ["libfoo#10"],
+			static_libs: ["libbaz"],
 			system_shared_libs: [],
 			stl: "none",
 			apex_available: [ "myapex2" ],
@@ -819,6 +821,14 @@
 			stl: "none",
 		}
 
+		cc_library_static {
+			name: "libbaz",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			apex_available: [ "myapex2" ],
+		}
+
 	`)
 
 	apexRule := ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Rule("apexRule")
@@ -846,10 +856,10 @@
 	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")
+
+	ensureListContains(t, depsInfo, "mylib <- myapex2")
+	ensureListContains(t, depsInfo, "libbaz <- mylib")
+	ensureListContains(t, depsInfo, "libfoo (external) <- mylib")
 }
 
 func TestApexWithRuntimeLibsDependency(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index e267e49..5e0baf4 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -596,19 +596,14 @@
 		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)
+	for _, key := range android.SortedStringKeys(a.depInfos) {
+		info := a.depInfos[key]
+		toName := info.to
+		if info.isExternal {
+			toName = toName + " (external)"
+		}
+		fmt.Fprintf(&content, "%s <- %s\\n", toName, strings.Join(android.SortedUniqueStrings(info.from), ", "))
 	}
 
 	depsInfoFile := android.PathForOutput(ctx, a.Name()+"-deps-info.txt")
diff --git a/cc/cc.go b/cc/cc.go
index 6ceaf2e..ce9d33a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -407,13 +407,6 @@
 	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
@@ -477,9 +470,6 @@
 	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 {
@@ -1295,15 +1285,6 @@
 	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()
@@ -2389,8 +2370,6 @@
 		c.sabi.Properties.ReexportedIncludes = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludes)
 	}
 
-	c.allStaticDeps = gatherTransitiveStaticDeps(directStaticDeps)
-
 	return depPaths
 }
 
@@ -2550,10 +2529,6 @@
 	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/linkable.go b/cc/linkable.go
index 2abb112..e4f034c 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -54,8 +54,6 @@
 	ToolchainLibrary() bool
 	NdkPrebuiltStl() bool
 	StubDecorator() bool
-
-	AllStaticDeps() []string
 }
 
 type DependencyTag struct {
diff --git a/rust/rust.go b/rust/rust.go
index 33ef714..de6512c 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -354,11 +354,6 @@
 	return nil
 }
 
-func (mod *Module) AllStaticDeps() []string {
-	// TODO(jiyong): do this for rust?
-	return nil
-}
-
 func (mod *Module) Module() android.Module {
 	return mod
 }