Generate file list installed from a filesystem

Generate file list installed from a filesystem, so it can be compared
with files installed from KATI.

Bug: 346873717
Test: File list generated with aosp_cf_system_x86_64
Change-Id: I8c8f555d57fee90753120f637dc3bc633f276a09
Merged-In: I8c8f555d57fee90753120f637dc3bc633f276a09
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
index 8daee85..5c047bc 100644
--- a/filesystem/aconfig_files.go
+++ b/filesystem/aconfig_files.go
@@ -16,7 +16,6 @@
 
 import (
 	"android/soong/android"
-	"path/filepath"
 	"strings"
 
 	"github.com/google/blueprint/proptools"
@@ -56,6 +55,7 @@
 	sb.WriteString(" \\\n")
 	sb.WriteString(sbCaches.String())
 	cmd.ImplicitOutput(installAconfigFlagsPath)
+	f.appendToEntry(ctx, installAconfigFlagsPath)
 
 	installAconfigStorageDir := dir.Join(ctx, "etc", "aconfig")
 	sb.WriteString("mkdir -p ")
@@ -63,16 +63,18 @@
 	sb.WriteRune('\n')
 
 	generatePartitionAconfigStorageFile := func(fileType, fileName string) {
+		outputPath := installAconfigStorageDir.Join(ctx, fileName)
 		sb.WriteString(aconfigToolPath.String())
 		sb.WriteString(" create-storage --container ")
 		sb.WriteString(f.PartitionType())
 		sb.WriteString(" --file ")
 		sb.WriteString(fileType)
 		sb.WriteString(" --out ")
-		sb.WriteString(filepath.Join(installAconfigStorageDir.String(), fileName))
+		sb.WriteString(outputPath.String())
 		sb.WriteString(" \\\n")
 		sb.WriteString(sbCaches.String())
-		cmd.ImplicitOutput(installAconfigStorageDir.Join(ctx, fileName))
+		cmd.ImplicitOutput(outputPath)
+		f.appendToEntry(ctx, outputPath)
 	}
 	generatePartitionAconfigStorageFile("package_map", "package.map")
 	generatePartitionAconfigStorageFile("flag_map", "flag.map")
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index c889dd6..ffa30a0 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -60,7 +60,9 @@
 	output     android.OutputPath
 	installDir android.InstallPath
 
-	// For testing. Keeps the result of CopySpecsToDir()
+	fileListFile android.OutputPath
+
+	// Keeps the entries installed from this filesystem
 	entries []string
 }
 
@@ -221,8 +223,26 @@
 
 	f.installDir = android.PathForModuleInstall(ctx, "etc")
 	ctx.InstallFile(f.installDir, f.installFileName(), f.output)
-
 	ctx.SetOutputFiles([]android.Path{f.output}, "")
+
+	f.fileListFile = android.PathForModuleOut(ctx, "fileList").OutputPath
+	android.WriteFileRule(ctx, f.fileListFile, f.installedFilesList())
+}
+
+func (f *filesystem) appendToEntry(ctx android.ModuleContext, installedFile android.OutputPath) {
+	partitionBaseDir := android.PathForModuleOut(ctx, "root", f.partitionName()).String() + "/"
+
+	relPath, inTargetPartition := strings.CutPrefix(installedFile.String(), partitionBaseDir)
+	if inTargetPartition {
+		f.entries = append(f.entries, relPath)
+	}
+}
+
+func (f *filesystem) installedFilesList() string {
+	installedFilePaths := android.FirstUniqueStrings(f.entries)
+	slices.Sort(installedFilePaths)
+
+	return strings.Join(installedFilePaths, "\n")
 }
 
 func validatePartitionType(ctx android.ModuleContext, p partition) {
@@ -269,17 +289,19 @@
 		builder.Command().Textf("(! [ -e %s -o -L %s ] || (echo \"%s already exists from an earlier stage of the build\" && exit 1))", dst, dst, dst)
 		builder.Command().Text("mkdir -p").Text(filepath.Dir(dst.String()))
 		builder.Command().Text("ln -sf").Text(proptools.ShellEscape(target)).Text(dst.String())
+		f.appendToEntry(ctx, dst)
 	}
 
 	// create extra files if there's any
 	if f.buildExtraFiles != nil {
 		rootForExtraFiles := android.PathForModuleGen(ctx, "root-extra").OutputPath
 		extraFiles := f.buildExtraFiles(ctx, rootForExtraFiles)
-		for _, f := range extraFiles {
-			rel, err := filepath.Rel(rootForExtraFiles.String(), f.String())
+		for _, extraFile := range extraFiles {
+			rel, err := filepath.Rel(rootForExtraFiles.String(), extraFile.String())
 			if err != nil || strings.HasPrefix(rel, "..") {
-				ctx.ModuleErrorf("can't make %q relative to %q", f, rootForExtraFiles)
+				ctx.ModuleErrorf("can't make %q relative to %q", extraFile, rootForExtraFiles)
 			}
+			f.appendToEntry(ctx, rootDir.Join(ctx, rel))
 		}
 		if len(extraFiles) > 0 {
 			builder.Command().BuiltTool("merge_directories").
@@ -535,6 +557,8 @@
 	for _, path := range android.SortedKeys(logtagsFilePaths) {
 		cmd.Text(path)
 	}
+
+	f.appendToEntry(ctx, eventLogtagsPath)
 }
 
 type partition interface {
@@ -558,6 +582,7 @@
 			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_PATH", f.installDir.String())
 				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", f.installFileName())
+				entries.SetString("LOCAL_FILESYSTEM_FILELIST", f.fileListFile.String())
 			},
 		},
 	}}
