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