Include kernel and dtb.img information in SBOM built in soong-only

Bug: 401366170
Bug: 401366536
Test: presubmits
Change-Id: I4a3e6834b02b6bbe2d83d90e5f0c7cc0bc2582f5
diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go
index 7c0ab85..9ddaee8 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -18,7 +18,9 @@
 	"bytes"
 	"encoding/csv"
 	"fmt"
+	"path/filepath"
 	"slices"
+	"sort"
 	"strconv"
 	"strings"
 
@@ -127,32 +129,37 @@
 // dependencies, built/installed files, etc. It is a wrapper on a map[string]string with some utility
 // methods to get/set properties' values.
 type ComplianceMetadataInfo struct {
-	properties     map[string]string
-	filesContained []string
+	properties          map[string]string
+	filesContained      []string
+	prebuiltFilesCopied []string
 }
 
 type complianceMetadataInfoGob struct {
-	Properties     map[string]string
-	FilesContained []string
+	Properties          map[string]string
+	FilesContained      []string
+	PrebuiltFilesCopied []string
 }
 
 func NewComplianceMetadataInfo() *ComplianceMetadataInfo {
 	return &ComplianceMetadataInfo{
-		properties:     map[string]string{},
-		filesContained: make([]string, 0),
+		properties:          map[string]string{},
+		filesContained:      make([]string, 0),
+		prebuiltFilesCopied: make([]string, 0),
 	}
 }
 
 func (m *ComplianceMetadataInfo) ToGob() *complianceMetadataInfoGob {
 	return &complianceMetadataInfoGob{
-		Properties:     m.properties,
-		FilesContained: m.filesContained,
+		Properties:          m.properties,
+		FilesContained:      m.filesContained,
+		PrebuiltFilesCopied: m.prebuiltFilesCopied,
 	}
 }
 
 func (m *ComplianceMetadataInfo) FromGob(data *complianceMetadataInfoGob) {
 	m.properties = data.Properties
 	m.filesContained = data.FilesContained
+	m.prebuiltFilesCopied = data.PrebuiltFilesCopied
 }
 
 func (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) {
@@ -182,6 +189,14 @@
 	return c.filesContained
 }
 
