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