Fix missing avb keys

Previously we were using the "specific" board avb key path, but it's
actually common for the partition-specific avb key to not be set and
instead fall back to the global avb key. Add that fallback to the
global avb key.

Also, now that we're properly using the keys, generate filegroups
for the keys as they're often in a different folder. Also use
pre-existing filegroups where possible.

Bug: 377563298
Test: m product_config_to_bp and check the generated bp file for avb keys
Change-Id: Iafef06b95c895c47d5b55c8aef2061a636754b28
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index d46f679..c74579a 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -64,6 +64,7 @@
 		generatedPrebuiltEtcModuleNames := createPrebuiltEtcModules(ctx)
 		avbpubkeyGenerated := createAvbpubkeyModule(ctx)
 		createFsGenState(ctx, generatedPrebuiltEtcModuleNames, avbpubkeyGenerated)
+		module.createAvbKeyFilegroups(ctx)
 		module.createInternalModules(ctx)
 	})
 
@@ -254,6 +255,51 @@
 	return true
 }
 
+// Creates filegroups for the files specified in BOARD_(partition_)AVB_KEY_PATH
+func (f *filesystemCreator) createAvbKeyFilegroups(ctx android.LoadHookContext) {
+	partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
+	var files []string
+
+	if len(partitionVars.BoardAvbKeyPath) > 0 {
+		files = append(files, partitionVars.BoardAvbKeyPath)
+	}
+	for _, partition := range android.SortedKeys(partitionVars.PartitionQualifiedVariables) {
+		specificPartitionVars := partitionVars.PartitionQualifiedVariables[partition]
+		if len(specificPartitionVars.BoardAvbKeyPath) > 0 {
+			files = append(files, specificPartitionVars.BoardAvbKeyPath)
+		}
+	}
+
+	fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
+	for _, file := range files {
+		if _, ok := fsGenState.avbKeyFilegroups[file]; ok {
+			continue
+		}
+		if file == "external/avb/test/data/testkey_rsa4096.pem" {
+			// There already exists a checked-in filegroup for this commonly-used key, just use that
+			fsGenState.avbKeyFilegroups[file] = "avb_testkey_rsa4096"
+			continue
+		}
+		dir := filepath.Dir(file)
+		base := filepath.Base(file)
+		name := fmt.Sprintf("avb_key_%x", strings.ReplaceAll(file, "/", "_"))
+		ctx.CreateModuleInDirectory(
+			android.FileGroupFactory,
+			dir,
+			&struct {
+				Name       *string
+				Srcs       []string
+				Visibility []string
+			}{
+				Name:       proptools.StringPtr(name),
+				Srcs:       []string{base},
+				Visibility: []string{"//visibility:public"},
+			},
+		)
+		fsGenState.avbKeyFilegroups[file] = name
+	}
+}
+
 // createPrebuiltKernelModules creates `prebuilt_kernel_modules`. These modules will be added to deps of the
 // autogenerated *_dlkm filsystem modules. Each _dlkm partition should have a single prebuilt_kernel_modules dependency.
 // This ensures that the depmod artifacts (modules.* installed in /lib/modules/) are generated with a complete view.
@@ -419,21 +465,41 @@
 }
 
 func generateFsProps(ctx android.EarlyModuleContext, partitionType string) (*filesystem.FilesystemProperties, bool) {
+	fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
 	fsProps := &filesystem.FilesystemProperties{}
 
 	partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
-	var specificPartitionVars android.PartitionQualifiedVariablesType
 	var boardAvbEnable bool
+	var boardAvbKeyPath string
+	var boardAvbAlgorithm string
+	var boardAvbRollbackIndex string
 	var fsType string
 	if strings.Contains(partitionType, "ramdisk") {
 		fsType = "compressed_cpio"
 	} else {
-		specificPartitionVars = partitionVars.PartitionQualifiedVariables[partitionType]
-		boardAvbEnable = partitionVars.BoardAvbEnable
+		specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType]
 		fsType = specificPartitionVars.BoardFileSystemType
+		boardAvbEnable = partitionVars.BoardAvbEnable
+		boardAvbKeyPath = specificPartitionVars.BoardAvbKeyPath
+		boardAvbAlgorithm = specificPartitionVars.BoardAvbAlgorithm
+		boardAvbRollbackIndex = specificPartitionVars.BoardAvbRollbackIndex
+		if boardAvbEnable {
+			if boardAvbKeyPath == "" {
+				boardAvbKeyPath = partitionVars.BoardAvbKeyPath
+			}
+			if boardAvbAlgorithm == "" {
+				boardAvbAlgorithm = partitionVars.BoardAvbAlgorithm
+			}
+			if boardAvbRollbackIndex == "" {
+				boardAvbRollbackIndex = partitionVars.BoardAvbRollbackIndex
+			}
+		}
+		if fsType == "" {
+			fsType = "ext4" //default
+		}
 	}