diff --git a/filesystem/fsverity_metadata.go b/filesystem/fsverity_metadata.go
index 3e50ff7..d7bb654 100644
--- a/filesystem/fsverity_metadata.go
+++ b/filesystem/fsverity_metadata.go
@@ -87,6 +87,7 @@
 		sb.WriteRune(' ')
 		sb.WriteString(srcPath.String())
 		sb.WriteRune('\n')
+		f.appendToEntry(ctx, destPath)
 	}
 
 	// STEP 2: generate signed BuildManifest.apk
@@ -108,6 +109,7 @@
 	sb.WriteString(" --output ")
 	sb.WriteString(manifestPbPath.String())
 	sb.WriteRune(' ')
+	f.appendToEntry(ctx, manifestPbPath)
 
 	manifestGeneratorListPath := android.PathForModuleOut(ctx, "fsverity_manifest.list")
 	f.writeManifestGeneratorListFile(ctx, manifestGeneratorListPath.OutputPath, matchedSpecs, rebasedDir)
@@ -115,15 +117,18 @@
 	sb.WriteString(manifestGeneratorListPath.String())
 	sb.WriteRune('\n')
 	cmd.Implicit(manifestGeneratorListPath)
+	f.appendToEntry(ctx, manifestGeneratorListPath.OutputPath)
 
 	// STEP 2-2: generate BuildManifest.apk (unsigned)
 	aapt2Path := ctx.Config().HostToolPath(ctx, "aapt2")
 	apkPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", "BuildManifest.apk")
+	idsigPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", "BuildManifest.apk.idsig")
 	manifestTemplatePath := android.PathForSource(ctx, "system/security/fsverity/AndroidManifest.xml")
 	libs := android.PathsForModuleSrc(ctx, f.properties.Fsverity.Libs)
 	cmd.Implicit(aapt2Path)
 	cmd.Implicit(manifestTemplatePath)
 	cmd.Implicits(libs)
+	cmd.ImplicitOutput(apkPath)
 
 	sb.WriteString(aapt2Path.String())
 	sb.WriteString(" link -o ")
@@ -150,12 +155,15 @@
 	sb.WriteString(f.partitionName())
 	sb.WriteRune('\n')
 
+	f.appendToEntry(ctx, apkPath)
+
 	// STEP 2-3: sign BuildManifest.apk
 	apksignerPath := ctx.Config().HostToolPath(ctx, "apksigner")
 	pemPath, keyPath := ctx.Config().DefaultAppCertificate(ctx)
 	cmd.Implicit(apksignerPath)
 	cmd.Implicit(pemPath)
 	cmd.Implicit(keyPath)
+	cmd.ImplicitOutput(idsigPath)
 	sb.WriteString(apksignerPath.String())
 	sb.WriteString(" sign --in ")
 	sb.WriteString(apkPath.String())
@@ -165,5 +173,7 @@
 	sb.WriteString(keyPath.String())
 	sb.WriteRune('\n')
 
+	f.appendToEntry(ctx, idsigPath)
+
 	android.WriteExecutableFileRuleVerbatim(ctx, fsverityBuilderPath, sb.String())
 }