• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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