-	if fsType == "" {
-		fsType = "ext4" //default
+	if boardAvbKeyPath != "" {
+		boardAvbKeyPath = ":" + fsGenState.avbKeyFilegroups[boardAvbKeyPath]
 	}
 
 	fsProps.Type = proptools.StringPtr(fsType)
@@ -449,11 +515,11 @@
 	// BOARD_AVB_ENABLE
 	fsProps.Use_avb = proptools.BoolPtr(boardAvbEnable)
 	// BOARD_AVB_KEY_PATH
-	fsProps.Avb_private_key = proptools.StringPtr(specificPartitionVars.BoardAvbKeyPath)
+	fsProps.Avb_private_key = proptools.StringPtr(boardAvbKeyPath)
 	// BOARD_AVB_ALGORITHM
-	fsProps.Avb_algorithm = proptools.StringPtr(specificPartitionVars.BoardAvbAlgorithm)
+	fsProps.Avb_algorithm = proptools.StringPtr(boardAvbAlgorithm)
 	// BOARD_AVB_SYSTEM_ROLLBACK_INDEX
-	if rollbackIndex, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndex, 10, 64); err == nil {
+	if rollbackIndex, err := strconv.ParseInt(boardAvbRollbackIndex, 10, 64); err == nil {
 		fsProps.Rollback_index = proptools.Int64Ptr(rollbackIndex)
 	}
 
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
index 6111a41..fe4a403 100644
--- a/fsgen/filesystem_creator_test.go
+++ b/fsgen/filesystem_creator_test.go
@@ -47,6 +47,12 @@
 		}),
 		android.FixtureMergeMockFs(android.MockFS{
 			"external/avb/test/data/testkey_rsa4096.pem": nil,
+			"external/avb/test/Android.bp": []byte(`
+			filegroup {
+				name: "avb_testkey_rsa4096",
+				srcs: ["data/testkey_rsa4096.pem"],
+			}
+			`),
 			"build/soong/fsgen/Android.bp": []byte(`
 			soong_filesystem_creator {
 				name: "foo",
@@ -66,8 +72,8 @@
 	)
 	android.AssertStringEquals(
 		t,
-		"Property expected to match the product variable 'BOARD_AVB_KEY_PATH'",
-		"external/avb/test/data/testkey_rsa4096.pem",
+		"Property the avb_private_key property to be set to the existing filegroup",
+		":avb_testkey_rsa4096",
 		proptools.String(fooSystem.FsProps().Avb_private_key),
 	)
 	android.AssertStringEquals(
diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go
index f6fe7c4..7b30264 100644
--- a/fsgen/fsgen_mutators.go
+++ b/fsgen/fsgen_mutators.go
@@ -68,6 +68,8 @@
 	moduleToInstallationProps map[string]installationProperties
 	// List of prebuilt_* modules that are autogenerated.
 	generatedPrebuiltEtcModuleNames []string
+	// Mapping from a path to an avb key to the name of a filegroup module that contains it
+	avbKeyFilegroups map[string]string
 }
 
 type installationProperties struct {
@@ -179,6 +181,7 @@
 			fsDepsMutex:                     sync.Mutex{},
 			moduleToInstallationProps:       map[string]installationProperties{},
 			generatedPrebuiltEtcModuleNames: generatedPrebuiltEtcModuleNames,
+			avbKeyFilegroups:                map[string]string{},
 		}
 
 		if avbpubkeyGenerated {