1// Copyright (C) 2018 The Android Open Source Project 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 15// package apex implements build rules for creating the APEX files which are container for 16// lower-level system components. See https://source.android.com/devices/tech/ota/apex 17package apex 18 19import ( 20 "fmt" 21 "path/filepath" 22 "regexp" 23 "sort" 24 "strings" 25 26 "github.com/google/blueprint" 27 "github.com/google/blueprint/proptools" 28 29 "android/soong/android" 30 "android/soong/bpf" 31 "android/soong/cc" 32 prebuilt_etc "android/soong/etc" 33 "android/soong/filesystem" 34 "android/soong/java" 35 "android/soong/multitree" 36 "android/soong/rust" 37 "android/soong/sh" 38) 39 40func init() { 41 registerApexBuildComponents(android.InitRegistrationContext) 42} 43 44func registerApexBuildComponents(ctx android.RegistrationContext) { 45 ctx.RegisterModuleType("apex", BundleFactory) 46 ctx.RegisterModuleType("apex_test", TestApexBundleFactory) 47 ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory) 48 ctx.RegisterModuleType("apex_defaults", DefaultsFactory) 49 ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory) 50 ctx.RegisterModuleType("override_apex", OverrideApexFactory) 51 ctx.RegisterModuleType("apex_set", apexSetFactory) 52 53 ctx.PreArchMutators(registerPreArchMutators) 54 ctx.PreDepsMutators(RegisterPreDepsMutators) 55 ctx.PostDepsMutators(RegisterPostDepsMutators) 56} 57 58func registerPreArchMutators(ctx android.RegisterMutatorsContext) { 59 ctx.TopDown("prebuilt_apex_module_creator", prebuiltApexModuleCreatorMutator).Parallel() 60} 61 62func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) { 63 ctx.TopDown("apex_vndk", apexVndkMutator).Parallel() 64 ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel() 65} 66 67func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { 68 ctx.TopDown("apex_info", apexInfoMutator).Parallel() 69 ctx.BottomUp("apex_unique", apexUniqueVariationsMutator).Parallel() 70 ctx.BottomUp("apex_test_for_deps", apexTestForDepsMutator).Parallel() 71 ctx.BottomUp("apex_test_for", apexTestForMutator).Parallel() 72 // Run mark_platform_availability before the apexMutator as the apexMutator needs to know whether 73 // it should create a platform variant. 74 ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel() 75 ctx.Transition("apex", &apexTransitionMutator{}) 76 ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel() 77 ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel() 78 // Register after apex_info mutator so that it can use ApexVariationName 79 ctx.TopDown("apex_strict_updatability_lint", apexStrictUpdatibilityLintMutator).Parallel() 80} 81 82type apexBundleProperties struct { 83 // Json manifest file describing meta info of this APEX bundle. Refer to 84 // system/apex/proto/apex_manifest.proto for the schema. Default: "apex_manifest.json" 85 Manifest *string `android:"path"` 86 87 // AndroidManifest.xml file used for the zip container of this APEX bundle. If unspecified, 88 // a default one is automatically generated. 89 AndroidManifest *string `android:"path"` 90 91 // Determines the file contexts file for setting the security contexts to files in this APEX 92 // bundle. For platform APEXes, this should points to a file under /system/sepolicy Default: 93 // /system/sepolicy/apex/<module_name>_file_contexts. 94 File_contexts *string `android:"path"` 95 96 // By default, file_contexts is amended by force-labelling / and /apex_manifest.pb as system_file 97 // to avoid mistakes. When set as true, no force-labelling. 98 Use_file_contexts_as_is *bool 99 100 // Path to the canned fs config file for customizing file's 101 // uid/gid/mod/capabilities. The content of this file is appended to the 102 // default config, so that the custom entries are preferred. The format is 103 // /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where 104 // path_or_glob is a path or glob pattern for a file or set of files, 105 // uid/gid are numerial values of user ID and group ID, mode is octal value 106 // for the file mode, and cap is hexadecimal value for the capability. 107 Canned_fs_config *string `android:"path"` 108 109 ApexNativeDependencies 110 111 Multilib apexMultilibProperties 112 113 // List of runtime resource overlays (RROs) that are embedded inside this APEX. 114 Rros []string 115 116 // List of bootclasspath fragments that are embedded inside this APEX bundle. 117 Bootclasspath_fragments []string 118 119 // List of systemserverclasspath fragments that are embedded inside this APEX bundle. 120 Systemserverclasspath_fragments []string 121 122 // List of java libraries that are embedded inside this APEX bundle. 123 Java_libs []string 124 125 // List of sh binaries that are embedded inside this APEX bundle. 126 Sh_binaries []string 127 128 // List of platform_compat_config files that are embedded inside this APEX bundle. 129 Compat_configs []string 130 131 // List of filesystem images that are embedded inside this APEX bundle. 132 Filesystems []string 133 134 // List of module names which we don't want to add as transitive deps. This can be used as 135 // a workaround when the current implementation collects more than necessary. For example, 136 // Rust binaries with prefer_rlib:true add unnecessary dependencies. 137 Unwanted_transitive_deps []string 138 139 // Whether this APEX is considered updatable or not. When set to true, this will enforce 140 // additional rules for making sure that the APEX is truly updatable. To be updatable, 141 // min_sdk_version should be set as well. This will also disable the size optimizations like 142 // symlinking to the system libs. Default is true. 143 Updatable *bool 144 145 // Marks that this APEX is designed to be updatable in the future, although it's not 146 // updatable yet. This is used to mimic some of the build behaviors that are applied only to 147 // updatable APEXes. Currently, this disables the size optimization, so that the size of 148 // APEX will not increase when the APEX is actually marked as truly updatable. Default is 149 // false. 150 Future_updatable *bool 151 152 // Whether this APEX can use platform APIs or not. Can be set to true only when `updatable: 153 // false`. Default is false. 154 Platform_apis *bool 155 156 // Whether this APEX is installable to one of the partitions like system, vendor, etc. 157 // Default: true. 158 Installable *bool 159 160 // If set true, VNDK libs are considered as stable libs and are not included in this APEX. 161 // Should be only used in non-system apexes (e.g. vendor: true). Default is false. 162 Use_vndk_as_stable *bool 163 164 // The type of filesystem to use. Either 'ext4', 'f2fs' or 'erofs'. Default 'ext4'. 165 Payload_fs_type *string 166 167 // For telling the APEX to ignore special handling for system libraries such as bionic. 168 // Default is false. 169 Ignore_system_library_special_case *bool 170 171 // Whenever apex_payload.img of the APEX should include dm-verity hashtree. 172 // Default value is true. 173 Generate_hashtree *bool 174 175 // Whenever apex_payload.img of the APEX should not be dm-verity signed. Should be only 176 // used in tests. 177 Test_only_unsigned_payload *bool 178 179 // Whenever apex should be compressed, regardless of product flag used. Should be only 180 // used in tests. 181 Test_only_force_compression *bool 182 183 // Put extra tags (signer=<value>) to apexkeys.txt, so that release tools can sign this apex 184 // with the tool to sign payload contents. 185 Custom_sign_tool *string 186 187 // Whether this is a dynamic common lib apex, if so the native shared libs will be placed 188 // in a special way that include the digest of the lib file under /lib(64)? 189 Dynamic_common_lib_apex *bool 190 191 // Canonical name of this APEX bundle. Used to determine the path to the 192 // activated APEX on device (i.e. /apex/<apexVariationName>), and used for the 193 // apex mutator variations. For override_apex modules, this is the name of the 194 // overridden base module. 195 ApexVariationName string `blueprint:"mutated"` 196 197 IsCoverageVariant bool `blueprint:"mutated"` 198 199 // List of sanitizer names that this APEX is enabled for 200 SanitizerNames []string `blueprint:"mutated"` 201 202 PreventInstall bool `blueprint:"mutated"` 203 204 HideFromMake bool `blueprint:"mutated"` 205 206 // Name that dependencies can specify in their apex_available properties to refer to this module. 207 // If not specified, this defaults to Soong module name. This must be the name of a Soong module. 208 Apex_available_name *string 209 210 // Variant version of the mainline module. Must be an integer between 0-9 211 Variant_version *string 212} 213 214type ApexNativeDependencies struct { 215 // List of native libraries that are embedded inside this APEX. 216 Native_shared_libs []string 217 218 // List of JNI libraries that are embedded inside this APEX. 219 Jni_libs []string 220 221 // List of rust dyn libraries that are embedded inside this APEX. 222 Rust_dyn_libs []string 223 224 // List of native executables that are embedded inside this APEX. 225 Binaries []string 226 227 // List of native tests that are embedded inside this APEX. 228 Tests []string 229 230 // List of filesystem images that are embedded inside this APEX bundle. 231 Filesystems []string 232 233 // List of prebuilt_etcs that are embedded inside this APEX bundle. 234 Prebuilts []string 235 236 // List of native libraries to exclude from this APEX. 237 Exclude_native_shared_libs []string 238 239 // List of JNI libraries to exclude from this APEX. 240 Exclude_jni_libs []string 241 242 // List of rust dyn libraries to exclude from this APEX. 243 Exclude_rust_dyn_libs []string 244 245 // List of native executables to exclude from this APEX. 246 Exclude_binaries []string 247 248 // List of native tests to exclude from this APEX. 249 Exclude_tests []string 250 251 // List of filesystem images to exclude from this APEX bundle. 252 Exclude_filesystems []string 253 254 // List of prebuilt_etcs to exclude from this APEX bundle. 255 Exclude_prebuilts []string 256} 257 258// Merge combines another ApexNativeDependencies into this one 259func (a *ApexNativeDependencies) Merge(b ApexNativeDependencies) { 260 a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs...) 261 a.Jni_libs = append(a.Jni_libs, b.Jni_libs...) 262 a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...) 263 a.Binaries = append(a.Binaries, b.Binaries...) 264 a.Tests = append(a.Tests, b.Tests...) 265 a.Filesystems = append(a.Filesystems, b.Filesystems...) 266 a.Prebuilts = append(a.Prebuilts, b.Prebuilts...) 267 268 a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...) 269 a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...) 270 a.Exclude_rust_dyn_libs = append(a.Exclude_rust_dyn_libs, b.Exclude_rust_dyn_libs...) 271 a.Exclude_binaries = append(a.Exclude_binaries, b.Exclude_binaries...) 272 a.Exclude_tests = append(a.Exclude_tests, b.Exclude_tests...) 273 a.Exclude_filesystems = append(a.Exclude_filesystems, b.Exclude_filesystems...) 274 a.Exclude_prebuilts = append(a.Exclude_prebuilts, b.Exclude_prebuilts...) 275} 276 277type apexMultilibProperties struct { 278 // Native dependencies whose compile_multilib is "first" 279 First ApexNativeDependencies 280 281 // Native dependencies whose compile_multilib is "both" 282 Both ApexNativeDependencies 283 284 // Native dependencies whose compile_multilib is "prefer32" 285 Prefer32 ApexNativeDependencies 286 287 // Native dependencies whose compile_multilib is "32" 288 Lib32 ApexNativeDependencies 289 290 // Native dependencies whose compile_multilib is "64" 291 Lib64 ApexNativeDependencies 292} 293 294type apexTargetBundleProperties struct { 295 Target struct { 296 // Multilib properties only for android. 297 Android struct { 298 Multilib apexMultilibProperties 299 } 300 301 // Multilib properties only for host. 302 Host struct { 303 Multilib apexMultilibProperties 304 } 305 306 // Multilib properties only for host linux_bionic. 307 Linux_bionic struct { 308 Multilib apexMultilibProperties 309 } 310 311 // Multilib properties only for host linux_glibc. 312 Linux_glibc struct { 313 Multilib apexMultilibProperties 314 } 315 } 316} 317 318type apexArchBundleProperties struct { 319 Arch struct { 320 Arm struct { 321 ApexNativeDependencies 322 } 323 Arm64 struct { 324 ApexNativeDependencies 325 } 326 Riscv64 struct { 327 ApexNativeDependencies 328 } 329 X86 struct { 330 ApexNativeDependencies 331 } 332 X86_64 struct { 333 ApexNativeDependencies 334 } 335 } 336} 337 338// These properties can be used in override_apex to override the corresponding properties in the 339// base apex. 340type overridableProperties struct { 341 // List of APKs that are embedded inside this APEX. 342 Apps []string 343 344 // List of prebuilt files that are embedded inside this APEX bundle. 345 Prebuilts []string 346 347 // List of BPF programs inside this APEX bundle. 348 Bpfs []string 349 350 // Names of modules to be overridden. Listed modules can only be other binaries (in Make or 351 // Soong). This does not completely prevent installation of the overridden binaries, but if 352 // both binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will 353 // be removed from PRODUCT_PACKAGES. 354 Overrides []string 355 356 Multilib apexMultilibProperties 357 358 // Logging parent value. 359 Logging_parent string 360 361 // Apex Container package name. Override value for attribute package:name in 362 // AndroidManifest.xml 363 Package_name string 364 365 // A txt file containing list of files that are allowed to be included in this APEX. 366 Allowed_files *string `android:"path"` 367 368 // Name of the apex_key module that provides the private key to sign this APEX bundle. 369 Key *string 370 371 // Specifies the certificate and the private key to sign the zip container of this APEX. If 372 // this is "foo", foo.x509.pem and foo.pk8 under PRODUCT_DEFAULT_DEV_CERTIFICATE are used 373 // as the certificate and the private key, respectively. If this is ":module", then the 374 // certificate and the private key are provided from the android_app_certificate module 375 // named "module". 376 Certificate *string 377 378 // Whether this APEX can be compressed or not. Setting this property to false means this 379 // APEX will never be compressed. When set to true, APEX will be compressed if other 380 // conditions, e.g., target device needs to support APEX compression, are also fulfilled. 381 // Default: false. 382 Compressible *bool 383 384 // Trim against a specific Dynamic Common Lib APEX 385 Trim_against *string 386 387 // The minimum SDK version that this APEX must support at minimum. This is usually set to 388 // the SDK version that the APEX was first introduced. 389 Min_sdk_version *string 390} 391 392type apexBundle struct { 393 // Inherited structs 394 android.ModuleBase 395 android.DefaultableModuleBase 396 android.OverridableModuleBase 397 multitree.ExportableModuleBase 398 399 // Properties 400 properties apexBundleProperties 401 targetProperties apexTargetBundleProperties 402 archProperties apexArchBundleProperties 403 overridableProperties overridableProperties 404 vndkProperties apexVndkProperties // only for apex_vndk modules 405 406 /////////////////////////////////////////////////////////////////////////////////////////// 407 // Inputs 408 409 // Keys for apex_payload.img 410 publicKeyFile android.Path 411 privateKeyFile android.Path 412 413 // Cert/priv-key for the zip container 414 containerCertificateFile android.Path 415 containerPrivateKeyFile android.Path 416 417 // Flags for special variants of APEX 418 testApex bool 419 vndkApex bool 420 421 // File system type of apex_payload.img 422 payloadFsType fsType 423 424 // Whether to create symlink to the system file instead of having a file inside the apex or 425 // not 426 linkToSystemLib bool 427 428 // List of files to be included in this APEX. This is filled in the first part of 429 // GenerateAndroidBuildActions. 430 filesInfo []apexFile 431 432 // List of other module names that should be installed when this APEX gets installed (LOCAL_REQUIRED_MODULES). 433 makeModulesToInstall []string 434 435 /////////////////////////////////////////////////////////////////////////////////////////// 436 // Outputs (final and intermediates) 437 438 // Processed apex manifest in JSONson format (for Q) 439 manifestJsonOut android.WritablePath 440 441 // Processed apex manifest in PB format (for R+) 442 manifestPbOut android.WritablePath 443 444 // Processed file_contexts files 445 fileContexts android.WritablePath 446 447 // The built APEX file. This is the main product. 448 // Could be .apex or .capex 449 outputFile android.WritablePath 450 451 // The built uncompressed .apex file. 452 outputApexFile android.WritablePath 453 454 // The built APEX file in app bundle format. This file is not directly installed to the 455 // device. For an APEX, multiple app bundles are created each of which is for a specific ABI 456 // like arm, arm64, x86, etc. Then they are processed again (outside of the Android build 457 // system) to be merged into a single app bundle file that Play accepts. See 458 // vendor/google/build/build_unbundled_mainline_module.sh for more detail. 459 bundleModuleFile android.WritablePath 460 461 // Target directory to install this APEX. Usually out/target/product/<device>/<partition>/apex. 462 installDir android.InstallPath 463 464 // Path where this APEX was installed. 465 installedFile android.InstallPath 466 467 // fragment for this apex for apexkeys.txt 468 apexKeysPath android.WritablePath 469 470 // Installed locations of symlinks for backward compatibility. 471 compatSymlinks android.InstallPaths 472 473 // Text file having the list of individual files that are included in this APEX. Used for 474 // debugging purpose. 475 installedFilesFile android.WritablePath 476 477 // List of module names that this APEX is including (to be shown via *-deps-info target). 478 // Used for debugging purpose. 479 android.ApexBundleDepsInfo 480 481 // Optional list of lint report zip files for apexes that contain java or app modules 482 lintReports android.Paths 483 484 isCompressed bool 485 486 // Path of API coverage generate file 487 nativeApisUsedByModuleFile android.ModuleOutPath 488 nativeApisBackedByModuleFile android.ModuleOutPath 489 javaApisUsedByModuleFile android.ModuleOutPath 490 491 aconfigFiles []android.Path 492} 493 494// apexFileClass represents a type of file that can be included in APEX. 495type apexFileClass int 496 497const ( 498 app apexFileClass = iota 499 appSet 500 etc 501 javaSharedLib 502 nativeExecutable 503 nativeSharedLib 504 nativeTest 505 shBinary 506) 507 508var ( 509 classes = map[string]apexFileClass{ 510 "app": app, 511 "appSet": appSet, 512 "etc": etc, 513 "javaSharedLib": javaSharedLib, 514 "nativeExecutable": nativeExecutable, 515 "nativeSharedLib": nativeSharedLib, 516 "nativeTest": nativeTest, 517 "shBinary": shBinary, 518 } 519) 520 521// apexFile represents a file in an APEX bundle. This is created during the first half of 522// GenerateAndroidBuildActions by traversing the dependencies of the APEX. Then in the second half 523// of the function, this is used to create commands that copies the files into a staging directory, 524// where they are packaged into the APEX file. 525type apexFile struct { 526 // buildFile is put in the installDir inside the APEX. 527 builtFile android.Path 528 installDir string 529 partition string 530 customStem string 531 symlinks []string // additional symlinks 532 533 // Info for Android.mk Module name of `module` in AndroidMk. Note the generated AndroidMk 534 // module for apexFile is named something like <AndroidMk module name>.<apex name>[<apex 535 // suffix>] 536 androidMkModuleName string // becomes LOCAL_MODULE 537 class apexFileClass // becomes LOCAL_MODULE_CLASS 538 moduleDir string // becomes LOCAL_PATH 539 requiredModuleNames []string // becomes LOCAL_REQUIRED_MODULES 540 targetRequiredModuleNames []string // becomes LOCAL_TARGET_REQUIRED_MODULES 541 hostRequiredModuleNames []string // becomes LOCAL_HOST_REQUIRED_MODULES 542 dataPaths []android.DataPath // becomes LOCAL_TEST_DATA 543 544 jacocoReportClassesFile android.Path // only for javalibs and apps 545 lintDepSets java.LintDepSets // only for javalibs and apps 546 certificate java.Certificate // only for apps 547 overriddenPackageName string // only for apps 548 549 transitiveDep bool 550 isJniLib bool 551 552 multilib string 553 554 // TODO(jiyong): remove this 555 module android.Module 556} 557 558// TODO(jiyong): shorten the arglist using an option struct 559func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidMkModuleName string, installDir string, class apexFileClass, module android.Module) apexFile { 560 ret := apexFile{ 561 builtFile: builtFile, 562 installDir: installDir, 563 androidMkModuleName: androidMkModuleName, 564 class: class, 565 module: module, 566 } 567 if module != nil { 568 ret.moduleDir = ctx.OtherModuleDir(module) 569 ret.partition = module.PartitionTag(ctx.DeviceConfig()) 570 ret.requiredModuleNames = module.RequiredModuleNames() 571 ret.targetRequiredModuleNames = module.TargetRequiredModuleNames() 572 ret.hostRequiredModuleNames = module.HostRequiredModuleNames() 573 ret.multilib = module.Target().Arch.ArchType.Multilib 574 } 575 return ret 576} 577 578func (af *apexFile) ok() bool { 579 return af.builtFile != nil && af.builtFile.String() != "" 580} 581 582// apexRelativePath returns the relative path of the given path from the install directory of this 583// apexFile. 584// TODO(jiyong): rename this 585func (af *apexFile) apexRelativePath(path string) string { 586 return filepath.Join(af.installDir, path) 587} 588 589// path returns path of this apex file relative to the APEX root 590func (af *apexFile) path() string { 591 return af.apexRelativePath(af.stem()) 592} 593 594// stem returns the base filename of this apex file 595func (af *apexFile) stem() string { 596 if af.customStem != "" { 597 return af.customStem 598 } 599 return af.builtFile.Base() 600} 601 602// symlinkPaths returns paths of the symlinks (if any) relative to the APEX root 603func (af *apexFile) symlinkPaths() []string { 604 var ret []string 605 for _, symlink := range af.symlinks { 606 ret = append(ret, af.apexRelativePath(symlink)) 607 } 608 return ret 609} 610 611// availableToPlatform tests whether this apexFile is from a module that can be installed to the 612// platform. 613func (af *apexFile) availableToPlatform() bool { 614 if af.module == nil { 615 return false 616 } 617 if am, ok := af.module.(android.ApexModule); ok { 618 return am.AvailableFor(android.AvailableToPlatform) 619 } 620 return false 621} 622 623//////////////////////////////////////////////////////////////////////////////////////////////////// 624// Mutators 625// 626// Brief description about mutators for APEX. The following three mutators are the most important 627// ones. 628// 629// 1) DepsMutator: from the properties like native_shared_libs, java_libs, etc., modules are added 630// to the (direct) dependencies of this APEX bundle. 631// 632// 2) apexInfoMutator: this is a post-deps mutator, so runs after DepsMutator. Its goal is to 633// collect modules that are direct and transitive dependencies of each APEX bundle. The collected 634// modules are marked as being included in the APEX via BuildForApex(). 635// 636// 3) apexMutator: this is a post-deps mutator that runs after apexInfoMutator. For each module that 637// are marked by the apexInfoMutator, apex variations are created using CreateApexVariations(). 638 639type dependencyTag struct { 640 blueprint.BaseDependencyTag 641 name string 642 643 // Determines if the dependent will be part of the APEX payload. Can be false for the 644 // dependencies to the signing key module, etc. 645 payload bool 646 647 // True if the dependent can only be a source module, false if a prebuilt module is a suitable 648 // replacement. This is needed because some prebuilt modules do not provide all the information 649 // needed by the apex. 650 sourceOnly bool 651 652 // If not-nil and an APEX is a member of an SDK then dependencies of that APEX with this tag will 653 // also be added as exported members of that SDK. 654 memberType android.SdkMemberType 655} 656 657func (d *dependencyTag) SdkMemberType(_ android.Module) android.SdkMemberType { 658 return d.memberType 659} 660 661func (d *dependencyTag) ExportMember() bool { 662 return true 663} 664 665func (d *dependencyTag) String() string { 666 return fmt.Sprintf("apex.dependencyTag{%q}", d.name) 667} 668 669func (d *dependencyTag) ReplaceSourceWithPrebuilt() bool { 670 return !d.sourceOnly 671} 672 673var _ android.ReplaceSourceWithPrebuilt = &dependencyTag{} 674var _ android.SdkMemberDependencyTag = &dependencyTag{} 675 676var ( 677 androidAppTag = &dependencyTag{name: "androidApp", payload: true} 678 bpfTag = &dependencyTag{name: "bpf", payload: true} 679 certificateTag = &dependencyTag{name: "certificate"} 680 dclaTag = &dependencyTag{name: "dcla"} 681 executableTag = &dependencyTag{name: "executable", payload: true} 682 fsTag = &dependencyTag{name: "filesystem", payload: true} 683 bcpfTag = &dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true, memberType: java.BootclasspathFragmentSdkMemberType} 684 sscpfTag = &dependencyTag{name: "systemserverclasspathFragment", payload: true, sourceOnly: true, memberType: java.SystemServerClasspathFragmentSdkMemberType} 685 compatConfigTag = &dependencyTag{name: "compatConfig", payload: true, sourceOnly: true, memberType: java.CompatConfigSdkMemberType} 686 javaLibTag = &dependencyTag{name: "javaLib", payload: true} 687 jniLibTag = &dependencyTag{name: "jniLib", payload: true} 688 keyTag = &dependencyTag{name: "key"} 689 prebuiltTag = &dependencyTag{name: "prebuilt", payload: true} 690 rroTag = &dependencyTag{name: "rro", payload: true} 691 sharedLibTag = &dependencyTag{name: "sharedLib", payload: true} 692 testForTag = &dependencyTag{name: "test for"} 693 testTag = &dependencyTag{name: "test", payload: true} 694 shBinaryTag = &dependencyTag{name: "shBinary", payload: true} 695) 696 697// TODO(jiyong): shorten this function signature 698func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ApexNativeDependencies, target android.Target, imageVariation string) { 699 binVariations := target.Variations() 700 libVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"}) 701 rustLibVariations := append( 702 target.Variations(), []blueprint.Variation{ 703 {Mutator: "rust_libraries", Variation: "dylib"}, 704 {Mutator: "link", Variation: ""}, 705 }..., 706 ) 707 708 // Append "image" variation 709 binVariations = append(binVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation}) 710 libVariations = append(libVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation}) 711 rustLibVariations = append(rustLibVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation}) 712 713 // Use *FarVariation* to be able to depend on modules having conflicting variations with 714 // this module. This is required since arch variant of an APEX bundle is 'common' but it is 715 // 'arm' or 'arm64' for native shared libs. 716 ctx.AddFarVariationDependencies(binVariations, executableTag, 717 android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...) 718 ctx.AddFarVariationDependencies(binVariations, testTag, 719 android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...) 720 ctx.AddFarVariationDependencies(libVariations, jniLibTag, 721 android.RemoveListFromList(nativeModules.Jni_libs, nativeModules.Exclude_jni_libs)...) 722 ctx.AddFarVariationDependencies(libVariations, sharedLibTag, 723 android.RemoveListFromList(nativeModules.Native_shared_libs, nativeModules.Exclude_native_shared_libs)...) 724 ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag, 725 android.RemoveListFromList(nativeModules.Rust_dyn_libs, nativeModules.Exclude_rust_dyn_libs)...) 726 ctx.AddFarVariationDependencies(target.Variations(), fsTag, 727 android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...) 728 ctx.AddFarVariationDependencies(target.Variations(), prebuiltTag, 729 android.RemoveListFromList(nativeModules.Prebuilts, nativeModules.Exclude_prebuilts)...) 730} 731 732func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) { 733 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Android.Multilib, nil) 734} 735 736// getImageVariationPair returns a pair for the image variation name as its 737// prefix and suffix. The prefix indicates whether it's core/vendor/product and the 738// suffix indicates the vndk version for vendor/product if vndk is enabled. 739// getImageVariation can simply join the result of this function to get the 740// image variation name. 741func (a *apexBundle) getImageVariationPair() (string, string) { 742 if a.vndkApex { 743 return cc.VendorVariationPrefix, a.vndkVersion() 744 } 745 746 prefix := android.CoreVariation 747 if a.SocSpecific() || a.DeviceSpecific() { 748 prefix = cc.VendorVariation 749 } else if a.ProductSpecific() { 750 prefix = cc.ProductVariation 751 } 752 753 return prefix, "" 754} 755 756// getImageVariation returns the image variant name for this apexBundle. In most cases, it's simply 757// android.CoreVariation, but gets complicated for the vendor APEXes and the VNDK APEX. 758func (a *apexBundle) getImageVariation() string { 759 prefix, vndkVersion := a.getImageVariationPair() 760 return prefix + vndkVersion 761} 762 763func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { 764 // apexBundle is a multi-arch targets module. Arch variant of apexBundle is set to 'common'. 765 // arch-specific targets are enabled by the compile_multilib setting of the apex bundle. For 766 // each target os/architectures, appropriate dependencies are selected by their 767 // target.<os>.multilib.<type> groups and are added as (direct) dependencies. 768 targets := ctx.MultiTargets() 769 imageVariation := a.getImageVariation() 770 771 a.combineProperties(ctx) 772 773 has32BitTarget := false 774 for _, target := range targets { 775 if target.Arch.ArchType.Multilib == "lib32" { 776 has32BitTarget = true 777 } 778 } 779 for i, target := range targets { 780 var deps ApexNativeDependencies 781 782 // Add native modules targeting both ABIs. When multilib.* is omitted for 783 // native_shared_libs/jni_libs/tests, it implies multilib.both 784 deps.Merge(a.properties.Multilib.Both) 785 deps.Merge(ApexNativeDependencies{ 786 Native_shared_libs: a.properties.Native_shared_libs, 787 Tests: a.properties.Tests, 788 Jni_libs: a.properties.Jni_libs, 789 Binaries: nil, 790 }) 791 792 // Add native modules targeting the first ABI When multilib.* is omitted for 793 // binaries, it implies multilib.first 794 isPrimaryAbi := i == 0 795 if isPrimaryAbi { 796 deps.Merge(a.properties.Multilib.First) 797 deps.Merge(ApexNativeDependencies{ 798 Native_shared_libs: nil, 799 Tests: nil, 800 Jni_libs: nil, 801 Binaries: a.properties.Binaries, 802 }) 803 } 804 805 // Add native modules targeting either 32-bit or 64-bit ABI 806 switch target.Arch.ArchType.Multilib { 807 case "lib32": 808 deps.Merge(a.properties.Multilib.Lib32) 809 deps.Merge(a.properties.Multilib.Prefer32) 810 case "lib64": 811 deps.Merge(a.properties.Multilib.Lib64) 812 if !has32BitTarget { 813 deps.Merge(a.properties.Multilib.Prefer32) 814 } 815 } 816 817 // Add native modules targeting a specific arch variant 818 switch target.Arch.ArchType { 819 case android.Arm: 820 deps.Merge(a.archProperties.Arch.Arm.ApexNativeDependencies) 821 case android.Arm64: 822 deps.Merge(a.archProperties.Arch.Arm64.ApexNativeDependencies) 823 case android.Riscv64: 824 deps.Merge(a.archProperties.Arch.Riscv64.ApexNativeDependencies) 825 case android.X86: 826 deps.Merge(a.archProperties.Arch.X86.ApexNativeDependencies) 827 case android.X86_64: 828 deps.Merge(a.archProperties.Arch.X86_64.ApexNativeDependencies) 829 default: 830 panic(fmt.Errorf("unsupported arch %v\n", ctx.Arch().ArchType)) 831 } 832 833 addDependenciesForNativeModules(ctx, deps, target, imageVariation) 834 if isPrimaryAbi { 835 ctx.AddFarVariationDependencies([]blueprint.Variation{ 836 {Mutator: "os", Variation: target.OsVariation()}, 837 {Mutator: "arch", Variation: target.ArchVariation()}, 838 }, shBinaryTag, a.properties.Sh_binaries...) 839 } 840 } 841 842 // Common-arch dependencies come next 843 commonVariation := ctx.Config().AndroidCommonTarget.Variations() 844 ctx.AddFarVariationDependencies(commonVariation, rroTag, a.properties.Rros...) 845 ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments...) 846 ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments...) 847 ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...) 848 ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...) 849 ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...) 850} 851 852// DepsMutator for the overridden properties. 853func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) { 854 if a.overridableProperties.Allowed_files != nil { 855 android.ExtractSourceDeps(ctx, a.overridableProperties.Allowed_files) 856 } 857 858 commonVariation := ctx.Config().AndroidCommonTarget.Variations() 859 ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps...) 860 ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...) 861 if prebuilts := a.overridableProperties.Prebuilts; len(prebuilts) > 0 { 862 // For prebuilt_etc, use the first variant (64 on 64/32bit device, 32 on 32bit device) 863 // regardless of the TARGET_PREFER_* setting. See b/144532908 864 arches := ctx.DeviceConfig().Arches() 865 if len(arches) != 0 { 866 archForPrebuiltEtc := arches[0] 867 for _, arch := range arches { 868 // Prefer 64-bit arch if there is any 869 if arch.ArchType.Multilib == "lib64" { 870 archForPrebuiltEtc = arch 871 break 872 } 873 } 874 ctx.AddFarVariationDependencies([]blueprint.Variation{ 875 {Mutator: "os", Variation: ctx.Os().String()}, 876 {Mutator: "arch", Variation: archForPrebuiltEtc.String()}, 877 }, prebuiltTag, prebuilts...) 878 } 879 } 880 881 // Dependencies for signing 882 if String(a.overridableProperties.Key) == "" { 883 ctx.PropertyErrorf("key", "missing") 884 return 885 } 886 ctx.AddDependency(ctx.Module(), keyTag, String(a.overridableProperties.Key)) 887 888 cert := android.SrcIsModule(a.getCertString(ctx)) 889 if cert != "" { 890 ctx.AddDependency(ctx.Module(), certificateTag, cert) 891 // empty cert is not an error. Cert and private keys will be directly found under 892 // PRODUCT_DEFAULT_DEV_CERTIFICATE 893 } 894} 895 896func apexDCLADepsMutator(mctx android.BottomUpMutatorContext) { 897 if !mctx.Config().ApexTrimEnabled() { 898 return 899 } 900 if a, ok := mctx.Module().(*apexBundle); ok && a.overridableProperties.Trim_against != nil { 901 commonVariation := mctx.Config().AndroidCommonTarget.Variations() 902 mctx.AddFarVariationDependencies(commonVariation, dclaTag, String(a.overridableProperties.Trim_against)) 903 } else if o, ok := mctx.Module().(*OverrideApex); ok { 904 for _, p := range o.GetProperties() { 905 properties, ok := p.(*overridableProperties) 906 if !ok { 907 continue 908 } 909 if properties.Trim_against != nil { 910 commonVariation := mctx.Config().AndroidCommonTarget.Variations() 911 mctx.AddFarVariationDependencies(commonVariation, dclaTag, String(properties.Trim_against)) 912 } 913 } 914 } 915} 916 917type DCLAInfo struct { 918 ProvidedLibs []string 919} 920 921var DCLAInfoProvider = blueprint.NewMutatorProvider[DCLAInfo]("apex_info") 922 923var _ ApexInfoMutator = (*apexBundle)(nil) 924 925func (a *apexBundle) ApexVariationName() string { 926 return a.properties.ApexVariationName 927} 928 929// ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are 930// identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and 931// indirect) dependencies are collected. But a few types of modules that shouldn't be included in 932// the apexBundle (e.g. stub libraries) are not collected. Note that a single module can be depended 933// on by multiple apexBundles. In that case, the module is collected for all of the apexBundles. 934// 935// For each dependency between an apex and an ApexModule an ApexInfo object describing the apex 936// is passed to that module's BuildForApex(ApexInfo) method which collates them all in a list. 937// The apexMutator uses that list to create module variants for the apexes to which it belongs. 938// The relationship between module variants and apexes is not one-to-one as variants will be 939// shared between compatible apexes. 940func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { 941 942 // The VNDK APEX is special. For the APEX, the membership is described in a very different 943 // way. There is no dependency from the VNDK APEX to the VNDK libraries. Instead, VNDK 944 // libraries are self-identified by their vndk.enabled properties. There is no need to run 945 // this mutator for the APEX as nothing will be collected. So, let's return fast. 946 if a.vndkApex { 947 return 948 } 949 950 // Special casing for APEXes on non-system (e.g., vendor, odm, etc.) partitions. They are 951 // provided with a property named use_vndk_as_stable, which when set to true doesn't collect 952 // VNDK libraries as transitive dependencies. This option is useful for reducing the size of 953 // the non-system APEXes because the VNDK libraries won't be included (and duped) in the 954 // APEX, but shared across APEXes via the VNDK APEX. 955 useVndk := a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && mctx.Config().EnforceProductPartitionInterface()) 956 if proptools.Bool(a.properties.Use_vndk_as_stable) { 957 if !useVndk { 958 mctx.PropertyErrorf("use_vndk_as_stable", "not supported for system/system_ext APEXes") 959 } 960 if a.minSdkVersionValue(mctx) != "" { 961 mctx.PropertyErrorf("use_vndk_as_stable", "not supported when min_sdk_version is set") 962 } 963 if mctx.Failed() { 964 return 965 } 966 } 967 968 continueApexDepsWalk := func(child, parent android.Module) bool { 969 am, ok := child.(android.ApexModule) 970 if !ok || !am.CanHaveApexVariants() { 971 return false 972 } 973 depTag := mctx.OtherModuleDependencyTag(child) 974 975 // Check to see if the tag always requires that the child module has an apex variant for every 976 // apex variant of the parent module. If it does not then it is still possible for something 977 // else, e.g. the DepIsInSameApex(...) method to decide that a variant is required. 978 if required, ok := depTag.(android.AlwaysRequireApexVariantTag); ok && required.AlwaysRequireApexVariant() { 979 return true 980 } 981 if !android.IsDepInSameApex(mctx, parent, child) { 982 return false 983 } 984 985 if useVndk && child.Name() == "libbinder" { 986 mctx.ModuleErrorf("Module %s in the vendor APEX %s should not use libbinder. Use libbinder_ndk instead.", parent.Name(), a.Name()) 987 } 988 989 // By default, all the transitive dependencies are collected, unless filtered out 990 // above. 991 return true 992 } 993 994 // Records whether a certain module is included in this apexBundle via direct dependency or 995 // inndirect dependency. 996 contents := make(map[string]android.ApexMembership) 997 mctx.WalkDeps(func(child, parent android.Module) bool { 998 if !continueApexDepsWalk(child, parent) { 999 return false 1000 } 1001 // If the parent is apexBundle, this child is directly depended. 1002 _, directDep := parent.(*apexBundle) 1003 depName := mctx.OtherModuleName(child) 1004 contents[depName] = contents[depName].Add(directDep) 1005 return true 1006 }) 1007 1008 // The membership information is saved for later access 1009 apexContents := android.NewApexContents(contents) 1010 android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{ 1011 Contents: apexContents, 1012 }) 1013 1014 minSdkVersion := a.minSdkVersion(mctx) 1015 // When min_sdk_version is not set, the apex is built against FutureApiLevel. 1016 if minSdkVersion.IsNone() { 1017 minSdkVersion = android.FutureApiLevel 1018 } 1019 1020 // This is the main part of this mutator. Mark the collected dependencies that they need to 1021 // be built for this apexBundle. 1022 1023 apexVariationName := mctx.ModuleName() // could be com.android.foo 1024 if overridable, ok := mctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" { 1025 // use the overridden name com.mycompany.android.foo 1026 apexVariationName = overridable.GetOverriddenBy() 1027 } 1028 1029 a.properties.ApexVariationName = apexVariationName 1030 testApexes := []string{} 1031 if a.testApex { 1032 testApexes = []string{apexVariationName} 1033 } 1034 apexInfo := android.ApexInfo{ 1035 ApexVariationName: apexVariationName, 1036 MinSdkVersion: minSdkVersion, 1037 Updatable: a.Updatable(), 1038 UsePlatformApis: a.UsePlatformApis(), 1039 InApexVariants: []string{apexVariationName}, 1040 InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo 1041 ApexContents: []*android.ApexContents{apexContents}, 1042 TestApexes: testApexes, 1043 } 1044 mctx.WalkDeps(func(child, parent android.Module) bool { 1045 if !continueApexDepsWalk(child, parent) { 1046 return false 1047 } 1048 child.(android.ApexModule).BuildForApex(apexInfo) // leave a mark! 1049 return true 1050 }) 1051 1052 if a.dynamic_common_lib_apex() { 1053 android.SetProvider(mctx, DCLAInfoProvider, DCLAInfo{ 1054 ProvidedLibs: a.properties.Native_shared_libs, 1055 }) 1056 } 1057} 1058 1059type ApexInfoMutator interface { 1060 // ApexVariationName returns the name of the APEX variation to use in the apex 1061 // mutator etc. It is the same name as ApexInfo.ApexVariationName. 1062 ApexVariationName() string 1063 1064 // ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are 1065 // depended upon by an apex and which require an apex specific variant. 1066 ApexInfoMutator(android.TopDownMutatorContext) 1067} 1068 1069// apexInfoMutator delegates the work of identifying which modules need an ApexInfo and apex 1070// specific variant to modules that support the ApexInfoMutator. 1071// It also propagates updatable=true to apps of updatable apexes 1072func apexInfoMutator(mctx android.TopDownMutatorContext) { 1073 if !mctx.Module().Enabled(mctx) { 1074 return 1075 } 1076 1077 if a, ok := mctx.Module().(ApexInfoMutator); ok { 1078 a.ApexInfoMutator(mctx) 1079 } 1080 1081 if am, ok := mctx.Module().(android.ApexModule); ok { 1082 android.ApexInfoMutator(mctx, am) 1083 } 1084 enforceAppUpdatability(mctx) 1085} 1086 1087// apexStrictUpdatibilityLintMutator propagates strict_updatability_linting to transitive deps of a mainline module 1088// This check is enforced for updatable modules 1089func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) { 1090 if !mctx.Module().Enabled(mctx) { 1091 return 1092 } 1093 if apex, ok := mctx.Module().(*apexBundle); ok && apex.checkStrictUpdatabilityLinting(mctx) { 1094 mctx.WalkDeps(func(child, parent android.Module) bool { 1095 // b/208656169 Do not propagate strict updatability linting to libcore/ 1096 // These libs are available on the classpath during compilation 1097 // These libs are transitive deps of the sdk. See java/sdk.go:decodeSdkDep 1098 // Only skip libraries defined in libcore root, not subdirectories 1099 if mctx.OtherModuleDir(child) == "libcore" { 1100 // Do not traverse transitive deps of libcore/ libs 1101 return false 1102 } 1103 if android.InList(child.Name(), skipLintJavalibAllowlist) { 1104 return false 1105 } 1106 if lintable, ok := child.(java.LintDepSetsIntf); ok { 1107 lintable.SetStrictUpdatabilityLinting(true) 1108 } 1109 // visit transitive deps 1110 return true 1111 }) 1112 } 1113} 1114 1115// enforceAppUpdatability propagates updatable=true to apps of updatable apexes 1116func enforceAppUpdatability(mctx android.TopDownMutatorContext) { 1117 if !mctx.Module().Enabled(mctx) { 1118 return 1119 } 1120 if apex, ok := mctx.Module().(*apexBundle); ok && apex.Updatable() { 1121 // checking direct deps is sufficient since apex->apk is a direct edge, even when inherited via apex_defaults 1122 mctx.VisitDirectDeps(func(module android.Module) { 1123 // ignore android_test_app 1124 if app, ok := module.(*java.AndroidApp); ok { 1125 app.SetUpdatable(true) 1126 } 1127 }) 1128 } 1129} 1130 1131// TODO: b/215736885 Whittle the denylist 1132// Transitive deps of certain mainline modules baseline NewApi errors 1133// Skip these mainline modules for now 1134var ( 1135 skipStrictUpdatabilityLintAllowlist = []string{ 1136 // go/keep-sorted start 1137 "PackageManagerTestApex", 1138 "com.android.adservices", 1139 "com.android.appsearch", 1140 "com.android.art", 1141 "com.android.art.debug", 1142 "com.android.btservices", 1143 "com.android.cellbroadcast", 1144 "com.android.configinfrastructure", 1145 "com.android.conscrypt", 1146 "com.android.extservices", 1147 "com.android.extservices_tplus", 1148 "com.android.healthfitness", 1149 "com.android.ipsec", 1150 "com.android.media", 1151 "com.android.mediaprovider", 1152 "com.android.ondevicepersonalization", 1153 "com.android.os.statsd", 1154 "com.android.permission", 1155 "com.android.profiling", 1156 "com.android.rkpd", 1157 "com.android.scheduling", 1158 "com.android.tethering", 1159 "com.android.uwb", 1160 "com.android.wifi", 1161 "test_com.android.art", 1162 "test_com.android.cellbroadcast", 1163 "test_com.android.conscrypt", 1164 "test_com.android.extservices", 1165 "test_com.android.ipsec", 1166 "test_com.android.media", 1167 "test_com.android.mediaprovider", 1168 "test_com.android.os.statsd", 1169 "test_com.android.permission", 1170 "test_com.android.wifi", 1171 "test_jitzygote_com.android.art", 1172 // go/keep-sorted end 1173 } 1174 1175 // TODO: b/215736885 Remove this list 1176 skipLintJavalibAllowlist = []string{ 1177 "conscrypt.module.platform.api.stubs", 1178 "conscrypt.module.public.api.stubs", 1179 "conscrypt.module.public.api.stubs.system", 1180 "conscrypt.module.public.api.stubs.module_lib", 1181 "framework-media.stubs", 1182 "framework-media.stubs.system", 1183 "framework-media.stubs.module_lib", 1184 } 1185) 1186 1187func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.TopDownMutatorContext) bool { 1188 // The allowlist contains the base apex name, so use that instead of the ApexVariationName 1189 return a.Updatable() && !android.InList(mctx.ModuleName(), skipStrictUpdatabilityLintAllowlist) 1190} 1191 1192// apexUniqueVariationsMutator checks if any dependencies use unique apex variations. If so, use 1193// unique apex variations for this module. See android/apex.go for more about unique apex variant. 1194// TODO(jiyong): move this to android/apex.go? 1195func apexUniqueVariationsMutator(mctx android.BottomUpMutatorContext) { 1196 if !mctx.Module().Enabled(mctx) { 1197 return 1198 } 1199 if am, ok := mctx.Module().(android.ApexModule); ok { 1200 android.UpdateUniqueApexVariationsForDeps(mctx, am) 1201 } 1202} 1203 1204// apexTestForDepsMutator checks if this module is a test for an apex. If so, add a dependency on 1205// the apex in order to retrieve its contents later. 1206// TODO(jiyong): move this to android/apex.go? 1207func apexTestForDepsMutator(mctx android.BottomUpMutatorContext) { 1208 if !mctx.Module().Enabled(mctx) { 1209 return 1210 } 1211 if am, ok := mctx.Module().(android.ApexModule); ok { 1212 if testFor := am.TestFor(); len(testFor) > 0 { 1213 mctx.AddFarVariationDependencies([]blueprint.Variation{ 1214 {Mutator: "os", Variation: am.Target().OsVariation()}, 1215 {"arch", "common"}, 1216 }, testForTag, testFor...) 1217 } 1218 } 1219} 1220 1221// TODO(jiyong): move this to android/apex.go? 1222func apexTestForMutator(mctx android.BottomUpMutatorContext) { 1223 if !mctx.Module().Enabled(mctx) { 1224 return 1225 } 1226 if _, ok := mctx.Module().(android.ApexModule); ok { 1227 var contents []*android.ApexContents 1228 for _, testFor := range mctx.GetDirectDepsWithTag(testForTag) { 1229 abInfo, _ := android.OtherModuleProvider(mctx, testFor, android.ApexBundleInfoProvider) 1230 contents = append(contents, abInfo.Contents) 1231 } 1232 android.SetProvider(mctx, android.ApexTestForInfoProvider, android.ApexTestForInfo{ 1233 ApexContents: contents, 1234 }) 1235 } 1236} 1237 1238// markPlatformAvailability marks whether or not a module can be available to platform. A module 1239// cannot be available to platform if 1) it is explicitly marked as not available (i.e. 1240// "//apex_available:platform" is absent) or 2) it depends on another module that isn't (or can't 1241// be) available to platform 1242// TODO(jiyong): move this to android/apex.go? 1243func markPlatformAvailability(mctx android.BottomUpMutatorContext) { 1244 // Recovery is not considered as platform 1245 if mctx.Module().InstallInRecovery() { 1246 return 1247 } 1248 1249 am, ok := mctx.Module().(android.ApexModule) 1250 if !ok { 1251 return 1252 } 1253 1254 availableToPlatform := am.AvailableFor(android.AvailableToPlatform) 1255 1256 // If any of the dep is not available to platform, this module is also considered as being 1257 // not available to platform even if it has "//apex_available:platform" 1258 mctx.VisitDirectDeps(func(child android.Module) { 1259 if !android.IsDepInSameApex(mctx, am, child) { 1260 // if the dependency crosses apex boundary, don't consider it 1261 return 1262 } 1263 if dep, ok := child.(android.ApexModule); ok && dep.NotAvailableForPlatform() { 1264 availableToPlatform = false 1265 // TODO(b/154889534) trigger an error when 'am' has 1266 // "//apex_available:platform" 1267 } 1268 }) 1269 1270 // Exception 1: check to see if the module always requires it. 1271 if am.AlwaysRequiresPlatformApexVariant() { 1272 availableToPlatform = true 1273 } 1274 1275 // Exception 2: bootstrap bionic libraries are also always available to platform 1276 if cc.InstallToBootstrap(mctx.ModuleName(), mctx.Config()) { 1277 availableToPlatform = true 1278 } 1279 1280 if !availableToPlatform { 1281 am.SetNotAvailableForPlatform() 1282 } 1283} 1284 1285type apexTransitionMutator struct{} 1286 1287func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []string { 1288 // apexBundle itself is mutated so that it and its dependencies have the same apex variant. 1289 if ai, ok := ctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) { 1290 if overridable, ok := ctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" { 1291 return []string{overridable.GetOverriddenBy()} 1292 } 1293 return []string{ai.ApexVariationName()} 1294 } else if _, ok := ctx.Module().(*OverrideApex); ok { 1295 return []string{ctx.ModuleName()} 1296 } 1297 return []string{""} 1298} 1299 1300func (a *apexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { 1301 return sourceVariation 1302} 1303 1304func (a *apexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { 1305 if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() { 1306 return android.IncomingApexTransition(ctx, incomingVariation) 1307 } else if ai, ok := ctx.Module().(ApexInfoMutator); ok { 1308 if overridable, ok := ctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" { 1309 return overridable.GetOverriddenBy() 1310 } 1311 return ai.ApexVariationName() 1312 } else if _, ok := ctx.Module().(*OverrideApex); ok { 1313 return ctx.Module().Name() 1314 } 1315 1316 return "" 1317} 1318 1319func (a *apexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { 1320 if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() { 1321 android.MutateApexTransition(ctx, variation) 1322 } 1323} 1324 1325// apexModuleTypeRequiresVariant determines whether the module supplied requires an apex specific 1326// variant. 1327func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool { 1328 if a, ok := module.(*apexBundle); ok { 1329 // TODO(jiyong): document the reason why the VNDK APEX is an exception here. 1330 return !a.vndkApex 1331 } 1332 1333 return true 1334} 1335 1336// See android.UpdateDirectlyInAnyApex 1337// TODO(jiyong): move this to android/apex.go? 1338func apexDirectlyInAnyMutator(mctx android.BottomUpMutatorContext) { 1339 if !mctx.Module().Enabled(mctx) { 1340 return 1341 } 1342 if am, ok := mctx.Module().(android.ApexModule); ok { 1343 android.UpdateDirectlyInAnyApex(mctx, am) 1344 } 1345} 1346 1347const ( 1348 // File extensions of an APEX for different packaging methods 1349 imageApexSuffix = ".apex" 1350 imageCapexSuffix = ".capex" 1351 1352 // variant names each of which is for a packaging method 1353 imageApexType = "image" 1354 1355 ext4FsType = "ext4" 1356 f2fsFsType = "f2fs" 1357 erofsFsType = "erofs" 1358) 1359 1360var _ android.DepIsInSameApex = (*apexBundle)(nil) 1361 1362// Implements android.DepInInSameApex 1363func (a *apexBundle) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool { 1364 // direct deps of an APEX bundle are all part of the APEX bundle 1365 // TODO(jiyong): shouldn't we look into the payload field of the dependencyTag? 1366 return true 1367} 1368 1369var _ android.OutputFileProducer = (*apexBundle)(nil) 1370 1371// Implements android.OutputFileProducer 1372func (a *apexBundle) OutputFiles(tag string) (android.Paths, error) { 1373 switch tag { 1374 case "", android.DefaultDistTag: 1375 // This is the default dist path. 1376 return android.Paths{a.outputFile}, nil 1377 case imageApexSuffix: 1378 // uncompressed one 1379 if a.outputApexFile != nil { 1380 return android.Paths{a.outputApexFile}, nil 1381 } 1382 fallthrough 1383 default: 1384 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 1385 } 1386} 1387 1388var _ multitree.Exportable = (*apexBundle)(nil) 1389 1390func (a *apexBundle) Exportable() bool { 1391 return true 1392} 1393 1394func (a *apexBundle) TaggedOutputs() map[string]android.Paths { 1395 ret := make(map[string]android.Paths) 1396 ret["apex"] = android.Paths{a.outputFile} 1397 return ret 1398} 1399 1400var _ cc.Coverage = (*apexBundle)(nil) 1401 1402// Implements cc.Coverage 1403func (a *apexBundle) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool { 1404 return ctx.DeviceConfig().NativeCoverageEnabled() 1405} 1406 1407// Implements cc.Coverage 1408func (a *apexBundle) SetPreventInstall() { 1409 a.properties.PreventInstall = true 1410} 1411 1412// Implements cc.Coverage 1413func (a *apexBundle) HideFromMake() { 1414 a.properties.HideFromMake = true 1415 // This HideFromMake is shadowing the ModuleBase one, call through to it for now. 1416 // TODO(ccross): untangle these 1417 a.ModuleBase.HideFromMake() 1418} 1419 1420// Implements cc.Coverage 1421func (a *apexBundle) MarkAsCoverageVariant(coverage bool) { 1422 a.properties.IsCoverageVariant = coverage 1423} 1424 1425// Implements cc.Coverage 1426func (a *apexBundle) EnableCoverageIfNeeded() {} 1427 1428var _ android.ApexBundleDepsInfoIntf = (*apexBundle)(nil) 1429 1430// Implements android.ApexBundleDepsInfoIntf 1431func (a *apexBundle) Updatable() bool { 1432 return proptools.BoolDefault(a.properties.Updatable, true) 1433} 1434 1435func (a *apexBundle) FutureUpdatable() bool { 1436 return proptools.BoolDefault(a.properties.Future_updatable, false) 1437} 1438 1439func (a *apexBundle) UsePlatformApis() bool { 1440 return proptools.BoolDefault(a.properties.Platform_apis, false) 1441} 1442 1443// getCertString returns the name of the cert that should be used to sign this APEX. This is 1444// basically from the "certificate" property, but could be overridden by the device config. 1445func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string { 1446 moduleName := ctx.ModuleName() 1447 // VNDK APEXes share the same certificate. To avoid adding a new VNDK version to the 1448 // OVERRIDE_* list, we check with the pseudo module name to see if its certificate is 1449 // overridden. 1450 if a.vndkApex { 1451 moduleName = vndkApexName 1452 } 1453 certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(moduleName) 1454 if overridden { 1455 return ":" + certificate 1456 } 1457 return String(a.overridableProperties.Certificate) 1458} 1459 1460// See the installable property 1461func (a *apexBundle) installable() bool { 1462 return !a.properties.PreventInstall && (a.properties.Installable == nil || proptools.Bool(a.properties.Installable)) 1463} 1464 1465// See the generate_hashtree property 1466func (a *apexBundle) shouldGenerateHashtree() bool { 1467 return proptools.BoolDefault(a.properties.Generate_hashtree, true) 1468} 1469 1470// See the test_only_unsigned_payload property 1471func (a *apexBundle) testOnlyShouldSkipPayloadSign() bool { 1472 return proptools.Bool(a.properties.Test_only_unsigned_payload) 1473} 1474 1475// See the test_only_force_compression property 1476func (a *apexBundle) testOnlyShouldForceCompression() bool { 1477 return proptools.Bool(a.properties.Test_only_force_compression) 1478} 1479 1480// See the dynamic_common_lib_apex property 1481func (a *apexBundle) dynamic_common_lib_apex() bool { 1482 return proptools.BoolDefault(a.properties.Dynamic_common_lib_apex, false) 1483} 1484 1485// See the list of libs to trim 1486func (a *apexBundle) libs_to_trim(ctx android.ModuleContext) []string { 1487 dclaModules := ctx.GetDirectDepsWithTag(dclaTag) 1488 if len(dclaModules) > 1 { 1489 panic(fmt.Errorf("expected exactly at most one dcla dependency, got %d", len(dclaModules))) 1490 } 1491 if len(dclaModules) > 0 { 1492 DCLAInfo, _ := android.OtherModuleProvider(ctx, dclaModules[0], DCLAInfoProvider) 1493 return DCLAInfo.ProvidedLibs 1494 } 1495 return []string{} 1496} 1497 1498// These functions are interfacing with cc/sanitizer.go. The entire APEX (along with all of its 1499// members) can be sanitized, either forcibly, or by the global configuration. For some of the 1500// sanitizers, extra dependencies can be forcibly added as well. 1501 1502func (a *apexBundle) EnableSanitizer(sanitizerName string) { 1503 if !android.InList(sanitizerName, a.properties.SanitizerNames) { 1504 a.properties.SanitizerNames = append(a.properties.SanitizerNames, sanitizerName) 1505 } 1506} 1507 1508func (a *apexBundle) IsSanitizerEnabled(config android.Config, sanitizerName string) bool { 1509 if android.InList(sanitizerName, a.properties.SanitizerNames) { 1510 return true 1511 } 1512 1513 // Then follow the global setting 1514 var globalSanitizerNames []string 1515 arches := config.SanitizeDeviceArch() 1516 if len(arches) == 0 || android.InList(a.Arch().ArchType.Name, arches) { 1517 globalSanitizerNames = config.SanitizeDevice() 1518 } 1519 return android.InList(sanitizerName, globalSanitizerNames) 1520} 1521 1522func (a *apexBundle) AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string) { 1523 // TODO(jiyong): move this info (the sanitizer name, the lib name, etc.) to cc/sanitize.go 1524 // Keep only the mechanism here. 1525 if sanitizerName == "hwaddress" && strings.HasPrefix(a.Name(), "com.android.runtime") { 1526 imageVariation := a.getImageVariation() 1527 for _, target := range ctx.MultiTargets() { 1528 if target.Arch.ArchType.Multilib == "lib64" { 1529 addDependenciesForNativeModules(ctx, ApexNativeDependencies{ 1530 Native_shared_libs: []string{"libclang_rt.hwasan"}, 1531 Tests: nil, 1532 Jni_libs: nil, 1533 Binaries: nil, 1534 }, target, imageVariation) 1535 break 1536 } 1537 } 1538 } 1539} 1540 1541// apexFileFor<Type> functions below create an apexFile struct for a given Soong module. The 1542// returned apexFile saves information about the Soong module that will be used for creating the 1543// build rules. 1544func apexFileForNativeLibrary(ctx android.BaseModuleContext, ccMod *cc.Module, handleSpecialLibs bool) apexFile { 1545 // Decide the APEX-local directory by the multilib of the library In the future, we may 1546 // query this to the module. 1547 // TODO(jiyong): use the new PackagingSpec 1548 var dirInApex string 1549 switch ccMod.Arch().ArchType.Multilib { 1550 case "lib32": 1551 dirInApex = "lib" 1552 case "lib64": 1553 dirInApex = "lib64" 1554 } 1555 if ccMod.Target().NativeBridge == android.NativeBridgeEnabled { 1556 dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath) 1557 } 1558 if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), ctx.Config()) { 1559 // Special case for Bionic libs and other libs installed with them. This is to 1560 // prevent those libs from being included in the search path 1561 // /apex/com.android.runtime/${LIB}. This exclusion is required because those libs 1562 // in the Runtime APEX are available via the legacy paths in /system/lib/. By the 1563 // init process, the libs in the APEX are bind-mounted to the legacy paths and thus 1564 // will be loaded into the default linker namespace (aka "platform" namespace). If 1565 // the libs are directly in /apex/com.android.runtime/${LIB} then the same libs will 1566 // be loaded again into the runtime linker namespace, which will result in double 1567 // loading of them, which isn't supported. 1568 dirInApex = filepath.Join(dirInApex, "bionic") 1569 } 1570 // This needs to go after the runtime APEX handling because otherwise we would get 1571 // weird paths like lib64/rel_install_path/bionic rather than 1572 // lib64/bionic/rel_install_path. 1573 dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath()) 1574 1575 fileToCopy := android.OutputFileForModule(ctx, ccMod, "") 1576 androidMkModuleName := ccMod.BaseModuleName() + ccMod.Properties.SubName 1577 return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, ccMod) 1578} 1579 1580func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFile { 1581 dirInApex := "bin" 1582 if cc.Target().NativeBridge == android.NativeBridgeEnabled { 1583 dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath) 1584 } 1585 dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath()) 1586 fileToCopy := android.OutputFileForModule(ctx, cc, "") 1587 androidMkModuleName := cc.BaseModuleName() + cc.Properties.SubName 1588 af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, cc) 1589 af.symlinks = cc.Symlinks() 1590 af.dataPaths = cc.DataPaths() 1591 return af 1592} 1593 1594func apexFileForRustExecutable(ctx android.BaseModuleContext, rustm *rust.Module) apexFile { 1595 dirInApex := "bin" 1596 if rustm.Target().NativeBridge == android.NativeBridgeEnabled { 1597 dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath) 1598 } 1599 dirInApex = filepath.Join(dirInApex, rustm.RelativeInstallPath()) 1600 fileToCopy := android.OutputFileForModule(ctx, rustm, "") 1601 androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName 1602 af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, rustm) 1603 return af 1604} 1605 1606func apexFileForRustLibrary(ctx android.BaseModuleContext, rustm *rust.Module) apexFile { 1607 // Decide the APEX-local directory by the multilib of the library 1608 // In the future, we may query this to the module. 1609 var dirInApex string 1610 switch rustm.Arch().ArchType.Multilib { 1611 case "lib32": 1612 dirInApex = "lib" 1613 case "lib64": 1614 dirInApex = "lib64" 1615 } 1616 if rustm.Target().NativeBridge == android.NativeBridgeEnabled { 1617 dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath) 1618 } 1619 dirInApex = filepath.Join(dirInApex, rustm.RelativeInstallPath()) 1620 fileToCopy := android.OutputFileForModule(ctx, rustm, "") 1621 androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName 1622 return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, rustm) 1623} 1624 1625func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFile { 1626 dirInApex := filepath.Join("bin", sh.SubDir()) 1627 if sh.Target().NativeBridge == android.NativeBridgeEnabled { 1628 dirInApex = filepath.Join(dirInApex, sh.Target().NativeBridgeRelativePath) 1629 } 1630 fileToCopy := sh.OutputFile() 1631 af := newApexFile(ctx, fileToCopy, sh.BaseModuleName(), dirInApex, shBinary, sh) 1632 af.symlinks = sh.Symlinks() 1633 return af 1634} 1635 1636func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, outputFile android.Path) apexFile { 1637 dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir()) 1638 makeModuleName := strings.ReplaceAll(filepath.Join(dirInApex, outputFile.Base()), "/", "_") 1639 return newApexFile(ctx, outputFile, makeModuleName, dirInApex, etc, prebuilt) 1640} 1641 1642func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile { 1643 dirInApex := filepath.Join("etc", config.SubDir()) 1644 fileToCopy := config.CompatConfig() 1645 return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, config) 1646} 1647 1648// javaModule is an interface to handle all Java modules (java_library, dex_import, etc) in the same 1649// way. 1650type javaModule interface { 1651 android.Module 1652 BaseModuleName() string 1653 DexJarBuildPath(ctx android.ModuleErrorfContext) java.OptionalDexJarPath 1654 JacocoReportClassesFile() android.Path 1655 LintDepSets() java.LintDepSets 1656 Stem() string 1657} 1658 1659var _ javaModule = (*java.Library)(nil) 1660var _ javaModule = (*java.Import)(nil) 1661var _ javaModule = (*java.SdkLibrary)(nil) 1662var _ javaModule = (*java.DexImport)(nil) 1663var _ javaModule = (*java.SdkLibraryImport)(nil) 1664 1665// apexFileForJavaModule creates an apexFile for a java module's dex implementation jar. 1666func apexFileForJavaModule(ctx android.ModuleContext, module javaModule) apexFile { 1667 return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath(ctx).PathOrNil()) 1668} 1669 1670// apexFileForJavaModuleWithFile creates an apexFile for a java module with the supplied file. 1671func apexFileForJavaModuleWithFile(ctx android.ModuleContext, module javaModule, dexImplementationJar android.Path) apexFile { 1672 dirInApex := "javalib" 1673 af := newApexFile(ctx, dexImplementationJar, module.BaseModuleName(), dirInApex, javaSharedLib, module) 1674 af.jacocoReportClassesFile = module.JacocoReportClassesFile() 1675 af.lintDepSets = module.LintDepSets() 1676 af.customStem = module.Stem() + ".jar" 1677 // TODO: b/338641779 - Remove special casing of sdkLibrary once bcpf and sscpf depends 1678 // on the implementation library 1679 if sdkLib, ok := module.(*java.SdkLibrary); ok { 1680 for _, install := range sdkLib.BuiltInstalledForApex() { 1681 af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName()) 1682 install.PackageFile(ctx) 1683 } 1684 } else if dexpreopter, ok := module.(java.DexpreopterInterface); ok { 1685 for _, install := range dexpreopter.DexpreoptBuiltInstalledForApex() { 1686 af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName()) 1687 install.PackageFile(ctx) 1688 } 1689 } 1690 return af 1691} 1692 1693func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile { 1694 if dexpreopter, ok := module.(java.DexpreopterInterface); ok { 1695 if profilePathOnHost := dexpreopter.OutputProfilePathOnHost(); profilePathOnHost != nil { 1696 dirInApex := "javalib" 1697 af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil) 1698 af.customStem = module.Stem() + ".jar.prof" 1699 return &af 1700 } 1701 } 1702 return nil 1703} 1704 1705// androidApp is an interface to handle all app modules (android_app, android_app_import, etc.) in 1706// the same way. 1707type androidApp interface { 1708 android.Module 1709 Privileged() bool 1710 InstallApkName() string 1711 OutputFile() android.Path 1712 JacocoReportClassesFile() android.Path 1713 Certificate() java.Certificate 1714 BaseModuleName() string 1715 LintDepSets() java.LintDepSets 1716 PrivAppAllowlist() android.OptionalPath 1717} 1718 1719var _ androidApp = (*java.AndroidApp)(nil) 1720var _ androidApp = (*java.AndroidAppImport)(nil) 1721 1722func sanitizedBuildIdForPath(ctx android.BaseModuleContext) string { 1723 buildId := ctx.Config().BuildId() 1724 1725 // The build ID is used as a suffix for a filename, so ensure that 1726 // the set of characters being used are sanitized. 1727 // - any word character: [a-zA-Z0-9_] 1728 // - dots: . 1729 // - dashes: - 1730 validRegex := regexp.MustCompile(`^[\w\.\-\_]+$`) 1731 if !validRegex.MatchString(buildId) { 1732 ctx.ModuleErrorf("Unable to use build id %s as filename suffix, valid characters are [a-z A-Z 0-9 _ . -].", buildId) 1733 } 1734 return buildId 1735} 1736 1737func apexFilesForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) []apexFile { 1738 appDir := "app" 1739 if aapp.Privileged() { 1740 appDir = "priv-app" 1741 } 1742 1743 // TODO(b/224589412, b/226559955): Ensure that the subdirname is suffixed 1744 // so that PackageManager correctly invalidates the existing installed apk 1745 // in favour of the new APK-in-APEX. See bugs for more information. 1746 dirInApex := filepath.Join(appDir, aapp.InstallApkName()+"@"+sanitizedBuildIdForPath(ctx)) 1747 fileToCopy := aapp.OutputFile() 1748 1749 af := newApexFile(ctx, fileToCopy, aapp.BaseModuleName(), dirInApex, app, aapp) 1750 af.jacocoReportClassesFile = aapp.JacocoReportClassesFile() 1751 af.lintDepSets = aapp.LintDepSets() 1752 af.certificate = aapp.Certificate() 1753 1754 if app, ok := aapp.(interface { 1755 OverriddenManifestPackageName() string 1756 }); ok { 1757 af.overriddenPackageName = app.OverriddenManifestPackageName() 1758 } 1759 1760 apexFiles := []apexFile{} 1761 1762 if allowlist := aapp.PrivAppAllowlist(); allowlist.Valid() { 1763 dirInApex := filepath.Join("etc", "permissions") 1764 privAppAllowlist := newApexFile(ctx, allowlist.Path(), aapp.BaseModuleName()+"_privapp", dirInApex, etc, aapp) 1765 apexFiles = append(apexFiles, privAppAllowlist) 1766 } 1767 1768 apexFiles = append(apexFiles, af) 1769 1770 return apexFiles 1771} 1772 1773func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, rro java.RuntimeResourceOverlayModule) apexFile { 1774 rroDir := "overlay" 1775 dirInApex := filepath.Join(rroDir, rro.Theme()) 1776 fileToCopy := rro.OutputFile() 1777 af := newApexFile(ctx, fileToCopy, rro.Name(), dirInApex, app, rro) 1778 af.certificate = rro.Certificate() 1779 1780 if a, ok := rro.(interface { 1781 OverriddenManifestPackageName() string 1782 }); ok { 1783 af.overriddenPackageName = a.OverriddenManifestPackageName() 1784 } 1785 return af 1786} 1787 1788func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram bpf.BpfModule) apexFile { 1789 dirInApex := filepath.Join("etc", "bpf", apex_sub_dir) 1790 return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram) 1791} 1792 1793func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, fs filesystem.Filesystem) apexFile { 1794 dirInApex := filepath.Join("etc", "fs") 1795 return newApexFile(ctx, buildFile, buildFile.Base(), dirInApex, etc, fs) 1796} 1797 1798// WalkPayloadDeps visits dependencies that contributes to the payload of this APEX. For each of the 1799// visited module, the `do` callback is executed. Returning true in the callback continues the visit 1800// to the child modules. Returning false makes the visit to continue in the sibling or the parent 1801// modules. This is used in check* functions below. 1802func (a *apexBundle) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) { 1803 ctx.WalkDeps(func(child, parent android.Module) bool { 1804 am, ok := child.(android.ApexModule) 1805 if !ok || !am.CanHaveApexVariants() { 1806 return false 1807 } 1808 1809 // Filter-out unwanted depedendencies 1810 depTag := ctx.OtherModuleDependencyTag(child) 1811 if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { 1812 return false 1813 } 1814 if dt, ok := depTag.(*dependencyTag); ok && !dt.payload { 1815 return false 1816 } 1817 if depTag == android.RequiredDepTag { 1818 return false 1819 } 1820 1821 ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider) 1822 externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants) 1823 1824 // Visit actually 1825 return do(ctx, parent, am, externalDep) 1826 }) 1827} 1828 1829// filesystem type of the apex_payload.img inside the APEX. Currently, ext4 and f2fs are supported. 1830type fsType int 1831 1832const ( 1833 ext4 fsType = iota 1834 f2fs 1835 erofs 1836) 1837 1838func (f fsType) string() string { 1839 switch f { 1840 case ext4: 1841 return ext4FsType 1842 case f2fs: 1843 return f2fsFsType 1844 case erofs: 1845 return erofsFsType 1846 default: 1847 panic(fmt.Errorf("unknown APEX payload type %d", f)) 1848 } 1849} 1850 1851func (a *apexBundle) setCompression(ctx android.ModuleContext) { 1852 if a.testOnlyShouldForceCompression() { 1853 a.isCompressed = true 1854 } else { 1855 a.isCompressed = ctx.Config().ApexCompressionEnabled() && a.isCompressable() 1856 } 1857} 1858 1859func (a *apexBundle) setSystemLibLink(ctx android.ModuleContext) { 1860 // Optimization. If we are building bundled APEX, for the files that are gathered due to the 1861 // transitive dependencies, don't place them inside the APEX, but place a symlink pointing 1862 // the same library in the system partition, thus effectively sharing the same libraries 1863 // across the APEX boundary. For unbundled APEX, all the gathered files are actually placed 1864 // in the APEX. 1865 a.linkToSystemLib = !ctx.Config().UnbundledBuild() && a.installable() 1866 1867 // APEXes targeting other than system/system_ext partitions use vendor/product variants. 1868 // So we can't link them to /system/lib libs which are core variants. 1869 if a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { 1870 a.linkToSystemLib = false 1871 } 1872 1873 forced := ctx.Config().ForceApexSymlinkOptimization() 1874 updatable := a.Updatable() || a.FutureUpdatable() 1875 1876 // We don't need the optimization for updatable APEXes, as it might give false signal 1877 // to the system health when the APEXes are still bundled (b/149805758). 1878 if !forced && updatable { 1879 a.linkToSystemLib = false 1880 } 1881} 1882 1883func (a *apexBundle) setPayloadFsType(ctx android.ModuleContext) { 1884 switch proptools.StringDefault(a.properties.Payload_fs_type, ext4FsType) { 1885 case ext4FsType: 1886 a.payloadFsType = ext4 1887 case f2fsFsType: 1888 a.payloadFsType = f2fs 1889 case erofsFsType: 1890 a.payloadFsType = erofs 1891 default: 1892 ctx.PropertyErrorf("payload_fs_type", "%q is not a valid filesystem for apex [ext4, f2fs, erofs]", *a.properties.Payload_fs_type) 1893 } 1894} 1895 1896func (a *apexBundle) isCompressable() bool { 1897 return proptools.BoolDefault(a.overridableProperties.Compressible, false) && !a.testApex 1898} 1899 1900func (a *apexBundle) commonBuildActions(ctx android.ModuleContext) bool { 1901 a.checkApexAvailability(ctx) 1902 a.checkUpdatable(ctx) 1903 a.CheckMinSdkVersion(ctx) 1904 a.checkStaticLinkingToStubLibraries(ctx) 1905 a.checkStaticExecutables(ctx) 1906 if len(a.properties.Tests) > 0 && !a.testApex { 1907 ctx.PropertyErrorf("tests", "property allowed only in apex_test module type") 1908 return false 1909 } 1910 return true 1911} 1912 1913type visitorContext struct { 1914 // all the files that will be included in this APEX 1915 filesInfo []apexFile 1916 1917 // native lib dependencies 1918 provideNativeLibs []string 1919 requireNativeLibs []string 1920 1921 handleSpecialLibs bool 1922 1923 // if true, raise error on duplicate apexFile 1924 checkDuplicate bool 1925 1926 // visitor skips these from this list of module names 1927 unwantedTransitiveDeps []string 1928 1929 aconfigFiles []android.Path 1930} 1931 1932func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) { 1933 encountered := make(map[string]apexFile) 1934 for _, f := range vctx.filesInfo { 1935 // Skips unwanted transitive deps. This happens, for example, with Rust binaries with prefer_rlib:true. 1936 // TODO(b/295593640) 1937 // Needs additional verification for the resulting APEX to ensure that skipped artifacts don't make problems. 1938 // For example, DT_NEEDED modules should be found within the APEX unless they are marked in `requiredNativeLibs`. 1939 if f.transitiveDep && f.module != nil && android.InList(mctx.OtherModuleName(f.module), vctx.unwantedTransitiveDeps) { 1940 continue 1941 } 1942 dest := filepath.Join(f.installDir, f.builtFile.Base()) 1943 if e, ok := encountered[dest]; !ok { 1944 encountered[dest] = f 1945 } else { 1946 if vctx.checkDuplicate && f.builtFile.String() != e.builtFile.String() { 1947 mctx.ModuleErrorf("apex file %v is provided by two different files %v and %v", 1948 dest, e.builtFile, f.builtFile) 1949 return 1950 } 1951 // If a module is directly included and also transitively depended on 1952 // consider it as directly included. 1953 e.transitiveDep = e.transitiveDep && f.transitiveDep 1954 // If a module is added as both a JNI library and a regular shared library, consider it as a 1955 // JNI library. 1956 e.isJniLib = e.isJniLib || f.isJniLib 1957 encountered[dest] = e 1958 } 1959 } 1960 vctx.filesInfo = vctx.filesInfo[:0] 1961 for _, v := range encountered { 1962 vctx.filesInfo = append(vctx.filesInfo, v) 1963 } 1964 sort.Slice(vctx.filesInfo, func(i, j int) bool { 1965 // Sort by destination path so as to ensure consistent ordering even if the source of the files 1966 // changes. 1967 return vctx.filesInfo[i].path() < vctx.filesInfo[j].path() 1968 }) 1969} 1970 1971func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent blueprint.Module) bool { 1972 depTag := ctx.OtherModuleDependencyTag(child) 1973 if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { 1974 return false 1975 } 1976 if mod, ok := child.(android.Module); ok && !mod.Enabled(ctx) { 1977 return false 1978 } 1979 depName := ctx.OtherModuleName(child) 1980 if _, isDirectDep := parent.(*apexBundle); isDirectDep { 1981 switch depTag { 1982 case sharedLibTag, jniLibTag: 1983 isJniLib := depTag == jniLibTag 1984 propertyName := "native_shared_libs" 1985 if isJniLib { 1986 propertyName = "jni_libs" 1987 } 1988 switch ch := child.(type) { 1989 case *cc.Module: 1990 if ch.IsStubs() { 1991 ctx.PropertyErrorf(propertyName, "%q is a stub. Remove it from the list.", depName) 1992 } 1993 fi := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs) 1994 fi.isJniLib = isJniLib 1995 vctx.filesInfo = append(vctx.filesInfo, fi) 1996 addAconfigFiles(vctx, ctx, child) 1997 // Collect the list of stub-providing libs except: 1998 // - VNDK libs are only for vendors 1999 // - bootstrap bionic libs are treated as provided by system 2000 if ch.HasStubsVariants() && !a.vndkApex && !cc.InstallToBootstrap(ch.BaseModuleName(), ctx.Config()) { 2001 vctx.provideNativeLibs = append(vctx.provideNativeLibs, fi.stem()) 2002 } 2003 return true // track transitive dependencies 2004 case *rust.Module: 2005 fi := apexFileForRustLibrary(ctx, ch) 2006 fi.isJniLib = isJniLib 2007 vctx.filesInfo = append(vctx.filesInfo, fi) 2008 addAconfigFiles(vctx, ctx, child) 2009 return true // track transitive dependencies 2010 default: 2011 ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName) 2012 } 2013 case executableTag: 2014 switch ch := child.(type) { 2015 case *cc.Module: 2016 vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch)) 2017 addAconfigFiles(vctx, ctx, child) 2018 return true // track transitive dependencies 2019 case *rust.Module: 2020 vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, ch)) 2021 addAconfigFiles(vctx, ctx, child) 2022 return true // track transitive dependencies 2023 default: 2024 ctx.PropertyErrorf("binaries", 2025 "%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, nor (host) bootstrap_go_binary", depName) 2026 } 2027 case shBinaryTag: 2028 if csh, ok := child.(*sh.ShBinary); ok { 2029 vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, csh)) 2030 } else { 2031 ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName) 2032 } 2033 case bcpfTag: 2034 _, ok := child.(*java.BootclasspathFragmentModule) 2035 if !ok { 2036 ctx.PropertyErrorf("bootclasspath_fragments", "%q is not a bootclasspath_fragment module", depName) 2037 return false 2038 } 2039 2040 vctx.filesInfo = append(vctx.filesInfo, apexBootclasspathFragmentFiles(ctx, child)...) 2041 return true 2042 case sscpfTag: 2043 if _, ok := child.(*java.SystemServerClasspathModule); !ok { 2044 ctx.PropertyErrorf("systemserverclasspath_fragments", 2045 "%q is not a systemserverclasspath_fragment module", depName) 2046 return false 2047 } 2048 if af := apexClasspathFragmentProtoFile(ctx, child); af != nil { 2049 vctx.filesInfo = append(vctx.filesInfo, *af) 2050 } 2051 return true 2052 case javaLibTag: 2053 switch child.(type) { 2054 case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import: 2055 af := apexFileForJavaModule(ctx, child.(javaModule)) 2056 if !af.ok() { 2057 ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName) 2058 return false 2059 } 2060 vctx.filesInfo = append(vctx.filesInfo, af) 2061 addAconfigFiles(vctx, ctx, child) 2062 return true // track transitive dependencies 2063 default: 2064 ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child)) 2065 } 2066 case androidAppTag: 2067 switch ap := child.(type) { 2068 case *java.AndroidApp: 2069 vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...) 2070 addAconfigFiles(vctx, ctx, child) 2071 return true // track transitive dependencies 2072 case *java.AndroidAppImport: 2073 vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...) 2074 addAconfigFiles(vctx, ctx, child) 2075 case *java.AndroidTestHelperApp: 2076 vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...) 2077 addAconfigFiles(vctx, ctx, child) 2078 case *java.AndroidAppSet: 2079 appDir := "app" 2080 if ap.Privileged() { 2081 appDir = "priv-app" 2082 } 2083 // TODO(b/224589412, b/226559955): Ensure that the dirname is 2084 // suffixed so that PackageManager correctly invalidates the 2085 // existing installed apk in favour of the new APK-in-APEX. 2086 // See bugs for more information. 2087 appDirName := filepath.Join(appDir, ap.BaseModuleName()+"@"+sanitizedBuildIdForPath(ctx)) 2088 af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(), appDirName, appSet, ap) 2089 af.certificate = java.PresignedCertificate 2090 vctx.filesInfo = append(vctx.filesInfo, af) 2091 addAconfigFiles(vctx, ctx, child) 2092 default: 2093 ctx.PropertyErrorf("apps", "%q is not an android_app module", depName) 2094 } 2095 case rroTag: 2096 if rro, ok := child.(java.RuntimeResourceOverlayModule); ok { 2097 vctx.filesInfo = append(vctx.filesInfo, apexFileForRuntimeResourceOverlay(ctx, rro)) 2098 } else { 2099 ctx.PropertyErrorf("rros", "%q is not an runtime_resource_overlay module", depName) 2100 } 2101 case bpfTag: 2102 if bpfProgram, ok := child.(bpf.BpfModule); ok { 2103 filesToCopy := android.OutputFilesForModule(ctx, bpfProgram, "") 2104 apex_sub_dir := bpfProgram.SubDir() 2105 for _, bpfFile := range filesToCopy { 2106 vctx.filesInfo = append(vctx.filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, bpfProgram)) 2107 } 2108 } else { 2109 ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName) 2110 } 2111 case fsTag: 2112 if fs, ok := child.(filesystem.Filesystem); ok { 2113 vctx.filesInfo = append(vctx.filesInfo, apexFileForFilesystem(ctx, fs.OutputPath(), fs)) 2114 } else { 2115 ctx.PropertyErrorf("filesystems", "%q is not a filesystem module", depName) 2116 } 2117 case prebuiltTag: 2118 if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok { 2119 filesToCopy := android.OutputFilesForModule(ctx, prebuilt, "") 2120 for _, etcFile := range filesToCopy { 2121 vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile)) 2122 } 2123 addAconfigFiles(vctx, ctx, child) 2124 } else { 2125 ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName) 2126 } 2127 case compatConfigTag: 2128 if compatConfig, ok := child.(java.PlatformCompatConfigIntf); ok { 2129 vctx.filesInfo = append(vctx.filesInfo, apexFileForCompatConfig(ctx, compatConfig, depName)) 2130 } else { 2131 ctx.PropertyErrorf("compat_configs", "%q is not a platform_compat_config module", depName) 2132 } 2133 case testTag: 2134 if ccTest, ok := child.(*cc.Module); ok { 2135 if ccTest.IsTestPerSrcAllTestsVariation() { 2136 // Multiple-output test module (where `test_per_src: true`). 2137 // 2138 // `ccTest` is the "" ("all tests") variation of a `test_per_src` module. 2139 // We do not add this variation to `filesInfo`, as it has no output; 2140 // however, we do add the other variations of this module as indirect 2141 // dependencies (see below). 2142 } else { 2143 // Single-output test module (where `test_per_src: false`). 2144 af := apexFileForExecutable(ctx, ccTest) 2145 af.class = nativeTest 2146 vctx.filesInfo = append(vctx.filesInfo, af) 2147 addAconfigFiles(vctx, ctx, child) 2148 } 2149 return true // track transitive dependencies 2150 } else { 2151 ctx.PropertyErrorf("tests", "%q is not a cc module", depName) 2152 } 2153 case keyTag: 2154 if key, ok := child.(*apexKey); ok { 2155 a.privateKeyFile = key.privateKeyFile 2156 a.publicKeyFile = key.publicKeyFile 2157 } else { 2158 ctx.PropertyErrorf("key", "%q is not an apex_key module", depName) 2159 } 2160 case certificateTag: 2161 if dep, ok := child.(*java.AndroidAppCertificate); ok { 2162 a.containerCertificateFile = dep.Certificate.Pem 2163 a.containerPrivateKeyFile = dep.Certificate.Key 2164 } else { 2165 ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName) 2166 } 2167 } 2168 return false 2169 } 2170 2171 if a.vndkApex { 2172 return false 2173 } 2174 2175 // indirect dependencies 2176 am, ok := child.(android.ApexModule) 2177 if !ok { 2178 return false 2179 } 2180 // We cannot use a switch statement on `depTag` here as the checked 2181 // tags used below are private (e.g. `cc.sharedDepTag`). 2182 if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) { 2183 if ch, ok := child.(*cc.Module); ok { 2184 af := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs) 2185 af.transitiveDep = true 2186 2187 abInfo, _ := android.ModuleProvider(ctx, android.ApexBundleInfoProvider) 2188 if !abInfo.Contents.DirectlyInApex(depName) && (ch.IsStubs() || ch.HasStubsVariants()) { 2189 // If the dependency is a stubs lib, don't include it in this APEX, 2190 // but make sure that the lib is installed on the device. 2191 // In case no APEX is having the lib, the lib is installed to the system 2192 // partition. 2193 // 2194 // Always include if we are a host-apex however since those won't have any 2195 // system libraries. 2196 // 2197 // Skip the dependency in unbundled builds where the device image is not 2198 // being built. 2199 if ch.IsStubsImplementationRequired() && !am.DirectlyInAnyApex() && !ctx.Config().UnbundledBuild() { 2200 // we need a module name for Make 2201 name := ch.ImplementationModuleNameForMake(ctx) + ch.Properties.SubName 2202 if !android.InList(name, a.makeModulesToInstall) { 2203 a.makeModulesToInstall = append(a.makeModulesToInstall, name) 2204 } 2205 } 2206 vctx.requireNativeLibs = append(vctx.requireNativeLibs, af.stem()) 2207 // Don't track further 2208 return false 2209 } 2210 2211 // If the dep is not considered to be in the same 2212 // apex, don't add it to filesInfo so that it is not 2213 // included in this APEX. 2214 // TODO(jiyong): move this to at the top of the 2215 // else-if clause for the indirect dependencies. 2216 // Currently, that's impossible because we would 2217 // like to record requiredNativeLibs even when 2218 // DepIsInSameAPex is false. We also shouldn't do 2219 // this for host. 2220 // 2221 // TODO(jiyong): explain why the same module is passed in twice. 2222 // Switching the first am to parent breaks lots of tests. 2223 if !android.IsDepInSameApex(ctx, am, am) { 2224 return false 2225 } 2226 2227 vctx.filesInfo = append(vctx.filesInfo, af) 2228 addAconfigFiles(vctx, ctx, child) 2229 return true // track transitive dependencies 2230 } else if rm, ok := child.(*rust.Module); ok { 2231 af := apexFileForRustLibrary(ctx, rm) 2232 af.transitiveDep = true 2233 vctx.filesInfo = append(vctx.filesInfo, af) 2234 addAconfigFiles(vctx, ctx, child) 2235 return true // track transitive dependencies 2236 } 2237 } else if cc.IsTestPerSrcDepTag(depTag) { 2238 if ch, ok := child.(*cc.Module); ok { 2239 af := apexFileForExecutable(ctx, ch) 2240 // Handle modules created as `test_per_src` variations of a single test module: 2241 // use the name of the generated test binary (`fileToCopy`) instead of the name 2242 // of the original test module (`depName`, shared by all `test_per_src` 2243 // variations of that module). 2244 af.androidMkModuleName = filepath.Base(af.builtFile.String()) 2245 // these are not considered transitive dep 2246 af.transitiveDep = false 2247 vctx.filesInfo = append(vctx.filesInfo, af) 2248 return true // track transitive dependencies 2249 } 2250 } else if cc.IsHeaderDepTag(depTag) { 2251 // nothing 2252 } else if java.IsJniDepTag(depTag) { 2253 // Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps 2254 } else if java.IsXmlPermissionsFileDepTag(depTag) { 2255 if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok { 2256 filesToCopy := android.OutputFilesForModule(ctx, prebuilt, "") 2257 for _, etcFile := range filesToCopy { 2258 vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile)) 2259 } 2260 } 2261 } else if rust.IsDylibDepTag(depTag) { 2262 if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() { 2263 af := apexFileForRustLibrary(ctx, rustm) 2264 af.transitiveDep = true 2265 vctx.filesInfo = append(vctx.filesInfo, af) 2266 addAconfigFiles(vctx, ctx, child) 2267 return true // track transitive dependencies 2268 } 2269 } else if rust.IsRlibDepTag(depTag) { 2270 // Rlib is statically linked, but it might have shared lib 2271 // dependencies. Track them. 2272 return true 2273 } else if java.IsBootclasspathFragmentContentDepTag(depTag) { 2274 // Add the contents of the bootclasspath fragment to the apex. 2275 switch child.(type) { 2276 case *java.Library, *java.SdkLibrary: 2277 javaModule := child.(javaModule) 2278 af := apexFileForBootclasspathFragmentContentModule(ctx, parent, javaModule) 2279 if !af.ok() { 2280 ctx.PropertyErrorf("bootclasspath_fragments", 2281 "bootclasspath_fragment content %q is not configured to be compiled into dex", depName) 2282 return false 2283 } 2284 vctx.filesInfo = append(vctx.filesInfo, af) 2285 addAconfigFiles(vctx, ctx, child) 2286 return true // track transitive dependencies 2287 default: 2288 ctx.PropertyErrorf("bootclasspath_fragments", 2289 "bootclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child)) 2290 } 2291 } else if java.IsSystemServerClasspathFragmentContentDepTag(depTag) { 2292 // Add the contents of the systemserverclasspath fragment to the apex. 2293 switch child.(type) { 2294 case *java.Library, *java.SdkLibrary: 2295 af := apexFileForJavaModule(ctx, child.(javaModule)) 2296 vctx.filesInfo = append(vctx.filesInfo, af) 2297 if profileAf := apexFileForJavaModuleProfile(ctx, child.(javaModule)); profileAf != nil { 2298 vctx.filesInfo = append(vctx.filesInfo, *profileAf) 2299 } 2300 addAconfigFiles(vctx, ctx, child) 2301 return true // track transitive dependencies 2302 default: 2303 ctx.PropertyErrorf("systemserverclasspath_fragments", 2304 "systemserverclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child)) 2305 } 2306 } else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok { 2307 // nothing 2308 } else if depTag == android.DarwinUniversalVariantTag { 2309 // nothing 2310 } else if depTag == android.RequiredDepTag { 2311 // nothing 2312 } else if am.CanHaveApexVariants() && am.IsInstallableToApex() { 2313 ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName) 2314 } 2315 return false 2316} 2317 2318func addAconfigFiles(vctx *visitorContext, ctx android.ModuleContext, module blueprint.Module) { 2319 if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigPropagatingProviderKey); ok { 2320 if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil { 2321 vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...) 2322 } 2323 } 2324 2325 validationFlag := ctx.DeviceConfig().AconfigContainerValidation() 2326 if validationFlag == "error" || validationFlag == "warning" { 2327 android.VerifyAconfigBuildMode(ctx, ctx.ModuleName(), module, validationFlag == "error") 2328 } 2329} 2330 2331func (a *apexBundle) shouldCheckDuplicate(ctx android.ModuleContext) bool { 2332 // TODO(b/263308293) remove this 2333 if a.properties.IsCoverageVariant { 2334 return false 2335 } 2336 if ctx.DeviceConfig().DeviceArch() == "" { 2337 return false 2338 } 2339 return true 2340} 2341 2342// Creates build rules for an APEX. It consists of the following major steps: 2343// 2344// 1) do some validity checks such as apex_available, min_sdk_version, etc. 2345// 2) traverse the dependency tree to collect apexFile structs from them. 2346// 3) some fields in apexBundle struct are configured 2347// 4) generate the build rules to create the APEX. This is mostly done in builder.go. 2348func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { 2349 //////////////////////////////////////////////////////////////////////////////////////////// 2350 // 1) do some validity checks such as apex_available, min_sdk_version, etc. 2351 if !a.commonBuildActions(ctx) { 2352 return 2353 } 2354 //////////////////////////////////////////////////////////////////////////////////////////// 2355 // 2) traverse the dependency tree to collect apexFile structs from them. 2356 2357 // TODO(jiyong): do this using WalkPayloadDeps 2358 // TODO(jiyong): make this clean!!! 2359 vctx := visitorContext{ 2360 handleSpecialLibs: !android.Bool(a.properties.Ignore_system_library_special_case), 2361 checkDuplicate: a.shouldCheckDuplicate(ctx), 2362 unwantedTransitiveDeps: a.properties.Unwanted_transitive_deps, 2363 } 2364 ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) }) 2365 vctx.normalizeFileInfo(ctx) 2366 if a.privateKeyFile == nil { 2367 if ctx.Config().AllowMissingDependencies() { 2368 // TODO(b/266099037): a better approach for slim manifests. 2369 ctx.AddMissingDependencies([]string{String(a.overridableProperties.Key)}) 2370 // Create placeholder paths for later stages that expect to see those paths, 2371 // though they won't be used. 2372 var unusedPath = android.PathForModuleOut(ctx, "nonexistentprivatekey") 2373 ctx.Build(pctx, android.BuildParams{ 2374 Rule: android.ErrorRule, 2375 Output: unusedPath, 2376 Args: map[string]string{ 2377 "error": "Private key not available", 2378 }, 2379 }) 2380 a.privateKeyFile = unusedPath 2381 } else { 2382 ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.overridableProperties.Key)) 2383 return 2384 } 2385 } 2386 2387 if a.publicKeyFile == nil { 2388 if ctx.Config().AllowMissingDependencies() { 2389 // TODO(b/266099037): a better approach for slim manifests. 2390 ctx.AddMissingDependencies([]string{String(a.overridableProperties.Key)}) 2391 // Create placeholder paths for later stages that expect to see those paths, 2392 // though they won't be used. 2393 var unusedPath = android.PathForModuleOut(ctx, "nonexistentpublickey") 2394 ctx.Build(pctx, android.BuildParams{ 2395 Rule: android.ErrorRule, 2396 Output: unusedPath, 2397 Args: map[string]string{ 2398 "error": "Public key not available", 2399 }, 2400 }) 2401 a.publicKeyFile = unusedPath 2402 } else { 2403 ctx.PropertyErrorf("key", "public_key for %q could not be found", String(a.overridableProperties.Key)) 2404 return 2405 } 2406 } 2407 2408 //////////////////////////////////////////////////////////////////////////////////////////// 2409 // 3) some fields in apexBundle struct are configured 2410 a.installDir = android.PathForModuleInstall(ctx, "apex") 2411 a.filesInfo = vctx.filesInfo 2412 a.aconfigFiles = android.FirstUniquePaths(vctx.aconfigFiles) 2413 2414 a.setPayloadFsType(ctx) 2415 a.setSystemLibLink(ctx) 2416 a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx) 2417 2418 //////////////////////////////////////////////////////////////////////////////////////////// 2419 // 4) generate the build rules to create the APEX. This is done in builder.go. 2420 a.buildManifest(ctx, vctx.provideNativeLibs, vctx.requireNativeLibs) 2421 a.buildApex(ctx) 2422 a.buildApexDependencyInfo(ctx) 2423 a.buildLintReports(ctx) 2424 2425 // Set a provider for dexpreopt of bootjars 2426 a.provideApexExportsInfo(ctx) 2427 2428 a.providePrebuiltInfo(ctx) 2429} 2430 2431// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file 2432// with information about whether source or prebuilt of an apex was used during the build. 2433func (a *apexBundle) providePrebuiltInfo(ctx android.ModuleContext) { 2434 info := android.PrebuiltInfo{ 2435 Name: a.Name(), 2436 Is_prebuilt: false, 2437 } 2438 android.SetProvider(ctx, android.PrebuiltInfoProvider, info) 2439} 2440 2441// Set a provider containing information about the jars and .prof provided by the apex 2442// Apexes built from source retrieve this information by visiting `bootclasspath_fragments` 2443// Used by dex_bootjars to generate the boot image 2444func (a *apexBundle) provideApexExportsInfo(ctx android.ModuleContext) { 2445 ctx.VisitDirectDepsWithTag(bcpfTag, func(child android.Module) { 2446 if info, ok := android.OtherModuleProvider(ctx, child, java.BootclasspathFragmentApexContentInfoProvider); ok { 2447 exports := android.ApexExportsInfo{ 2448 ApexName: a.ApexVariationName(), 2449 ProfilePathOnHost: info.ProfilePathOnHost(), 2450 LibraryNameToDexJarPathOnHost: info.DexBootJarPathMap(), 2451 } 2452 android.SetProvider(ctx, android.ApexExportsInfoProvider, exports) 2453 } 2454 }) 2455} 2456 2457// apexBootclasspathFragmentFiles returns the list of apexFile structures defining the files that 2458// the bootclasspath_fragment contributes to the apex. 2459func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint.Module) []apexFile { 2460 bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, module, java.BootclasspathFragmentApexContentInfoProvider) 2461 var filesToAdd []apexFile 2462 2463 // Add classpaths.proto config. 2464 if af := apexClasspathFragmentProtoFile(ctx, module); af != nil { 2465 filesToAdd = append(filesToAdd, *af) 2466 } 2467 2468 pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex() 2469 if pathInApex != "" { 2470 pathOnHost := bootclasspathFragmentInfo.ProfilePathOnHost() 2471 tempPath := android.PathForModuleOut(ctx, "boot_image_profile", pathInApex) 2472 2473 if pathOnHost != nil { 2474 // We need to copy the profile to a temporary path with the right filename because the apexer 2475 // will take the filename as is. 2476 ctx.Build(pctx, android.BuildParams{ 2477 Rule: android.Cp, 2478 Input: pathOnHost, 2479 Output: tempPath, 2480 }) 2481 } else { 2482 // At this point, the boot image profile cannot be generated. It is probably because the boot 2483 // image profile source file does not exist on the branch, or it is not available for the 2484 // current build target. 2485 // However, we cannot enforce the boot image profile to be generated because some build 2486 // targets (such as module SDK) do not need it. It is only needed when the APEX is being 2487 // built. Therefore, we create an error rule so that an error will occur at the ninja phase 2488 // only if the APEX is being built. 2489 ctx.Build(pctx, android.BuildParams{ 2490 Rule: android.ErrorRule, 2491 Output: tempPath, 2492 Args: map[string]string{ 2493 "error": "Boot image profile cannot be generated", 2494 }, 2495 }) 2496 } 2497 2498 androidMkModuleName := filepath.Base(pathInApex) 2499 af := newApexFile(ctx, tempPath, androidMkModuleName, filepath.Dir(pathInApex), etc, nil) 2500 filesToAdd = append(filesToAdd, af) 2501 } 2502 2503 return filesToAdd 2504} 2505 2506// apexClasspathFragmentProtoFile returns *apexFile structure defining the classpath.proto config that 2507// the module contributes to the apex; or nil if the proto config was not generated. 2508func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) *apexFile { 2509 info, _ := android.OtherModuleProvider(ctx, module, java.ClasspathFragmentProtoContentInfoProvider) 2510 if !info.ClasspathFragmentProtoGenerated { 2511 return nil 2512 } 2513 classpathProtoOutput := info.ClasspathFragmentProtoOutput 2514 af := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), info.ClasspathFragmentProtoInstallDir.Rel(), etc, nil) 2515 return &af 2516} 2517 2518// apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment 2519// content module, i.e. a library that is part of the bootclasspath. 2520func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule blueprint.Module, javaModule javaModule) apexFile { 2521 bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragmentModule, java.BootclasspathFragmentApexContentInfoProvider) 2522 2523 // Get the dexBootJar from the bootclasspath_fragment as that is responsible for performing the 2524 // hidden API encpding. 2525 dexBootJar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(javaModule) 2526 if err != nil { 2527 ctx.ModuleErrorf("%s", err) 2528 } 2529 2530 // Create an apexFile as for a normal java module but with the dex boot jar provided by the 2531 // bootclasspath_fragment. 2532 af := apexFileForJavaModuleWithFile(ctx, javaModule, dexBootJar) 2533 return af 2534} 2535 2536/////////////////////////////////////////////////////////////////////////////////////////////////// 2537// Factory functions 2538// 2539 2540func newApexBundle() *apexBundle { 2541 module := &apexBundle{} 2542 2543 module.AddProperties(&module.properties) 2544 module.AddProperties(&module.targetProperties) 2545 module.AddProperties(&module.archProperties) 2546 module.AddProperties(&module.overridableProperties) 2547 2548 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 2549 android.InitDefaultableModule(module) 2550 android.InitOverridableModule(module, &module.overridableProperties.Overrides) 2551 multitree.InitExportableModule(module) 2552 return module 2553} 2554 2555func ApexBundleFactory(testApex bool) android.Module { 2556 bundle := newApexBundle() 2557 bundle.testApex = testApex 2558 return bundle 2559} 2560 2561// apex_test is an APEX for testing. The difference from the ordinary apex module type is that 2562// certain compatibility checks such as apex_available are not done for apex_test. 2563func TestApexBundleFactory() android.Module { 2564 bundle := newApexBundle() 2565 bundle.testApex = true 2566 return bundle 2567} 2568 2569// apex packages other modules into an APEX file which is a packaging format for system-level 2570// components like binaries, shared libraries, etc. 2571func BundleFactory() android.Module { 2572 return newApexBundle() 2573} 2574 2575type Defaults struct { 2576 android.ModuleBase 2577 android.DefaultsModuleBase 2578} 2579 2580// apex_defaults provides defaultable properties to other apex modules. 2581func DefaultsFactory() android.Module { 2582 module := &Defaults{} 2583 2584 module.AddProperties( 2585 &apexBundleProperties{}, 2586 &apexTargetBundleProperties{}, 2587 &apexArchBundleProperties{}, 2588 &overridableProperties{}, 2589 ) 2590 2591 android.InitDefaultsModule(module) 2592 return module 2593} 2594 2595type OverrideApex struct { 2596 android.ModuleBase 2597 android.OverrideModuleBase 2598} 2599 2600func (o *OverrideApex) GenerateAndroidBuildActions(_ android.ModuleContext) { 2601 // All the overrides happen in the base module. 2602} 2603 2604// override_apex is used to create an apex module based on another apex module by overriding some of 2605// its properties. 2606func OverrideApexFactory() android.Module { 2607 m := &OverrideApex{} 2608 2609 m.AddProperties(&overridableProperties{}) 2610 2611 android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon) 2612 android.InitOverrideModule(m) 2613 return m 2614} 2615 2616/////////////////////////////////////////////////////////////////////////////////////////////////// 2617// Vality check routines 2618// 2619// These are called in at the very beginning of GenerateAndroidBuildActions to flag an error when 2620// certain conditions are not met. 2621// 2622// TODO(jiyong): move these checks to a separate go file. 2623 2624var _ android.ModuleWithMinSdkVersionCheck = (*apexBundle)(nil) 2625 2626// Ensures that min_sdk_version of the included modules are equal or less than the min_sdk_version 2627// of this apexBundle. 2628func (a *apexBundle) CheckMinSdkVersion(ctx android.ModuleContext) { 2629 if a.testApex || a.vndkApex { 2630 return 2631 } 2632 // apexBundle::minSdkVersion reports its own errors. 2633 minSdkVersion := a.minSdkVersion(ctx) 2634 android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps) 2635} 2636 2637// Returns apex's min_sdk_version string value, honoring overrides 2638func (a *apexBundle) minSdkVersionValue(ctx android.EarlyModuleContext) string { 2639 // Only override the minSdkVersion value on Apexes which already specify 2640 // a min_sdk_version (it's optional for non-updatable apexes), and that its 2641 // min_sdk_version value is lower than the one to override with. 2642 minApiLevel := android.MinSdkVersionFromValue(ctx, proptools.String(a.overridableProperties.Min_sdk_version)) 2643 if minApiLevel.IsNone() { 2644 return "" 2645 } 2646 2647 overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride() 2648 overrideApiLevel := android.MinSdkVersionFromValue(ctx, overrideMinSdkValue) 2649 if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(minApiLevel) > 0 { 2650 minApiLevel = overrideApiLevel 2651 } 2652 2653 return minApiLevel.String() 2654} 2655 2656// Returns apex's min_sdk_version SdkSpec, honoring overrides 2657func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 2658 return a.minSdkVersion(ctx) 2659} 2660 2661// Returns apex's min_sdk_version ApiLevel, honoring overrides 2662func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 2663 return android.MinSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx)) 2664} 2665 2666// Ensures that a lib providing stub isn't statically linked 2667func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext) { 2668 // Practically, we only care about regular APEXes on the device. 2669 if a.testApex || a.vndkApex { 2670 return 2671 } 2672 2673 abInfo, _ := android.ModuleProvider(ctx, android.ApexBundleInfoProvider) 2674 2675 a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool { 2676 if ccm, ok := to.(*cc.Module); ok { 2677 apexName := ctx.ModuleName() 2678 fromName := ctx.OtherModuleName(from) 2679 toName := ctx.OtherModuleName(to) 2680 2681 // If `to` is not actually in the same APEX as `from` then it does not need 2682 // apex_available and neither do any of its dependencies. 2683 // 2684 // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps(). 2685 if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) { 2686 // As soon as the dependency graph crosses the APEX boundary, don't go further. 2687 return false 2688 } 2689 2690 // The dynamic linker and crash_dump tool in the runtime APEX is the only 2691 // exception to this rule. It can't make the static dependencies dynamic 2692 // because it can't do the dynamic linking for itself. 2693 // Same rule should be applied to linkerconfig, because it should be executed 2694 // only with static linked libraries before linker is available with ld.config.txt 2695 if apexName == "com.android.runtime" && (fromName == "linker" || fromName == "crash_dump" || fromName == "linkerconfig") { 2696 return false 2697 } 2698 2699 isStubLibraryFromOtherApex := ccm.HasStubsVariants() && !abInfo.Contents.DirectlyInApex(toName) 2700 if isStubLibraryFromOtherApex && !externalDep { 2701 ctx.ModuleErrorf("%q required by %q is a native library providing stub. "+ 2702 "It shouldn't be included in this APEX via static linking. Dependency path: %s", to.String(), fromName, ctx.GetPathString(false)) 2703 } 2704 2705 } 2706 return true 2707 }) 2708} 2709 2710// checkUpdatable enforces APEX and its transitive dep properties to have desired values for updatable APEXes. 2711func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { 2712 if a.Updatable() { 2713 if a.minSdkVersionValue(ctx) == "" { 2714 ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well") 2715 } 2716 if a.UsePlatformApis() { 2717 ctx.PropertyErrorf("updatable", "updatable APEXes can't use platform APIs") 2718 } 2719 if proptools.Bool(a.properties.Use_vndk_as_stable) { 2720 ctx.PropertyErrorf("use_vndk_as_stable", "updatable APEXes can't use external VNDK libs") 2721 } 2722 if a.FutureUpdatable() { 2723 ctx.PropertyErrorf("future_updatable", "Already updatable. Remove `future_updatable: true:`") 2724 } 2725 a.checkJavaStableSdkVersion(ctx) 2726 a.checkClasspathFragments(ctx) 2727 } 2728} 2729 2730// checkClasspathFragments enforces that all classpath fragments in deps generate classpaths.proto config. 2731func (a *apexBundle) checkClasspathFragments(ctx android.ModuleContext) { 2732 ctx.VisitDirectDeps(func(module android.Module) { 2733 if tag := ctx.OtherModuleDependencyTag(module); tag == bcpfTag || tag == sscpfTag { 2734 info, _ := android.OtherModuleProvider(ctx, module, java.ClasspathFragmentProtoContentInfoProvider) 2735 if !info.ClasspathFragmentProtoGenerated { 2736 ctx.OtherModuleErrorf(module, "is included in updatable apex %v, it must not set generate_classpaths_proto to false", ctx.ModuleName()) 2737 } 2738 } 2739 }) 2740} 2741 2742// checkJavaStableSdkVersion enforces that all Java deps are using stable SDKs to compile. 2743func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) { 2744 // Visit direct deps only. As long as we guarantee top-level deps are using stable SDKs, 2745 // java's checkLinkType guarantees correct usage for transitive deps 2746 ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) { 2747 tag := ctx.OtherModuleDependencyTag(module) 2748 switch tag { 2749 case javaLibTag, androidAppTag: 2750 if m, ok := module.(interface { 2751 CheckStableSdkVersion(ctx android.BaseModuleContext) error 2752 }); ok { 2753 if err := m.CheckStableSdkVersion(ctx); err != nil { 2754 ctx.ModuleErrorf("cannot depend on \"%v\": %v", ctx.OtherModuleName(module), err) 2755 } 2756 } 2757 } 2758 }) 2759} 2760 2761// checkApexAvailability ensures that the all the dependencies are marked as available for this APEX. 2762func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { 2763 // Let's be practical. Availability for test, host, and the VNDK apex isn't important 2764 if a.testApex || a.vndkApex { 2765 return 2766 } 2767 2768 // Because APEXes targeting other than system/system_ext partitions can't set 2769 // apex_available, we skip checks for these APEXes 2770 if a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { 2771 return 2772 } 2773 2774 // Coverage build adds additional dependencies for the coverage-only runtime libraries. 2775 // Requiring them and their transitive depencies with apex_available is not right 2776 // because they just add noise. 2777 if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") || a.IsNativeCoverageNeeded(ctx) { 2778 return 2779 } 2780 2781 a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool { 2782 // As soon as the dependency graph crosses the APEX boundary, don't go further. 2783 if externalDep { 2784 return false 2785 } 2786 2787 apexName := ctx.ModuleName() 2788 for _, props := range ctx.Module().GetProperties() { 2789 if apexProps, ok := props.(*apexBundleProperties); ok { 2790 if apexProps.Apex_available_name != nil { 2791 apexName = *apexProps.Apex_available_name 2792 } 2793 } 2794 } 2795 fromName := ctx.OtherModuleName(from) 2796 toName := ctx.OtherModuleName(to) 2797 2798 // If `to` is not actually in the same APEX as `from` then it does not need 2799 // apex_available and neither do any of its dependencies. 2800 // 2801 // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps(). 2802 if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) { 2803 // As soon as the dependency graph crosses the APEX boundary, don't go 2804 // further. 2805 return false 2806 } 2807 2808 if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) { 2809 return true 2810 } 2811 ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+ 2812 "\n\nDependency path:%s\n\n"+ 2813 "Consider adding %q to 'apex_available' property of %q", 2814 fromName, toName, ctx.GetPathString(true), apexName, toName) 2815 // Visit this module's dependencies to check and report any issues with their availability. 2816 return true 2817 }) 2818} 2819 2820// checkStaticExecutable ensures that executables in an APEX are not static. 2821func (a *apexBundle) checkStaticExecutables(ctx android.ModuleContext) { 2822 ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) { 2823 if ctx.OtherModuleDependencyTag(module) != executableTag { 2824 return 2825 } 2826 2827 if l, ok := module.(cc.LinkableInterface); ok && l.StaticExecutable() { 2828 apex := a.ApexVariationName() 2829 exec := ctx.OtherModuleName(module) 2830 if isStaticExecutableAllowed(apex, exec) { 2831 return 2832 } 2833 ctx.ModuleErrorf("executable %s is static", ctx.OtherModuleName(module)) 2834 } 2835 }) 2836} 2837 2838// A small list of exceptions where static executables are allowed in APEXes. 2839func isStaticExecutableAllowed(apex string, exec string) bool { 2840 m := map[string][]string{ 2841 "com.android.runtime": { 2842 "linker", 2843 "linkerconfig", 2844 }, 2845 } 2846 execNames, ok := m[apex] 2847 return ok && android.InList(exec, execNames) 2848} 2849 2850// Collect information for opening IDE project files in java/jdeps.go. 2851func (a *apexBundle) IDEInfo(dpInfo *android.IdeInfo) { 2852 dpInfo.Deps = append(dpInfo.Deps, a.properties.Java_libs...) 2853 dpInfo.Deps = append(dpInfo.Deps, a.properties.Bootclasspath_fragments...) 2854 dpInfo.Deps = append(dpInfo.Deps, a.properties.Systemserverclasspath_fragments...) 2855} 2856 2857var ( 2858 apexAvailBaseline = makeApexAvailableBaseline() 2859 inverseApexAvailBaseline = invertApexBaseline(apexAvailBaseline) 2860) 2861 2862func baselineApexAvailable(apex, moduleName string) bool { 2863 key := apex 2864 moduleName = normalizeModuleName(moduleName) 2865 2866 if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) { 2867 return true 2868 } 2869 2870 key = android.AvailableToAnyApex 2871 if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) { 2872 return true 2873 } 2874 2875 return false 2876} 2877 2878func normalizeModuleName(moduleName string) string { 2879 // Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build 2880 // system. Trim the prefix for the check since they are confusing 2881 moduleName = android.RemoveOptionalPrebuiltPrefix(moduleName) 2882 if strings.HasPrefix(moduleName, "libclang_rt.") { 2883 // This module has many arch variants that depend on the product being built. 2884 // We don't want to list them all 2885 moduleName = "libclang_rt" 2886 } 2887 if strings.HasPrefix(moduleName, "androidx.") { 2888 // TODO(b/156996905) Set apex_available/min_sdk_version for androidx support libraries 2889 moduleName = "androidx" 2890 } 2891 return moduleName 2892} 2893 2894// Transform the map of apex -> modules to module -> apexes. 2895func invertApexBaseline(m map[string][]string) map[string][]string { 2896 r := make(map[string][]string) 2897 for apex, modules := range m { 2898 for _, module := range modules { 2899 r[module] = append(r[module], apex) 2900 } 2901 } 2902 return r 2903} 2904 2905// Retrieve the baseline of apexes to which the supplied module belongs. 2906func BaselineApexAvailable(moduleName string) []string { 2907 return inverseApexAvailBaseline[normalizeModuleName(moduleName)] 2908} 2909 2910// This is a map from apex to modules, which overrides the apex_available setting for that 2911// particular module to make it available for the apex regardless of its setting. 2912// TODO(b/147364041): remove this 2913func makeApexAvailableBaseline() map[string][]string { 2914 // The "Module separator"s below are employed to minimize merge conflicts. 2915 m := make(map[string][]string) 2916 // 2917 // Module separator 2918 // 2919 m["com.android.runtime"] = []string{ 2920 "libz", 2921 } 2922 return m 2923} 2924 2925func init() { 2926 android.AddNeverAllowRules(createBcpPermittedPackagesRules(qBcpPackages())...) 2927 android.AddNeverAllowRules(createBcpPermittedPackagesRules(rBcpPackages())...) 2928} 2929 2930func createBcpPermittedPackagesRules(bcpPermittedPackages map[string][]string) []android.Rule { 2931 rules := make([]android.Rule, 0, len(bcpPermittedPackages)) 2932 for jar, permittedPackages := range bcpPermittedPackages { 2933 permittedPackagesRule := android.NeverAllow(). 2934 With("name", jar). 2935 WithMatcher("permitted_packages", android.NotInList(permittedPackages)). 2936 Because(jar + 2937 " bootjar may only use these package prefixes: " + strings.Join(permittedPackages, ",") + 2938 ". Please consider the following alternatives:\n" + 2939 " 1. If the offending code is from a statically linked library, consider " + 2940 "removing that dependency and using an alternative already in the " + 2941 "bootclasspath, or perhaps a shared library." + 2942 " 2. Move the offending code into an allowed package.\n" + 2943 " 3. Jarjar the offending code. Please be mindful of the potential system " + 2944 "health implications of bundling that code, particularly if the offending jar " + 2945 "is part of the bootclasspath.") 2946 2947 rules = append(rules, permittedPackagesRule) 2948 } 2949 return rules 2950} 2951 2952// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART. 2953// Adding code to the bootclasspath in new packages will cause issues on module update. 2954func qBcpPackages() map[string][]string { 2955 return map[string][]string{ 2956 "conscrypt": { 2957 "android.net.ssl", 2958 "com.android.org.conscrypt", 2959 }, 2960 "updatable-media": { 2961 "android.media", 2962 }, 2963 } 2964} 2965 2966// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART. 2967// Adding code to the bootclasspath in new packages will cause issues on module update. 2968func rBcpPackages() map[string][]string { 2969 return map[string][]string{ 2970 "framework-mediaprovider": { 2971 "android.provider", 2972 }, 2973 "framework-permission": { 2974 "android.permission", 2975 "android.app.role", 2976 "com.android.permission", 2977 "com.android.role", 2978 }, 2979 "framework-sdkextensions": { 2980 "android.os.ext", 2981 }, 2982 "framework-statsd": { 2983 "android.app", 2984 "android.os", 2985 "android.util", 2986 "com.android.internal.statsd", 2987 "com.android.server.stats", 2988 }, 2989 "framework-wifi": { 2990 "com.android.server.wifi", 2991 "com.android.wifi.x", 2992 "android.hardware.wifi", 2993 "android.net.wifi", 2994 }, 2995 "framework-tethering": { 2996 "android.net", 2997 }, 2998 } 2999} 3000 3001func (a *apexBundle) IsTestApex() bool { 3002 return a.testApex 3003} 3004