1// Copyright 2018 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 "strconv" 21 "strings" 22 23 "android/soong/android" 24 "android/soong/dexpreopt" 25 26 "github.com/google/blueprint" 27 "github.com/google/blueprint/proptools" 28) 29 30type AndroidLibraryDependency interface { 31 ExportPackage() android.Path 32 ExportedProguardFlagFiles() android.Paths 33 ExportedRRODirs() []rroDir 34 ExportedStaticPackages() android.Paths 35 ExportedManifests() android.Paths 36 ExportedAssets() android.OptionalPath 37 SetRROEnforcedForDependent(enforce bool) 38 IsRROEnforced(ctx android.BaseModuleContext) bool 39} 40 41func init() { 42 RegisterAARBuildComponents(android.InitRegistrationContext) 43} 44 45func RegisterAARBuildComponents(ctx android.RegistrationContext) { 46 ctx.RegisterModuleType("android_library_import", AARImportFactory) 47 ctx.RegisterModuleType("android_library", AndroidLibraryFactory) 48 ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { 49 ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel() 50 }) 51} 52 53// 54// AAR (android library) 55// 56 57type androidLibraryProperties struct { 58 BuildAAR bool `blueprint:"mutated"` 59} 60 61type aaptProperties struct { 62 // flags passed to aapt when creating the apk 63 Aaptflags []string 64 65 // include all resource configurations, not just the product-configured 66 // ones. 67 Aapt_include_all_resources *bool 68 69 // list of directories relative to the Blueprints file containing assets. 70 // Defaults to ["assets"] if a directory called assets exists. Set to [] 71 // to disable the default. 72 Asset_dirs []string 73 74 // list of directories relative to the Blueprints file containing 75 // Android resources. Defaults to ["res"] if a directory called res exists. 76 // Set to [] to disable the default. 77 Resource_dirs []string 78 79 // list of zip files containing Android resources. 80 Resource_zips []string `android:"path"` 81 82 // path to AndroidManifest.xml. If unset, defaults to "AndroidManifest.xml". 83 Manifest *string `android:"path"` 84 85 // paths to additional manifest files to merge with main manifest. 86 Additional_manifests []string `android:"path"` 87 88 // do not include AndroidManifest from dependent libraries 89 Dont_merge_manifests *bool 90 91 // true if RRO is enforced for any of the dependent modules 92 RROEnforcedForDependent bool `blueprint:"mutated"` 93} 94 95type aapt struct { 96 aaptSrcJar android.Path 97 exportPackage android.Path 98 manifestPath android.Path 99 transitiveManifestPaths android.Paths 100 proguardOptionsFile android.Path 101 rroDirs []rroDir 102 rTxt android.Path 103 extraAaptPackagesFile android.Path 104 mergedManifestFile android.Path 105 noticeFile android.OptionalPath 106 assetPackage android.OptionalPath 107 isLibrary bool 108 useEmbeddedNativeLibs bool 109 useEmbeddedDex bool 110 usesNonSdkApis bool 111 hasNoCode bool 112 LoggingParent string 113 resourceFiles android.Paths 114 115 splitNames []string 116 splits []split 117 118 aaptProperties aaptProperties 119} 120 121type split struct { 122 name string 123 suffix string 124 path android.Path 125} 126 127// Propagate RRO enforcement flag to static lib dependencies transitively. 128func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) { 129 m := ctx.Module() 130 if d, ok := m.(AndroidLibraryDependency); ok && d.IsRROEnforced(ctx) { 131 ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) { 132 if a, ok := d.(AndroidLibraryDependency); ok { 133 a.SetRROEnforcedForDependent(true) 134 } 135 }) 136 } 137} 138 139func (a *aapt) ExportPackage() android.Path { 140 return a.exportPackage 141} 142 143func (a *aapt) ExportedRRODirs() []rroDir { 144 return a.rroDirs 145} 146 147func (a *aapt) ExportedManifests() android.Paths { 148 return a.transitiveManifestPaths 149} 150 151func (a *aapt) ExportedAssets() android.OptionalPath { 152 return a.assetPackage 153} 154 155func (a *aapt) SetRROEnforcedForDependent(enforce bool) { 156 a.aaptProperties.RROEnforcedForDependent = enforce 157} 158 159func (a *aapt) IsRROEnforced(ctx android.BaseModuleContext) bool { 160 // True if RRO is enforced for this module or... 161 return ctx.Config().EnforceRROForModule(ctx.ModuleName()) || 162 // if RRO is enforced for any of its dependents. 163 a.aaptProperties.RROEnforcedForDependent 164} 165 166func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkContext, 167 manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths, 168 resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) { 169 170 hasVersionCode := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-code") 171 hasVersionName := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-name") 172 173 // Flags specified in Android.bp 174 linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...) 175 176 linkFlags = append(linkFlags, "--no-static-lib-packages") 177 178 // Find implicit or explicit asset and resource dirs 179 assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets") 180 resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res") 181 resourceZips := android.PathsForModuleSrc(ctx, a.aaptProperties.Resource_zips) 182 183 // Glob directories into lists of paths 184 for _, dir := range resourceDirs { 185 resDirs = append(resDirs, globbedResourceDir{ 186 dir: dir, 187 files: androidResourceGlob(ctx, dir), 188 }) 189 resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, a, dir) 190 overlayDirs = append(overlayDirs, resOverlayDirs...) 191 rroDirs = append(rroDirs, resRRODirs...) 192 } 193 194 var assetDeps android.Paths 195 for i, dir := range assetDirs { 196 // Add a dependency on every file in the asset directory. This ensures the aapt2 197 // rule will be rerun if one of the files in the asset directory is modified. 198 assetDeps = append(assetDeps, androidResourceGlob(ctx, dir)...) 199 200 // Add a dependency on a file that contains a list of all the files in the asset directory. 201 // This ensures the aapt2 rule will be run if a file is removed from the asset directory, 202 // or a file is added whose timestamp is older than the output of aapt2. 203 assetFileListFile := android.PathForModuleOut(ctx, "asset_dir_globs", strconv.Itoa(i)+".glob") 204 androidResourceGlobList(ctx, dir, assetFileListFile) 205 assetDeps = append(assetDeps, assetFileListFile) 206 } 207 208 assetDirStrings := assetDirs.Strings() 209 if a.noticeFile.Valid() { 210 assetDirStrings = append(assetDirStrings, filepath.Dir(a.noticeFile.Path().String())) 211 assetDeps = append(assetDeps, a.noticeFile.Path()) 212 } 213 214 linkFlags = append(linkFlags, "--manifest "+manifestPath.String()) 215 linkDeps = append(linkDeps, manifestPath) 216 217 linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirStrings, "-A ")) 218 linkDeps = append(linkDeps, assetDeps...) 219 220 // SDK version flags 221 minSdkVersion, err := sdkContext.MinSdkVersion(ctx).EffectiveVersionString(ctx) 222 if err != nil { 223 ctx.ModuleErrorf("invalid minSdkVersion: %s", err) 224 } 225 226 linkFlags = append(linkFlags, "--min-sdk-version "+minSdkVersion) 227 linkFlags = append(linkFlags, "--target-sdk-version "+minSdkVersion) 228 229 // Version code 230 if !hasVersionCode { 231 linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion().String()) 232 } 233 234 if !hasVersionName { 235 var versionName string 236 if ctx.ModuleName() == "framework-res" { 237 // Some builds set AppsDefaultVersionName() to include the build number ("O-123456"). aapt2 copies the 238 // version name of framework-res into app manifests as compileSdkVersionCodename, which confuses things 239 // if it contains the build number. Use the PlatformVersionName instead. 240 versionName = ctx.Config().PlatformVersionName() 241 } else { 242 versionName = ctx.Config().AppsDefaultVersionName() 243 } 244 versionName = proptools.NinjaEscape(versionName) 245 linkFlags = append(linkFlags, "--version-name ", versionName) 246 } 247 248 linkFlags, compileFlags = android.FilterList(linkFlags, []string{"--legacy"}) 249 250 // Always set --pseudo-localize, it will be stripped out later for release 251 // builds that don't want it. 252 compileFlags = append(compileFlags, "--pseudo-localize") 253 254 return compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resourceZips 255} 256 257func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkDep sdkDep) { 258 if sdkDep.frameworkResModule != "" { 259 ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule) 260 } 261} 262 263var extractAssetsRule = pctx.AndroidStaticRule("extractAssets", 264 blueprint.RuleParams{ 265 Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} "assets/**/*"`, 266 CommandDeps: []string{"${config.Zip2ZipCmd}"}, 267 }) 268 269func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkContext, 270 classLoaderContexts dexpreopt.ClassLoaderContextMap, extraLinkFlags ...string) { 271 272 transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags := 273 aaptLibs(ctx, sdkContext, classLoaderContexts) 274 275 // App manifest file 276 manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml") 277 manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile) 278 279 manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, classLoaderContexts, 280 a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode, 281 a.LoggingParent) 282 283 // Add additional manifest files to transitive manifests. 284 additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests) 285 a.transitiveManifestPaths = append(android.Paths{manifestPath}, additionalManifests...) 286 a.transitiveManifestPaths = append(a.transitiveManifestPaths, transitiveStaticLibManifests...) 287 288 if len(a.transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) { 289 a.mergedManifestFile = manifestMerger(ctx, a.transitiveManifestPaths[0], a.transitiveManifestPaths[1:], a.isLibrary) 290 if !a.isLibrary { 291 // Only use the merged manifest for applications. For libraries, the transitive closure of manifests 292 // will be propagated to the final application and merged there. The merged manifest for libraries is 293 // only passed to Make, which can't handle transitive dependencies. 294 manifestPath = a.mergedManifestFile 295 } 296 } else { 297 a.mergedManifestFile = manifestPath 298 } 299 300 compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, sdkContext, manifestPath) 301 302 rroDirs = append(rroDirs, staticRRODirs...) 303 linkFlags = append(linkFlags, libFlags...) 304 linkDeps = append(linkDeps, libDeps...) 305 linkFlags = append(linkFlags, extraLinkFlags...) 306 if a.isLibrary { 307 linkFlags = append(linkFlags, "--static-lib") 308 } 309 310 packageRes := android.PathForModuleOut(ctx, "package-res.apk") 311 // the subdir "android" is required to be filtered by package names 312 srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar") 313 proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options") 314 rTxt := android.PathForModuleOut(ctx, "R.txt") 315 // This file isn't used by Soong, but is generated for exporting 316 extraPackages := android.PathForModuleOut(ctx, "extra_packages") 317 318 var compiledResDirs []android.Paths 319 for _, dir := range resDirs { 320 a.resourceFiles = append(a.resourceFiles, dir.files...) 321 compiledResDirs = append(compiledResDirs, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths()) 322 } 323 324 for i, zip := range resZips { 325 flata := android.PathForModuleOut(ctx, fmt.Sprintf("reszip.%d.flata", i)) 326 aapt2CompileZip(ctx, flata, zip, "", compileFlags) 327 compiledResDirs = append(compiledResDirs, android.Paths{flata}) 328 } 329 330 var compiledRes, compiledOverlay android.Paths 331 332 compiledOverlay = append(compiledOverlay, transitiveStaticLibs...) 333 334 if len(transitiveStaticLibs) > 0 { 335 // If we are using static android libraries, every source file becomes an overlay. 336 // This is to emulate old AAPT behavior which simulated library support. 337 for _, compiledResDir := range compiledResDirs { 338 compiledOverlay = append(compiledOverlay, compiledResDir...) 339 } 340 } else if a.isLibrary { 341 // Otherwise, for a static library we treat all the resources equally with no overlay. 342 for _, compiledResDir := range compiledResDirs { 343 compiledRes = append(compiledRes, compiledResDir...) 344 } 345 } else if len(compiledResDirs) > 0 { 346 // Without static libraries, the first directory is our directory, which can then be 347 // overlaid by the rest. 348 compiledRes = append(compiledRes, compiledResDirs[0]...) 349 for _, compiledResDir := range compiledResDirs[1:] { 350 compiledOverlay = append(compiledOverlay, compiledResDir...) 351 } 352 } 353 354 for _, dir := range overlayDirs { 355 compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths()...) 356 } 357 358 var splitPackages android.WritablePaths 359 var splits []split 360 361 for _, s := range a.splitNames { 362 suffix := strings.Replace(s, ",", "_", -1) 363 path := android.PathForModuleOut(ctx, "package_"+suffix+".apk") 364 linkFlags = append(linkFlags, "--split", path.String()+":"+s) 365 splitPackages = append(splitPackages, path) 366 splits = append(splits, split{ 367 name: s, 368 suffix: suffix, 369 path: path, 370 }) 371 } 372 373 aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages, 374 linkFlags, linkDeps, compiledRes, compiledOverlay, assetPackages, splitPackages) 375 376 // Extract assets from the resource package output so that they can be used later in aapt2link 377 // for modules that depend on this one. 378 if android.PrefixInList(linkFlags, "-A ") || len(assetPackages) > 0 { 379 assets := android.PathForModuleOut(ctx, "assets.zip") 380 ctx.Build(pctx, android.BuildParams{ 381 Rule: extractAssetsRule, 382 Input: packageRes, 383 Output: assets, 384 Description: "extract assets from built resource file", 385 }) 386 a.assetPackage = android.OptionalPathForPath(assets) 387 } 388 389 a.aaptSrcJar = srcJar 390 a.exportPackage = packageRes 391 a.manifestPath = manifestPath 392 a.proguardOptionsFile = proguardOptionsFile 393 a.rroDirs = rroDirs 394 a.extraAaptPackagesFile = extraPackages 395 a.rTxt = rTxt 396 a.splits = splits 397} 398 399// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths 400func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap) ( 401 transitiveStaticLibs, transitiveStaticLibManifests android.Paths, staticRRODirs []rroDir, assets, deps android.Paths, flags []string) { 402 403 var sharedLibs android.Paths 404 405 if classLoaderContexts == nil { 406 // Not all callers need to compute class loader context, those who don't just pass nil. 407 // Create a temporary class loader context here (it will be computed, but not used). 408 classLoaderContexts = make(dexpreopt.ClassLoaderContextMap) 409 } 410 411 sdkDep := decodeSdkDep(ctx, sdkContext) 412 if sdkDep.useFiles { 413 sharedLibs = append(sharedLibs, sdkDep.jars...) 414 } 415 416 ctx.VisitDirectDeps(func(module android.Module) { 417 depTag := ctx.OtherModuleDependencyTag(module) 418 419 var exportPackage android.Path 420 aarDep, _ := module.(AndroidLibraryDependency) 421 if aarDep != nil { 422 exportPackage = aarDep.ExportPackage() 423 } 424 425 switch depTag { 426 case instrumentationForTag: 427 // Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2. 428 case libTag: 429 if exportPackage != nil { 430 sharedLibs = append(sharedLibs, exportPackage) 431 } 432 case frameworkResTag: 433 if exportPackage != nil { 434 sharedLibs = append(sharedLibs, exportPackage) 435 } 436 case staticLibTag: 437 if exportPackage != nil { 438 transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...) 439 transitiveStaticLibs = append(transitiveStaticLibs, exportPackage) 440 transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...) 441 if aarDep.ExportedAssets().Valid() { 442 assets = append(assets, aarDep.ExportedAssets().Path()) 443 } 444 445 outer: 446 for _, d := range aarDep.ExportedRRODirs() { 447 for _, e := range staticRRODirs { 448 if d.path == e.path { 449 continue outer 450 } 451 } 452 staticRRODirs = append(staticRRODirs, d) 453 } 454 } 455 } 456 457 addCLCFromDep(ctx, module, classLoaderContexts) 458 }) 459 460 deps = append(deps, sharedLibs...) 461 deps = append(deps, transitiveStaticLibs...) 462 463 if len(transitiveStaticLibs) > 0 { 464 flags = append(flags, "--auto-add-overlay") 465 } 466 467 for _, sharedLib := range sharedLibs { 468 flags = append(flags, "-I "+sharedLib.String()) 469 } 470 471 transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs) 472 transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests) 473 474 return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags 475} 476 477type AndroidLibrary struct { 478 Library 479 aapt 480 481 androidLibraryProperties androidLibraryProperties 482 483 aarFile android.WritablePath 484 485 exportedProguardFlagFiles android.Paths 486 exportedStaticPackages android.Paths 487} 488 489func (a *AndroidLibrary) ExportedProguardFlagFiles() android.Paths { 490 return a.exportedProguardFlagFiles 491} 492 493func (a *AndroidLibrary) ExportedStaticPackages() android.Paths { 494 return a.exportedStaticPackages 495} 496 497var _ AndroidLibraryDependency = (*AndroidLibrary)(nil) 498 499func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { 500 a.Module.deps(ctx) 501 sdkDep := decodeSdkDep(ctx, android.SdkContext(a)) 502 if sdkDep.hasFrameworkLibs() { 503 a.aapt.deps(ctx, sdkDep) 504 } 505} 506 507func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { 508 a.aapt.isLibrary = true 509 a.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap) 510 a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts) 511 512 a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() 513 514 ctx.CheckbuildFile(a.proguardOptionsFile) 515 ctx.CheckbuildFile(a.exportPackage) 516 ctx.CheckbuildFile(a.aaptSrcJar) 517 518 // apps manifests are handled by aapt, don't let Module see them 519 a.properties.Manifest = nil 520 521 a.linter.mergedManifest = a.aapt.mergedManifestFile 522 a.linter.manifest = a.aapt.manifestPath 523 a.linter.resources = a.aapt.resourceFiles 524 525 a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, 526 a.proguardOptionsFile) 527 528 a.Module.compile(ctx, a.aaptSrcJar) 529 530 a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar") 531 var res android.Paths 532 if a.androidLibraryProperties.BuildAAR { 533 BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res) 534 ctx.CheckbuildFile(a.aarFile) 535 } 536 537 a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, 538 android.PathsForModuleSrc(ctx, a.dexProperties.Optimize.Proguard_flags_files)...) 539 ctx.VisitDirectDeps(func(m android.Module) { 540 if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag { 541 a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...) 542 a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportPackage()) 543 a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportedStaticPackages()...) 544 } 545 }) 546 547 a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles) 548 a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages) 549} 550 551// android_library builds and links sources into a `.jar` file for the device along with Android resources. 552// 553// An android_library has a single variant that produces a `.jar` file containing `.class` files that were 554// compiled against the device bootclasspath, along with a `package-res.apk` file containing Android resources compiled 555// with aapt2. This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of 556// an android_app module. 557func AndroidLibraryFactory() android.Module { 558 module := &AndroidLibrary{} 559 560 module.Module.addHostAndDeviceProperties() 561 module.AddProperties( 562 &module.aaptProperties, 563 &module.androidLibraryProperties) 564 565 module.androidLibraryProperties.BuildAAR = true 566 module.Module.linter.library = true 567 568 android.InitApexModule(module) 569 InitJavaModule(module, android.DeviceSupported) 570 return module 571} 572 573// 574// AAR (android library) prebuilts 575// 576 577type AARImportProperties struct { 578 Aars []string `android:"path"` 579 580 Sdk_version *string 581 Min_sdk_version *string 582 583 Static_libs []string 584 Libs []string 585 586 // if set to true, run Jetifier against .aar file. Defaults to false. 587 Jetifier *bool 588} 589 590type AARImport struct { 591 android.ModuleBase 592 android.DefaultableModuleBase 593 android.ApexModuleBase 594 prebuilt android.Prebuilt 595 596 // Functionality common to Module and Import. 597 embeddableInModuleAndImport 598 599 properties AARImportProperties 600 601 classpathFile android.WritablePath 602 proguardFlags android.WritablePath 603 exportPackage android.WritablePath 604 extraAaptPackagesFile android.WritablePath 605 manifest android.WritablePath 606 607 exportedStaticPackages android.Paths 608 609 hideApexVariantFromMake bool 610 611 aarPath android.Path 612 613 sdkVersion android.SdkSpec 614 minSdkVersion android.SdkSpec 615} 616 617var _ android.OutputFileProducer = (*AARImport)(nil) 618 619// For OutputFileProducer interface 620func (a *AARImport) OutputFiles(tag string) (android.Paths, error) { 621 switch tag { 622 case ".aar": 623 return []android.Path{a.aarPath}, nil 624 case "": 625 return []android.Path{a.classpathFile}, nil 626 default: 627 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 628 } 629} 630 631func (a *AARImport) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { 632 return android.SdkSpecFrom(ctx, String(a.properties.Sdk_version)) 633} 634 635func (a *AARImport) SystemModules() string { 636 return "" 637} 638 639func (a *AARImport) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { 640 if a.properties.Min_sdk_version != nil { 641 return android.SdkSpecFrom(ctx, *a.properties.Min_sdk_version) 642 } 643 return a.SdkVersion(ctx) 644} 645 646func (a *AARImport) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { 647 return a.SdkVersion(ctx) 648} 649 650func (a *AARImport) javaVersion() string { 651 return "" 652} 653 654var _ AndroidLibraryDependency = (*AARImport)(nil) 655 656func (a *AARImport) ExportPackage() android.Path { 657 return a.exportPackage 658} 659 660func (a *AARImport) ExportedProguardFlagFiles() android.Paths { 661 return android.Paths{a.proguardFlags} 662} 663 664func (a *AARImport) ExportedRRODirs() []rroDir { 665 return nil 666} 667 668func (a *AARImport) ExportedStaticPackages() android.Paths { 669 return a.exportedStaticPackages 670} 671 672func (a *AARImport) ExportedManifests() android.Paths { 673 return android.Paths{a.manifest} 674} 675 676// TODO(jungjw): Decide whether we want to implement this. 677func (a *AARImport) ExportedAssets() android.OptionalPath { 678 return android.OptionalPath{} 679} 680 681// RRO enforcement is not available on aar_import since its RRO dirs are not 682// exported. 683func (a *AARImport) SetRROEnforcedForDependent(enforce bool) { 684} 685 686// RRO enforcement is not available on aar_import since its RRO dirs are not 687// exported. 688func (a *AARImport) IsRROEnforced(ctx android.BaseModuleContext) bool { 689 return false 690} 691 692func (a *AARImport) Prebuilt() *android.Prebuilt { 693 return &a.prebuilt 694} 695 696func (a *AARImport) Name() string { 697 return a.prebuilt.Name(a.ModuleBase.Name()) 698} 699 700func (a *AARImport) JacocoReportClassesFile() android.Path { 701 return nil 702} 703 704func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) { 705 if !ctx.Config().AlwaysUsePrebuiltSdks() { 706 sdkDep := decodeSdkDep(ctx, android.SdkContext(a)) 707 if sdkDep.useModule && sdkDep.frameworkResModule != "" { 708 ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule) 709 } 710 } 711 712 ctx.AddVariationDependencies(nil, libTag, a.properties.Libs...) 713 ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...) 714} 715 716// Unzip an AAR into its constituent files and directories. Any files in Outputs that don't exist in the AAR will be 717// touched to create an empty file. The res directory is not extracted, as it will be extracted in its own rule. 718var unzipAAR = pctx.AndroidStaticRule("unzipAAR", 719 blueprint.RuleParams{ 720 Command: `rm -rf $outDir && mkdir -p $outDir && ` + 721 `unzip -qoDD -d $outDir $in && rm -rf $outDir/res && touch $out && ` + 722 `${config.MergeZipsCmd} $combinedClassesJar $$(ls $outDir/classes.jar 2> /dev/null) $$(ls $outDir/libs/*.jar 2> /dev/null)`, 723 CommandDeps: []string{"${config.MergeZipsCmd}"}, 724 }, 725 "outDir", "combinedClassesJar") 726 727func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { 728 if len(a.properties.Aars) != 1 { 729 ctx.PropertyErrorf("aars", "exactly one aar is required") 730 return 731 } 732 733 a.sdkVersion = a.SdkVersion(ctx) 734 a.minSdkVersion = a.MinSdkVersion(ctx) 735 736 a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() 737 738 aarName := ctx.ModuleName() + ".aar" 739 a.aarPath = android.PathForModuleSrc(ctx, a.properties.Aars[0]) 740 741 if Bool(a.properties.Jetifier) { 742 inputFile := a.aarPath 743 a.aarPath = android.PathForModuleOut(ctx, "jetifier", aarName) 744 TransformJetifier(ctx, a.aarPath.(android.WritablePath), inputFile) 745 } 746 747 extractedAARDir := android.PathForModuleOut(ctx, "aar") 748 a.classpathFile = extractedAARDir.Join(ctx, "classes-combined.jar") 749 a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt") 750 a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml") 751 752 ctx.Build(pctx, android.BuildParams{ 753 Rule: unzipAAR, 754 Input: a.aarPath, 755 Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest}, 756 Description: "unzip AAR", 757 Args: map[string]string{ 758 "outDir": extractedAARDir.String(), 759 "combinedClassesJar": a.classpathFile.String(), 760 }, 761 }) 762 763 // Always set --pseudo-localize, it will be stripped out later for release 764 // builds that don't want it. 765 compileFlags := []string{"--pseudo-localize"} 766 compiledResDir := android.PathForModuleOut(ctx, "flat-res") 767 flata := compiledResDir.Join(ctx, "gen_res.flata") 768 aapt2CompileZip(ctx, flata, a.aarPath, "res", compileFlags) 769 770 a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk") 771 // the subdir "android" is required to be filtered by package names 772 srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar") 773 proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options") 774 rTxt := android.PathForModuleOut(ctx, "R.txt") 775 a.extraAaptPackagesFile = android.PathForModuleOut(ctx, "extra_packages") 776 777 var linkDeps android.Paths 778 779 linkFlags := []string{ 780 "--static-lib", 781 "--no-static-lib-packages", 782 "--auto-add-overlay", 783 } 784 785 linkFlags = append(linkFlags, "--manifest "+a.manifest.String()) 786 linkDeps = append(linkDeps, a.manifest) 787 788 transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags := 789 aaptLibs(ctx, android.SdkContext(a), nil) 790 791 _ = staticLibManifests 792 _ = staticRRODirs 793 794 linkDeps = append(linkDeps, libDeps...) 795 linkFlags = append(linkFlags, libFlags...) 796 797 overlayRes := append(android.Paths{flata}, transitiveStaticLibs...) 798 799 aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile, 800 linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil) 801 802 ctx.SetProvider(JavaInfoProvider, JavaInfo{ 803 HeaderJars: android.PathsIfNonNil(a.classpathFile), 804 ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile), 805 ImplementationJars: android.PathsIfNonNil(a.classpathFile), 806 }) 807} 808 809func (a *AARImport) HeaderJars() android.Paths { 810 return android.Paths{a.classpathFile} 811} 812 813func (a *AARImport) ImplementationAndResourcesJars() android.Paths { 814 return android.Paths{a.classpathFile} 815} 816 817func (a *AARImport) DexJarBuildPath() android.Path { 818 return nil 819} 820 821func (a *AARImport) DexJarInstallPath() android.Path { 822 return nil 823} 824 825func (a *AARImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { 826 return nil 827} 828 829var _ android.ApexModule = (*AARImport)(nil) 830 831// Implements android.ApexModule 832func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { 833 return a.depIsInSameApex(ctx, dep) 834} 835 836// Implements android.ApexModule 837func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, 838 sdkVersion android.ApiLevel) error { 839 return nil 840} 841 842var _ android.PrebuiltInterface = (*Import)(nil) 843 844// android_library_import imports an `.aar` file into the build graph as if it was built with android_library. 845// 846// This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of 847// an android_app module. 848func AARImportFactory() android.Module { 849 module := &AARImport{} 850 851 module.AddProperties(&module.properties) 852 853 android.InitPrebuiltModule(module, &module.properties.Aars) 854 android.InitApexModule(module) 855 InitJavaModule(module, android.DeviceSupported) 856 return module 857} 858