1// Copyright 2015 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 android_app, android_test, and some more 18// related module types, including their override variants. 19 20import ( 21 "fmt" 22 "path/filepath" 23 "strings" 24 25 "github.com/google/blueprint" 26 "github.com/google/blueprint/depset" 27 "github.com/google/blueprint/proptools" 28 29 "android/soong/android" 30 "android/soong/cc" 31 "android/soong/dexpreopt" 32 "android/soong/tradefed" 33) 34 35func init() { 36 RegisterAppBuildComponents(android.InitRegistrationContext) 37 pctx.HostBinToolVariable("ModifyAllowlistCmd", "modify_permissions_allowlist") 38} 39 40var ( 41 modifyAllowlist = pctx.AndroidStaticRule("modifyAllowlist", 42 blueprint.RuleParams{ 43 Command: "${ModifyAllowlistCmd} $in $packageName $out", 44 CommandDeps: []string{"${ModifyAllowlistCmd}"}, 45 }, "packageName") 46) 47 48type FlagsPackages struct { 49 // Paths to the aconfig dump output text files that are consumed by aapt2 50 AconfigTextFiles android.Paths 51} 52 53var FlagsPackagesProvider = blueprint.NewProvider[FlagsPackages]() 54 55func RegisterAppBuildComponents(ctx android.RegistrationContext) { 56 ctx.RegisterModuleType("android_app", AndroidAppFactory) 57 ctx.RegisterModuleType("android_test", AndroidTestFactory) 58 ctx.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory) 59 ctx.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory) 60 ctx.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory) 61 ctx.RegisterModuleType("override_android_test", OverrideAndroidTestModuleFactory) 62} 63 64type AppInfo struct { 65 // Updatable is set to the value of the updatable property 66 Updatable bool 67 68 // TestHelperApp is true if the module is a android_test_helper_app 69 TestHelperApp bool 70 71 // EmbeddedJNILibs is the list of paths to JNI libraries that were embedded in the APK. 72 EmbeddedJNILibs android.Paths 73} 74 75var AppInfoProvider = blueprint.NewProvider[*AppInfo]() 76 77// AndroidManifest.xml merging 78// package splits 79 80type appProperties struct { 81 // Names of extra android_app_certificate modules to sign the apk with in the form ":module". 82 Additional_certificates []string 83 84 // If set, create package-export.apk, which other packages can 85 // use to get PRODUCT-agnostic resource data like IDs and type definitions. 86 Export_package_resources *bool 87 88 // Specifies that this app should be installed to the priv-app directory, 89 // where the system will grant it additional privileges not available to 90 // normal apps. 91 Privileged *bool 92 93 // list of resource labels to generate individual resource packages 94 Package_splits []string 95 96 // list of native libraries that will be provided in or alongside the resulting jar 97 Jni_libs proptools.Configurable[[]string] `android:"arch_variant"` 98 99 // if true, use JNI libraries that link against platform APIs even if this module sets 100 // sdk_version. 101 Jni_uses_platform_apis *bool 102 103 // if true, use JNI libraries that link against SDK APIs even if this module does not set 104 // sdk_version. 105 Jni_uses_sdk_apis *bool 106 107 // STL library to use for JNI libraries. 108 Stl *string `android:"arch_variant"` 109 110 // Store native libraries uncompressed in the APK and set the android:extractNativeLibs="false" manifest 111 // flag so that they are used from inside the APK at runtime. Defaults to true for android_test modules unless 112 // sdk_version or min_sdk_version is set to a version that doesn't support it (<23), defaults to true for 113 // android_app modules that are embedded to APEXes, defaults to false for other module types where the native 114 // libraries are generally preinstalled outside the APK. 115 Use_embedded_native_libs *bool 116 117 // Store dex files uncompressed in the APK and set the android:useEmbeddedDex="true" manifest attribute so that 118 // they are used from inside the APK at runtime. 119 Use_embedded_dex *bool 120 121 // Forces native libraries to always be packaged into the APK, 122 // Use_embedded_native_libs still selects whether they are stored uncompressed and aligned or compressed. 123 // True for android_test* modules. 124 AlwaysPackageNativeLibs bool `blueprint:"mutated"` 125 126 // If set, find and merge all NOTICE files that this module and its dependencies have and store 127 // it in the APK as an asset. 128 Embed_notices *bool 129 130 // cc.Coverage related properties 131 PreventInstall bool `blueprint:"mutated"` 132 IsCoverageVariant bool `blueprint:"mutated"` 133 134 // It can be set to test the behaviour of default target sdk version. 135 // Only required when updatable: false. It is an error if updatable: true and this is false. 136 Enforce_default_target_sdk_version *bool 137 138 // If set, the targetSdkVersion for the target is set to the latest default API level. 139 // This would be by default false, unless updatable: true or 140 // enforce_default_target_sdk_version: true in which case this defaults to true. 141 EnforceDefaultTargetSdkVersion bool `blueprint:"mutated"` 142 143 // Whether this app is considered mainline updatable or not. When set to true, this will enforce 144 // additional rules to make sure an app can safely be updated. Default is false. 145 // Prefer using other specific properties if build behaviour must be changed; avoid using this 146 // flag for anything but neverallow rules (unless the behaviour change is invisible to owners). 147 Updatable *bool 148 149 // Specifies the file that contains the allowlist for this app. 150 Privapp_allowlist *string `android:"path"` 151 152 // If set, create an RRO package which contains only resources having PRODUCT_CHARACTERISTICS 153 // and install the RRO package to /product partition, instead of passing --product argument 154 // to aapt2. Default is false. 155 // Setting this will make this APK identical to all targets, regardless of 156 // PRODUCT_CHARACTERISTICS. 157 Generate_product_characteristics_rro *bool 158 159 ProductCharacteristicsRROPackageName *string `blueprint:"mutated"` 160 ProductCharacteristicsRROManifestModuleName *string `blueprint:"mutated"` 161} 162 163// android_app properties that can be overridden by override_android_app 164type overridableAppProperties struct { 165 // The name of a certificate in the default certificate directory, blank to use the default product certificate, 166 // or an android_app_certificate module name in the form ":module". 167 Certificate proptools.Configurable[string] `android:"replace_instead_of_append"` 168 169 // Name of the signing certificate lineage file or filegroup module. 170 Lineage *string `android:"path"` 171 172 // For overriding the --rotation-min-sdk-version property of apksig 173 RotationMinSdkVersion *string 174 175 // the package name of this app. The package name in the manifest file is used if one was not given. 176 Package_name proptools.Configurable[string] 177 178 // the logging parent of this app. 179 Logging_parent *string 180 181 // Whether to rename the package in resources to the override name rather than the base name. Defaults to true. 182 Rename_resources_package *bool 183 184 // Names of modules to be overridden. Listed modules can only be other binaries 185 // (in Make or Soong). 186 // This does not completely prevent installation of the overridden binaries, but if both 187 // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed 188 // from PRODUCT_PACKAGES. 189 Overrides []string 190} 191 192type AndroidApp struct { 193 Library 194 aapt 195 android.OverridableModuleBase 196 197 certificate Certificate 198 199 appProperties appProperties 200 201 overridableAppProperties overridableAppProperties 202 203 jniLibs []jniLib 204 installPathForJNISymbols android.Path 205 embeddedJniLibs bool 206 jniCoverageOutputs android.Paths 207 208 bundleFile android.Path 209 210 // the install APK name is normally the same as the module name, but can be overridden with PRODUCT_PACKAGE_NAME_OVERRIDES. 211 installApkName string 212 213 installDir android.InstallPath 214 215 onDeviceDir string 216 217 additionalAaptFlags []string 218 219 overriddenManifestPackageName string 220 221 android.ApexBundleDepsInfo 222 223 javaApiUsedByOutputFile android.ModuleOutPath 224 225 privAppAllowlist android.OptionalPath 226 227 requiredModuleNames []string 228} 229 230func (a *AndroidApp) IsInstallable() bool { 231 return Bool(a.properties.Installable) 232} 233 234func (a *AndroidApp) ResourcesNodeDepSet() depset.DepSet[*resourcesNode] { 235 return a.aapt.resourcesNodesDepSet 236} 237 238func (a *AndroidApp) OutputFile() android.Path { 239 return a.outputFile 240} 241 242func (a *AndroidApp) Certificate() Certificate { 243 return a.certificate 244} 245 246func (a *AndroidApp) JniCoverageOutputs() android.Paths { 247 return a.jniCoverageOutputs 248} 249 250func (a *AndroidApp) PrivAppAllowlist() android.OptionalPath { 251 return a.privAppAllowlist 252} 253 254var _ AndroidLibraryDependency = (*AndroidApp)(nil) 255 256type Certificate struct { 257 Pem, Key android.Path 258 presigned bool 259} 260 261var PresignedCertificate = Certificate{presigned: true} 262 263func (c Certificate) AndroidMkString() string { 264 if c.presigned { 265 return "PRESIGNED" 266 } else { 267 return c.Pem.String() 268 } 269} 270 271func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) { 272 if String(a.appProperties.Stl) == "c++_shared" && !a.SdkVersion(ctx).Specified() { 273 ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared") 274 } 275 276 sdkDep := decodeSdkDep(ctx, android.SdkContext(a)) 277 a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs()) 278 a.Module.deps(ctx) 279 if sdkDep.hasFrameworkLibs() { 280 a.aapt.deps(ctx, sdkDep) 281 } 282 283 usesSDK := a.SdkVersion(ctx).Specified() && a.SdkVersion(ctx).Kind != android.SdkCorePlatform 284 285 if usesSDK && Bool(a.appProperties.Jni_uses_sdk_apis) { 286 ctx.PropertyErrorf("jni_uses_sdk_apis", 287 "can only be set for modules that do not set sdk_version") 288 } else if !usesSDK && Bool(a.appProperties.Jni_uses_platform_apis) { 289 ctx.PropertyErrorf("jni_uses_platform_apis", 290 "can only be set for modules that set sdk_version") 291 } 292 293 for _, jniTarget := range ctx.MultiTargets() { 294 variation := append(jniTarget.Variations(), 295 blueprint.Variation{Mutator: "link", Variation: "shared"}) 296 297 // Test whether to use the SDK variant or the non-SDK variant of JNI dependencies. 298 // Many factors are considered here. 299 // 1. Basically, the selection follows whether the app has sdk_version set or not. 300 jniUsesSdkVariant := usesSDK 301 // 2. However, jni_uses_platform_apis and jni_uses_sdk_apis can override it 302 if Bool(a.appProperties.Jni_uses_sdk_apis) { 303 jniUsesSdkVariant = true 304 } 305 if Bool(a.appProperties.Jni_uses_platform_apis) { 306 jniUsesSdkVariant = false 307 } 308 // 3. Then the use of SDK variant is again prohibited for the following cases: 309 // 3.1. the app is shipped on unbundled partitions like vendor. Since the entire 310 // partition (not only the app) is considered unbudled, there's no need to use the 311 // SDK variant. 312 // 3.2. the app doesn't support embedding the JNI libs 313 if a.RequiresStableAPIs(ctx) || !a.shouldEmbedJnis(ctx) { 314 jniUsesSdkVariant = false 315 } 316 if jniUsesSdkVariant { 317 variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"}) 318 } 319 320 // Use the installable dep tag when the JNIs are not embedded 321 var tag dependencyTag 322 if a.shouldEmbedJnis(ctx) { 323 tag = jniLibTag 324 } else { 325 tag = jniInstallTag 326 } 327 ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs.GetOrDefault(ctx, nil)...) 328 } 329 for _, aconfig_declaration := range a.aaptProperties.Flags_packages { 330 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration) 331 } 332} 333 334func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) { 335 cert := android.SrcIsModule(a.getCertString(ctx)) 336 if cert != "" { 337 ctx.AddDependency(ctx.Module(), certificateTag, cert) 338 } 339 340 if a.appProperties.Privapp_allowlist != nil && !Bool(a.appProperties.Privileged) { 341 // There are a few uids that are explicitly considered privileged regardless of their 342 // app's location. Bluetooth is one such app. It should arguably be moved to priv-app, 343 // but for now, allow it not to be in priv-app. 344 privilegedBecauseOfUid := ctx.ModuleName() == "Bluetooth" 345 if !privilegedBecauseOfUid { 346 ctx.PropertyErrorf("privapp_allowlist", "privileged must be set in order to use privapp_allowlist (with a few exceptions)") 347 } 348 } 349 350 for _, cert := range a.appProperties.Additional_certificates { 351 cert = android.SrcIsModule(cert) 352 if cert != "" { 353 ctx.AddDependency(ctx.Module(), certificateTag, cert) 354 } else { 355 ctx.PropertyErrorf("additional_certificates", 356 `must be names of android_app_certificate modules in the form ":module"`) 357 } 358 } 359} 360 361// TODO(b/156476221): Remove this allowlist 362var ( 363 missingMinSdkVersionMtsAllowlist = []string{ 364 "CellBroadcastReceiverGoogleUnitTests", 365 "CellBroadcastReceiverUnitTests", 366 "CtsBatterySavingTestCases", 367 "CtsDeviceAndProfileOwnerApp23", 368 "CtsDeviceAndProfileOwnerApp30", 369 "CtsIntentSenderApp", 370 "CtsJobSchedulerTestCases", 371 "CtsMimeMapTestCases", 372 "CtsTareTestCases", 373 "LibStatsPullTests", 374 "MediaProviderClientTests", 375 "TeleServiceTests", 376 "TestExternalImsServiceApp", 377 "TestSmsRetrieverApp", 378 "TetheringPrivilegedTests", 379 } 380) 381 382func checkMinSdkVersionMts(ctx android.ModuleContext, minSdkVersion android.ApiLevel) { 383 if includedInMts(ctx.Module()) && !minSdkVersion.Specified() && !android.InList(ctx.ModuleName(), missingMinSdkVersionMtsAllowlist) { 384 ctx.PropertyErrorf("min_sdk_version", "min_sdk_version is a required property for tests included in MTS") 385 } 386} 387 388func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { 389 checkMinSdkVersionMts(ctx, a.MinSdkVersion(ctx)) 390 applicationId := a.appTestHelperAppProperties.Manifest_values.ApplicationId 391 if applicationId != nil { 392 packageName := a.overridableAppProperties.Package_name.Get(ctx) 393 if packageName.IsPresent() { 394 ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.") 395 } 396 a.aapt.manifestValues.applicationId = *applicationId 397 } 398 a.generateAndroidBuildActions(ctx) 399 android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{ 400 TestOnly: true, 401 }) 402 android.SetProvider(ctx, AppInfoProvider, &AppInfo{ 403 Updatable: Bool(a.appProperties.Updatable), 404 TestHelperApp: true, 405 }) 406} 407 408func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { 409 a.checkAppSdkVersions(ctx) 410 a.checkEmbedJnis(ctx) 411 a.generateAndroidBuildActions(ctx) 412 a.generateJavaUsedByApex(ctx) 413 414 var embeddedJniLibs []android.Path 415 416 if a.embeddedJniLibs { 417 for _, jni := range a.jniLibs { 418 embeddedJniLibs = append(embeddedJniLibs, jni.path) 419 } 420 } 421 android.SetProvider(ctx, AppInfoProvider, &AppInfo{ 422 Updatable: Bool(a.appProperties.Updatable), 423 TestHelperApp: false, 424 EmbeddedJNILibs: embeddedJniLibs, 425 }) 426 427 a.requiredModuleNames = a.getRequiredModuleNames(ctx) 428} 429 430func (a *AndroidApp) getRequiredModuleNames(ctx android.ModuleContext) []string { 431 var required []string 432 if proptools.Bool(a.appProperties.Generate_product_characteristics_rro) { 433 required = []string{a.productCharacteristicsRROPackageName()} 434 } 435 // Install the vendor overlay variant if this app is installed. 436 if len(filterRRO(a.rroDirsDepSet, device)) > 0 { 437 required = append(required, AutogeneratedRroModuleName(ctx, ctx.Module().Name(), "vendor")) 438 } 439 // Install the product overlay variant if this app is installed. 440 if len(filterRRO(a.rroDirsDepSet, product)) > 0 { 441 required = append(required, AutogeneratedRroModuleName(ctx, ctx.Module().Name(), "product")) 442 } 443 return required 444} 445 446func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { 447 if a.Updatable() { 448 if !a.SdkVersion(ctx).Stable() { 449 ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.SdkVersion(ctx)) 450 } 451 if String(a.overridableProperties.Min_sdk_version) == "" { 452 ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.") 453 } 454 455 if minSdkVersion, err := a.MinSdkVersion(ctx).EffectiveVersion(ctx); err == nil { 456 a.checkJniLibsSdkVersion(ctx, minSdkVersion) 457 android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps) 458 } else { 459 ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) 460 } 461 462 if !BoolDefault(a.appProperties.Enforce_default_target_sdk_version, true) { 463 ctx.PropertyErrorf("enforce_default_target_sdk_version", "Updatable apps must enforce default target sdk version") 464 } 465 // TODO(b/227460469) after all the modules removes the target sdk version, throw an error if the target sdk version is explicitly set. 466 if a.deviceProperties.Target_sdk_version == nil { 467 a.SetEnforceDefaultTargetSdkVersion(true) 468 } 469 } 470 471 a.checkPlatformAPI(ctx) 472 a.checkSdkVersions(ctx) 473} 474 475// Ensures that use_embedded_native_libs are set for apk-in-apex 476func (a *AndroidApp) checkEmbedJnis(ctx android.BaseModuleContext) { 477 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 478 apkInApex := !apexInfo.IsForPlatform() 479 hasJnis := len(a.appProperties.Jni_libs.GetOrDefault(ctx, nil)) > 0 480 481 if apkInApex && hasJnis && !Bool(a.appProperties.Use_embedded_native_libs) { 482 ctx.ModuleErrorf("APK in APEX should have use_embedded_native_libs: true") 483 } 484} 485 486// If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it. 487// This check is enforced for "updatable" APKs (including APK-in-APEX). 488func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) { 489 // It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType() 490 ctx.VisitDirectDeps(func(m android.Module) { 491 if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) { 492 return 493 } 494 dep, _ := m.(*cc.Module) 495 // The domain of cc.sdk_version is "current" and <number> 496 // We can rely on android.SdkSpec to convert it to <number> so that "current" is 497 // handled properly regardless of sdk finalization. 498 jniSdkVersion, err := android.SdkSpecFrom(ctx, dep.MinSdkVersion()).EffectiveVersion(ctx) 499 if err != nil || minSdkVersion.LessThan(jniSdkVersion) { 500 ctx.OtherModuleErrorf(dep, "min_sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)", 501 dep.MinSdkVersion(), minSdkVersion, ctx.ModuleName()) 502 return 503 } 504 505 }) 506} 507 508// Returns true if the native libraries should be stored in the APK uncompressed and the 509// extractNativeLibs application flag should be set to false in the manifest. 510func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool { 511 minSdkVersion, err := a.MinSdkVersion(ctx).EffectiveVersion(ctx) 512 if err != nil { 513 ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.MinSdkVersion(ctx), err) 514 } 515 516 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 517 return (minSdkVersion.FinalOrFutureInt() >= 23 && Bool(a.appProperties.Use_embedded_native_libs)) || 518 !apexInfo.IsForPlatform() 519} 520 521// Returns whether this module should have the dex file stored uncompressed in the APK. 522func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) bool { 523 if Bool(a.appProperties.Use_embedded_dex) { 524 return true 525 } 526 527 // Uncompress dex in APKs of privileged apps (even for unbundled builds, they may 528 // be preinstalled as prebuilts). 529 if ctx.Config().UncompressPrivAppDex() && a.Privileged() { 530 return true 531 } 532 533 if ctx.Config().UnbundledBuild() { 534 return false 535 } 536 537 return shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &a.dexpreopter) 538} 539 540func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool { 541 return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) || 542 Bool(a.appProperties.Updatable) || 543 a.appProperties.AlwaysPackageNativeLibs 544} 545 546func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string { 547 aaptFlags := []string{"--rename-manifest-package " + packageName} 548 if renameResourcesPackage { 549 // Required to rename the package name in the resources table. 550 aaptFlags = append(aaptFlags, "--rename-resources-package "+packageName) 551 } 552 return aaptFlags 553} 554 555func (a *AndroidApp) OverriddenManifestPackageName() string { 556 return a.overriddenManifestPackageName 557} 558 559func (a *AndroidApp) renameResourcesPackage() bool { 560 return proptools.BoolDefault(a.overridableAppProperties.Rename_resources_package, true) 561} 562 563func getAconfigFilePaths(ctx android.ModuleContext) (aconfigTextFilePaths android.Paths) { 564 ctx.VisitDirectDeps(func(dep android.Module) { 565 tag := ctx.OtherModuleDependencyTag(dep) 566 switch tag { 567 case staticLibTag: 568 if flagPackages, ok := android.OtherModuleProvider(ctx, dep, FlagsPackagesProvider); ok { 569 aconfigTextFilePaths = append(aconfigTextFilePaths, flagPackages.AconfigTextFiles...) 570 } 571 572 case aconfigDeclarationTag: 573 if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok { 574 aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath) 575 } else { 576 ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+ 577 "flags_packages property, but %s is not aconfig_declarations module type", 578 dep.Name(), 579 ) 580 } 581 } 582 }) 583 584 return android.FirstUniquePaths(aconfigTextFilePaths) 585} 586 587func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { 588 usePlatformAPI := proptools.Bool(a.Module.deviceProperties.Platform_apis) 589 if ctx.Module().(android.SdkContext).SdkVersion(ctx).Kind == android.SdkModule { 590 usePlatformAPI = true 591 } 592 a.aapt.usesNonSdkApis = usePlatformAPI 593 594 // Ask manifest_fixer to add or update the application element indicating this app has no code. 595 a.aapt.hasNoCode = !a.hasCode(ctx) 596 597 aaptLinkFlags := []string{} 598 599 // Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided. 600 autogenerateRRO := proptools.Bool(a.appProperties.Generate_product_characteristics_rro) 601 hasProduct := android.PrefixInList(a.aaptProperties.Aaptflags, "--product") 602 characteristics := ctx.Config().ProductAAPTCharacteristics() 603 if !autogenerateRRO && !hasProduct && len(characteristics) > 0 && characteristics != "default" { 604 aaptLinkFlags = append(aaptLinkFlags, "--product", characteristics) 605 } 606 607 if !Bool(a.aaptProperties.Aapt_include_all_resources) { 608 // Product AAPT config 609 for _, aaptConfig := range ctx.Config().ProductAAPTConfig() { 610 aaptLinkFlags = append(aaptLinkFlags, "-c", aaptConfig) 611 } 612 613 // Product AAPT preferred config 614 if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 { 615 aaptLinkFlags = append(aaptLinkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig()) 616 } 617 } 618 619 manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName()) 620 packageNameProp := a.overridableAppProperties.Package_name.Get(ctx) 621 if overridden || packageNameProp.IsPresent() { 622 // The product override variable has a priority over the package_name property. 623 if !overridden { 624 manifestPackageName = packageNameProp.Get() 625 } 626 aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, a.renameResourcesPackage())...) 627 a.overriddenManifestPackageName = manifestPackageName 628 } 629 630 aaptLinkFlags = append(aaptLinkFlags, a.additionalAaptFlags...) 631 632 a.aapt.splitNames = a.appProperties.Package_splits 633 a.aapt.LoggingParent = String(a.overridableAppProperties.Logging_parent) 634 if a.Updatable() { 635 if override := ctx.Config().Getenv("OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION"); override != "" { 636 a.aapt.defaultManifestVersion = override 637 } else { 638 a.aapt.defaultManifestVersion = ctx.Config().ReleaseDefaultUpdatableModuleVersion() 639 } 640 } 641 642 // Use non final ids if we are doing optimized shrinking and are using R8. 643 nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled() 644 645 aconfigTextFilePaths := getAconfigFilePaths(ctx) 646 647 a.aapt.buildActions(ctx, 648 aaptBuildActionOptions{ 649 sdkContext: android.SdkContext(a), 650 classLoaderContexts: a.classLoaderContexts, 651 excludedLibs: a.usesLibraryProperties.Exclude_uses_libs, 652 enforceDefaultTargetSdkVersion: a.enforceDefaultTargetSdkVersion(), 653 forceNonFinalResourceIDs: nonFinalIds, 654 extraLinkFlags: aaptLinkFlags, 655 aconfigTextFiles: aconfigTextFilePaths, 656 usesLibrary: &a.usesLibrary, 657 }, 658 ) 659 660 // apps manifests are handled by aapt, don't let Module see them 661 a.properties.Manifest = nil 662 663 android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{ 664 AconfigTextFiles: aconfigTextFilePaths, 665 }) 666} 667 668func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) { 669 var staticLibProguardFlagFiles android.Paths 670 ctx.VisitDirectDeps(func(m android.Module) { 671 depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider) 672 staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.UnconditionallyExportedProguardFlags.ToList()...) 673 if ctx.OtherModuleDependencyTag(m) == staticLibTag { 674 staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.ProguardFlagsFiles.ToList()...) 675 } 676 }) 677 678 staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles) 679 680 a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...) 681 if !(a.dexProperties.optimizedResourceShrinkingEnabled(ctx)) { 682 // When using the optimized shrinking the R8 enqueuer will traverse the xml files that become 683 // live for code references and (transitively) mark these as live. 684 // In this case we explicitly don't wan't the aapt2 generated keep files (which would keep the now 685 // dead code alive) 686 a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, a.proguardOptionsFile) 687 } 688} 689 690func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath { 691 var installDir string 692 if ctx.ModuleName() == "framework-res" { 693 // framework-res.apk is installed as system/framework/framework-res.apk 694 installDir = "framework" 695 } else if a.Privileged() { 696 installDir = filepath.Join("priv-app", a.installApkName) 697 } else { 698 installDir = filepath.Join("app", a.installApkName) 699 } 700 701 return android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk") 702} 703 704func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, android.Path) { 705 a.dexpreopter.installPath = a.installPath(ctx) 706 a.dexpreopter.isApp = true 707 if a.dexProperties.Uncompress_dex == nil { 708 // If the value was not force-set by the user, use reasonable default based on the module. 709 a.dexProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx)) 710 } 711 a.dexpreopter.uncompressedDex = *a.dexProperties.Uncompress_dex 712 a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries(ctx) 713 a.dexpreopter.classLoaderContexts = a.classLoaderContexts 714 a.dexpreopter.manifestFile = a.mergedManifestFile 715 a.dexpreopter.preventInstall = a.appProperties.PreventInstall 716 717 var packageResources = a.exportPackage 718 719 if ctx.ModuleName() != "framework-res" { 720 if a.dexProperties.resourceShrinkingEnabled(ctx) { 721 protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk") 722 aapt2Convert(ctx, protoFile, packageResources, "proto") 723 a.dexer.resourcesInput = android.OptionalPathForPath(protoFile) 724 } 725 726 var extraSrcJars android.Paths 727 var extraClasspathJars android.Paths 728 var extraCombinedJars android.Paths 729 if a.useResourceProcessorBusyBox(ctx) { 730 // When building an app with ResourceProcessorBusyBox enabled ResourceProcessorBusyBox has already 731 // created R.class files that provide IDs for resources in busybox/R.jar. Pass that file in the 732 // classpath when compiling everything else, and add it to the final classes jar. 733 extraClasspathJars = android.Paths{a.aapt.rJar} 734 extraCombinedJars = android.Paths{a.aapt.rJar} 735 } else { 736 // When building an app without ResourceProcessorBusyBox the aapt2 rule creates R.srcjar containing 737 // R.java files for the app's package and the packages from all transitive static android_library 738 // dependencies. Compile the srcjar alongside the rest of the sources. 739 extraSrcJars = android.Paths{a.aapt.aaptSrcJar} 740 } 741 742 a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil) 743 if a.dexProperties.resourceShrinkingEnabled(ctx) { 744 binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk") 745 aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary") 746 packageResources = binaryResources 747 } 748 } 749 750 return a.dexJarFile.PathOrNil(), packageResources 751} 752 753func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, prebuiltJniPackages android.Paths, ctx android.ModuleContext) android.WritablePath { 754 var jniJarFile android.WritablePath 755 if len(jniLibs) > 0 || len(prebuiltJniPackages) > 0 { 756 a.jniLibs = jniLibs 757 if a.shouldEmbedJnis(ctx) { 758 jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip") 759 a.installPathForJNISymbols = a.installPath(ctx) 760 TransformJniLibsToJar(ctx, jniJarFile, jniLibs, prebuiltJniPackages, a.useEmbeddedNativeLibs(ctx)) 761 for _, jni := range jniLibs { 762 if jni.coverageFile.Valid() { 763 // Only collect coverage for the first target arch if this is a multilib target. 764 // TODO(jungjw): Ideally, we want to collect both reports, but that would cause coverage 765 // data file path collisions since the current coverage file path format doesn't contain 766 // arch-related strings. This is fine for now though; the code coverage team doesn't use 767 // multi-arch targets such as test_suite_* for coverage collections yet. 768 // 769 // Work with the team to come up with a new format that handles multilib modules properly 770 // and change this. 771 if len(ctx.Config().Targets[android.Android]) == 1 || 772 ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType == jni.target.Arch.ArchType { 773 a.jniCoverageOutputs = append(a.jniCoverageOutputs, jni.coverageFile.Path()) 774 } 775 } 776 } 777 a.embeddedJniLibs = true 778 } 779 } 780 return jniJarFile 781} 782 783func (a *AndroidApp) JNISymbolsInstalls(installPath string) android.RuleBuilderInstalls { 784 var jniSymbols android.RuleBuilderInstalls 785 for _, jniLib := range a.jniLibs { 786 if jniLib.unstrippedFile != nil { 787 jniSymbols = append(jniSymbols, android.RuleBuilderInstall{ 788 From: jniLib.unstrippedFile, 789 To: filepath.Join(installPath, targetToJniDir(jniLib.target), jniLib.unstrippedFile.Base()), 790 }) 791 } 792 } 793 return jniSymbols 794} 795 796// Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it 797// isn't a cert module reference. Also checks and enforces system cert restriction if applicable. 798func processMainCert(m android.ModuleBase, certPropValue string, certificates []Certificate, 799 ctx android.ModuleContext) (mainCertificate Certificate, allCertificates []Certificate) { 800 if android.SrcIsModule(certPropValue) == "" { 801 var mainCert Certificate 802 if certPropValue != "" { 803 defaultDir := ctx.Config().DefaultAppCertificateDir(ctx) 804 mainCert = Certificate{ 805 Pem: defaultDir.Join(ctx, certPropValue+".x509.pem"), 806 Key: defaultDir.Join(ctx, certPropValue+".pk8"), 807 } 808 } else { 809 pem, key := ctx.Config().DefaultAppCertificate(ctx) 810 mainCert = Certificate{ 811 Pem: pem, 812 Key: key, 813 } 814 } 815 certificates = append([]Certificate{mainCert}, certificates...) 816 } 817 818 if len(certificates) > 0 { 819 mainCertificate = certificates[0] 820 } else { 821 // This can be reached with an empty certificate list if AllowMissingDependencies is set 822 // and the certificate property for this module is a module reference to a missing module. 823 if !ctx.Config().AllowMissingDependencies() && len(ctx.GetMissingDependencies()) > 0 { 824 panic("Should only get here if AllowMissingDependencies set and there are missing dependencies") 825 } 826 // Set a certificate to avoid panics later when accessing it. 827 mainCertificate = Certificate{ 828 Key: android.PathForModuleOut(ctx, "missing.pk8"), 829 Pem: android.PathForModuleOut(ctx, "missing.x509.pem"), 830 } 831 } 832 833 if !m.Platform() { 834 certPath := mainCertificate.Pem.String() 835 systemCertPath := ctx.Config().DefaultAppCertificateDir(ctx).String() 836 if strings.HasPrefix(certPath, systemCertPath) { 837 enforceSystemCert := ctx.Config().EnforceSystemCertificate() 838 allowed := ctx.Config().EnforceSystemCertificateAllowList() 839 840 if enforceSystemCert && !inList(m.Name(), allowed) { 841 ctx.PropertyErrorf("certificate", "The module in product partition cannot be signed with certificate in system.") 842 } 843 } 844 } 845 846 return mainCertificate, certificates 847} 848 849func (a *AndroidApp) InstallApkName() string { 850 return a.installApkName 851} 852 853func (a *AndroidApp) createPrivappAllowlist(ctx android.ModuleContext) android.Path { 854 if a.appProperties.Privapp_allowlist == nil { 855 return nil 856 } 857 858 isOverrideApp := a.GetOverriddenBy() != "" 859 if !isOverrideApp { 860 // if this is not an override, we don't need to rewrite the existing privapp allowlist 861 return android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist) 862 } 863 864 packageNameProp := a.overridableAppProperties.Package_name.Get(ctx) 865 if packageNameProp.IsEmpty() { 866 ctx.PropertyErrorf("privapp_allowlist", "package_name must be set to use privapp_allowlist") 867 } 868 869 packageName := packageNameProp.Get() 870 fileName := "privapp_allowlist_" + packageName + ".xml" 871 outPath := android.PathForModuleOut(ctx, fileName) 872 ctx.Build(pctx, android.BuildParams{ 873 Rule: modifyAllowlist, 874 Input: android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist), 875 Output: outPath, 876 Args: map[string]string{ 877 "packageName": packageName, 878 }, 879 }) 880 return outPath 881} 882 883func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { 884 var apkDeps android.Paths 885 886 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 887 if !apexInfo.IsForPlatform() { 888 a.hideApexVariantFromMake = true 889 } 890 891 a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx) 892 a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex) 893 894 // Unlike installApkName, a.stem should respect base module name for override_android_app. 895 // Therefore, use ctx.ModuleName() instead of a.Name(). 896 a.stem = proptools.StringDefault(a.overridableProperties.Stem, ctx.ModuleName()) 897 898 // Check if the install APK name needs to be overridden. 899 // Both android_app and override_android_app module are expected to possess 900 // its module bound apk path. However, override_android_app inherits ctx.ModuleName() 901 // from the base module. Therefore, use a.Name() which represents 902 // the module name for both android_app and override_android_app. 903 a.installApkName = ctx.DeviceConfig().OverridePackageNameFor( 904 proptools.StringDefault(a.overridableProperties.Stem, a.Name())) 905 906 if ctx.ModuleName() == "framework-res" { 907 // framework-res.apk is installed as system/framework/framework-res.apk 908 a.installDir = android.PathForModuleInstall(ctx, "framework") 909 } else if a.Privileged() { 910 a.installDir = android.PathForModuleInstall(ctx, "priv-app", a.installApkName) 911 } else if ctx.InstallInTestcases() { 912 a.installDir = android.PathForModuleInstall(ctx, a.installApkName, ctx.DeviceConfig().DeviceArch()) 913 } else { 914 a.installDir = android.PathForModuleInstall(ctx, "app", a.installApkName) 915 } 916 a.onDeviceDir = android.InstallPathToOnDevicePath(ctx, a.installDir) 917 918 a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx) 919 if a.usesLibrary.shouldDisableDexpreopt { 920 a.dexpreopter.disableDexpreopt() 921 } 922 923 var noticeAssetPath android.WritablePath 924 if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") { 925 // The rule to create the notice file can't be generated yet, as the final output path 926 // for the apk isn't known yet. Add the path where the notice file will be generated to the 927 // aapt rules now before calling aaptBuildActions, the rule to create the notice file will 928 // be generated later. 929 noticeAssetPath = android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz") 930 a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath) 931 } 932 933 // For apps targeting latest target_sdk_version 934 if Bool(a.appProperties.Enforce_default_target_sdk_version) { 935 a.SetEnforceDefaultTargetSdkVersion(true) 936 } 937 938 // Process all building blocks, from AAPT to certificates. 939 a.aaptBuildActions(ctx) 940 // The decision to enforce <uses-library> checks is made before adding implicit SDK libraries. 941 a.usesLibrary.freezeEnforceUsesLibraries(ctx) 942 943 // Check that the <uses-library> list is coherent with the manifest. 944 if a.usesLibrary.enforceUsesLibraries(ctx) { 945 manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest( 946 ctx, a.mergedManifestFile, &a.classLoaderContexts) 947 apkDeps = append(apkDeps, manifestCheckFile) 948 } 949 950 a.proguardBuildActions(ctx) 951 952 a.linter.mergedManifest = a.aapt.mergedManifestFile 953 a.linter.manifest = a.aapt.manifestPath 954 a.linter.resources = a.aapt.resourceFiles 955 a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps() 956 957 dexJarFile, packageResources := a.dexBuildActions(ctx) 958 959 // No need to check the SDK version of the JNI deps unless we embed them 960 checkNativeSdkVersion := a.shouldEmbedJnis(ctx) && !Bool(a.appProperties.Jni_uses_platform_apis) 961 jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), checkNativeSdkVersion) 962 jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx) 963 964 if ctx.Failed() { 965 return 966 } 967 968 a.certificate, certificates = processMainCert(a.ModuleBase, a.getCertString(ctx), certificates, ctx) 969 970 // Build a final signed app package. 971 packageFile := android.PathForModuleOut(ctx, a.installApkName+".apk") 972 v4SigningRequested := Bool(a.Module.deviceProperties.V4_signature) 973 var v4SignatureFile android.WritablePath = nil 974 if v4SigningRequested { 975 v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+".apk.idsig") 976 } 977 var lineageFile android.Path 978 if lineage := String(a.overridableAppProperties.Lineage); lineage != "" { 979 lineageFile = android.PathForModuleSrc(ctx, lineage) 980 } 981 rotationMinSdkVersion := String(a.overridableAppProperties.RotationMinSdkVersion) 982 983 CreateAndSignAppPackage(ctx, packageFile, packageResources, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion) 984 a.outputFile = packageFile 985 if v4SigningRequested { 986 a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile) 987 } 988 989 if a.aapt.noticeFile.Valid() { 990 // Generating the notice file rule has to be here after a.outputFile is known. 991 noticeFile := android.PathForModuleOut(ctx, "NOTICE.html.gz") 992 android.BuildNoticeHtmlOutputFromLicenseMetadata( 993 ctx, noticeFile, "", "", 994 []string{ 995 a.installDir.String() + "/", 996 android.PathForModuleInstall(ctx).String() + "/", 997 a.outputFile.String(), 998 }) 999 builder := android.NewRuleBuilder(pctx, ctx) 1000 builder.Command().Text("cp"). 1001 Input(noticeFile). 1002 Output(noticeAssetPath) 1003 builder.Build("notice_dir", "Building notice dir") 1004 } 1005 1006 for _, split := range a.aapt.splits { 1007 // Sign the split APKs 1008 packageFile := android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk") 1009 if v4SigningRequested { 1010 v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig") 1011 } 1012 CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion) 1013 a.extraOutputFiles = append(a.extraOutputFiles, packageFile) 1014 if v4SigningRequested { 1015 a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile) 1016 } 1017 } 1018 1019 // Build an app bundle. 1020 bundleFile := android.PathForModuleOut(ctx, "base.zip") 1021 BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile) 1022 a.bundleFile = bundleFile 1023 1024 allowlist := a.createPrivappAllowlist(ctx) 1025 if allowlist != nil { 1026 a.privAppAllowlist = android.OptionalPathForPath(allowlist) 1027 } 1028 1029 // Install the app package. 1030 shouldInstallAppPackage := (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() && !a.appProperties.PreventInstall 1031 if shouldInstallAppPackage { 1032 if a.privAppAllowlist.Valid() { 1033 allowlistInstallPath := android.PathForModuleInstall(ctx, "etc", "permissions") 1034 allowlistInstallFilename := a.installApkName + ".xml" 1035 ctx.InstallFile(allowlistInstallPath, allowlistInstallFilename, a.privAppAllowlist.Path()) 1036 } 1037 1038 var extraInstalledPaths android.InstallPaths 1039 for _, extra := range a.extraOutputFiles { 1040 installed := ctx.InstallFile(a.installDir, extra.Base(), extra) 1041 extraInstalledPaths = append(extraInstalledPaths, installed) 1042 } 1043 // If we don't embed jni libs, make sure that those are installed along with the 1044 // app, and also place symlinks to the installed paths under the lib/<arch> 1045 // directory of the app installation directory. ex: 1046 // /system/app/MyApp/lib/arm64/libfoo.so -> /system/lib64/libfoo.so 1047 if !a.embeddedJniLibs { 1048 for _, jniLib := range jniLibs { 1049 archStr := jniLib.target.Arch.ArchType.String() 1050 symlinkDir := a.installDir.Join(ctx, "lib", archStr) 1051 for _, installedLib := range jniLib.installPaths { 1052 // install the symlink itself 1053 symlinkName := installedLib.Base() 1054 symlinkTarget := android.InstallPathToOnDevicePath(ctx, installedLib) 1055 ctx.InstallAbsoluteSymlink(symlinkDir, symlinkName, symlinkTarget) 1056 } 1057 } 1058 } 1059 ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...) 1060 } 1061 1062 ctx.CheckbuildFile(a.outputFile) 1063 1064 a.buildAppDependencyInfo(ctx) 1065 1066 providePrebuiltInfo(ctx, 1067 prebuiltInfoProps{ 1068 baseModuleName: a.BaseModuleName(), 1069 isPrebuilt: false, 1070 }, 1071 ) 1072 1073 a.setOutputFiles(ctx) 1074} 1075 1076func (a *AndroidApp) setOutputFiles(ctx android.ModuleContext) { 1077 ctx.SetOutputFiles([]android.Path{a.proguardOptionsFile}, ".aapt.proguardOptionsFile") 1078 if a.aaptSrcJar != nil { 1079 ctx.SetOutputFiles([]android.Path{a.aaptSrcJar}, ".aapt.srcjar") 1080 } 1081 if a.rJar != nil { 1082 ctx.SetOutputFiles([]android.Path{a.rJar}, ".aapt.jar") 1083 } 1084 ctx.SetOutputFiles([]android.Path{a.outputFile}, ".apk") 1085 ctx.SetOutputFiles([]android.Path{a.exportPackage}, ".export-package.apk") 1086 ctx.SetOutputFiles([]android.Path{a.aapt.manifestPath}, ".manifest.xml") 1087 setOutputFiles(ctx, a.Library.Module) 1088} 1089 1090type appDepsInterface interface { 1091 SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec 1092 MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel 1093 RequiresStableAPIs(ctx android.BaseModuleContext) bool 1094} 1095 1096func collectAppDeps(ctx android.ModuleContext, app appDepsInterface, 1097 shouldCollectRecursiveNativeDeps bool, 1098 checkNativeSdkVersion bool) ([]jniLib, android.Paths, []Certificate) { 1099 1100 if checkNativeSdkVersion { 1101 checkNativeSdkVersion = app.SdkVersion(ctx).Specified() && 1102 app.SdkVersion(ctx).Kind != android.SdkCorePlatform && !app.RequiresStableAPIs(ctx) 1103 } 1104 jniLib, prebuiltJniPackages := collectJniDeps(ctx, shouldCollectRecursiveNativeDeps, 1105 checkNativeSdkVersion, func(parent, child android.Module) bool { 1106 apkInApex := ctx.Module().(android.ApexModule).NotInPlatform() 1107 childLinkable, _ := child.(cc.LinkableInterface) 1108 parentLinkable, _ := parent.(cc.LinkableInterface) 1109 useStubsOfDep := childLinkable.IsStubs() 1110 if apkInApex && parentLinkable != nil { 1111 // APK-in-APEX 1112 // If the parent is a linkable interface, use stubs if the dependency edge crosses an apex boundary. 1113 useStubsOfDep = useStubsOfDep || (childLinkable.HasStubsVariants() && cc.ShouldUseStubForApex(ctx, parent, child)) 1114 } 1115 return !childLinkable.IsNdk(ctx.Config()) && !useStubsOfDep 1116 }) 1117 1118 var certificates []Certificate 1119 1120 var directImplementationDeps android.Paths 1121 var transitiveImplementationDeps []depset.DepSet[android.Path] 1122 ctx.VisitDirectDeps(func(module android.Module) { 1123 otherName := ctx.OtherModuleName(module) 1124 tag := ctx.OtherModuleDependencyTag(module) 1125 1126 if tag == certificateTag { 1127 if dep, ok := module.(*AndroidAppCertificate); ok { 1128 certificates = append(certificates, dep.Certificate) 1129 } else { 1130 ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName) 1131 } 1132 } 1133 1134 if IsJniDepTag(tag) { 1135 directImplementationDeps = append(directImplementationDeps, android.OutputFileForModule(ctx, module, "")) 1136 if info, ok := android.OtherModuleProvider(ctx, module, cc.ImplementationDepInfoProvider); ok { 1137 transitiveImplementationDeps = append(transitiveImplementationDeps, info.ImplementationDeps) 1138 } 1139 } 1140 }) 1141 android.SetProvider(ctx, cc.ImplementationDepInfoProvider, &cc.ImplementationDepInfo{ 1142 ImplementationDeps: depset.New(depset.PREORDER, directImplementationDeps, transitiveImplementationDeps), 1143 }) 1144 1145 return jniLib, prebuiltJniPackages, certificates 1146} 1147 1148func collectJniDeps(ctx android.ModuleContext, 1149 shouldCollectRecursiveNativeDeps bool, 1150 checkNativeSdkVersion bool, 1151 filter func(parent, child android.Module) bool) ([]jniLib, android.Paths) { 1152 var jniLibs []jniLib 1153 var prebuiltJniPackages android.Paths 1154 seenModulePaths := make(map[string]bool) 1155 1156 ctx.WalkDeps(func(module android.Module, parent android.Module) bool { 1157 otherName := ctx.OtherModuleName(module) 1158 tag := ctx.OtherModuleDependencyTag(module) 1159 1160 if IsJniDepTag(tag) || cc.IsSharedDepTag(tag) { 1161 if dep, ok := module.(cc.LinkableInterface); ok { 1162 if filter != nil && !filter(parent, module) { 1163 return false 1164 } 1165 1166 lib := dep.OutputFile() 1167 if lib.Valid() { 1168 path := lib.Path() 1169 if seenModulePaths[path.String()] { 1170 return false 1171 } 1172 seenModulePaths[path.String()] = true 1173 1174 if checkNativeSdkVersion && dep.SdkVersion() == "" { 1175 ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not", 1176 otherName) 1177 } 1178 1179 jniLibs = append(jniLibs, jniLib{ 1180 name: ctx.OtherModuleName(module), 1181 path: path, 1182 target: module.Target(), 1183 coverageFile: dep.CoverageOutputFile(), 1184 unstrippedFile: dep.UnstrippedOutputFile(), 1185 partition: dep.Partition(), 1186 installPaths: android.OtherModuleProviderOrDefault(ctx, dep, android.InstallFilesProvider).InstallFiles, 1187 }) 1188 } else if ctx.Config().AllowMissingDependencies() { 1189 ctx.AddMissingDependencies([]string{otherName}) 1190 } else { 1191 ctx.ModuleErrorf("dependency %q missing output file", otherName) 1192 } 1193 } else { 1194 ctx.ModuleErrorf("jni_libs dependency %q must be a cc library", otherName) 1195 } 1196 1197 return shouldCollectRecursiveNativeDeps 1198 } 1199 1200 if info, ok := android.OtherModuleProvider(ctx, module, JniPackageProvider); ok { 1201 prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...) 1202 } 1203 1204 return false 1205 }) 1206 1207 return jniLibs, prebuiltJniPackages 1208} 1209 1210func (a *AndroidApp) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) { 1211 ctx.WalkDeps(func(child, parent android.Module) bool { 1212 isExternal := !a.DepIsInSameApex(ctx, child) 1213 if am, ok := child.(android.ApexModule); ok { 1214 if !do(ctx, parent, am, isExternal) { 1215 return false 1216 } 1217 } 1218 return !isExternal 1219 }) 1220} 1221 1222func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { 1223 if ctx.Host() { 1224 return 1225 } 1226 1227 depsInfo := android.DepNameToDepInfoMap{} 1228 a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool { 1229 depName := to.Name() 1230 1231 // Skip dependencies that are only available to APEXes; they are developed with updatability 1232 // in mind and don't need manual approval. 1233 if to.(android.ApexModule).NotAvailableForPlatform() { 1234 return true 1235 } 1236 1237 if info, exist := depsInfo[depName]; exist { 1238 info.From = append(info.From, from.Name()) 1239 info.IsExternal = info.IsExternal && externalDep 1240 depsInfo[depName] = info 1241 } else { 1242 toMinSdkVersion := "(no version)" 1243 if m, ok := to.(interface { 1244 MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel 1245 }); ok { 1246 if v := m.MinSdkVersion(ctx); !v.IsNone() { 1247 toMinSdkVersion = v.String() 1248 } 1249 } else if m, ok := to.(interface{ MinSdkVersion() string }); ok { 1250 // TODO(b/175678607) eliminate the use of MinSdkVersion returning 1251 // string 1252 if v := m.MinSdkVersion(); v != "" { 1253 toMinSdkVersion = v 1254 } 1255 } 1256 depsInfo[depName] = android.ApexModuleDepInfo{ 1257 To: depName, 1258 From: []string{from.Name()}, 1259 IsExternal: externalDep, 1260 MinSdkVersion: toMinSdkVersion, 1261 } 1262 } 1263 return true 1264 }) 1265 1266 a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(ctx).String(), depsInfo) 1267} 1268 1269func (a *AndroidApp) enforceDefaultTargetSdkVersion() bool { 1270 return a.appProperties.EnforceDefaultTargetSdkVersion 1271} 1272 1273func (a *AndroidApp) SetEnforceDefaultTargetSdkVersion(val bool) { 1274 a.appProperties.EnforceDefaultTargetSdkVersion = val 1275} 1276 1277func (a *AndroidApp) Updatable() bool { 1278 return Bool(a.appProperties.Updatable) 1279} 1280 1281func (a *AndroidApp) getCertString(ctx android.BaseModuleContext) string { 1282 certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName()) 1283 if overridden { 1284 return ":" + certificate 1285 } 1286 return a.overridableAppProperties.Certificate.GetOrDefault(ctx, "") 1287} 1288 1289func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { 1290 if IsJniDepTag(ctx.OtherModuleDependencyTag(dep)) { 1291 return true 1292 } 1293 return a.Library.DepIsInSameApex(ctx, dep) 1294} 1295 1296func (a *AndroidApp) Privileged() bool { 1297 return Bool(a.appProperties.Privileged) 1298} 1299 1300func (a *AndroidApp) IsNativeCoverageNeeded(ctx cc.IsNativeCoverageNeededContext) bool { 1301 return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled() 1302} 1303 1304func (a *AndroidApp) SetPreventInstall() { 1305 a.appProperties.PreventInstall = true 1306} 1307 1308func (a *AndroidApp) MarkAsCoverageVariant(coverage bool) { 1309 a.appProperties.IsCoverageVariant = coverage 1310} 1311 1312func (a *AndroidApp) EnableCoverageIfNeeded() {} 1313 1314var _ cc.Coverage = (*AndroidApp)(nil) 1315 1316func (a *AndroidApp) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) { 1317 a.Library.IDEInfo(ctx, dpInfo) 1318 a.aapt.IDEInfo(ctx, dpInfo) 1319} 1320 1321func (a *AndroidApp) productCharacteristicsRROPackageName() string { 1322 return proptools.String(a.appProperties.ProductCharacteristicsRROPackageName) 1323} 1324 1325func (a *AndroidApp) productCharacteristicsRROManifestModuleName() string { 1326 return proptools.String(a.appProperties.ProductCharacteristicsRROManifestModuleName) 1327} 1328 1329// android_app compiles sources and Android resources into an Android application package `.apk` file. 1330func AndroidAppFactory() android.Module { 1331 module := &AndroidApp{} 1332 1333 module.Module.dexProperties.Optimize.EnabledByDefault = true 1334 module.Module.dexProperties.Optimize.Shrink = proptools.BoolPtr(true) 1335 module.Module.dexProperties.Optimize.Proguard_compatibility = proptools.BoolPtr(false) 1336 1337 module.Module.properties.Instrument = true 1338 module.Module.properties.Supports_static_instrumentation = true 1339 module.Module.properties.Installable = proptools.BoolPtr(true) 1340 1341 module.addHostAndDeviceProperties() 1342 module.AddProperties( 1343 &module.aaptProperties, 1344 &module.appProperties, 1345 &module.overridableAppProperties, 1346 &module.Library.sourceProperties) 1347 1348 module.usesLibrary.enforce = true 1349 1350 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 1351 android.InitDefaultableModule(module) 1352 android.InitOverridableModule(module, &module.overridableAppProperties.Overrides) 1353 android.InitApexModule(module) 1354 1355 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 1356 a := ctx.Module().(*AndroidApp) 1357 1358 characteristics := ctx.Config().ProductAAPTCharacteristics() 1359 if characteristics == "default" || characteristics == "" { 1360 module.appProperties.Generate_product_characteristics_rro = nil 1361 // no need to create RRO 1362 return 1363 } 1364 1365 if !proptools.Bool(module.appProperties.Generate_product_characteristics_rro) { 1366 return 1367 } 1368 1369 rroPackageName := a.Name() + "__" + strings.ReplaceAll(characteristics, ",", "_") + "__auto_generated_characteristics_rro" 1370 rroManifestName := rroPackageName + "_manifest" 1371 1372 a.appProperties.ProductCharacteristicsRROPackageName = proptools.StringPtr(rroPackageName) 1373 a.appProperties.ProductCharacteristicsRROManifestModuleName = proptools.StringPtr(rroManifestName) 1374 1375 rroManifestProperties := struct { 1376 Name *string 1377 Tools []string 1378 Out []string 1379 Srcs []string 1380 Cmd *string 1381 }{ 1382 Name: proptools.StringPtr(rroManifestName), 1383 Tools: []string{"characteristics_rro_generator", "aapt2"}, 1384 Out: []string{"AndroidManifest.xml"}, 1385 Srcs: []string{":" + a.Name() + "{.apk}"}, 1386 Cmd: proptools.StringPtr("$(location characteristics_rro_generator) $$($(location aapt2) dump packagename $(in)) $(out)"), 1387 } 1388 ctx.CreateModule(GenRuleFactory, &rroManifestProperties) 1389 1390 rroProperties := struct { 1391 Name *string 1392 Filter_product *string 1393 Aaptflags []string 1394 Manifest *string 1395 Resource_dirs proptools.Configurable[[]string] 1396 Flags_packages []string 1397 }{ 1398 Name: proptools.StringPtr(rroPackageName), 1399 Filter_product: proptools.StringPtr(characteristics), 1400 Aaptflags: []string{"--auto-add-overlay"}, 1401 Manifest: proptools.StringPtr(":" + rroManifestName), 1402 Resource_dirs: a.aaptProperties.Resource_dirs, 1403 Flags_packages: a.aaptProperties.Flags_packages, 1404 } 1405 if !Bool(a.aaptProperties.Aapt_include_all_resources) { 1406 for _, aaptConfig := range ctx.Config().ProductAAPTConfig() { 1407 rroProperties.Aaptflags = append(rroProperties.Aaptflags, "-c", aaptConfig) 1408 } 1409 } 1410 ctx.CreateModule(RuntimeResourceOverlayFactory, &rroProperties) 1411 1412 }) 1413 1414 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { 1415 createInternalRuntimeOverlays(ctx, module.ModuleBase) 1416 }) 1417 1418 return module 1419} 1420 1421func AutogeneratedRroModuleName(ctx android.EarlyModuleContext, moduleName, partition string) string { 1422 return fmt.Sprintf("%s__%s__auto_generated_rro_%s", moduleName, ctx.Config().DeviceProduct(), partition) 1423} 1424 1425type createModuleContext interface { 1426 android.EarlyModuleContext 1427 CreateModule(android.ModuleFactory, ...interface{}) android.Module 1428} 1429 1430func createInternalRuntimeOverlays(ctx createModuleContext, a android.ModuleBase) { 1431 if !ctx.Config().HasDeviceProduct() { 1432 return 1433 } 1434 // vendor 1435 vendorOverlayProps := struct { 1436 Name *string 1437 Base *string 1438 Vendor *bool 1439 Product_specific *bool 1440 System_ext_specific *bool 1441 Manifest *string 1442 Sdk_version *string 1443 Compile_multilib *string 1444 Enabled proptools.Configurable[bool] 1445 }{ 1446 Name: proptools.StringPtr(AutogeneratedRroModuleName(ctx, a.Name(), "vendor")), 1447 Base: proptools.StringPtr(a.Name()), 1448 Vendor: proptools.BoolPtr(true), 1449 Product_specific: proptools.BoolPtr(false), 1450 System_ext_specific: proptools.BoolPtr(false), 1451 Manifest: proptools.StringPtr(":" + a.Name() + "{.manifest.xml}"), 1452 Sdk_version: proptools.StringPtr("current"), 1453 Compile_multilib: proptools.StringPtr("first"), 1454 Enabled: a.EnabledProperty().Clone(), 1455 } 1456 ctx.CreateModule(AutogenRuntimeResourceOverlayFactory, &vendorOverlayProps) 1457 1458 // product 1459 productOverlayProps := struct { 1460 Name *string 1461 Base *string 1462 Vendor *bool 1463 Proprietary *bool 1464 Soc_specific *bool 1465 Product_specific *bool 1466 System_ext_specific *bool 1467 Manifest *string 1468 Sdk_version *string 1469 Compile_multilib *string 1470 Enabled proptools.Configurable[bool] 1471 }{ 1472 Name: proptools.StringPtr(AutogeneratedRroModuleName(ctx, a.Name(), "product")), 1473 Base: proptools.StringPtr(a.Name()), 1474 Vendor: proptools.BoolPtr(false), 1475 Proprietary: proptools.BoolPtr(false), 1476 Soc_specific: proptools.BoolPtr(false), 1477 Product_specific: proptools.BoolPtr(true), 1478 System_ext_specific: proptools.BoolPtr(false), 1479 Manifest: proptools.StringPtr(":" + a.Name() + "{.manifest.xml}"), 1480 Sdk_version: proptools.StringPtr("current"), 1481 Compile_multilib: proptools.StringPtr("first"), 1482 Enabled: a.EnabledProperty().Clone(), 1483 } 1484 ctx.CreateModule(AutogenRuntimeResourceOverlayFactory, &productOverlayProps) 1485} 1486 1487// A dictionary of values to be overridden in the manifest. 1488type Manifest_values struct { 1489 // Overrides the value of package_name in the manifest 1490 ApplicationId *string 1491} 1492 1493type appTestProperties struct { 1494 // The name of the android_app module that the tests will run against. 1495 Instrumentation_for *string 1496 1497 // If specified, the instrumentation target package name in the manifest is overwritten by it. 1498 Instrumentation_target_package *string 1499 1500 // If specified, the mainline module package name in the test config is overwritten by it. 1501 Mainline_package_name *string 1502 1503 Manifest_values Manifest_values 1504} 1505 1506type AndroidTest struct { 1507 AndroidApp 1508 1509 appTestProperties appTestProperties 1510 1511 testProperties testProperties 1512 1513 testConfig android.Path 1514 extraTestConfigs android.Paths 1515 data android.Paths 1516} 1517 1518func (a *AndroidTest) InstallInTestcases() bool { 1519 return true 1520} 1521 1522type androidTestApp interface { 1523 includedInTestSuite(searchPrefix string) bool 1524} 1525 1526func (a *AndroidTest) includedInTestSuite(searchPrefix string) bool { 1527 return android.PrefixInList(a.testProperties.Test_suites, searchPrefix) 1528} 1529 1530func (a *AndroidTestHelperApp) includedInTestSuite(searchPrefix string) bool { 1531 return android.PrefixInList(a.appTestHelperAppProperties.Test_suites, searchPrefix) 1532} 1533 1534func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1535 checkMinSdkVersionMts(ctx, a.MinSdkVersion(ctx)) 1536 var configs []tradefed.Config 1537 if a.appTestProperties.Instrumentation_target_package != nil { 1538 a.additionalAaptFlags = append(a.additionalAaptFlags, 1539 "--rename-instrumentation-target-package "+*a.appTestProperties.Instrumentation_target_package) 1540 } else if a.appTestProperties.Instrumentation_for != nil { 1541 // Check if the instrumentation target package is overridden. 1542 manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(*a.appTestProperties.Instrumentation_for) 1543 if overridden { 1544 a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+manifestPackageName) 1545 } 1546 } 1547 applicationId := a.appTestProperties.Manifest_values.ApplicationId 1548 if applicationId != nil { 1549 packageNameProp := a.overridableAppProperties.Package_name.Get(ctx) 1550 if packageNameProp.IsPresent() { 1551 ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.") 1552 } 1553 a.aapt.manifestValues.applicationId = *applicationId 1554 } 1555 a.generateAndroidBuildActions(ctx) 1556 1557 for _, module := range a.testProperties.Test_mainline_modules { 1558 configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module}) 1559 } 1560 1561 testConfig := tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, 1562 a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, 1563 a.testProperties.Auto_gen_config, configs, a.testProperties.Test_options.Test_runner_options) 1564 a.testConfig = a.FixTestConfig(ctx, testConfig) 1565 a.extraTestConfigs = android.PathsForModuleSrc(ctx, a.testProperties.Test_options.Extra_test_configs) 1566 a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) 1567 a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_common_data)...) 1568 a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_data)...) 1569 a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_prefer32_data)...) 1570 1571 android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{ 1572 TestcaseRelDataFiles: testcaseRel(a.data), 1573 OutputFile: a.OutputFile(), 1574 TestConfig: a.testConfig, 1575 HostRequiredModuleNames: a.HostRequiredModuleNames(), 1576 TestSuites: a.testProperties.Test_suites, 1577 IsHost: false, 1578 LocalCertificate: a.certificate.AndroidMkString(), 1579 IsUnitTest: Bool(a.testProperties.Test_options.Unit_test), 1580 MkInclude: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk", 1581 MkAppClass: "APPS", 1582 }) 1583 android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{ 1584 TestOnly: true, 1585 TopLevelTarget: true, 1586 }) 1587 1588} 1589 1590func testcaseRel(paths android.Paths) []string { 1591 relPaths := []string{} 1592 for _, p := range paths { 1593 relPaths = append(relPaths, p.Rel()) 1594 } 1595 return relPaths 1596} 1597 1598func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig android.Path) android.Path { 1599 if testConfig == nil { 1600 return nil 1601 } 1602 1603 fixedConfig := android.PathForModuleOut(ctx, "test_config_fixer", "AndroidTest.xml") 1604 rule := android.NewRuleBuilder(pctx, ctx) 1605 command := rule.Command().BuiltTool("test_config_fixer").Input(testConfig).Output(fixedConfig) 1606 fixNeeded := false 1607 1608 // Auto-generated test config uses `ModuleName` as the APK name. So fix it if it is not the case. 1609 if ctx.ModuleName() != a.installApkName { 1610 fixNeeded = true 1611 command.FlagWithArg("--test-file-name ", a.installApkName+".apk") 1612 } 1613 1614 packageNameProp := a.overridableAppProperties.Package_name.Get(ctx) 1615 if packageNameProp.IsPresent() { 1616 fixNeeded = true 1617 command.FlagWithInput("--manifest ", a.manifestPath). 1618 FlagWithArg("--package-name ", packageNameProp.Get()) 1619 } 1620 1621 if a.appTestProperties.Mainline_package_name != nil { 1622 fixNeeded = true 1623 command.FlagWithArg("--mainline-package-name ", *a.appTestProperties.Mainline_package_name) 1624 } 1625 1626 if fixNeeded { 1627 rule.Build("fix_test_config", "fix test config") 1628 return fixedConfig 1629 } 1630 return testConfig 1631} 1632 1633func (a *AndroidTestHelperApp) DepsMutator(ctx android.BottomUpMutatorContext) { 1634 if len(a.ApexProperties.Apex_available) == 0 && ctx.Config().IsEnvTrue("EMMA_API_MAPPER") { 1635 // Instrument the android_test_helper target to log potential API calls at the run time. 1636 // Contact android-xts-infra team before using the environment var EMMA_API_MAPPER. 1637 ctx.AddVariationDependencies(nil, staticLibTag, "apimapper-helper-device-lib") 1638 a.setApiMapper(true) 1639 } 1640 a.AndroidApp.DepsMutator(ctx) 1641} 1642 1643func (a *AndroidTest) DepsMutator(ctx android.BottomUpMutatorContext) { 1644 if len(a.ApexProperties.Apex_available) == 0 && ctx.Config().IsEnvTrue("EMMA_API_MAPPER") { 1645 // Instrument the android_test_helper target to log potential API calls at the run time. 1646 // Contact android-xts-infra team before using the environment var EMMA_API_MAPPER. 1647 ctx.AddVariationDependencies(nil, staticLibTag, "apimapper-helper-device-lib") 1648 a.setApiMapper(true) 1649 } 1650 a.AndroidApp.DepsMutator(ctx) 1651} 1652 1653func (a *AndroidTest) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) { 1654 a.AndroidApp.OverridablePropertiesDepsMutator(ctx) 1655 if a.appTestProperties.Instrumentation_for != nil { 1656 // The android_app dependency listed in instrumentation_for needs to be added to the classpath for javac, 1657 // but not added to the aapt2 link includes like a normal android_app or android_library dependency, so 1658 // use instrumentationForTag instead of libTag. 1659 ctx.AddVariationDependencies(nil, instrumentationForTag, String(a.appTestProperties.Instrumentation_for)) 1660 } 1661} 1662 1663// android_test compiles test sources and Android resources into an Android application package `.apk` file and 1664// creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file. 1665func AndroidTestFactory() android.Module { 1666 module := &AndroidTest{} 1667 1668 module.Module.dexProperties.Optimize.EnabledByDefault = false 1669 1670 module.Module.properties.Instrument = true 1671 module.Module.properties.Supports_static_instrumentation = true 1672 module.Module.properties.Installable = proptools.BoolPtr(true) 1673 module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true) 1674 module.appProperties.AlwaysPackageNativeLibs = true 1675 module.Module.dexpreopter.isTest = true 1676 module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) 1677 1678 module.addHostAndDeviceProperties() 1679 module.AddProperties( 1680 &module.aaptProperties, 1681 &module.appProperties, 1682 &module.appTestProperties, 1683 &module.overridableAppProperties, 1684 &module.testProperties) 1685 1686 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 1687 android.InitDefaultableModule(module) 1688 android.InitOverridableModule(module, &module.overridableAppProperties.Overrides) 1689 1690 return module 1691} 1692 1693type appTestHelperAppProperties struct { 1694 // list of compatibility suites (for example "cts", "vts") that the module should be 1695 // installed into. 1696 Test_suites []string `android:"arch_variant"` 1697 1698 // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml 1699 // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true 1700 // explicitly. 1701 Auto_gen_config *bool 1702 1703 // Install the test into a folder named for the module in all test suites. 1704 Per_testcase_directory *bool 1705 1706 Manifest_values Manifest_values 1707} 1708 1709type AndroidTestHelperApp struct { 1710 AndroidApp 1711 1712 appTestHelperAppProperties appTestHelperAppProperties 1713} 1714 1715func (a *AndroidTestHelperApp) InstallInTestcases() bool { 1716 return true 1717} 1718 1719// android_test_helper_app compiles sources and Android resources into an Android application package `.apk` file that 1720// will be used by tests, but does not produce an `AndroidTest.xml` file so the module will not be run directly as a 1721// test. 1722func AndroidTestHelperAppFactory() android.Module { 1723 module := &AndroidTestHelperApp{} 1724 1725 // TODO(b/192032291): Disable by default after auditing downstream usage. 1726 module.Module.dexProperties.Optimize.EnabledByDefault = true 1727 1728 module.Module.properties.Installable = proptools.BoolPtr(true) 1729 module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true) 1730 module.appProperties.AlwaysPackageNativeLibs = true 1731 module.Module.dexpreopter.isTest = true 1732 module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) 1733 1734 module.addHostAndDeviceProperties() 1735 module.AddProperties( 1736 &module.aaptProperties, 1737 &module.appProperties, 1738 &module.appTestHelperAppProperties, 1739 &module.overridableAppProperties) 1740 1741 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 1742 android.InitDefaultableModule(module) 1743 android.InitApexModule(module) 1744 return module 1745} 1746 1747type AndroidAppCertificate struct { 1748 android.ModuleBase 1749 1750 properties AndroidAppCertificateProperties 1751 Certificate Certificate 1752} 1753 1754type AndroidAppCertificateProperties struct { 1755 // Name of the certificate files. Extensions .x509.pem and .pk8 will be added to the name. 1756 Certificate *string 1757} 1758 1759// android_app_certificate modules can be referenced by the certificates property of android_app modules to select 1760// the signing key. 1761func AndroidAppCertificateFactory() android.Module { 1762 module := &AndroidAppCertificate{} 1763 module.AddProperties(&module.properties) 1764 android.InitAndroidModule(module) 1765 return module 1766} 1767 1768func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1769 cert := String(c.properties.Certificate) 1770 c.Certificate = Certificate{ 1771 Pem: android.PathForModuleSrc(ctx, cert+".x509.pem"), 1772 Key: android.PathForModuleSrc(ctx, cert+".pk8"), 1773 } 1774} 1775 1776type OverrideAndroidApp struct { 1777 android.ModuleBase 1778 android.OverrideModuleBase 1779} 1780 1781func (i *OverrideAndroidApp) GenerateAndroidBuildActions(_ android.ModuleContext) { 1782 // All the overrides happen in the base module. 1783 // TODO(jungjw): Check the base module type. 1784} 1785 1786// override_android_app is used to create an android_app module based on another android_app by overriding 1787// some of its properties. 1788func OverrideAndroidAppModuleFactory() android.Module { 1789 m := &OverrideAndroidApp{} 1790 m.AddProperties( 1791 &OverridableProperties{}, 1792 &overridableAppProperties{}, 1793 ) 1794 1795 android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon) 1796 android.InitOverrideModule(m) 1797 android.AddLoadHookWithPriority(m, func(ctx android.LoadHookContext) { 1798 createInternalRuntimeOverlays(ctx, m.ModuleBase) 1799 }, 1) // Run after soong config load hoook 1800 1801 return m 1802} 1803 1804type OverrideAndroidTest struct { 1805 android.ModuleBase 1806 android.OverrideModuleBase 1807} 1808 1809func (i *OverrideAndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1810 // All the overrides happen in the base module. 1811 // TODO(jungjw): Check the base module type. 1812 android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{ 1813 TestOnly: true, 1814 TopLevelTarget: true, 1815 }) 1816} 1817 1818// override_android_test is used to create an android_app module based on another android_test by overriding 1819// some of its properties. 1820func OverrideAndroidTestModuleFactory() android.Module { 1821 m := &OverrideAndroidTest{} 1822 m.AddProperties(&overridableAppProperties{}) 1823 m.AddProperties(&appTestProperties{}) 1824 1825 android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon) 1826 android.InitOverrideModule(m) 1827 return m 1828} 1829 1830type UsesLibraryProperties struct { 1831 // A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file. 1832 Uses_libs proptools.Configurable[[]string] 1833 1834 // A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file with 1835 // required=false. 1836 Optional_uses_libs proptools.Configurable[[]string] 1837 1838 // If true, the list of uses_libs and optional_uses_libs modules must match the AndroidManifest.xml file. Defaults 1839 // to true if either uses_libs or optional_uses_libs is set. Will unconditionally default to true in the future. 1840 Enforce_uses_libs *bool 1841 1842 // Optional name of the <uses-library> provided by this module. This is needed for non-SDK 1843 // libraries, because SDK ones are automatically picked up by Soong. The <uses-library> name 1844 // normally is the same as the module name, but there are exceptions. 1845 Provides_uses_lib *string 1846 1847 // A list of shared library names to exclude from the classpath of the APK. Adding a library here 1848 // will prevent it from being used when precompiling the APK and prevent it from being implicitly 1849 // added to the APK's manifest's <uses-library> elements. 1850 // 1851 // Care must be taken when using this as it could result in runtime errors if the APK actually 1852 // uses classes provided by the library and which are not provided in any other way. 1853 // 1854 // This is primarily intended for use by various CTS tests that check the runtime handling of the 1855 // android.test.base shared library (and related libraries) but which depend on some common 1856 // libraries that depend on the android.test.base library. Without this those tests will end up 1857 // with a <uses-library android:name="android.test.base"/> in their manifest which would either 1858 // render the tests worthless (as they would be testing the wrong behavior), or would break the 1859 // test altogether by providing access to classes that the tests were not expecting. Those tests 1860 // provide the android.test.base statically and use jarjar to rename them so they do not collide 1861 // with the classes provided by the android.test.base library. 1862 Exclude_uses_libs []string 1863 1864 // The module names of optional uses-library libraries that are missing from the source tree. 1865 Missing_optional_uses_libs []string `blueprint:"mutated"` 1866} 1867 1868// usesLibrary provides properties and helper functions for AndroidApp and AndroidAppImport to verify that the 1869// <uses-library> tags that end up in the manifest of an APK match the ones known to the build system through the 1870// uses_libs and optional_uses_libs properties. The build system's values are used by dexpreopt to preopt apps 1871// with knowledge of their shared libraries. 1872type usesLibrary struct { 1873 usesLibraryProperties UsesLibraryProperties 1874 1875 // Whether to enforce verify_uses_library check. 1876 enforce bool 1877 1878 // Whether dexpreopt should be disabled 1879 shouldDisableDexpreopt bool 1880} 1881 1882func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps bool) { 1883 if !ctx.Config().UnbundledBuild() || ctx.Config().UnbundledBuildImage() { 1884 ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs.GetOrDefault(ctx, nil)...) 1885 presentOptionalUsesLibs := u.presentOptionalUsesLibs(ctx) 1886 ctx.AddVariationDependencies(nil, usesLibOptTag, presentOptionalUsesLibs...) 1887 // Only add these extra dependencies if the module is an app that depends on framework 1888 // libs. This avoids creating a cyclic dependency: 1889 // e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res. 1890 if addCompatDeps { 1891 // Dexpreopt needs paths to the dex jars of these libraries in order to construct 1892 // class loader context for dex2oat. Add them as a dependency with a special tag. 1893 ctx.AddVariationDependencies(nil, usesLibCompat29ReqTag, dexpreopt.CompatUsesLibs29...) 1894 ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...) 1895 ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...) 1896 } 1897 _, diff, _ := android.ListSetDifference(u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil), presentOptionalUsesLibs) 1898 u.usesLibraryProperties.Missing_optional_uses_libs = diff 1899 } else { 1900 ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.usesLibraryProperties.Uses_libs.GetOrDefault(ctx, nil)...) 1901 ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.presentOptionalUsesLibs(ctx)...) 1902 } 1903} 1904 1905// presentOptionalUsesLibs returns optional_uses_libs after filtering out libraries that don't exist in the source tree. 1906func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string { 1907 optionalUsesLibs := android.FilterListPred(u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil), func(s string) bool { 1908 exists := ctx.OtherModuleExists(s) 1909 if !exists && !android.InList(ctx.ModuleName(), ctx.Config().BuildWarningBadOptionalUsesLibsAllowlist()) { 1910 fmt.Printf("Warning: Module '%s' depends on non-existing optional_uses_libs '%s'\n", ctx.ModuleName(), s) 1911 } 1912 return exists 1913 }) 1914 return optionalUsesLibs 1915} 1916 1917// Returns a map of module names of shared library dependencies to the paths to their dex jars on 1918// host and on device. 1919func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext) dexpreopt.ClassLoaderContextMap { 1920 clcMap := make(dexpreopt.ClassLoaderContextMap) 1921 1922 // Skip when UnbundledBuild() is true, but UnbundledBuildImage() is false. With 1923 // UnbundledBuildImage() it is necessary to generate dexpreopt.config for post-dexpreopting. 1924 if ctx.Config().UnbundledBuild() && !ctx.Config().UnbundledBuildImage() { 1925 return clcMap 1926 } 1927 1928 ctx.VisitDirectDeps(func(m android.Module) { 1929 tag, isUsesLibTag := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag) 1930 if !isUsesLibTag { 1931 return 1932 } 1933 1934 dep := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(m)) 1935 1936 // Skip stub libraries. A dependency on the implementation library has been added earlier, 1937 // so it will be added to CLC, but the stub shouldn't be. Stub libraries can be distingushed 1938 // from implementation libraries by their name, which is different as it has a suffix. 1939 if comp, ok := m.(SdkLibraryComponentDependency); ok { 1940 if impl := comp.OptionalSdkLibraryImplementation(); impl != nil && *impl != dep { 1941 return 1942 } 1943 } 1944 1945 if lib, ok := m.(UsesLibraryDependency); ok { 1946 if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok { 1947 // Skip java_sdk_library dependencies that provide stubs, but not an implementation. 1948 // This will be restricted to optional_uses_libs 1949 if tag == usesLibOptTag && lib.DexJarBuildPath(ctx).PathOrNil() == nil { 1950 u.shouldDisableDexpreopt = true 1951 return 1952 } 1953 } 1954 libName := dep 1955 if ulib, ok := m.(ProvidesUsesLib); ok && ulib.ProvidesUsesLib() != nil { 1956 libName = *ulib.ProvidesUsesLib() 1957 } 1958 clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional, 1959 lib.DexJarBuildPath(ctx).PathOrNil(), lib.DexJarInstallPath(), 1960 lib.ClassLoaderContexts()) 1961 } else if ctx.Config().AllowMissingDependencies() { 1962 ctx.AddMissingDependencies([]string{dep}) 1963 } else { 1964 ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library", dep) 1965 } 1966 }) 1967 return clcMap 1968} 1969 1970// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs 1971// properties. Defaults to true if either of uses_libs or optional_uses_libs is specified. Will default to true 1972// unconditionally in the future. 1973func (u *usesLibrary) enforceUsesLibraries(ctx android.ModuleContext) bool { 1974 defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs.GetOrDefault(ctx, nil)) > 0 || 1975 len(u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil)) > 0 1976 return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, u.enforce || defaultEnforceUsesLibs) 1977} 1978 1979// Freeze the value of `enforce_uses_libs` based on the current values of `uses_libs` and `optional_uses_libs`. 1980func (u *usesLibrary) freezeEnforceUsesLibraries(ctx android.ModuleContext) { 1981 enforce := u.enforceUsesLibraries(ctx) 1982 u.usesLibraryProperties.Enforce_uses_libs = &enforce 1983} 1984 1985// verifyUsesLibraries checks the <uses-library> tags in the manifest against the ones specified 1986// in the `uses_libs`/`optional_uses_libs` properties. The input can be either an XML manifest, or 1987// an APK with the manifest embedded in it (manifest_check will know which one it is by the file 1988// extension: APKs are supposed to end with '.apk'). 1989func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile android.Path, 1990 outputFile android.WritablePath, classLoaderContexts *dexpreopt.ClassLoaderContextMap) android.Path { 1991 1992 statusFile := dexpreopt.UsesLibrariesStatusFile(ctx) 1993 1994 // Disable verify_uses_libraries check if dexpreopt is globally disabled. Without dexpreopt the 1995 // check is not necessary, and although it is good to have, it is difficult to maintain on 1996 // non-linux build platforms where dexpreopt is generally disabled (the check may fail due to 1997 // various unrelated reasons, such as a failure to get manifest from an APK). 1998 global := dexpreopt.GetGlobalConfig(ctx) 1999 if global.DisablePreopt || global.OnlyPreoptArtBootImage { 2000 return inputFile 2001 } 2002 2003 rule := android.NewRuleBuilder(pctx, ctx) 2004 cmd := rule.Command().BuiltTool("manifest_check"). 2005 Flag("--enforce-uses-libraries"). 2006 Input(inputFile). 2007 FlagWithOutput("--enforce-uses-libraries-status ", statusFile). 2008 FlagWithInput("--aapt ", ctx.Config().HostToolPath(ctx, "aapt2")) 2009 2010 if outputFile != nil { 2011 cmd.FlagWithOutput("-o ", outputFile) 2012 } 2013 2014 if dexpreopt.GetGlobalConfig(ctx).RelaxUsesLibraryCheck { 2015 cmd.Flag("--enforce-uses-libraries-relax") 2016 } 2017 2018 requiredUsesLibs, optionalUsesLibs := classLoaderContexts.UsesLibs() 2019 for _, lib := range requiredUsesLibs { 2020 cmd.FlagWithArg("--uses-library ", lib) 2021 } 2022 for _, lib := range optionalUsesLibs { 2023 cmd.FlagWithArg("--optional-uses-library ", lib) 2024 } 2025 2026 // Also add missing optional uses libs, as the manifest check expects them. 2027 // Note that what we add here are the module names of those missing libs, not library names, while 2028 // the manifest check actually expects library names. However, the case where a library is missing 2029 // and the module name != the library name is too rare for us to handle. 2030 for _, lib := range u.usesLibraryProperties.Missing_optional_uses_libs { 2031 cmd.FlagWithArg("--missing-optional-uses-library ", lib) 2032 } 2033 2034 rule.Build("verify_uses_libraries", "verify <uses-library>") 2035 return outputFile 2036} 2037 2038// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against 2039// the build system and returns the path to a copy of the manifest. 2040func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path, 2041 classLoaderContexts *dexpreopt.ClassLoaderContextMap) android.Path { 2042 outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml") 2043 return u.verifyUsesLibraries(ctx, manifest, outputFile, classLoaderContexts) 2044} 2045 2046// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the build 2047// system and returns the path to a copy of the APK. 2048func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path, 2049 classLoaderContexts *dexpreopt.ClassLoaderContextMap) { 2050 u.verifyUsesLibraries(ctx, apk, nil, classLoaderContexts) // for APKs manifest_check does not write output file 2051} 2052