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 "android/soong/android" 19 "fmt" 20) 21 22func init() { 23 android.RegisterSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory) 24 android.RegisterModuleType("platform_compat_config", PlatformCompatConfigFactory) 25 android.RegisterModuleType("global_compat_config", globalCompatConfigFactory) 26} 27 28func platformCompatConfigPath(ctx android.PathContext) android.OutputPath { 29 return android.PathForOutput(ctx, "compat_config", "merged_compat_config.xml") 30} 31 32type platformCompatConfigSingleton struct { 33 metadata android.Path 34} 35 36type platformCompatConfigProperties struct { 37 Src *string `android:"path"` 38} 39 40type platformCompatConfig struct { 41 android.ModuleBase 42 43 properties platformCompatConfigProperties 44 installDirPath android.InstallPath 45 configFile android.OutputPath 46 metadataFile android.OutputPath 47} 48 49func (p *platformCompatConfig) compatConfigMetadata() android.OutputPath { 50 return p.metadataFile 51} 52 53func (p *platformCompatConfig) CompatConfig() android.OutputPath { 54 return p.configFile 55} 56 57func (p *platformCompatConfig) SubDir() string { 58 return "compatconfig" 59} 60 61type PlatformCompatConfigIntf interface { 62 android.Module 63 64 compatConfigMetadata() android.OutputPath 65 CompatConfig() android.OutputPath 66 // Sub dir under etc dir. 67 SubDir() string 68} 69 70var _ PlatformCompatConfigIntf = (*platformCompatConfig)(nil) 71 72// compat singleton rules 73func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) { 74 75 var compatConfigMetadata android.Paths 76 77 ctx.VisitAllModules(func(module android.Module) { 78 if c, ok := module.(PlatformCompatConfigIntf); ok { 79 metadata := c.compatConfigMetadata() 80 compatConfigMetadata = append(compatConfigMetadata, metadata) 81 } 82 }) 83 84 if compatConfigMetadata == nil { 85 // nothing to do. 86 return 87 } 88 89 rule := android.NewRuleBuilder() 90 outputPath := platformCompatConfigPath(ctx) 91 92 rule.Command(). 93 BuiltTool(ctx, "process-compat-config"). 94 FlagForEachInput("--xml ", compatConfigMetadata). 95 FlagWithOutput("--merged-config ", outputPath) 96 97 rule.Build(pctx, ctx, "merged-compat-config", "Merge compat config") 98 99 p.metadata = outputPath 100} 101 102func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) { 103 if p.metadata != nil { 104 ctx.Strict("INTERNAL_PLATFORM_MERGED_COMPAT_CONFIG", p.metadata.String()) 105 } 106} 107 108func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { 109 rule := android.NewRuleBuilder() 110 111 configFileName := p.Name() + ".xml" 112 metadataFileName := p.Name() + "_meta.xml" 113 p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath 114 p.metadataFile = android.PathForModuleOut(ctx, metadataFileName).OutputPath 115 path := android.PathForModuleSrc(ctx, String(p.properties.Src)) 116 117 rule.Command(). 118 BuiltTool(ctx, "process-compat-config"). 119 FlagWithInput("--jar ", path). 120 FlagWithOutput("--device-config ", p.configFile). 121 FlagWithOutput("--merged-config ", p.metadataFile) 122 123 p.installDirPath = android.PathForModuleInstall(ctx, "etc", "compatconfig") 124 rule.Build(pctx, ctx, configFileName, "Extract compat/compat_config.xml and install it") 125 126} 127 128func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries { 129 return []android.AndroidMkEntries{android.AndroidMkEntries{ 130 Class: "ETC", 131 OutputFile: android.OptionalPathForPath(p.configFile), 132 Include: "$(BUILD_PREBUILT)", 133 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 134 func(entries *android.AndroidMkEntries) { 135 entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.ToMakePath().String()) 136 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.configFile.Base()) 137 }, 138 }, 139 }} 140} 141 142func platformCompatConfigSingletonFactory() android.Singleton { 143 return &platformCompatConfigSingleton{} 144} 145 146func PlatformCompatConfigFactory() android.Module { 147 module := &platformCompatConfig{} 148 module.AddProperties(&module.properties) 149 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 150 return module 151} 152 153//============== merged_compat_config ================= 154type globalCompatConfigProperties struct { 155 // name of the file into which the metadata will be copied. 156 Filename *string 157} 158 159type globalCompatConfig struct { 160 android.ModuleBase 161 162 properties globalCompatConfigProperties 163 164 outputFilePath android.OutputPath 165} 166 167func (c *globalCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { 168 filename := String(c.properties.Filename) 169 170 inputPath := platformCompatConfigPath(ctx) 171 c.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath 172 173 // This ensures that outputFilePath has the correct name for others to 174 // use, as the source file may have a different name. 175 ctx.Build(pctx, android.BuildParams{ 176 Rule: android.Cp, 177 Output: c.outputFilePath, 178 Input: inputPath, 179 }) 180} 181 182func (h *globalCompatConfig) OutputFiles(tag string) (android.Paths, error) { 183 switch tag { 184 case "": 185 return android.Paths{h.outputFilePath}, nil 186 default: 187 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 188 } 189} 190 191// global_compat_config provides access to the merged compat config xml file generated by the build. 192func globalCompatConfigFactory() android.Module { 193 module := &globalCompatConfig{} 194 module.AddProperties(&module.properties) 195 android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) 196 return module 197} 198