+func (c *ComplianceMetadataInfo) SetPrebuiltFilesCopied(files []string) {
+	c.prebuiltFilesCopied = files
+}
+
+func (c *ComplianceMetadataInfo) GetPrebuiltFilesCopied() []string {
+	return c.prebuiltFilesCopied
+}
+
 func (c *ComplianceMetadataInfo) getStringValue(propertyName string) string {
 	if !slices.Contains(COMPLIANCE_METADATA_PROPS, propertyName) {
 		panic(fmt.Errorf("Unknown metadata property: %s.", propertyName))
@@ -329,24 +344,40 @@
 	makeMetadataCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-metadata.csv")
 	makeModulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-modules.csv")
 
+	productOutPath := filepath.Join(ctx.Config().OutDir(), "target", "product", String(ctx.Config().productVariables.DeviceName))
 	if !ctx.Config().KatiEnabled() {
-		// In soong-only build the installed file list is from android_device module
 		ctx.VisitAllModuleProxies(func(module ModuleProxy) {
-			if androidDeviceInfo, ok := OtherModuleProvider(ctx, module, AndroidDeviceInfoProvider); !ok || !androidDeviceInfo.Main_device {
-				return
-			}
-			if metadataInfo, ok := OtherModuleProvider(ctx, module, ComplianceMetadataProvider); ok {
-				if len(metadataInfo.filesContained) > 0 {
-					csvHeaders := "installed_file,module_path,is_soong_module,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,static_libs,whole_static_libs,license_text"
-					csvContent := make([]string, 0, len(metadataInfo.filesContained)+1)
-					csvContent = append(csvContent, csvHeaders)
-					for _, file := range metadataInfo.filesContained {
-						csvContent = append(csvContent, file+",,Y,,,,,,,")
+			// In soong-only build the installed file list is from android_device module
+			if androidDeviceInfo, ok := OtherModuleProvider(ctx, module, AndroidDeviceInfoProvider); ok && androidDeviceInfo.Main_device {
+				if metadataInfo, ok := OtherModuleProvider(ctx, module, ComplianceMetadataProvider); ok {
+					if len(metadataInfo.filesContained) > 0 || len(metadataInfo.prebuiltFilesCopied) > 0 {
+						allFiles := make([]string, 0, len(metadataInfo.filesContained)+len(metadataInfo.prebuiltFilesCopied))
+						allFiles = append(allFiles, metadataInfo.filesContained...)
+						prebuiltFilesSrcDest := make(map[string]string)
+						for _, srcDestPair := range metadataInfo.prebuiltFilesCopied {
+							prebuiltFilePath := filepath.Join(productOutPath, strings.Split(srcDestPair, ":")[1])
+							allFiles = append(allFiles, prebuiltFilePath)
+							prebuiltFilesSrcDest[prebuiltFilePath] = srcDestPair
+						}
+						sort.Strings(allFiles)
+
+						csvHeaders := "installed_file,module_path,is_soong_module,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,static_libs,whole_static_libs,license_text"
+						csvContent := make([]string, 0, len(allFiles)+1)
+						csvContent = append(csvContent, csvHeaders)
+						for _, file := range allFiles {
+							if _, ok := prebuiltFilesSrcDest[file]; ok {
+								srcDestPair := prebuiltFilesSrcDest[file]
+								csvContent = append(csvContent, file+",,,,"+srcDestPair+",,,,,")
+							} else {
+								csvContent = append(csvContent, file+",,Y,,,,,,,")
+							}
+						}
+
+						WriteFileRuleVerbatim(ctx, makeMetadataCsv, strings.Join(csvContent, "\n"))
+						WriteFileRuleVerbatim(ctx, makeModulesCsv, "name,module_path,module_class,module_type,static_libs,whole_static_libs,built_files,installed_files")
 					}
-					WriteFileRuleVerbatim(ctx, makeMetadataCsv, strings.Join(csvContent, "\n"))
-					WriteFileRuleVerbatim(ctx, makeModulesCsv, "name,module_path,module_class,module_type,static_libs,whole_static_libs,built_files,installed_files")
+					return
 				}
-				return
 			}
 		})
 	}
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index a616ee0..931adfd 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -294,18 +294,26 @@
 }
 
 func buildComplianceMetadata(ctx android.ModuleContext, tags ...blueprint.DependencyTag) {
+	// Collect metadata from deps
 	filesContained := make([]string, 0)
+	prebuiltFilesCopied := make([]string, 0)
 	for _, tag := range tags {
 		ctx.VisitDirectDepsProxyWithTag(tag, func(m android.ModuleProxy) {
 			if complianceMetadataInfo, ok := android.OtherModuleProvider(ctx, m, android.ComplianceMetadataProvider); ok {
 				filesContained = append(filesContained, complianceMetadataInfo.GetFilesContained()...)
+				prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...)
 			}
 		})
 	}
-	sort.Strings(filesContained)
-
+	// Merge to module's ComplianceMetadataInfo
 	complianceMetadataInfo := ctx.ComplianceMetadataInfo()
+	filesContained = append(filesContained, complianceMetadataInfo.GetFilesContained()...)
+	sort.Strings(filesContained)
 	complianceMetadataInfo.SetFilesContained(filesContained)
+
+	prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...)
+	sort.Strings(prebuiltFilesCopied)
+	complianceMetadataInfo.SetPrebuiltFilesCopied(prebuiltFilesCopied)
 }
 
 // Returns a list of modules that are installed, which are collected from the dependency
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 2bf0d59..c06c200 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -201,7 +201,8 @@
 		return
 	}
 
-	unsignedOutput := b.buildBootImage(ctx, b.getKernelPath(ctx))
+	kernelPath := b.getKernelPath(ctx)
+	unsignedOutput := b.buildBootImage(ctx, kernelPath)
 
 	output := unsignedOutput
 	if proptools.Bool(b.properties.Use_avb) {
@@ -212,7 +213,7 @@
 		case "default":
 			output = b.signImage(ctx, unsignedOutput)
 		case "make_legacy":
-			output = b.addAvbFooter(ctx, unsignedOutput, b.getKernelPath(ctx))
+			output = b.addAvbFooter(ctx, unsignedOutput, kernelPath)
 		default:
 			ctx.PropertyErrorf("avb_mode", `Unknown value for avb_mode, expected "default" or "make_legacy", got: %q`, *b.properties.Avb_mode)
 		}
@@ -235,10 +236,11 @@
 	}
 
 	// Set BootimgInfo for building target_files.zip
+	dtbPath := b.getDtbPath(ctx)
 	android.SetProvider(ctx, BootimgInfoProvider, BootimgInfo{
 		Cmdline:    b.properties.Cmdline,
-		Kernel:     b.getKernelPath(ctx),
-		Dtb:        b.getDtbPath(ctx),
+		Kernel:     kernelPath,
+		Dtb:        dtbPath,
 		Bootconfig: b.getBootconfigPath(ctx),
 		Output:     output,
 	})
@@ -265,6 +267,16 @@
 	})
 
 	// Dump compliance metadata
+	complianceMetadataInfo := ctx.ComplianceMetadataInfo()
+	prebuiltFilesCopied := make([]string, 0)
+	if kernelPath != nil {
+		prebuiltFilesCopied = append(prebuiltFilesCopied, kernelPath.String()+":kernel")
+	}
+	if dtbPath != nil {
+		prebuiltFilesCopied = append(prebuiltFilesCopied, dtbPath.String()+":dtb.img")
+	}
+	complianceMetadataInfo.SetPrebuiltFilesCopied(prebuiltFilesCopied)
+
 	if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" {
 		buildComplianceMetadata(ctx, bootimgRamdiskDep)
 	}