• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 Google Inc. All rights reserved.
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 java
16
17import (
18	"path/filepath"
19
20	"android/soong/android"
21
22	"github.com/google/blueprint"
23	"github.com/google/blueprint/proptools"
24)
25
26func init() {
27	registerPlatformCompatConfigBuildComponents(android.InitRegistrationContext)
28
29	android.RegisterSdkMemberType(CompatConfigSdkMemberType)
30}
31
32var CompatConfigSdkMemberType = &compatConfigMemberType{
33	SdkMemberTypeBase: android.SdkMemberTypeBase{
34		PropertyName: "compat_configs",
35		SupportsSdk:  true,
36	},
37}
38
39func registerPlatformCompatConfigBuildComponents(ctx android.RegistrationContext) {
40	ctx.RegisterParallelSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
41	ctx.RegisterModuleType("platform_compat_config", PlatformCompatConfigFactory)
42	ctx.RegisterModuleType("prebuilt_platform_compat_config", prebuiltCompatConfigFactory)
43	ctx.RegisterModuleType("global_compat_config", globalCompatConfigFactory)
44}
45
46type PlatformCompatConfigInfo struct {
47	CompatConfig android.OutputPath
48	SubDir       string
49}
50
51var PlatformCompatConfigInfoProvider = blueprint.NewProvider[PlatformCompatConfigInfo]()
52
53var PrepareForTestWithPlatformCompatConfig = android.FixtureRegisterWithContext(registerPlatformCompatConfigBuildComponents)
54
55func platformCompatConfigPath(ctx android.PathContext) android.OutputPath {
56	return android.PathForOutput(ctx, "compat_config", "merged_compat_config.xml")
57}
58
59type platformCompatConfigProperties struct {
60	Src *string `android:"path"`
61
62	// If true, we include it in the "merged" XML (merged_compat_config.xml).
63	// Default is true.
64	Include_in_merged_xml *bool
65}
66
67type platformCompatConfig struct {
68	android.ModuleBase
69
70	properties     platformCompatConfigProperties
71	installDirPath android.InstallPath
72	configFile     android.OutputPath
73	metadataFile   android.OutputPath
74	doMerge        bool
75
76	installConfigFile android.InstallPath
77}
78
79func (p *platformCompatConfig) compatConfigMetadata() android.Path {
80	return p.metadataFile
81}
82
83func (p *platformCompatConfig) includeInMergedXml() bool {
84	return p.doMerge
85}
86
87func (p *platformCompatConfig) CompatConfig() android.OutputPath {
88	return p.configFile
89}
90
91func (p *platformCompatConfig) SubDir() string {
92	return "compatconfig"
93}
94
95type platformCompatConfigMetadataProvider interface {
96	compatConfigMetadata() android.Path
97
98	// Whether to include it in the "merged" XML (merged_compat_config.xml) or not.
99	includeInMergedXml() bool
100}
101
102type PlatformCompatConfigMetadataInfo struct {
103	CompatConfigMetadata android.Path
104	// Whether to include it in the "merged" XML (merged_compat_config.xml) or not.
105	IncludeInMergedXml bool
106}
107
108var PlatformCompatConfigMetadataInfoProvider = blueprint.NewProvider[PlatformCompatConfigMetadataInfo]()
109
110type PlatformCompatConfigIntf interface {
111	android.Module
112
113	CompatConfig() android.OutputPath
114	// Sub dir under etc dir.
115	SubDir() string
116}
117
118var _ PlatformCompatConfigIntf = (*platformCompatConfig)(nil)
119var _ platformCompatConfigMetadataProvider = (*platformCompatConfig)(nil)
120
121func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
122	rule := android.NewRuleBuilder(pctx, ctx)
123
124	configFileName := p.Name() + ".xml"
125	metadataFileName := p.Name() + "_meta.xml"
126	p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath
127	p.metadataFile = android.PathForModuleOut(ctx, metadataFileName).OutputPath
128	p.doMerge = proptools.BoolDefault(p.properties.Include_in_merged_xml, true)
129	path := android.PathForModuleSrc(ctx, String(p.properties.Src))
130
131	rule.Command().
132		BuiltTool("process-compat-config").
133		FlagWithInput("--jar ", path).
134		FlagWithOutput("--device-config ", p.configFile).
135		FlagWithOutput("--merged-config ", p.metadataFile)
136
137	p.installDirPath = android.PathForModuleInstall(ctx, "etc", "compatconfig")
138	p.installConfigFile = android.PathForModuleInstall(ctx, "etc", "compatconfig", p.configFile.Base())
139	rule.Build(configFileName, "Extract compat/compat_config.xml and install it")
140	ctx.InstallFile(p.installDirPath, p.configFile.Base(), p.configFile)
141	ctx.SetOutputFiles(android.Paths{p.configFile}, "")
142
143	android.SetProvider(ctx, PlatformCompatConfigInfoProvider, PlatformCompatConfigInfo{
144		CompatConfig: p.CompatConfig(),
145		SubDir:       p.SubDir(),
146	})
147
148	android.SetProvider(ctx, PlatformCompatConfigMetadataInfoProvider, PlatformCompatConfigMetadataInfo{
149		CompatConfigMetadata: p.compatConfigMetadata(),
150		IncludeInMergedXml:   p.includeInMergedXml(),
151	})
152}
153
154func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries {
155	return []android.AndroidMkEntries{android.AndroidMkEntries{
156		Class:      "ETC",
157		OutputFile: android.OptionalPathForPath(p.configFile),
158	}}
159}
160
161func PlatformCompatConfigFactory() android.Module {
162	module := &platformCompatConfig{}
163	module.AddProperties(&module.properties)
164	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
165	return module
166}
167
168type compatConfigMemberType struct {
169	android.SdkMemberTypeBase
170}
171
172func (b *compatConfigMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
173	ctx.AddVariationDependencies(nil, dependencyTag, names...)
174}
175
176func (b *compatConfigMemberType) IsInstance(module android.Module) bool {
177	_, ok := module.(*platformCompatConfig)
178	return ok
179}
180
181func (b *compatConfigMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
182	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_platform_compat_config")
183}
184
185func (b *compatConfigMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
186	return &compatConfigSdkMemberProperties{}
187}
188
189type compatConfigSdkMemberProperties struct {
190	android.SdkMemberPropertiesBase
191
192	Metadata android.Path
193}
194
195func (b *compatConfigSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
196	module := variant.(*platformCompatConfig)
197	b.Metadata = module.metadataFile
198}
199
200func (b *compatConfigSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
201	builder := ctx.SnapshotBuilder()
202	if b.Metadata != nil {
203		snapshotRelativePath := filepath.Join("compat_configs", ctx.Name(), b.Metadata.Base())
204		builder.CopyToSnapshot(b.Metadata, snapshotRelativePath)
205		propertySet.AddProperty("metadata", snapshotRelativePath)
206	}
207}
208
209var _ android.SdkMemberType = (*compatConfigMemberType)(nil)
210
211// A prebuilt version of the platform compat config module.
212type prebuiltCompatConfigModule struct {
213	android.ModuleBase
214	prebuilt android.Prebuilt
215
216	properties prebuiltCompatConfigProperties
217
218	metadataFile android.Path
219}
220
221type prebuiltCompatConfigProperties struct {
222	Metadata *string `android:"path"`
223
224	// Name of the source soong module that gets shadowed by this prebuilt
225	// If unspecified, follows the naming convention that the source module of
226	// the prebuilt is Name() without "prebuilt_" prefix
227	Source_module_name *string
228}
229
230func (module *prebuiltCompatConfigModule) Prebuilt() *android.Prebuilt {
231	return &module.prebuilt
232}
233
234func (module *prebuiltCompatConfigModule) Name() string {
235	return module.prebuilt.Name(module.ModuleBase.Name())
236}
237
238func (module *prebuiltCompatConfigModule) compatConfigMetadata() android.Path {
239	return module.metadataFile
240}
241
242func (module *prebuiltCompatConfigModule) includeInMergedXml() bool {
243	return true // Always include in merged.xml
244}
245
246func (module *prebuiltCompatConfigModule) BaseModuleName() string {
247	return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name())
248}
249
250var _ platformCompatConfigMetadataProvider = (*prebuiltCompatConfigModule)(nil)
251
252func (module *prebuiltCompatConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
253	module.metadataFile = module.prebuilt.SingleSourcePath(ctx)
254
255	android.SetProvider(ctx, PlatformCompatConfigMetadataInfoProvider, PlatformCompatConfigMetadataInfo{
256		CompatConfigMetadata: module.compatConfigMetadata(),
257		IncludeInMergedXml:   module.includeInMergedXml(),
258	})
259}
260
261// A prebuilt version of platform_compat_config that provides the metadata.
262func prebuiltCompatConfigFactory() android.Module {
263	m := &prebuiltCompatConfigModule{}
264	m.AddProperties(&m.properties)
265	android.InitSingleSourcePrebuiltModule(m, &m.properties, "Metadata")
266	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
267	return m
268}
269
270// compat singleton rules
271type platformCompatConfigSingleton struct {
272	metadata android.Path
273}
274
275func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
276
277	var compatConfigMetadata android.Paths
278
279	ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
280		if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
281			return
282		}
283		if c, ok := android.OtherModuleProvider(ctx, module, PlatformCompatConfigMetadataInfoProvider); ok {
284			if !android.IsModulePreferredProxy(ctx, module) {
285				return
286			}
287			if !c.IncludeInMergedXml {
288				return
289			}
290			metadata := c.CompatConfigMetadata
291			compatConfigMetadata = append(compatConfigMetadata, metadata)
292		}
293	})
294
295	if compatConfigMetadata == nil {
296		// nothing to do.
297		return
298	}
299
300	rule := android.NewRuleBuilder(pctx, ctx)
301	outputPath := platformCompatConfigPath(ctx)
302
303	rule.Command().
304		BuiltTool("process-compat-config").
305		FlagForEachInput("--xml ", compatConfigMetadata).
306		FlagWithOutput("--merged-config ", outputPath)
307
308	rule.Build("merged-compat-config", "Merge compat config")
309
310	p.metadata = outputPath
311	ctx.DistForGoal("droidcore", p.metadata)
312}
313
314func platformCompatConfigSingletonFactory() android.Singleton {
315	return &platformCompatConfigSingleton{}
316}
317
318// ============== merged_compat_config =================
319type globalCompatConfigProperties struct {
320	// name of the file into which the metadata will be copied.
321	Filename *string
322}
323
324type globalCompatConfig struct {
325	android.ModuleBase
326
327	properties globalCompatConfigProperties
328}
329
330func (c *globalCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
331	filename := String(c.properties.Filename)
332
333	inputPath := platformCompatConfigPath(ctx)
334	outputFilePath := android.PathForModuleOut(ctx, filename).OutputPath
335
336	// This ensures that outputFilePath has the correct name for others to
337	// use, as the source file may have a different name.
338	ctx.Build(pctx, android.BuildParams{
339		Rule:   android.Cp,
340		Output: outputFilePath,
341		Input:  inputPath,
342	})
343
344	ctx.SetOutputFiles(android.Paths{outputFilePath}, "")
345}
346
347// global_compat_config provides access to the merged compat config xml file generated by the build.
348func globalCompatConfigFactory() android.Module {
349	module := &globalCompatConfig{}
350	module.AddProperties(&module.properties)
351	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
352	return module
353}
354