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