1// Copyright (C) 2024 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package filesystem 16 17import ( 18 "android/soong/android" 19 "strconv" 20 "strings" 21 22 "github.com/google/blueprint" 23 "github.com/google/blueprint/proptools" 24) 25 26func init() { 27 pctx.HostBinToolVariable("aconfig", "aconfig") 28} 29 30var ( 31 aconfigCreateStorage = pctx.AndroidStaticRule("aconfig_create_storage", blueprint.RuleParams{ 32 Command: `$aconfig create-storage --container $container --file $fileType --out $out --cache $in --version $version`, 33 CommandDeps: []string{"$aconfig"}, 34 }, "container", "fileType", "version") 35 36 subPartitionsInPartition = map[string][]string{ 37 "system": {"system_ext", "product", "vendor"}, 38 "vendor": {"odm"}, 39 } 40) 41 42func (f *filesystem) buildAconfigFlagsFiles( 43 ctx android.ModuleContext, 44 builder *android.RuleBuilder, 45 specs map[string]android.PackagingSpec, 46 dir android.OutputPath, 47 fullInstallPaths *[]FullInstallPathInfo, 48) { 49 if !proptools.Bool(f.properties.Gen_aconfig_flags_pb) { 50 return 51 } 52 53 partition := f.PartitionType() 54 subPartitionsFound := map[string]bool{} 55 fullInstallPath := android.PathForModuleInPartitionInstall(ctx, partition) 56 57 for _, subPartition := range subPartitionsInPartition[partition] { 58 subPartitionsFound[subPartition] = false 59 } 60 61 var caches []android.Path 62 for _, ps := range specs { 63 caches = append(caches, ps.GetAconfigPaths()...) 64 for subPartition, found := range subPartitionsFound { 65 if !found && strings.HasPrefix(ps.RelPathInPackage(), subPartition+"/") { 66 subPartitionsFound[subPartition] = true 67 break 68 } 69 } 70 } 71 caches = android.SortedUniquePaths(caches) 72 73 buildAconfigFlagsFiles := func(container string, dir android.OutputPath, fullInstallPath android.InstallPath) { 74 aconfigFlagsPb := android.PathForModuleOut(ctx, "aconfig", container, "aconfig_flags.pb") 75 aconfigFlagsPbBuilder := android.NewRuleBuilder(pctx, ctx) 76 cmd := aconfigFlagsPbBuilder.Command(). 77 BuiltTool("aconfig"). 78 Text(" dump-cache --dedup --format protobuf --out"). 79 Output(aconfigFlagsPb). 80 Textf("--filter container:%s+state:ENABLED", container). 81 Textf("--filter container:%s+permission:READ_WRITE", container) 82 for _, cache := range caches { 83 cmd.FlagWithInput("--cache ", cache) 84 } 85 aconfigFlagsPbBuilder.Build(container+"_aconfig_flags_pb", "build aconfig_flags.pb") 86 87 installEtcDir := dir.Join(ctx, "etc") 88 installAconfigFlagsPath := installEtcDir.Join(ctx, "aconfig_flags.pb") 89 builder.Command().Text("mkdir -p ").Text(installEtcDir.String()) 90 builder.Command().Text("cp").Input(aconfigFlagsPb).Text(installAconfigFlagsPath.String()) 91 *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ 92 FullInstallPath: fullInstallPath.Join(ctx, "etc/aconfig_flags.pb"), 93 SourcePath: aconfigFlagsPb, 94 }) 95 f.appendToEntry(ctx, installAconfigFlagsPath) 96 97 // To enable fingerprint, we need to have v2 storage files. The default version is 1. 98 storageFilesVersion := 1 99 if ctx.Config().ReleaseFingerprintAconfigPackages() { 100 storageFilesVersion = 2 101 } 102 103 installAconfigStorageDir := installEtcDir.Join(ctx, "aconfig") 104 builder.Command().Text("mkdir -p").Text(installAconfigStorageDir.String()) 105 106 generatePartitionAconfigStorageFile := func(fileType, fileName string) { 107 outPath := android.PathForModuleOut(ctx, "aconfig", container, fileName) 108 installPath := installAconfigStorageDir.Join(ctx, fileName) 109 ctx.Build(pctx, android.BuildParams{ 110 Rule: aconfigCreateStorage, 111 Input: aconfigFlagsPb, 112 Output: outPath, 113 Args: map[string]string{ 114 "container": container, 115 "fileType": fileType, 116 "version": strconv.Itoa(storageFilesVersion), 117 }, 118 }) 119 builder.Command(). 120 Text("cp").Input(outPath).Text(installPath.String()) 121 *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ 122 SourcePath: outPath, 123 FullInstallPath: fullInstallPath.Join(ctx, "etc/aconfig", fileName), 124 }) 125 f.appendToEntry(ctx, installPath) 126 } 127 128 if ctx.Config().ReleaseCreateAconfigStorageFile() { 129 generatePartitionAconfigStorageFile("package_map", "package.map") 130 generatePartitionAconfigStorageFile("flag_map", "flag.map") 131 generatePartitionAconfigStorageFile("flag_val", "flag.val") 132 generatePartitionAconfigStorageFile("flag_info", "flag.info") 133 } 134 } 135 136 buildAconfigFlagsFiles(partition, dir, fullInstallPath) 137 for _, subPartition := range android.SortedKeys(subPartitionsFound) { 138 if subPartitionsFound[subPartition] { 139 buildAconfigFlagsFiles(subPartition, dir.Join(ctx, subPartition), fullInstallPath.Join(ctx, subPartition)) 140 } 141 } 142} 143