Dist installed-files.* in soong only build

Implementation details:
- Define static rules for building installed-files.txt and
  installed-files.json
- Avoided adding dependency on the root dir and added dependency
  on the output image file instead
- Propagate the generated installed-files.* via filesystem info provider
  and generate the dist rule in the main android device

Test: m droid dist --soong-only && ls -l out/dist
Bug: 395162005
Bug: 394365683
Change-Id: I615b0374c557fd11c19fcd190232cab411e2d299
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index b783d0f..52b9d94 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -237,6 +237,26 @@
 	ctx.CheckbuildFile(allImagesStamp)
 
 	a.setVbmetaPhonyTargets(ctx)
+
+	a.distFiles(ctx)
+}
+
+func (a *androidDevice) distFiles(ctx android.ModuleContext) {
+	if !ctx.Config().KatiEnabled() {
+		if proptools.Bool(a.deviceProps.Main_device) {
+			fsInfoMap := a.getFsInfos(ctx)
+			for _, partition := range android.SortedKeys(fsInfoMap) {
+				fsInfo := fsInfoMap[partition]
+				if fsInfo.InstalledFiles.Json != nil {
+					ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Json)
+				}
+				if fsInfo.InstalledFiles.Txt != nil {
+					ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Txt)
+				}
+			}
+		}
+	}
+
 }
 
 func (a *androidDevice) MakeVars(ctx android.MakeVarsModuleContext) {
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 0ce31b2..21c0689 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -36,6 +36,7 @@
 func init() {
 	registerBuildComponents(android.InitRegistrationContext)
 	registerMutators(android.InitRegistrationContext)
+	pctx.HostBinToolVariable("fileslist", "fileslist")
 }
 
 func registerBuildComponents(ctx android.RegistrationContext) {
@@ -54,11 +55,24 @@
 	})
 }
 
-// Remember to add referenced files to implicits!
-var textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{
-	Command:     "build/soong/scripts/text_file_processor.py $in $out",
-	CommandDeps: []string{"build/soong/scripts/text_file_processor.py"},
-})
+var (
+	// Remember to add referenced files to implicits!
+	textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{
+		Command:     "build/soong/scripts/text_file_processor.py $in $out",
+		CommandDeps: []string{"build/soong/scripts/text_file_processor.py"},
+	})
+
+	// Remember to add the output image file as an implicit dependency!
+	installedFilesJsonRule = pctx.AndroidStaticRule("installed_files_json", blueprint.RuleParams{
+		Command:     `${fileslist} ${rootDir} > ${out}`,
+		CommandDeps: []string{"${fileslist}"},
+	}, "rootDir")
+
+	installedFilesTxtRule = pctx.AndroidStaticRule("installed_files_txt", blueprint.RuleParams{
+		Command:     `build/make/tools/fileslist_util.py -c ${in} > ${out}`,
+		CommandDeps: []string{"build/make/tools/fileslist_util.py"},
+	})
+)
 
 type filesystem struct {
 	android.ModuleBase
@@ -358,6 +372,11 @@
 	return fs == unknown
 }
 
+type InstalledFilesStruct struct {
+	Txt  android.Path
+	Json android.Path
+}
+
 type FilesystemInfo struct {
 	// The built filesystem image
 	Output android.Path
@@ -391,6 +410,9 @@
 	SpecsForSystemOther map[string]android.PackagingSpec
 
 	FullInstallPaths []FullInstallPathInfo
+
+	// Installed files list
+	InstalledFiles InstalledFilesStruct
 }
 
 // FullInstallPathInfo contains information about the "full install" paths of all the files
@@ -498,6 +520,34 @@
 	}
 }
 
+func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir android.Path, image android.Path) (txt android.ModuleOutPath, json android.ModuleOutPath) {
+	fileName := "installed-files"
+	if len(partition) > 0 {
+		fileName += fmt.Sprintf("-%s", partition)
+	}
+	txt = android.PathForModuleOut(ctx, fmt.Sprintf("%s.txt", fileName))
+	json = android.PathForModuleOut(ctx, fmt.Sprintf("%s.json", fileName))
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        installedFilesJsonRule,
+		Implicit:    image,
+		Output:      json,
+		Description: "Installed file list json",
+		Args: map[string]string{
+			"rootDir": rootDir.String(),
+		},
+	})
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        installedFilesTxtRule,
+		Input:       json,
+		Output:      txt,
+		Description: "Installed file list txt",
+	})
+
+	return txt, json
+}
+
 var pctx = android.NewPackageContext("android/soong/filesystem")
 
 func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -565,6 +615,12 @@
 	fileListFile := android.PathForModuleOut(ctx, "fileList")
 	android.WriteFileRule(ctx, fileListFile, f.installedFilesList())
 
+	partitionName := f.partitionName()
+	if partitionName == "system" {
+		partitionName = ""
+	}
+	installedFileTxt, installedFileJson := buildInstalledFiles(ctx, partitionName, rootDir, f.output)
+
 	fsInfo := FilesystemInfo{
 		Output:                 f.output,
 		OutputHermetic:         outputHermetic,
@@ -577,6 +633,10 @@
 		BuildImagePropFileDeps: buildImagePropFileDeps,
 		SpecsForSystemOther:    f.systemOtherFiles(ctx),
 		FullInstallPaths:       fullInstallPaths,
+		InstalledFiles: InstalledFilesStruct{
+			Txt:  installedFileTxt,
+			Json: installedFileJson,
+		},
 	}
 
 	android.SetProvider(ctx, FilesystemProvider, fsInfo)