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 46var PrepareForTestWithPlatformCompatConfig = android.FixtureRegisterWithContext(registerPlatformCompatConfigBuildComponents) 47 48func platformCompatConfigPath(ctx android.PathContext) android.OutputPath { 49 return android.PathForOutput(ctx, "compat_config", "merged_compat_config.xml") 50} 51 52type platformCompatConfigProperties struct { 53 Src *string `android:"path"` 54} 55 56type platformCompatConfig struct { 57 android.ModuleBase 58 59 properties platformCompatConfigProperties 60 installDirPath android.InstallPath 61 configFile android.OutputPath 62 metadataFile android.OutputPath 63 64 installConfigFile android.InstallPath 65} 66 67func (p *platformCompatConfig) compatConfigMetadata() android.Path { 68 return p.metadataFile 69} 70 71func (p *platformCompatConfig) CompatConfig() android.OutputPath { 72 return p.configFile 73} 74 75func (p *platformCompatConfig) SubDir() string { 76 return "compatconfig" 77} 78 79type platformCompatConfigMetadataProvider interface { 80 compatConfigMetadata() android.Path 81} 82 83type PlatformCompatConfigIntf interface { 84 android.Module 85 86 CompatConfig() android.OutputPath 87 // Sub dir under etc dir. 88 SubDir() string 89} 90 91var _ PlatformCompatConfigIntf = (*platformCompatConfig)(nil) 92var _ platformCompatConfigMetadataProvider = (*platformCompatConfig)(nil) 93 94func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { 95 rule := android.NewRuleBuilder(pctx, ctx) 96 97 configFileName := p.Name() + ".xml" 98 metadataFileName := p.Name() + "_meta.xml" 99 p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath 100 p.metadataFile = android.PathForModuleOut(ctx, metadataFileName).OutputPath 101 path := android.PathForModuleSrc(ctx, String(p.properties.Src)) 102 103 rule.Command(). 104 BuiltTool("process-compat-config"). 105 FlagWithInput("--jar ", path). 106 FlagWithOutput("--device-config ", p.configFile). 107 FlagWithOutput("--merged-config ", p.metadataFile) 108 109 p.installDirPath = android.PathForModuleInstall(ctx, "etc", "compatconfig") 110 p.installConfigFile = android.PathForModuleInstall(ctx, "etc", "compatconfig", p.configFile.Base()) 111 rule.Build(configFileName, "Extract compat/compat_config.xml and install it") 112 ctx.InstallFile(p.installDirPath, p.configFile.Base(), p.configFile) 113 ctx.SetOutputFiles(android.Paths{p.configFile}, "") 114} 115 116func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries { 117 return []android.AndroidMkEntries{android.AndroidMkEntries{ 118 Class: "ETC", 119 OutputFile: android.OptionalPathForPath(p.configFile), 120 }} 121} 122 123func PlatformCompatConfigFactory() android.Module { 124 module := &platformCompatConfig{} 125 module.AddProperties(&module.properties) 126 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) 127 return module 128} 129 130type compatConfigMemberType struct { 131 android.SdkMemberTypeBase 132} 133 134func (b *compatConfigMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) { 135 ctx.AddVariationDependencies(nil, dependencyTag, names...) 136} 137 138func (b *compatConfigMemberType) IsInstance(module android.Module) bool { 139 _, ok := module.(*platformCompatConfig) 140 return ok 141} 142 143func (b *compatConfigMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { 144 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_platform_compat_config") 145} 146 147func (b *compatConfigMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { 148 return &compatConfigSdkMemberProperties{} 149} 150 151type compatConfigSdkMemberProperties struct { 152 android.SdkMemberPropertiesBase 153 154 Metadata android.Path 155} 156 157func (b *compatConfigSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { 158 module := variant.(*platformCompatConfig) 159 b.Metadata = module.metadataFile 160} 161 162func (b *compatConfigSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { 163 builder := ctx.SnapshotBuilder() 164 if b.Metadata != nil { 165 snapshotRelativePath := filepath.Join("compat_configs", ctx.Name(), b.Metadata.Base()) 166 builder.CopyToSnapshot(b.Metadata, snapshotRelativePath) 167 propertySet.AddProperty("metadata", snapshotRelativePath) 168 } 169} 170 171var _ android.SdkMemberType = (*compatConfigMemberType)(nil) 172 173// A prebuilt version of the platform compat config module. 174type prebuiltCompatConfigModule struct { 175 android.ModuleBase 176 prebuilt android.Prebuilt 177 178 properties prebuiltCompatConfigProperties 179 180 metadataFile android.Path 181} 182 183type prebuiltCompatConfigProperties struct { 184 Metadata *string `android:"path"` 185 186 // Name of the source soong module that gets shadowed by this prebuilt 187 // If unspecified, follows the naming convention that the source module of 188 // the prebuilt is Name() without "prebuilt_" prefix 189 Source_module_name *string 190} 191 192func (module *prebuiltCompatConfigModule) Prebuilt() *android.Prebuilt { 193 return &module.prebuilt 194} 195 196func (module *prebuiltCompatConfigModule) Name() string { 197 return module.prebuilt.Name(module.ModuleBase.Name()) 198} 199 200func (module *prebuiltCompatConfigModule) compatConfigMetadata() android.Path { 201 return module.metadataFile 202} 203 204func (module *prebuiltCompatConfigModule) BaseModuleName() string { 205 return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name()) 206} 207 208var _ platformCompatConfigMetadataProvider = (*prebuiltCompatConfigModule)(nil) 209 210func (module *prebuiltCompatConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 211 module.metadataFile = module.prebuilt.SingleSourcePath(ctx) 212} 213 214// A prebuilt version of platform_compat_config that provides the metadata. 215func prebuiltCompatConfigFactory() android.Module { 216 m := &prebuiltCompatConfigModule{} 217 m.AddProperties(&m.properties) 218 android.InitSingleSourcePrebuiltModule(m, &m.properties, "Metadata") 219 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 220 return m 221} 222 223// compat singleton rules 224type platformCompatConfigSingleton struct { 225 metadata android.Path 226} 227 228func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) { 229 230 var compatConfigMetadata android.Paths 231 232 ctx.VisitAllModules(func(module android.Module) { 233 if !module.Enabled(ctx) { 234 return 235 } 236 if c, ok := module.(platformCompatConfigMetadataProvider); ok { 237 if !android.IsModulePreferred(module) { 238 return 239 } 240 metadata := c.compatConfigMetadata() 241 compatConfigMetadata = append(compatConfigMetadata, metadata) 242 } 243 }) 244 245 if compatConfigMetadata == nil { 246 // nothing to do. 247 return 248 } 249 250 rule := android.NewRuleBuilder(pctx, ctx) 251 outputPath := platformCompatConfigPath(ctx) 252 253 rule.Command(). 254 BuiltTool("process-compat-config"). 255 FlagForEachInput("--xml ", compatConfigMetadata). 256 FlagWithOutput("--merged-config ", outputPath) 257 258 rule.Build("merged-compat-config", "Merge compat config") 259 260 p.metadata = outputPath 261} 262 263func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) { 264 if p.metadata != nil { 265 ctx.DistForGoal("droidcore", p.metadata) 266 } 267} 268 269func platformCompatConfigSingletonFactory() android.Singleton { 270 return &platformCompatConfigSingleton{} 271} 272 273// ============== merged_compat_config ================= 274type globalCompatConfigProperties struct { 275 // name of the file into which the metadata will be copied. 276 Filename *string 277} 278 279type globalCompatConfig struct { 280 android.ModuleBase 281 282 properties globalCompatConfigProperties 283} 284 285func (c *globalCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { 286 filename := String(c.properties.Filename) 287 288 inputPath := platformCompatConfigPath(ctx) 289 outputFilePath := android.PathForModuleOut(ctx, filename).OutputPath 290 291 // This ensures that outputFilePath has the correct name for others to 292 // use, as the source file may have a different name. 293 ctx.Build(pctx, android.BuildParams{ 294 Rule: android.Cp, 295 Output: outputFilePath, 296 Input: inputPath, 297 }) 298 299 ctx.SetOutputFiles(android.Paths{outputFilePath}, "") 300} 301 302// global_compat_config provides access to the merged compat config xml file generated by the build. 303func globalCompatConfigFactory() android.Module { 304 module := &globalCompatConfig{} 305 module.AddProperties(&module.properties) 306 android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) 307 return module 308} 309