Export depsInfo into android package.

Move depsInfo into android for easier sharing with APK code.

Bug: 149622332
Test: m, diff'ing outputs for conscrypt module.
Change-Id: If0ee967d37425540e69b4ce9304229d9f2cd86bd
Merged-In: If0ee967d37425540e69b4ce9304229d9f2cd86bd
Exempt-From-Owner-Approval: cp from aosp
(cherry picked from commit 872a144dca543f40ee232f26e0233e580d97e86d)
diff --git a/android/apex.go b/android/apex.go
index c7410a1..19f58d3 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -18,6 +18,7 @@
 	"fmt"
 	"sort"
 	"strconv"
+	"strings"
 	"sync"
 
 	"github.com/google/blueprint"
@@ -395,3 +396,52 @@
 
 	m.AddProperties(&base.ApexProperties)
 }
+
+// A dependency info for a single ApexModule, either direct or transitive.
+type ApexModuleDepInfo struct {
+	// Name of the dependency
+	To string
+	// List of dependencies To belongs to. Includes APEX itself, if a direct dependency.
+	From []string
+	// Whether the dependency belongs to the final compiled APEX.
+	IsExternal bool
+}
+
+// A map of a dependency name to its ApexModuleDepInfo
+type DepNameToDepInfoMap map[string]ApexModuleDepInfo
+
+type ApexBundleDepsInfo struct {
+	fullListPath OutputPath
+}
+
+type ApexDepsInfoIntf interface {
+	FullListPath() Path
+}
+
+func (d *ApexBundleDepsInfo) FullListPath() Path {
+	return d.fullListPath
+}
+
+var _ ApexDepsInfoIntf = (*ApexBundleDepsInfo)(nil)
+
+func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, depInfos DepNameToDepInfoMap) {
+	var content strings.Builder
+	for _, key := range FirstUniqueStrings(SortedStringKeys(depInfos)) {
+		info := depInfos[key]
+		toName := info.To
+		if info.IsExternal {
+			toName = toName + " (external)"
+		}
+		fmt.Fprintf(&content, "%s <- %s\\n", toName, strings.Join(SortedUniqueStrings(info.From), ", "))
+	}
+
+	d.fullListPath = PathForModuleOut(ctx, "depsinfo", "fulllist.txt").OutputPath
+	ctx.Build(pctx, BuildParams{
+		Rule:        WriteFile,
+		Description: "Full Dependency Info",
+		Output:      d.fullListPath,
+		Args: map[string]string{
+			"content": content.String(),
+		},
+	})
+}
diff --git a/apex/apex.go b/apex/apex.go
index 7191365..45ba908 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1276,12 +1276,6 @@
 	return false
 }
 
-type depInfo struct {
-	to         string
-	from       []string
-	isExternal bool
-}
-
 type apexBundle struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
@@ -1316,7 +1310,7 @@
 	requiredDeps []string
 
 	// list of module names that this APEX is including (to be shown via *-deps-info target)
-	depInfos map[string]depInfo
+	android.ApexBundleDepsInfo
 
 	testApex        bool
 	vndkApex        bool
@@ -1876,35 +1870,6 @@
 	}
 }
 
-// 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) bool {
-		if from.Name() == to.Name() {
-			// This can happen for cc.reuseObjTag. We are not interested in tracking this.
-			// As soon as the dependency graph crosses the APEX boundary, don't go further.
-			return !externalDep
-		}
-
-		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,
-			}
-		}
-
-		// As soon as the dependency graph crosses the APEX boundary, don't go further.
-		return !externalDep
-	})
-}
-
 func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
 	switch a.properties.ApexType {
@@ -1942,7 +1907,6 @@
 
 	a.checkApexAvailability(ctx)
 	a.checkUpdatable(ctx)
-	a.collectDepsInfo(ctx)
 
 	handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index f1d80ae..f0e7ff3 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -478,7 +478,7 @@
 	ensureListContains(t, noticeInputs, "custom_notice")
 	ensureListContains(t, noticeInputs, "custom_notice_for_static_lib")
 
-	depsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("myapex-deps-info.txt").Args["content"], "\\n")
+	depsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
 	ensureListContains(t, depsInfo, "myjar <- myapex")
 	ensureListContains(t, depsInfo, "mylib <- myapex")
 	ensureListContains(t, depsInfo, "mylib2 <- mylib")
@@ -784,7 +784,7 @@
 	// 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")
+	depsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
 
 	ensureListContains(t, depsInfo, "mylib <- myapex2")
 	ensureListContains(t, depsInfo, "libbaz <- mylib")
diff --git a/apex/builder.go b/apex/builder.go
index 0d7e801..a3e6929 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -679,29 +679,37 @@
 		return
 	}
 
-	var content strings.Builder
-	for _, key := range android.SortedStringKeys(a.depInfos) {
-		info := a.depInfos[key]
-		toName := info.to
-		if info.isExternal {
-			toName = toName + " (external)"
+	depInfos := android.DepNameToDepInfoMap{}
+	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+		if from.Name() == to.Name() {
+			// This can happen for cc.reuseObjTag. We are not interested in tracking this.
+			// As soon as the dependency graph crosses the APEX boundary, don't go further.
+			return !externalDep
 		}
-		fmt.Fprintf(&content, "%s <- %s\\n", toName, strings.Join(android.SortedUniqueStrings(info.from), ", "))
-	}
 
-	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(),
-		},
+		if info, exists := depInfos[to.Name()]; exists {
+			if !android.InList(from.Name(), info.From) {
+				info.From = append(info.From, from.Name())
+			}
+			info.IsExternal = info.IsExternal && externalDep
+			depInfos[to.Name()] = info
+		} else {
+			depInfos[to.Name()] = android.ApexModuleDepInfo{
+				To:         to.Name(),
+				From:       []string{from.Name()},
+				IsExternal: externalDep,
+			}
+		}
+
+		// As soon as the dependency graph crosses the APEX boundary, don't go further.
+		return !externalDep
 	})
 
+	a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, depInfos)
+
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   android.Phony,
 		Output: android.PathForPhony(ctx, a.Name()+"-deps-info"),
-		Inputs: []android.Path{depsInfoFile},
+		Inputs: []android.Path{a.ApexBundleDepsInfo.FullListPath()},
 	})
 }