Dedupe logic to generate linker.config.pb

Between android_filesystem and generic_system_image.
`getLibsForLinkerConfig` will return a list of provideLibs and
requireLibs for the fileystem. `linkerConfig.BuildLinkerConfig` will
then filer out the non-stub libraries.

For `android_filesystem`, requireLibs is ignored for now to match the
logic in the kati built vendor.img

Test: m nothing --no-skip-soong-tests
Test: no diff in out/soong/.intermediates/build/make/target/product/generic/generic_system_image/android_common/gen/root-extra/system/etc/linker.config.pb
paste of cmd: https://diff.googleplex.com/#key=KAqqP9bhKZMD

Change-Id: I1f1d626a3a161fb2e12597909fd287533cbb8482
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index d178710..d0d4825 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -690,27 +690,13 @@
 }
 
 func (f *filesystem) buildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) {
-	getCStubLibs := func() []android.Module {
-		// Determine the list of C stub libraries that are part of this filesystem.
-		// These will be added to `provideLibs`.
-		// The current implementation assumes that stub libraries are listed explicitly in `deps`
-		// (direct deps). If this is not true, ctx.VisitDeps will need to be replaced by ctx.WalkDeps.
-		ret := []android.Module{}
-		ctx.VisitDirectDeps(func(child android.Module) {
-			if c, ok := child.(*cc.Module); ok && c.HasStubsVariants() {
-				ret = append(ret, c)
-			}
-		})
-		return ret
-	}
-
 	if len(f.properties.Linker_config_srcs) == 0 {
 		return
 	}
 
-	// cp to the final output
+	provideModules, _ := f.getLibsForLinkerConfig(ctx)
 	output := rebasedDir.Join(ctx, "etc", "linker.config.pb")
-	linkerconfig.BuildLinkerConfig(ctx, builder, android.PathsForModuleSrc(ctx, f.properties.Linker_config_srcs), getCStubLibs(), nil, output)
+	linkerconfig.BuildLinkerConfig(ctx, builder, android.PathsForModuleSrc(ctx, f.properties.Linker_config_srcs), provideModules, nil, output)
 
 	f.appendToEntry(ctx, output)
 }
@@ -823,3 +809,48 @@
 func (f *filesystemDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	validatePartitionType(ctx, f)
 }
+
+// getLibsForLinkerConfig returns
+// 1. A list of libraries installed in this filesystem
+// 2. A list of dep libraries _not_ installed in this filesystem
+//
+// `linkerconfig.BuildLinkerConfig` will convert these two to a linker.config.pb for the filesystem
+// (1) will be added to --provideLibs if they are C libraries with a stable interface (has stubs)
+// (2) will be added to --requireLibs if they are C libraries with a stable interface (has stubs)
+func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]android.Module, []android.Module) {
+	// we need "Module"s for packaging items
+	modulesInPackageByModule := make(map[android.Module]bool)
+	modulesInPackageByName := make(map[string]bool)
+
+	deps := f.gatherFilteredPackagingSpecs(ctx)
+	ctx.WalkDeps(func(child, parent android.Module) bool {
+		for _, ps := range android.OtherModuleProviderOrDefault(
+			ctx, child, android.InstallFilesProvider).PackagingSpecs {
+			if _, ok := deps[ps.RelPathInPackage()]; ok {
+				modulesInPackageByModule[child] = true
+				modulesInPackageByName[child.Name()] = true
+				return true
+			}
+		}
+		return true
+	})
+
+	provideModules := make([]android.Module, 0, len(modulesInPackageByModule))
+	for mod := range modulesInPackageByModule {
+		provideModules = append(provideModules, mod)
+	}
+
+	var requireModules []android.Module
+	ctx.WalkDeps(func(child, parent android.Module) bool {
+		_, parentInPackage := modulesInPackageByModule[parent]
+		_, childInPackageName := modulesInPackageByName[child.Name()]
+
+		// When parent is in the package, and child (or its variant) is not, this can be from an interface.
+		if parentInPackage && !childInPackageName {
+			requireModules = append(requireModules, child)
+		}
+		return true
+	})
+
+	return provideModules, requireModules
+}