1// Copyright 2020 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 17// This file contains the module implementations for runtime_resource_overlay and 18// override_runtime_resource_overlay. 19 20import ( 21 "android/soong/android" 22 23 "github.com/google/blueprint" 24 "github.com/google/blueprint/proptools" 25) 26 27func init() { 28 RegisterRuntimeResourceOverlayBuildComponents(android.InitRegistrationContext) 29} 30 31func RegisterRuntimeResourceOverlayBuildComponents(ctx android.RegistrationContext) { 32 ctx.RegisterModuleType("runtime_resource_overlay", RuntimeResourceOverlayFactory) 33 ctx.RegisterModuleType("autogen_runtime_resource_overlay", AutogenRuntimeResourceOverlayFactory) 34 ctx.RegisterModuleType("override_runtime_resource_overlay", OverrideRuntimeResourceOverlayModuleFactory) 35} 36 37type RuntimeResourceOverlay struct { 38 android.ModuleBase 39 android.DefaultableModuleBase 40 android.OverridableModuleBase 41 aapt 42 43 properties RuntimeResourceOverlayProperties 44 overridableProperties OverridableRuntimeResourceOverlayProperties 45 46 certificate Certificate 47 48 outputFile android.Path 49 installDir android.InstallPath 50} 51 52type RuntimeResourceOverlayProperties struct { 53 // the name of a certificate in the default certificate directory or an android_app_certificate 54 // module name in the form ":module". 55 Certificate proptools.Configurable[string] `android:"replace_instead_of_append"` 56 57 // Name of the signing certificate lineage file. 58 Lineage *string 59 60 // For overriding the --rotation-min-sdk-version property of apksig 61 RotationMinSdkVersion *string 62 63 // optional theme name. If specified, the overlay package will be applied 64 // only when the ro.boot.vendor.overlay.theme system property is set to the same value. 65 Theme *string 66 67 // If not blank, set to the version of the sdk to compile against. This 68 // can be either an API version (e.g. "29" for API level 29 AKA Android 10) 69 // or special subsets of the current platform, for example "none", "current", 70 // "core", "system", "test". See build/soong/java/sdk.go for the full and 71 // up-to-date list of possible values. 72 // Defaults to compiling against the current platform. 73 Sdk_version *string 74 75 // if not blank, set the minimum version of the sdk that the compiled artifacts will run against. 76 // Defaults to sdk_version if not set. 77 Min_sdk_version *string 78 79 // list of android_library modules whose resources are extracted and linked against statically 80 Static_libs proptools.Configurable[[]string] 81 82 // list of android_app modules whose resources are extracted and linked against 83 Resource_libs []string 84 85 // Names of modules to be overridden. Listed modules can only be other overlays 86 // (in Make or Soong). 87 // This does not completely prevent installation of the overridden overlays, but if both 88 // overlays would be installed by default (in PRODUCT_PACKAGES) the other overlay will be removed 89 // from PRODUCT_PACKAGES. 90 Overrides []string 91} 92 93// RuntimeResourceOverlayModule interface is used by the apex package to gather information from 94// a RuntimeResourceOverlay module. 95type RuntimeResourceOverlayModule interface { 96 android.Module 97 OutputFile() android.Path 98 Certificate() Certificate 99 Theme() string 100} 101 102// RRO's partition logic is different from the partition logic of other modules defined in soong/android/paths.go 103// The default partition for RRO is "/product" and not "/system" 104func rroPartition(ctx android.ModuleContext) string { 105 var partition string 106 if ctx.DeviceSpecific() { 107 partition = ctx.DeviceConfig().OdmPath() 108 } else if ctx.SocSpecific() { 109 partition = ctx.DeviceConfig().VendorPath() 110 } else if ctx.SystemExtSpecific() { 111 partition = ctx.DeviceConfig().SystemExtPath() 112 } else { 113 partition = ctx.DeviceConfig().ProductPath() 114 } 115 return partition 116} 117 118func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) { 119 sdkDep := decodeSdkDep(ctx, android.SdkContext(r)) 120 if sdkDep.hasFrameworkLibs() { 121 r.aapt.deps(ctx, sdkDep) 122 } 123 124 cert := android.SrcIsModule(r.properties.Certificate.GetOrDefault(ctx, "")) 125 if cert != "" { 126 ctx.AddDependency(ctx.Module(), certificateTag, cert) 127 } 128 129 ctx.AddVariationDependencies(nil, staticLibTag, r.properties.Static_libs.GetOrDefault(ctx, nil)...) 130 ctx.AddVariationDependencies(nil, libTag, r.properties.Resource_libs...) 131 132 for _, aconfig_declaration := range r.aaptProperties.Flags_packages { 133 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration) 134 } 135} 136 137func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) { 138 // Compile and link resources 139 r.aapt.hasNoCode = true 140 // Do not remove resources without default values nor dedupe resource configurations with the same value 141 aaptLinkFlags := []string{"--no-resource-deduping", "--no-resource-removal"} 142 // Allow the override of "package name" and "overlay target package name" 143 manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName()) 144 if overridden || r.overridableProperties.Package_name != nil { 145 // The product override variable has a priority over the package_name property. 146 if !overridden { 147 manifestPackageName = *r.overridableProperties.Package_name 148 } 149 aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, false)...) 150 } 151 if r.overridableProperties.Target_package_name != nil { 152 aaptLinkFlags = append(aaptLinkFlags, 153 "--rename-overlay-target-package "+*r.overridableProperties.Target_package_name) 154 } 155 if r.overridableProperties.Category != nil { 156 aaptLinkFlags = append(aaptLinkFlags, 157 "--rename-overlay-category "+*r.overridableProperties.Category) 158 } 159 aconfigTextFilePaths := getAconfigFilePaths(ctx) 160 r.aapt.buildActions(ctx, 161 aaptBuildActionOptions{ 162 sdkContext: r, 163 enforceDefaultTargetSdkVersion: false, 164 extraLinkFlags: aaptLinkFlags, 165 aconfigTextFiles: aconfigTextFilePaths, 166 }, 167 ) 168 169 // Sign the built package 170 _, _, certificates := collectAppDeps(ctx, r, false, false) 171 r.certificate, certificates = processMainCert(r.ModuleBase, r.properties.Certificate.GetOrDefault(ctx, ""), certificates, ctx) 172 signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk") 173 var lineageFile android.Path 174 if lineage := String(r.properties.Lineage); lineage != "" { 175 lineageFile = android.PathForModuleSrc(ctx, lineage) 176 } 177 178 rotationMinSdkVersion := String(r.properties.RotationMinSdkVersion) 179 180 SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil, lineageFile, rotationMinSdkVersion) 181 182 r.outputFile = signed 183 partition := rroPartition(ctx) 184 r.installDir = android.PathForModuleInPartitionInstall(ctx, partition, "overlay", String(r.properties.Theme)) 185 ctx.InstallFile(r.installDir, r.outputFile.Base(), r.outputFile) 186 187 android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{ 188 AconfigTextFiles: aconfigTextFilePaths, 189 }) 190} 191 192func (r *RuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { 193 return android.SdkSpecFrom(ctx, String(r.properties.Sdk_version)) 194} 195 196func (r *RuntimeResourceOverlay) SystemModules() string { 197 return "" 198} 199 200func (r *RuntimeResourceOverlay) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 201 if r.properties.Min_sdk_version != nil { 202 return android.ApiLevelFrom(ctx, *r.properties.Min_sdk_version) 203 } 204 return r.SdkVersion(ctx).ApiLevel 205} 206 207func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel { 208 return android.SdkSpecPrivate.ApiLevel 209} 210 211func (r *RuntimeResourceOverlay) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 212 return r.SdkVersion(ctx).ApiLevel 213} 214 215func (r *RuntimeResourceOverlay) Certificate() Certificate { 216 return r.certificate 217} 218 219func (r *RuntimeResourceOverlay) OutputFile() android.Path { 220 return r.outputFile 221} 222 223func (r *RuntimeResourceOverlay) Theme() string { 224 return String(r.properties.Theme) 225} 226 227// runtime_resource_overlay generates a resource-only apk file that can overlay application and 228// system resources at run time. 229func RuntimeResourceOverlayFactory() android.Module { 230 module := &RuntimeResourceOverlay{} 231 module.AddProperties( 232 &module.properties, 233 &module.aaptProperties, 234 &module.overridableProperties) 235 236 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 237 android.InitDefaultableModule(module) 238 android.InitOverridableModule(module, &module.properties.Overrides) 239 return module 240} 241 242// runtime_resource_overlay properties that can be overridden by override_runtime_resource_overlay 243type OverridableRuntimeResourceOverlayProperties struct { 244 // the package name of this app. The package name in the manifest file is used if one was not given. 245 Package_name *string 246 247 // the target package name of this overlay app. The target package name in the manifest file is used if one was not given. 248 Target_package_name *string 249 250 // the rro category of this overlay. The category in the manifest file is used if one was not given. 251 Category *string 252} 253 254type OverrideRuntimeResourceOverlay struct { 255 android.ModuleBase 256 android.OverrideModuleBase 257} 258 259func (i *OverrideRuntimeResourceOverlay) GenerateAndroidBuildActions(_ android.ModuleContext) { 260 // All the overrides happen in the base module. 261 // TODO(jungjw): Check the base module type. 262} 263 264// override_runtime_resource_overlay is used to create a module based on another 265// runtime_resource_overlay module by overriding some of its properties. 266func OverrideRuntimeResourceOverlayModuleFactory() android.Module { 267 m := &OverrideRuntimeResourceOverlay{} 268 m.AddProperties(&OverridableRuntimeResourceOverlayProperties{}) 269 270 android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon) 271 android.InitOverrideModule(m) 272 return m 273} 274 275var ( 276 generateOverlayManifestFile = pctx.AndroidStaticRule("generate_overlay_manifest", 277 blueprint.RuleParams{ 278 Command: "build/make/tools/generate-enforce-rro-android-manifest.py " + 279 "--package-info $in " + 280 "--partition ${partition} " + 281 "--priority ${priority} -o $out", 282 CommandDeps: []string{"build/make/tools/generate-enforce-rro-android-manifest.py"}, 283 }, "partition", "priority", 284 ) 285) 286 287type AutogenRuntimeResourceOverlay struct { 288 android.ModuleBase 289 aapt 290 291 properties AutogenRuntimeResourceOverlayProperties 292 293 certificate Certificate 294 outputFile android.Path 295} 296 297type AutogenRuntimeResourceOverlayProperties struct { 298 Base *string 299 Sdk_version *string 300 Manifest *string `android:"path"` 301} 302 303func AutogenRuntimeResourceOverlayFactory() android.Module { 304 m := &AutogenRuntimeResourceOverlay{} 305 m.AddProperties(&m.properties) 306 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 307 308 return m 309} 310 311type rroDependencyTag struct { 312 blueprint.DependencyTag 313} 314 315// Autogenerated RROs should always depend on the source android_app that created it. 316func (tag rroDependencyTag) ReplaceSourceWithPrebuilt() bool { 317 return false 318} 319 320var rroDepTag = rroDependencyTag{} 321 322func (a *AutogenRuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) { 323 sdkDep := decodeSdkDep(ctx, android.SdkContext(a)) 324 if sdkDep.hasFrameworkLibs() { 325 a.aapt.deps(ctx, sdkDep) 326 } 327 ctx.AddDependency(ctx.Module(), rroDepTag, proptools.String(a.properties.Base)) 328} 329 330func (a *AutogenRuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) { 331 if !a.Enabled(ctx) { 332 return 333 } 334 var rroDirs android.Paths 335 // Get rro dirs of the base app 336 ctx.VisitDirectDepsWithTag(rroDepTag, func(m android.Module) { 337 aarDep, _ := m.(AndroidLibraryDependency) 338 if ctx.InstallInProduct() { 339 rroDirs = filterRRO(aarDep.RRODirsDepSet(), product) 340 } else { 341 rroDirs = filterRRO(aarDep.RRODirsDepSet(), device) 342 } 343 }) 344 345 if len(rroDirs) == 0 { 346 return 347 } 348 349 // Generate a manifest file 350 genManifest := android.PathForModuleGen(ctx, "AndroidManifest.xml") 351 partition := "vendor" 352 priority := "0" 353 if ctx.InstallInProduct() { 354 partition = "product" 355 priority = "1" 356 } 357 ctx.Build(pctx, android.BuildParams{ 358 Rule: generateOverlayManifestFile, 359 Input: android.PathForModuleSrc(ctx, proptools.String(a.properties.Manifest)), 360 Output: genManifest, 361 Args: map[string]string{ 362 "partition": partition, 363 "priority": priority, 364 }, 365 }) 366 367 // Compile and link resources into package-res.apk 368 a.aapt.hasNoCode = true 369 aaptLinkFlags := []string{"--auto-add-overlay", "--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"} 370 371 a.aapt.buildActions(ctx, 372 aaptBuildActionOptions{ 373 sdkContext: a, 374 extraLinkFlags: aaptLinkFlags, 375 rroDirs: &rroDirs, 376 manifestForAapt: genManifest, 377 }, 378 ) 379 380 if a.exportPackage == nil { 381 return 382 } 383 // Sign the built package 384 var certificates []Certificate 385 a.certificate, certificates = processMainCert(a.ModuleBase, "", nil, ctx) 386 signed := android.PathForModuleOut(ctx, "signed", a.Name()+".apk") 387 SignAppPackage(ctx, signed, a.exportPackage, certificates, nil, nil, "") 388 a.outputFile = signed 389 390 // Install the signed apk 391 installDir := android.PathForModuleInstall(ctx, "overlay") 392 ctx.InstallFile(installDir, signed.Base(), signed) 393} 394 395func (a *AutogenRuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { 396 return android.SdkSpecFrom(ctx, String(a.properties.Sdk_version)) 397} 398 399func (a *AutogenRuntimeResourceOverlay) SystemModules() string { 400 return "" 401} 402 403func (a *AutogenRuntimeResourceOverlay) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 404 return a.SdkVersion(ctx).ApiLevel 405} 406 407func (r *AutogenRuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel { 408 return android.SdkSpecPrivate.ApiLevel 409} 410 411func (a *AutogenRuntimeResourceOverlay) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 412 return a.SdkVersion(ctx).ApiLevel 413} 414 415func (a *AutogenRuntimeResourceOverlay) InstallInProduct() bool { 416 return a.ProductSpecific() 417} 418