1// Copyright (C) 2018 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// package apex implements build rules for creating the APEX files which are container for 16// lower-level system components. See https://source.android.com/devices/tech/ota/apex 17package apex 18 19import ( 20 "fmt" 21 "path/filepath" 22 "regexp" 23 "sort" 24 "strings" 25 26 "android/soong/bazel/cquery" 27 28 "github.com/google/blueprint" 29 "github.com/google/blueprint/bootstrap" 30 "github.com/google/blueprint/proptools" 31 32 "android/soong/android" 33 "android/soong/bazel" 34 "android/soong/bpf" 35 "android/soong/cc" 36 prebuilt_etc "android/soong/etc" 37 "android/soong/filesystem" 38 "android/soong/java" 39 "android/soong/multitree" 40 "android/soong/python" 41 "android/soong/rust" 42 "android/soong/sh" 43) 44 45func init() { 46 registerApexBuildComponents(android.InitRegistrationContext) 47} 48 49func registerApexBuildComponents(ctx android.RegistrationContext) { 50 ctx.RegisterModuleType("apex", BundleFactory) 51 ctx.RegisterModuleType("apex_test", TestApexBundleFactory) 52 ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory) 53 ctx.RegisterModuleType("apex_defaults", DefaultsFactory) 54 ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory) 55 ctx.RegisterModuleType("override_apex", OverrideApexFactory) 56 ctx.RegisterModuleType("apex_set", apexSetFactory) 57 58 ctx.PreArchMutators(registerPreArchMutators) 59 ctx.PreDepsMutators(RegisterPreDepsMutators) 60 ctx.PostDepsMutators(RegisterPostDepsMutators) 61} 62 63func registerPreArchMutators(ctx android.RegisterMutatorsContext) { 64 ctx.TopDown("prebuilt_apex_module_creator", prebuiltApexModuleCreatorMutator).Parallel() 65} 66 67func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) { 68 ctx.TopDown("apex_vndk", apexVndkMutator).Parallel() 69 ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel() 70} 71 72func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { 73 ctx.TopDown("apex_info", apexInfoMutator).Parallel() 74 ctx.BottomUp("apex_unique", apexUniqueVariationsMutator).Parallel() 75 ctx.BottomUp("apex_test_for_deps", apexTestForDepsMutator).Parallel() 76 ctx.BottomUp("apex_test_for", apexTestForMutator).Parallel() 77 // Run mark_platform_availability before the apexMutator as the apexMutator needs to know whether 78 // it should create a platform variant. 79 ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel() 80 ctx.BottomUp("apex", apexMutator).Parallel() 81 ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel() 82 ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel() 83 ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel() 84 // Register after apex_info mutator so that it can use ApexVariationName 85 ctx.TopDown("apex_strict_updatability_lint", apexStrictUpdatibilityLintMutator).Parallel() 86} 87 88type apexBundleProperties struct { 89 // Json manifest file describing meta info of this APEX bundle. Refer to 90 // system/apex/proto/apex_manifest.proto for the schema. Default: "apex_manifest.json" 91 Manifest *string `android:"path"` 92 93 // AndroidManifest.xml file used for the zip container of this APEX bundle. If unspecified, 94 // a default one is automatically generated. 95 AndroidManifest *string `android:"path"` 96 97 // Determines the file contexts file for setting the security contexts to files in this APEX 98 // bundle. For platform APEXes, this should points to a file under /system/sepolicy Default: 99 // /system/sepolicy/apex/<module_name>_file_contexts. 100 File_contexts *string `android:"path"` 101 102 // By default, file_contexts is amended by force-labelling / and /apex_manifest.pb as system_file 103 // to avoid mistakes. When set as true, no force-labelling. 104 Use_file_contexts_as_is *bool 105 106 // Path to the canned fs config file for customizing file's 107 // uid/gid/mod/capabilities. The content of this file is appended to the 108 // default config, so that the custom entries are preferred. The format is 109 // /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where 110 // path_or_glob is a path or glob pattern for a file or set of files, 111 // uid/gid are numerial values of user ID and group ID, mode is octal value 112 // for the file mode, and cap is hexadecimal value for the capability. 113 Canned_fs_config *string `android:"path"` 114 115 ApexNativeDependencies 116 117 Multilib apexMultilibProperties 118 119 // List of runtime resource overlays (RROs) that are embedded inside this APEX. 120 Rros []string 121 122 // List of bootclasspath fragments that are embedded inside this APEX bundle. 123 Bootclasspath_fragments []string 124 125 // List of systemserverclasspath fragments that are embedded inside this APEX bundle. 126 Systemserverclasspath_fragments []string 127 128 // List of java libraries that are embedded inside this APEX bundle. 129 Java_libs []string 130 131 // List of sh binaries that are embedded inside this APEX bundle. 132 Sh_binaries []string 133 134 // List of platform_compat_config files that are embedded inside this APEX bundle. 135 Compat_configs []string 136 137 // List of filesystem images that are embedded inside this APEX bundle. 138 Filesystems []string 139 140 // The minimum SDK version that this APEX must support at minimum. This is usually set to 141 // the SDK version that the APEX was first introduced. 142 Min_sdk_version *string 143 144 // Whether this APEX is considered updatable or not. When set to true, this will enforce 145 // additional rules for making sure that the APEX is truly updatable. To be updatable, 146 // min_sdk_version should be set as well. This will also disable the size optimizations like 147 // symlinking to the system libs. Default is true. 148 Updatable *bool 149 150 // Marks that this APEX is designed to be updatable in the future, although it's not 151 // updatable yet. This is used to mimic some of the build behaviors that are applied only to 152 // updatable APEXes. Currently, this disables the size optimization, so that the size of 153 // APEX will not increase when the APEX is actually marked as truly updatable. Default is 154 // false. 155 Future_updatable *bool 156 157 // Whether this APEX can use platform APIs or not. Can be set to true only when `updatable: 158 // false`. Default is false. 159 Platform_apis *bool 160 161 // Whether this APEX is installable to one of the partitions like system, vendor, etc. 162 // Default: true. 163 Installable *bool 164 165 // If set true, VNDK libs are considered as stable libs and are not included in this APEX. 166 // Should be only used in non-system apexes (e.g. vendor: true). Default is false. 167 Use_vndk_as_stable *bool 168 169 // The type of APEX to build. Controls what the APEX payload is. Either 'image', 'zip' or 170 // 'both'. When set to image, contents are stored in a filesystem image inside a zip 171 // container. When set to zip, contents are stored in a zip container directly. This type is 172 // mostly for host-side debugging. When set to both, the two types are both built. Default 173 // is 'image'. 174 Payload_type *string 175 176 // The type of filesystem to use when the payload_type is 'image'. Either 'ext4', 'f2fs' 177 // or 'erofs'. Default 'ext4'. 178 Payload_fs_type *string 179 180 // For telling the APEX to ignore special handling for system libraries such as bionic. 181 // Default is false. 182 Ignore_system_library_special_case *bool 183 184 // Whenever apex_payload.img of the APEX should include dm-verity hashtree. 185 // Default value is true. 186 Generate_hashtree *bool 187 188 // Whenever apex_payload.img of the APEX should not be dm-verity signed. Should be only 189 // used in tests. 190 Test_only_unsigned_payload *bool 191 192 // Whenever apex should be compressed, regardless of product flag used. Should be only 193 // used in tests. 194 Test_only_force_compression *bool 195 196 // Put extra tags (signer=<value>) to apexkeys.txt, so that release tools can sign this apex 197 // with the tool to sign payload contents. 198 Custom_sign_tool *string 199 200 // Whether this is a dynamic common lib apex, if so the native shared libs will be placed 201 // in a special way that include the digest of the lib file under /lib(64)? 202 Dynamic_common_lib_apex *bool 203 204 // Canonical name of this APEX bundle. Used to determine the path to the 205 // activated APEX on device (i.e. /apex/<apexVariationName>), and used for the 206 // apex mutator variations. For override_apex modules, this is the name of the 207 // overridden base module. 208 ApexVariationName string `blueprint:"mutated"` 209 210 IsCoverageVariant bool `blueprint:"mutated"` 211 212 // List of sanitizer names that this APEX is enabled for 213 SanitizerNames []string `blueprint:"mutated"` 214 215 PreventInstall bool `blueprint:"mutated"` 216 217 HideFromMake bool `blueprint:"mutated"` 218 219 // Internal package method for this APEX. When payload_type is image, this can be either 220 // imageApex or flattenedApex depending on Config.FlattenApex(). When payload_type is zip, 221 // this becomes zipApex. 222 ApexType apexPackaging `blueprint:"mutated"` 223} 224 225type ApexNativeDependencies struct { 226 // List of native libraries that are embedded inside this APEX. 227 Native_shared_libs []string 228 229 // List of JNI libraries that are embedded inside this APEX. 230 Jni_libs []string 231 232 // List of rust dyn libraries that are embedded inside this APEX. 233 Rust_dyn_libs []string 234 235 // List of native executables that are embedded inside this APEX. 236 Binaries []string 237 238 // List of native tests that are embedded inside this APEX. 239 Tests []string 240 241 // List of filesystem images that are embedded inside this APEX bundle. 242 Filesystems []string 243 244 // List of native libraries to exclude from this APEX. 245 Exclude_native_shared_libs []string 246 247 // List of JNI libraries to exclude from this APEX. 248 Exclude_jni_libs []string 249 250 // List of rust dyn libraries to exclude from this APEX. 251 Exclude_rust_dyn_libs []string 252 253 // List of native executables to exclude from this APEX. 254 Exclude_binaries []string 255 256 // List of native tests to exclude from this APEX. 257 Exclude_tests []string 258 259 // List of filesystem images to exclude from this APEX bundle. 260 Exclude_filesystems []string 261} 262 263// Merge combines another ApexNativeDependencies into this one 264func (a *ApexNativeDependencies) Merge(b ApexNativeDependencies) { 265 a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs...) 266 a.Jni_libs = append(a.Jni_libs, b.Jni_libs...) 267 a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...) 268 a.Binaries = append(a.Binaries, b.Binaries...) 269 a.Tests = append(a.Tests, b.Tests...) 270 a.Filesystems = append(a.Filesystems, b.Filesystems...) 271 272 a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...) 273 a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...) 274 a.Exclude_rust_dyn_libs = append(a.Exclude_rust_dyn_libs, b.Exclude_rust_dyn_libs...) 275 a.Exclude_binaries = append(a.Exclude_binaries, b.Exclude_binaries...) 276 a.Exclude_tests = append(a.Exclude_tests, b.Exclude_tests...) 277 a.Exclude_filesystems = append(a.Exclude_filesystems, b.Exclude_filesystems...) 278} 279 280type apexMultilibProperties struct { 281 // Native dependencies whose compile_multilib is "first" 282 First ApexNativeDependencies 283 284 // Native dependencies whose compile_multilib is "both" 285 Both ApexNativeDependencies 286 287 // Native dependencies whose compile_multilib is "prefer32" 288 Prefer32 ApexNativeDependencies 289 290 // Native dependencies whose compile_multilib is "32" 291 Lib32 ApexNativeDependencies 292 293 // Native dependencies whose compile_multilib is "64" 294 Lib64 ApexNativeDependencies 295} 296 297type apexTargetBundleProperties struct { 298 Target struct { 299 // Multilib properties only for android. 300 Android struct { 301 Multilib apexMultilibProperties 302 } 303 304 // Multilib properties only for host. 305 Host struct { 306 Multilib apexMultilibProperties 307 } 308 309 // Multilib properties only for host linux_bionic. 310 Linux_bionic struct { 311 Multilib apexMultilibProperties 312 } 313 314 // Multilib properties only for host linux_glibc. 315 Linux_glibc struct { 316 Multilib apexMultilibProperties 317 } 318 } 319} 320 321type apexArchBundleProperties struct { 322 Arch struct { 323 Arm struct { 324 ApexNativeDependencies 325 } 326 Arm64 struct { 327 ApexNativeDependencies 328 } 329 Riscv64 struct { 330 ApexNativeDependencies 331 } 332 X86 struct { 333 ApexNativeDependencies 334 } 335 X86_64 struct { 336 ApexNativeDependencies 337 } 338 } 339} 340 341// These properties can be used in override_apex to override the corresponding properties in the 342// base apex. 343type overridableProperties struct { 344 // List of APKs that are embedded inside this APEX. 345 Apps []string 346 347 // List of prebuilt files that are embedded inside this APEX bundle. 348 Prebuilts []string 349 350 // List of BPF programs inside this APEX bundle. 351 Bpfs []string 352 353 // Names of modules to be overridden. Listed modules can only be other binaries (in Make or 354 // Soong). This does not completely prevent installation of the overridden binaries, but if 355 // both binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will 356 // be removed from PRODUCT_PACKAGES. 357 Overrides []string 358 359 // Logging parent value. 360 Logging_parent string 361 362 // Apex Container package name. Override value for attribute package:name in 363 // AndroidManifest.xml 364 Package_name string 365 366 // A txt file containing list of files that are allowed to be included in this APEX. 367 Allowed_files *string `android:"path"` 368 369 // Name of the apex_key module that provides the private key to sign this APEX bundle. 370 Key *string 371 372 // Specifies the certificate and the private key to sign the zip container of this APEX. If 373 // this is "foo", foo.x509.pem and foo.pk8 under PRODUCT_DEFAULT_DEV_CERTIFICATE are used 374 // as the certificate and the private key, respectively. If this is ":module", then the 375 // certificate and the private key are provided from the android_app_certificate module 376 // named "module". 377 Certificate *string 378 379 // Whether this APEX can be compressed or not. Setting this property to false means this 380 // APEX will never be compressed. When set to true, APEX will be compressed if other 381 // conditions, e.g., target device needs to support APEX compression, are also fulfilled. 382 // Default: false. 383 Compressible *bool 384 385 // Trim against a specific Dynamic Common Lib APEX 386 Trim_against *string 387} 388 389type apexBundle struct { 390 // Inherited structs 391 android.ModuleBase 392 android.DefaultableModuleBase 393 android.OverridableModuleBase 394 android.BazelModuleBase 395 multitree.ExportableModuleBase 396 397 // Properties 398 properties apexBundleProperties 399 targetProperties apexTargetBundleProperties 400 archProperties apexArchBundleProperties 401 overridableProperties overridableProperties 402 vndkProperties apexVndkProperties // only for apex_vndk modules 403 404 /////////////////////////////////////////////////////////////////////////////////////////// 405 // Inputs 406 407 // Keys for apex_paylaod.img 408 publicKeyFile android.Path 409 privateKeyFile android.Path 410 411 // Cert/priv-key for the zip container 412 containerCertificateFile android.Path 413 containerPrivateKeyFile android.Path 414 415 // Flags for special variants of APEX 416 testApex bool 417 vndkApex bool 418 419 // Tells whether this variant of the APEX bundle is the primary one or not. Only the primary 420 // one gets installed to the device. 421 primaryApexType bool 422 423 // Suffix of module name in Android.mk ".flattened", ".apex", ".zipapex", or "" 424 suffix string 425 426 // File system type of apex_payload.img 427 payloadFsType fsType 428 429 // Whether to create symlink to the system file instead of having a file inside the apex or 430 // not 431 linkToSystemLib bool 432 433 // List of files to be included in this APEX. This is filled in the first part of 434 // GenerateAndroidBuildActions. 435 filesInfo []apexFile 436 437 // List of other module names that should be installed when this APEX gets installed (LOCAL_REQUIRED_MODULES). 438 makeModulesToInstall []string 439 440 /////////////////////////////////////////////////////////////////////////////////////////// 441 // Outputs (final and intermediates) 442 443 // Processed apex manifest in JSONson format (for Q) 444 manifestJsonOut android.WritablePath 445 446 // Processed apex manifest in PB format (for R+) 447 manifestPbOut android.WritablePath 448 449 // Processed file_contexts files 450 fileContexts android.WritablePath 451 452 // The built APEX file. This is the main product. 453 // Could be .apex or .capex 454 outputFile android.WritablePath 455 456 // The built uncompressed .apex file. 457 outputApexFile android.WritablePath 458 459 // The built APEX file in app bundle format. This file is not directly installed to the 460 // device. For an APEX, multiple app bundles are created each of which is for a specific ABI 461 // like arm, arm64, x86, etc. Then they are processed again (outside of the Android build 462 // system) to be merged into a single app bundle file that Play accepts. See 463 // vendor/google/build/build_unbundled_mainline_module.sh for more detail. 464 bundleModuleFile android.WritablePath 465 466 // Target directory to install this APEX. Usually out/target/product/<device>/<partition>/apex. 467 installDir android.InstallPath 468 469 // Path where this APEX was installed. 470 installedFile android.InstallPath 471 472 // Installed locations of symlinks for backward compatibility. 473 compatSymlinks android.InstallPaths 474 475 // Text file having the list of individual files that are included in this APEX. Used for 476 // debugging purpose. 477 installedFilesFile android.WritablePath 478 479 // List of module names that this APEX is including (to be shown via *-deps-info target). 480 // Used for debugging purpose. 481 android.ApexBundleDepsInfo 482 483 // Optional list of lint report zip files for apexes that contain java or app modules 484 lintReports android.Paths 485 486 isCompressed bool 487 488 // Path of API coverage generate file 489 nativeApisUsedByModuleFile android.ModuleOutPath 490 nativeApisBackedByModuleFile android.ModuleOutPath 491 javaApisUsedByModuleFile android.ModuleOutPath 492 493 // Collect the module directory for IDE info in java/jdeps.go. 494 modulePaths []string 495} 496 497// apexFileClass represents a type of file that can be included in APEX. 498type apexFileClass int 499 500const ( 501 app apexFileClass = iota 502 appSet 503 etc 504 goBinary 505 javaSharedLib 506 nativeExecutable 507 nativeSharedLib 508 nativeTest 509 pyBinary 510 shBinary 511) 512 513var ( 514 classes = map[string]apexFileClass{ 515 "app": app, 516 "appSet": appSet, 517 "etc": etc, 518 "goBinary": goBinary, 519 "javaSharedLib": javaSharedLib, 520 "nativeExecutable": nativeExecutable, 521 "nativeSharedLib": nativeSharedLib, 522 "nativeTest": nativeTest, 523 "pyBinary": pyBinary, 524 "shBinary": shBinary, 525 } 526) 527 528// apexFile represents a file in an APEX bundle. This is created during the first half of 529// GenerateAndroidBuildActions by traversing the dependencies of the APEX. Then in the second half 530// of the function, this is used to create commands that copies the files into a staging directory, 531// where they are packaged into the APEX file. This struct is also used for creating Make modules 532// for each of the files in case when the APEX is flattened. 533type apexFile struct { 534 // buildFile is put in the installDir inside the APEX. 535 builtFile android.Path 536 installDir string 537 partition string 538 customStem string 539 symlinks []string // additional symlinks 540 541 // Info for Android.mk Module name of `module` in AndroidMk. Note the generated AndroidMk 542 // module for apexFile is named something like <AndroidMk module name>.<apex name>[<apex 543 // suffix>] 544 androidMkModuleName string // becomes LOCAL_MODULE 545 class apexFileClass // becomes LOCAL_MODULE_CLASS 546 moduleDir string // becomes LOCAL_PATH 547 requiredModuleNames []string // becomes LOCAL_REQUIRED_MODULES 548 targetRequiredModuleNames []string // becomes LOCAL_TARGET_REQUIRED_MODULES 549 hostRequiredModuleNames []string // becomes LOCAL_HOST_REQUIRED_MODULES 550 dataPaths []android.DataPath // becomes LOCAL_TEST_DATA 551 552 jacocoReportClassesFile android.Path // only for javalibs and apps 553 lintDepSets java.LintDepSets // only for javalibs and apps 554 certificate java.Certificate // only for apps 555 overriddenPackageName string // only for apps 556 557 transitiveDep bool 558 isJniLib bool 559 560 multilib string 561 562 isBazelPrebuilt bool 563 unstrippedBuiltFile android.Path 564 arch string 565 566 // TODO(jiyong): remove this 567 module android.Module 568} 569 570// TODO(jiyong): shorten the arglist using an option struct 571func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidMkModuleName string, installDir string, class apexFileClass, module android.Module) apexFile { 572 ret := apexFile{ 573 builtFile: builtFile, 574 installDir: installDir, 575 androidMkModuleName: androidMkModuleName, 576 class: class, 577 module: module, 578 } 579 if module != nil { 580 ret.moduleDir = ctx.OtherModuleDir(module) 581 ret.partition = module.PartitionTag(ctx.DeviceConfig()) 582 ret.requiredModuleNames = module.RequiredModuleNames() 583 ret.targetRequiredModuleNames = module.TargetRequiredModuleNames() 584 ret.hostRequiredModuleNames = module.HostRequiredModuleNames() 585 ret.multilib = module.Target().Arch.ArchType.Multilib 586 } 587 return ret 588} 589 590func (af *apexFile) ok() bool { 591 return af.builtFile != nil && af.builtFile.String() != "" 592} 593 594// apexRelativePath returns the relative path of the given path from the install directory of this 595// apexFile. 596// TODO(jiyong): rename this 597func (af *apexFile) apexRelativePath(path string) string { 598 return filepath.Join(af.installDir, path) 599} 600 601// path returns path of this apex file relative to the APEX root 602func (af *apexFile) path() string { 603 return af.apexRelativePath(af.stem()) 604} 605 606// stem returns the base filename of this apex file 607func (af *apexFile) stem() string { 608 if af.customStem != "" { 609 return af.customStem 610 } 611 return af.builtFile.Base() 612} 613 614// symlinkPaths returns paths of the symlinks (if any) relative to the APEX root 615func (af *apexFile) symlinkPaths() []string { 616 var ret []string 617 for _, symlink := range af.symlinks { 618 ret = append(ret, af.apexRelativePath(symlink)) 619 } 620 return ret 621} 622 623// availableToPlatform tests whether this apexFile is from a module that can be installed to the 624// platform. 625func (af *apexFile) availableToPlatform() bool { 626 if af.module == nil { 627 return false 628 } 629 if am, ok := af.module.(android.ApexModule); ok { 630 return am.AvailableFor(android.AvailableToPlatform) 631 } 632 return false 633} 634 635//////////////////////////////////////////////////////////////////////////////////////////////////// 636// Mutators 637// 638// Brief description about mutators for APEX. The following three mutators are the most important 639// ones. 640// 641// 1) DepsMutator: from the properties like native_shared_libs, java_libs, etc., modules are added 642// to the (direct) dependencies of this APEX bundle. 643// 644// 2) apexInfoMutator: this is a post-deps mutator, so runs after DepsMutator. Its goal is to 645// collect modules that are direct and transitive dependencies of each APEX bundle. The collected 646// modules are marked as being included in the APEX via BuildForApex(). 647// 648// 3) apexMutator: this is a post-deps mutator that runs after apexInfoMutator. For each module that 649// are marked by the apexInfoMutator, apex variations are created using CreateApexVariations(). 650 651type dependencyTag struct { 652 blueprint.BaseDependencyTag 653 name string 654 655 // Determines if the dependent will be part of the APEX payload. Can be false for the 656 // dependencies to the signing key module, etc. 657 payload bool 658 659 // True if the dependent can only be a source module, false if a prebuilt module is a suitable 660 // replacement. This is needed because some prebuilt modules do not provide all the information 661 // needed by the apex. 662 sourceOnly bool 663 664 // If not-nil and an APEX is a member of an SDK then dependencies of that APEX with this tag will 665 // also be added as exported members of that SDK. 666 memberType android.SdkMemberType 667} 668 669func (d *dependencyTag) SdkMemberType(_ android.Module) android.SdkMemberType { 670 return d.memberType 671} 672 673func (d *dependencyTag) ExportMember() bool { 674 return true 675} 676 677func (d *dependencyTag) String() string { 678 return fmt.Sprintf("apex.dependencyTag{%q}", d.name) 679} 680 681func (d *dependencyTag) ReplaceSourceWithPrebuilt() bool { 682 return !d.sourceOnly 683} 684 685var _ android.ReplaceSourceWithPrebuilt = &dependencyTag{} 686var _ android.SdkMemberDependencyTag = &dependencyTag{} 687 688var ( 689 androidAppTag = &dependencyTag{name: "androidApp", payload: true} 690 bpfTag = &dependencyTag{name: "bpf", payload: true} 691 certificateTag = &dependencyTag{name: "certificate"} 692 dclaTag = &dependencyTag{name: "dcla"} 693 executableTag = &dependencyTag{name: "executable", payload: true} 694 fsTag = &dependencyTag{name: "filesystem", payload: true} 695 bcpfTag = &dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true, memberType: java.BootclasspathFragmentSdkMemberType} 696 sscpfTag = &dependencyTag{name: "systemserverclasspathFragment", payload: true, sourceOnly: true, memberType: java.SystemServerClasspathFragmentSdkMemberType} 697 compatConfigTag = &dependencyTag{name: "compatConfig", payload: true, sourceOnly: true, memberType: java.CompatConfigSdkMemberType} 698 javaLibTag = &dependencyTag{name: "javaLib", payload: true} 699 jniLibTag = &dependencyTag{name: "jniLib", payload: true} 700 keyTag = &dependencyTag{name: "key"} 701 prebuiltTag = &dependencyTag{name: "prebuilt", payload: true} 702 rroTag = &dependencyTag{name: "rro", payload: true} 703 sharedLibTag = &dependencyTag{name: "sharedLib", payload: true} 704 testForTag = &dependencyTag{name: "test for"} 705 testTag = &dependencyTag{name: "test", payload: true} 706 shBinaryTag = &dependencyTag{name: "shBinary", payload: true} 707) 708 709// TODO(jiyong): shorten this function signature 710func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ApexNativeDependencies, target android.Target, imageVariation string) { 711 binVariations := target.Variations() 712 libVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"}) 713 rustLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "rust_libraries", Variation: "dylib"}) 714 715 if ctx.Device() { 716 binVariations = append(binVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation}) 717 libVariations = append(libVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation}) 718 rustLibVariations = append(rustLibVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation}) 719 } 720 721 // Use *FarVariation* to be able to depend on modules having conflicting variations with 722 // this module. This is required since arch variant of an APEX bundle is 'common' but it is 723 // 'arm' or 'arm64' for native shared libs. 724 ctx.AddFarVariationDependencies(binVariations, executableTag, 725 android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...) 726 ctx.AddFarVariationDependencies(binVariations, testTag, 727 android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...) 728 ctx.AddFarVariationDependencies(libVariations, jniLibTag, 729 android.RemoveListFromList(nativeModules.Jni_libs, nativeModules.Exclude_jni_libs)...) 730 ctx.AddFarVariationDependencies(libVariations, sharedLibTag, 731 android.RemoveListFromList(nativeModules.Native_shared_libs, nativeModules.Exclude_native_shared_libs)...) 732 ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag, 733 android.RemoveListFromList(nativeModules.Rust_dyn_libs, nativeModules.Exclude_rust_dyn_libs)...) 734 ctx.AddFarVariationDependencies(target.Variations(), fsTag, 735 android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...) 736} 737 738func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) { 739 if ctx.Device() { 740 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Android.Multilib, nil) 741 } else { 742 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Host.Multilib, nil) 743 if ctx.Os().Bionic() { 744 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_bionic.Multilib, nil) 745 } else { 746 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_glibc.Multilib, nil) 747 } 748 } 749} 750 751// getImageVariationPair returns a pair for the image variation name as its 752// prefix and suffix. The prefix indicates whether it's core/vendor/product and the 753// suffix indicates the vndk version when it's vendor or product. 754// getImageVariation can simply join the result of this function to get the 755// image variation name. 756func (a *apexBundle) getImageVariationPair(deviceConfig android.DeviceConfig) (string, string) { 757 if a.vndkApex { 758 return cc.VendorVariationPrefix, a.vndkVersion(deviceConfig) 759 } 760 761 var prefix string 762 var vndkVersion string 763 if deviceConfig.VndkVersion() != "" { 764 if a.SocSpecific() || a.DeviceSpecific() { 765 prefix = cc.VendorVariationPrefix 766 vndkVersion = deviceConfig.VndkVersion() 767 } else if a.ProductSpecific() { 768 prefix = cc.ProductVariationPrefix 769 vndkVersion = deviceConfig.ProductVndkVersion() 770 } 771 } 772 if vndkVersion == "current" { 773 vndkVersion = deviceConfig.PlatformVndkVersion() 774 } 775 if vndkVersion != "" { 776 return prefix, vndkVersion 777 } 778 779 return android.CoreVariation, "" // The usual case 780} 781 782// getImageVariation returns the image variant name for this apexBundle. In most cases, it's simply 783// android.CoreVariation, but gets complicated for the vendor APEXes and the VNDK APEX. 784func (a *apexBundle) getImageVariation(ctx android.BottomUpMutatorContext) string { 785 prefix, vndkVersion := a.getImageVariationPair(ctx.DeviceConfig()) 786 return prefix + vndkVersion 787} 788 789func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { 790 // apexBundle is a multi-arch targets module. Arch variant of apexBundle is set to 'common'. 791 // arch-specific targets are enabled by the compile_multilib setting of the apex bundle. For 792 // each target os/architectures, appropriate dependencies are selected by their 793 // target.<os>.multilib.<type> groups and are added as (direct) dependencies. 794 targets := ctx.MultiTargets() 795 imageVariation := a.getImageVariation(ctx) 796 797 a.combineProperties(ctx) 798 799 has32BitTarget := false 800 for _, target := range targets { 801 if target.Arch.ArchType.Multilib == "lib32" { 802 has32BitTarget = true 803 } 804 } 805 for i, target := range targets { 806 // Don't include artifacts for the host cross targets because there is no way for us 807 // to run those artifacts natively on host 808 if target.HostCross { 809 continue 810 } 811 812 var deps ApexNativeDependencies 813 814 // Add native modules targeting both ABIs. When multilib.* is omitted for 815 // native_shared_libs/jni_libs/tests, it implies multilib.both 816 deps.Merge(a.properties.Multilib.Both) 817 deps.Merge(ApexNativeDependencies{ 818 Native_shared_libs: a.properties.Native_shared_libs, 819 Tests: a.properties.Tests, 820 Jni_libs: a.properties.Jni_libs, 821 Binaries: nil, 822 }) 823 824 // Add native modules targeting the first ABI When multilib.* is omitted for 825 // binaries, it implies multilib.first 826 isPrimaryAbi := i == 0 827 if isPrimaryAbi { 828 deps.Merge(a.properties.Multilib.First) 829 deps.Merge(ApexNativeDependencies{ 830 Native_shared_libs: nil, 831 Tests: nil, 832 Jni_libs: nil, 833 Binaries: a.properties.Binaries, 834 }) 835 } 836 837 // Add native modules targeting either 32-bit or 64-bit ABI 838 switch target.Arch.ArchType.Multilib { 839 case "lib32": 840 deps.Merge(a.properties.Multilib.Lib32) 841 deps.Merge(a.properties.Multilib.Prefer32) 842 case "lib64": 843 deps.Merge(a.properties.Multilib.Lib64) 844 if !has32BitTarget { 845 deps.Merge(a.properties.Multilib.Prefer32) 846 } 847 } 848 849 // Add native modules targeting a specific arch variant 850 switch target.Arch.ArchType { 851 case android.Arm: 852 deps.Merge(a.archProperties.Arch.Arm.ApexNativeDependencies) 853 case android.Arm64: 854 deps.Merge(a.archProperties.Arch.Arm64.ApexNativeDependencies) 855 case android.Riscv64: 856 deps.Merge(a.archProperties.Arch.Riscv64.ApexNativeDependencies) 857 case android.X86: 858 deps.Merge(a.archProperties.Arch.X86.ApexNativeDependencies) 859 case android.X86_64: 860 deps.Merge(a.archProperties.Arch.X86_64.ApexNativeDependencies) 861 default: 862 panic(fmt.Errorf("unsupported arch %v\n", ctx.Arch().ArchType)) 863 } 864 865 addDependenciesForNativeModules(ctx, deps, target, imageVariation) 866 ctx.AddFarVariationDependencies([]blueprint.Variation{ 867 {Mutator: "os", Variation: target.OsVariation()}, 868 {Mutator: "arch", Variation: target.ArchVariation()}, 869 }, shBinaryTag, a.properties.Sh_binaries...) 870 } 871 872 // Common-arch dependencies come next 873 commonVariation := ctx.Config().AndroidCommonTarget.Variations() 874 ctx.AddFarVariationDependencies(commonVariation, rroTag, a.properties.Rros...) 875 ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments...) 876 ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments...) 877 ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...) 878 ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...) 879 ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...) 880} 881 882// DepsMutator for the overridden properties. 883func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) { 884 if a.overridableProperties.Allowed_files != nil { 885 android.ExtractSourceDeps(ctx, a.overridableProperties.Allowed_files) 886 } 887 888 commonVariation := ctx.Config().AndroidCommonTarget.Variations() 889 ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps...) 890 ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...) 891 if prebuilts := a.overridableProperties.Prebuilts; len(prebuilts) > 0 { 892 // For prebuilt_etc, use the first variant (64 on 64/32bit device, 32 on 32bit device) 893 // regardless of the TARGET_PREFER_* setting. See b/144532908 894 arches := ctx.DeviceConfig().Arches() 895 if len(arches) != 0 { 896 archForPrebuiltEtc := arches[0] 897 for _, arch := range arches { 898 // Prefer 64-bit arch if there is any 899 if arch.ArchType.Multilib == "lib64" { 900 archForPrebuiltEtc = arch 901 break 902 } 903 } 904 ctx.AddFarVariationDependencies([]blueprint.Variation{ 905 {Mutator: "os", Variation: ctx.Os().String()}, 906 {Mutator: "arch", Variation: archForPrebuiltEtc.String()}, 907 }, prebuiltTag, prebuilts...) 908 } 909 } 910 911 // Dependencies for signing 912 if String(a.overridableProperties.Key) == "" { 913 ctx.PropertyErrorf("key", "missing") 914 return 915 } 916 ctx.AddDependency(ctx.Module(), keyTag, String(a.overridableProperties.Key)) 917 918 cert := android.SrcIsModule(a.getCertString(ctx)) 919 if cert != "" { 920 ctx.AddDependency(ctx.Module(), certificateTag, cert) 921 // empty cert is not an error. Cert and private keys will be directly found under 922 // PRODUCT_DEFAULT_DEV_CERTIFICATE 923 } 924} 925 926func apexDCLADepsMutator(mctx android.BottomUpMutatorContext) { 927 if !mctx.Config().ApexTrimEnabled() { 928 return 929 } 930 if a, ok := mctx.Module().(*apexBundle); ok && a.overridableProperties.Trim_against != nil { 931 commonVariation := mctx.Config().AndroidCommonTarget.Variations() 932 mctx.AddFarVariationDependencies(commonVariation, dclaTag, String(a.overridableProperties.Trim_against)) 933 } else if o, ok := mctx.Module().(*OverrideApex); ok { 934 for _, p := range o.GetProperties() { 935 properties, ok := p.(*overridableProperties) 936 if !ok { 937 continue 938 } 939 if properties.Trim_against != nil { 940 commonVariation := mctx.Config().AndroidCommonTarget.Variations() 941 mctx.AddFarVariationDependencies(commonVariation, dclaTag, String(properties.Trim_against)) 942 } 943 } 944 } 945} 946 947type DCLAInfo struct { 948 ProvidedLibs []string 949} 950 951var DCLAInfoProvider = blueprint.NewMutatorProvider(DCLAInfo{}, "apex_info") 952 953type ApexBundleInfo struct { 954 Contents *android.ApexContents 955} 956 957var ApexBundleInfoProvider = blueprint.NewMutatorProvider(ApexBundleInfo{}, "apex_info") 958 959var _ ApexInfoMutator = (*apexBundle)(nil) 960 961func (a *apexBundle) ApexVariationName() string { 962 return a.properties.ApexVariationName 963} 964 965// ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are 966// identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and 967// indirect) dependencies are collected. But a few types of modules that shouldn't be included in 968// the apexBundle (e.g. stub libraries) are not collected. Note that a single module can be depended 969// on by multiple apexBundles. In that case, the module is collected for all of the apexBundles. 970// 971// For each dependency between an apex and an ApexModule an ApexInfo object describing the apex 972// is passed to that module's BuildForApex(ApexInfo) method which collates them all in a list. 973// The apexMutator uses that list to create module variants for the apexes to which it belongs. 974// The relationship between module variants and apexes is not one-to-one as variants will be 975// shared between compatible apexes. 976func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { 977 978 // The VNDK APEX is special. For the APEX, the membership is described in a very different 979 // way. There is no dependency from the VNDK APEX to the VNDK libraries. Instead, VNDK 980 // libraries are self-identified by their vndk.enabled properties. There is no need to run 981 // this mutator for the APEX as nothing will be collected. So, let's return fast. 982 if a.vndkApex { 983 return 984 } 985 986 // Special casing for APEXes on non-system (e.g., vendor, odm, etc.) partitions. They are 987 // provided with a property named use_vndk_as_stable, which when set to true doesn't collect 988 // VNDK libraries as transitive dependencies. This option is useful for reducing the size of 989 // the non-system APEXes because the VNDK libraries won't be included (and duped) in the 990 // APEX, but shared across APEXes via the VNDK APEX. 991 useVndk := a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && mctx.Config().EnforceProductPartitionInterface()) 992 excludeVndkLibs := useVndk && proptools.Bool(a.properties.Use_vndk_as_stable) 993 if proptools.Bool(a.properties.Use_vndk_as_stable) { 994 if !useVndk { 995 mctx.PropertyErrorf("use_vndk_as_stable", "not supported for system/system_ext APEXes") 996 } 997 if a.minSdkVersionValue(mctx) != "" { 998 mctx.PropertyErrorf("use_vndk_as_stable", "not supported when min_sdk_version is set") 999 } 1000 mctx.VisitDirectDepsWithTag(sharedLibTag, func(dep android.Module) { 1001 if c, ok := dep.(*cc.Module); ok && c.IsVndk() { 1002 mctx.PropertyErrorf("use_vndk_as_stable", "Trying to include a VNDK library(%s) while use_vndk_as_stable is true.", dep.Name()) 1003 } 1004 }) 1005 if mctx.Failed() { 1006 return 1007 } 1008 } 1009 1010 continueApexDepsWalk := func(child, parent android.Module) bool { 1011 am, ok := child.(android.ApexModule) 1012 if !ok || !am.CanHaveApexVariants() { 1013 return false 1014 } 1015 depTag := mctx.OtherModuleDependencyTag(child) 1016 1017 // Check to see if the tag always requires that the child module has an apex variant for every 1018 // apex variant of the parent module. If it does not then it is still possible for something 1019 // else, e.g. the DepIsInSameApex(...) method to decide that a variant is required. 1020 if required, ok := depTag.(android.AlwaysRequireApexVariantTag); ok && required.AlwaysRequireApexVariant() { 1021 return true 1022 } 1023 if !android.IsDepInSameApex(mctx, parent, child) { 1024 return false 1025 } 1026 if excludeVndkLibs { 1027 if c, ok := child.(*cc.Module); ok && c.IsVndk() { 1028 return false 1029 } 1030 } 1031 // By default, all the transitive dependencies are collected, unless filtered out 1032 // above. 1033 return true 1034 } 1035 1036 // Records whether a certain module is included in this apexBundle via direct dependency or 1037 // inndirect dependency. 1038 contents := make(map[string]android.ApexMembership) 1039 mctx.WalkDeps(func(child, parent android.Module) bool { 1040 if !continueApexDepsWalk(child, parent) { 1041 return false 1042 } 1043 // If the parent is apexBundle, this child is directly depended. 1044 _, directDep := parent.(*apexBundle) 1045 depName := mctx.OtherModuleName(child) 1046 contents[depName] = contents[depName].Add(directDep) 1047 return true 1048 }) 1049 1050 // The membership information is saved for later access 1051 apexContents := android.NewApexContents(contents) 1052 mctx.SetProvider(ApexBundleInfoProvider, ApexBundleInfo{ 1053 Contents: apexContents, 1054 }) 1055 1056 minSdkVersion := a.minSdkVersion(mctx) 1057 // When min_sdk_version is not set, the apex is built against FutureApiLevel. 1058 if minSdkVersion.IsNone() { 1059 minSdkVersion = android.FutureApiLevel 1060 } 1061 1062 // This is the main part of this mutator. Mark the collected dependencies that they need to 1063 // be built for this apexBundle. 1064 1065 apexVariationName := mctx.ModuleName() // could be com.android.foo 1066 a.properties.ApexVariationName = apexVariationName 1067 apexInfo := android.ApexInfo{ 1068 ApexVariationName: apexVariationName, 1069 MinSdkVersion: minSdkVersion, 1070 Updatable: a.Updatable(), 1071 UsePlatformApis: a.UsePlatformApis(), 1072 InApexVariants: []string{apexVariationName}, 1073 InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo 1074 ApexContents: []*android.ApexContents{apexContents}, 1075 } 1076 mctx.WalkDeps(func(child, parent android.Module) bool { 1077 if !continueApexDepsWalk(child, parent) { 1078 return false 1079 } 1080 child.(android.ApexModule).BuildForApex(apexInfo) // leave a mark! 1081 return true 1082 }) 1083 1084 if a.dynamic_common_lib_apex() { 1085 mctx.SetProvider(DCLAInfoProvider, DCLAInfo{ 1086 ProvidedLibs: a.properties.Native_shared_libs, 1087 }) 1088 } 1089} 1090 1091type ApexInfoMutator interface { 1092 // ApexVariationName returns the name of the APEX variation to use in the apex 1093 // mutator etc. It is the same name as ApexInfo.ApexVariationName. 1094 ApexVariationName() string 1095 1096 // ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are 1097 // depended upon by an apex and which require an apex specific variant. 1098 ApexInfoMutator(android.TopDownMutatorContext) 1099} 1100 1101// apexInfoMutator delegates the work of identifying which modules need an ApexInfo and apex 1102// specific variant to modules that support the ApexInfoMutator. 1103// It also propagates updatable=true to apps of updatable apexes 1104func apexInfoMutator(mctx android.TopDownMutatorContext) { 1105 if !mctx.Module().Enabled() { 1106 return 1107 } 1108 1109 if a, ok := mctx.Module().(ApexInfoMutator); ok { 1110 a.ApexInfoMutator(mctx) 1111 } 1112 enforceAppUpdatability(mctx) 1113} 1114 1115// apexStrictUpdatibilityLintMutator propagates strict_updatability_linting to transitive deps of a mainline module 1116// This check is enforced for updatable modules 1117func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) { 1118 if !mctx.Module().Enabled() { 1119 return 1120 } 1121 if apex, ok := mctx.Module().(*apexBundle); ok && apex.checkStrictUpdatabilityLinting() { 1122 mctx.WalkDeps(func(child, parent android.Module) bool { 1123 // b/208656169 Do not propagate strict updatability linting to libcore/ 1124 // These libs are available on the classpath during compilation 1125 // These libs are transitive deps of the sdk. See java/sdk.go:decodeSdkDep 1126 // Only skip libraries defined in libcore root, not subdirectories 1127 if mctx.OtherModuleDir(child) == "libcore" { 1128 // Do not traverse transitive deps of libcore/ libs 1129 return false 1130 } 1131 if android.InList(child.Name(), skipLintJavalibAllowlist) { 1132 return false 1133 } 1134 if lintable, ok := child.(java.LintDepSetsIntf); ok { 1135 lintable.SetStrictUpdatabilityLinting(true) 1136 } 1137 // visit transitive deps 1138 return true 1139 }) 1140 } 1141} 1142 1143// enforceAppUpdatability propagates updatable=true to apps of updatable apexes 1144func enforceAppUpdatability(mctx android.TopDownMutatorContext) { 1145 if !mctx.Module().Enabled() { 1146 return 1147 } 1148 if apex, ok := mctx.Module().(*apexBundle); ok && apex.Updatable() { 1149 // checking direct deps is sufficient since apex->apk is a direct edge, even when inherited via apex_defaults 1150 mctx.VisitDirectDeps(func(module android.Module) { 1151 // ignore android_test_app 1152 if app, ok := module.(*java.AndroidApp); ok { 1153 app.SetUpdatable(true) 1154 } 1155 }) 1156 } 1157} 1158 1159// TODO: b/215736885 Whittle the denylist 1160// Transitive deps of certain mainline modules baseline NewApi errors 1161// Skip these mainline modules for now 1162var ( 1163 skipStrictUpdatabilityLintAllowlist = []string{ 1164 "com.android.art", 1165 "com.android.art.debug", 1166 "com.android.conscrypt", 1167 "com.android.media", 1168 // test apexes 1169 "test_com.android.art", 1170 "test_com.android.conscrypt", 1171 "test_com.android.media", 1172 "test_jitzygote_com.android.art", 1173 } 1174 1175 // TODO: b/215736885 Remove this list 1176 skipLintJavalibAllowlist = []string{ 1177 "conscrypt.module.platform.api.stubs", 1178 "conscrypt.module.public.api.stubs", 1179 "conscrypt.module.public.api.stubs.system", 1180 "conscrypt.module.public.api.stubs.module_lib", 1181 "framework-media.stubs", 1182 "framework-media.stubs.system", 1183 "framework-media.stubs.module_lib", 1184 } 1185) 1186 1187func (a *apexBundle) checkStrictUpdatabilityLinting() bool { 1188 return a.Updatable() && !android.InList(a.ApexVariationName(), skipStrictUpdatabilityLintAllowlist) 1189} 1190 1191// apexUniqueVariationsMutator checks if any dependencies use unique apex variations. If so, use 1192// unique apex variations for this module. See android/apex.go for more about unique apex variant. 1193// TODO(jiyong): move this to android/apex.go? 1194func apexUniqueVariationsMutator(mctx android.BottomUpMutatorContext) { 1195 if !mctx.Module().Enabled() { 1196 return 1197 } 1198 if am, ok := mctx.Module().(android.ApexModule); ok { 1199 android.UpdateUniqueApexVariationsForDeps(mctx, am) 1200 } 1201} 1202 1203// apexTestForDepsMutator checks if this module is a test for an apex. If so, add a dependency on 1204// the apex in order to retrieve its contents later. 1205// TODO(jiyong): move this to android/apex.go? 1206func apexTestForDepsMutator(mctx android.BottomUpMutatorContext) { 1207 if !mctx.Module().Enabled() { 1208 return 1209 } 1210 if am, ok := mctx.Module().(android.ApexModule); ok { 1211 if testFor := am.TestFor(); len(testFor) > 0 { 1212 mctx.AddFarVariationDependencies([]blueprint.Variation{ 1213 {Mutator: "os", Variation: am.Target().OsVariation()}, 1214 {"arch", "common"}, 1215 }, testForTag, testFor...) 1216 } 1217 } 1218} 1219 1220// TODO(jiyong): move this to android/apex.go? 1221func apexTestForMutator(mctx android.BottomUpMutatorContext) { 1222 if !mctx.Module().Enabled() { 1223 return 1224 } 1225 if _, ok := mctx.Module().(android.ApexModule); ok { 1226 var contents []*android.ApexContents 1227 for _, testFor := range mctx.GetDirectDepsWithTag(testForTag) { 1228 abInfo := mctx.OtherModuleProvider(testFor, ApexBundleInfoProvider).(ApexBundleInfo) 1229 contents = append(contents, abInfo.Contents) 1230 } 1231 mctx.SetProvider(android.ApexTestForInfoProvider, android.ApexTestForInfo{ 1232 ApexContents: contents, 1233 }) 1234 } 1235} 1236 1237// markPlatformAvailability marks whether or not a module can be available to platform. A module 1238// cannot be available to platform if 1) it is explicitly marked as not available (i.e. 1239// "//apex_available:platform" is absent) or 2) it depends on another module that isn't (or can't 1240// be) available to platform 1241// TODO(jiyong): move this to android/apex.go? 1242func markPlatformAvailability(mctx android.BottomUpMutatorContext) { 1243 // Host and recovery are not considered as platform 1244 if mctx.Host() || mctx.Module().InstallInRecovery() { 1245 return 1246 } 1247 1248 am, ok := mctx.Module().(android.ApexModule) 1249 if !ok { 1250 return 1251 } 1252 1253 availableToPlatform := am.AvailableFor(android.AvailableToPlatform) 1254 1255 // If any of the dep is not available to platform, this module is also considered as being 1256 // not available to platform even if it has "//apex_available:platform" 1257 mctx.VisitDirectDeps(func(child android.Module) { 1258 if !android.IsDepInSameApex(mctx, am, child) { 1259 // if the dependency crosses apex boundary, don't consider it 1260 return 1261 } 1262 if dep, ok := child.(android.ApexModule); ok && dep.NotAvailableForPlatform() { 1263 availableToPlatform = false 1264 // TODO(b/154889534) trigger an error when 'am' has 1265 // "//apex_available:platform" 1266 } 1267 }) 1268 1269 // Exception 1: check to see if the module always requires it. 1270 if am.AlwaysRequiresPlatformApexVariant() { 1271 availableToPlatform = true 1272 } 1273 1274 // Exception 2: bootstrap bionic libraries are also always available to platform 1275 if cc.InstallToBootstrap(mctx.ModuleName(), mctx.Config()) { 1276 availableToPlatform = true 1277 } 1278 1279 if !availableToPlatform { 1280 am.SetNotAvailableForPlatform() 1281 } 1282} 1283 1284// apexMutator visits each module and creates apex variations if the module was marked in the 1285// previous run of apexInfoMutator. 1286func apexMutator(mctx android.BottomUpMutatorContext) { 1287 if !mctx.Module().Enabled() { 1288 return 1289 } 1290 1291 // This is the usual path. 1292 if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() { 1293 android.CreateApexVariations(mctx, am) 1294 return 1295 } 1296 1297 // apexBundle itself is mutated so that it and its dependencies have the same apex variant. 1298 if ai, ok := mctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) { 1299 apexBundleName := ai.ApexVariationName() 1300 mctx.CreateVariations(apexBundleName) 1301 if strings.HasPrefix(apexBundleName, "com.android.art") { 1302 // Create an alias from the platform variant. This is done to make 1303 // test_for dependencies work for modules that are split by the APEX 1304 // mutator, since test_for dependencies always go to the platform variant. 1305 // This doesn't happen for normal APEXes that are disjunct, so only do 1306 // this for the overlapping ART APEXes. 1307 // TODO(b/183882457): Remove this if the test_for functionality is 1308 // refactored to depend on the proper APEX variants instead of platform. 1309 mctx.CreateAliasVariation("", apexBundleName) 1310 } 1311 } else if o, ok := mctx.Module().(*OverrideApex); ok { 1312 apexBundleName := o.GetOverriddenModuleName() 1313 if apexBundleName == "" { 1314 mctx.ModuleErrorf("base property is not set") 1315 return 1316 } 1317 mctx.CreateVariations(apexBundleName) 1318 if strings.HasPrefix(apexBundleName, "com.android.art") { 1319 // TODO(b/183882457): See note for CreateAliasVariation above. 1320 mctx.CreateAliasVariation("", apexBundleName) 1321 } 1322 } 1323} 1324 1325// apexModuleTypeRequiresVariant determines whether the module supplied requires an apex specific 1326// variant. 1327func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool { 1328 if a, ok := module.(*apexBundle); ok { 1329 // TODO(jiyong): document the reason why the VNDK APEX is an exception here. 1330 return !a.vndkApex 1331 } 1332 1333 return true 1334} 1335 1336// See android.UpdateDirectlyInAnyApex 1337// TODO(jiyong): move this to android/apex.go? 1338func apexDirectlyInAnyMutator(mctx android.BottomUpMutatorContext) { 1339 if !mctx.Module().Enabled() { 1340 return 1341 } 1342 if am, ok := mctx.Module().(android.ApexModule); ok { 1343 android.UpdateDirectlyInAnyApex(mctx, am) 1344 } 1345} 1346 1347// apexPackaging represents a specific packaging method for an APEX. 1348type apexPackaging int 1349 1350const ( 1351 // imageApex is a packaging method where contents are included in a filesystem image which 1352 // is then included in a zip container. This is the most typical way of packaging. 1353 imageApex apexPackaging = iota 1354 1355 // zipApex is a packaging method where contents are directly included in the zip container. 1356 // This is used for host-side testing - because the contents are easily accessible by 1357 // unzipping the container. 1358 zipApex 1359 1360 // flattendApex is a packaging method where contents are not included in the APEX file, but 1361 // installed to /apex/<apexname> directory on the device. This packaging method is used for 1362 // old devices where the filesystem-based APEX file can't be supported. 1363 flattenedApex 1364) 1365 1366const ( 1367 // File extensions of an APEX for different packaging methods 1368 imageApexSuffix = ".apex" 1369 imageCapexSuffix = ".capex" 1370 zipApexSuffix = ".zipapex" 1371 flattenedSuffix = ".flattened" 1372 1373 // variant names each of which is for a packaging method 1374 imageApexType = "image" 1375 zipApexType = "zip" 1376 flattenedApexType = "flattened" 1377 1378 ext4FsType = "ext4" 1379 f2fsFsType = "f2fs" 1380 erofsFsType = "erofs" 1381) 1382 1383// The suffix for the output "file", not the module 1384func (a apexPackaging) suffix() string { 1385 switch a { 1386 case imageApex: 1387 return imageApexSuffix 1388 case zipApex: 1389 return zipApexSuffix 1390 default: 1391 panic(fmt.Errorf("unknown APEX type %d", a)) 1392 } 1393} 1394 1395func (a apexPackaging) name() string { 1396 switch a { 1397 case imageApex: 1398 return imageApexType 1399 case zipApex: 1400 return zipApexType 1401 default: 1402 panic(fmt.Errorf("unknown APEX type %d", a)) 1403 } 1404} 1405 1406// apexFlattenedMutator creates one or more variations each of which is for a packaging method. 1407// TODO(jiyong): give a better name to this mutator 1408func apexFlattenedMutator(mctx android.BottomUpMutatorContext) { 1409 if !mctx.Module().Enabled() { 1410 return 1411 } 1412 if ab, ok := mctx.Module().(*apexBundle); ok { 1413 var variants []string 1414 switch proptools.StringDefault(ab.properties.Payload_type, "image") { 1415 case "image": 1416 // This is the normal case. Note that both image and flattend APEXes are 1417 // created. The image type is installed to the system partition, while the 1418 // flattened APEX is (optionally) installed to the system_ext partition. 1419 // This is mostly for GSI which has to support wide range of devices. If GSI 1420 // is installed on a newer (APEX-capable) device, the image APEX in the 1421 // system will be used. However, if the same GSI is installed on an old 1422 // device which can't support image APEX, the flattened APEX in the 1423 // system_ext partion (which still is part of GSI) is used instead. 1424 variants = append(variants, imageApexType, flattenedApexType) 1425 case "zip": 1426 variants = append(variants, zipApexType) 1427 case "both": 1428 variants = append(variants, imageApexType, zipApexType, flattenedApexType) 1429 default: 1430 mctx.PropertyErrorf("payload_type", "%q is not one of \"image\", \"zip\", or \"both\".", *ab.properties.Payload_type) 1431 return 1432 } 1433 1434 modules := mctx.CreateLocalVariations(variants...) 1435 1436 for i, v := range variants { 1437 switch v { 1438 case imageApexType: 1439 modules[i].(*apexBundle).properties.ApexType = imageApex 1440 case zipApexType: 1441 modules[i].(*apexBundle).properties.ApexType = zipApex 1442 case flattenedApexType: 1443 modules[i].(*apexBundle).properties.ApexType = flattenedApex 1444 // See the comment above for why system_ext. 1445 if !mctx.Config().FlattenApex() && ab.Platform() { 1446 modules[i].(*apexBundle).MakeAsSystemExt() 1447 } 1448 } 1449 } 1450 } else if _, ok := mctx.Module().(*OverrideApex); ok { 1451 // payload_type is forcibly overridden to "image" 1452 // TODO(jiyong): is this the right decision? 1453 mctx.CreateVariations(imageApexType, flattenedApexType) 1454 } 1455} 1456 1457var _ android.DepIsInSameApex = (*apexBundle)(nil) 1458 1459// Implements android.DepInInSameApex 1460func (a *apexBundle) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool { 1461 // direct deps of an APEX bundle are all part of the APEX bundle 1462 // TODO(jiyong): shouldn't we look into the payload field of the dependencyTag? 1463 return true 1464} 1465 1466var _ android.OutputFileProducer = (*apexBundle)(nil) 1467 1468// Implements android.OutputFileProducer 1469func (a *apexBundle) OutputFiles(tag string) (android.Paths, error) { 1470 switch tag { 1471 case "", android.DefaultDistTag: 1472 // This is the default dist path. 1473 return android.Paths{a.outputFile}, nil 1474 case imageApexSuffix: 1475 // uncompressed one 1476 if a.outputApexFile != nil { 1477 return android.Paths{a.outputApexFile}, nil 1478 } 1479 fallthrough 1480 default: 1481 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 1482 } 1483} 1484 1485var _ multitree.Exportable = (*apexBundle)(nil) 1486 1487func (a *apexBundle) Exportable() bool { 1488 if a.properties.ApexType == flattenedApex { 1489 return false 1490 } 1491 return true 1492} 1493 1494func (a *apexBundle) TaggedOutputs() map[string]android.Paths { 1495 ret := make(map[string]android.Paths) 1496 ret["apex"] = android.Paths{a.outputFile} 1497 return ret 1498} 1499 1500var _ cc.Coverage = (*apexBundle)(nil) 1501 1502// Implements cc.Coverage 1503func (a *apexBundle) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool { 1504 return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled() 1505} 1506 1507// Implements cc.Coverage 1508func (a *apexBundle) SetPreventInstall() { 1509 a.properties.PreventInstall = true 1510} 1511 1512// Implements cc.Coverage 1513func (a *apexBundle) HideFromMake() { 1514 a.properties.HideFromMake = true 1515 // This HideFromMake is shadowing the ModuleBase one, call through to it for now. 1516 // TODO(ccross): untangle these 1517 a.ModuleBase.HideFromMake() 1518} 1519 1520// Implements cc.Coverage 1521func (a *apexBundle) MarkAsCoverageVariant(coverage bool) { 1522 a.properties.IsCoverageVariant = coverage 1523} 1524 1525// Implements cc.Coverage 1526func (a *apexBundle) EnableCoverageIfNeeded() {} 1527 1528var _ android.ApexBundleDepsInfoIntf = (*apexBundle)(nil) 1529 1530// Implements android.ApexBundleDepsInfoIntf 1531func (a *apexBundle) Updatable() bool { 1532 return proptools.BoolDefault(a.properties.Updatable, true) 1533} 1534 1535func (a *apexBundle) FutureUpdatable() bool { 1536 return proptools.BoolDefault(a.properties.Future_updatable, false) 1537} 1538 1539func (a *apexBundle) UsePlatformApis() bool { 1540 return proptools.BoolDefault(a.properties.Platform_apis, false) 1541} 1542 1543// getCertString returns the name of the cert that should be used to sign this APEX. This is 1544// basically from the "certificate" property, but could be overridden by the device config. 1545func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string { 1546 moduleName := ctx.ModuleName() 1547 // VNDK APEXes share the same certificate. To avoid adding a new VNDK version to the 1548 // OVERRIDE_* list, we check with the pseudo module name to see if its certificate is 1549 // overridden. 1550 if a.vndkApex { 1551 moduleName = vndkApexName 1552 } 1553 certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(moduleName) 1554 if overridden { 1555 return ":" + certificate 1556 } 1557 return String(a.overridableProperties.Certificate) 1558} 1559 1560// See the installable property 1561func (a *apexBundle) installable() bool { 1562 return !a.properties.PreventInstall && (a.properties.Installable == nil || proptools.Bool(a.properties.Installable)) 1563} 1564 1565// See the generate_hashtree property 1566func (a *apexBundle) shouldGenerateHashtree() bool { 1567 return proptools.BoolDefault(a.properties.Generate_hashtree, true) 1568} 1569 1570// See the test_only_unsigned_payload property 1571func (a *apexBundle) testOnlyShouldSkipPayloadSign() bool { 1572 return proptools.Bool(a.properties.Test_only_unsigned_payload) 1573} 1574 1575// See the test_only_force_compression property 1576func (a *apexBundle) testOnlyShouldForceCompression() bool { 1577 return proptools.Bool(a.properties.Test_only_force_compression) 1578} 1579 1580// See the dynamic_common_lib_apex property 1581func (a *apexBundle) dynamic_common_lib_apex() bool { 1582 return proptools.BoolDefault(a.properties.Dynamic_common_lib_apex, false) 1583} 1584 1585// See the list of libs to trim 1586func (a *apexBundle) libs_to_trim(ctx android.ModuleContext) []string { 1587 dclaModules := ctx.GetDirectDepsWithTag(dclaTag) 1588 if len(dclaModules) > 1 { 1589 panic(fmt.Errorf("expected exactly at most one dcla dependency, got %d", len(dclaModules))) 1590 } 1591 if len(dclaModules) > 0 { 1592 DCLAInfo := ctx.OtherModuleProvider(dclaModules[0], DCLAInfoProvider).(DCLAInfo) 1593 return DCLAInfo.ProvidedLibs 1594 } 1595 return []string{} 1596} 1597 1598// These functions are interfacing with cc/sanitizer.go. The entire APEX (along with all of its 1599// members) can be sanitized, either forcibly, or by the global configuration. For some of the 1600// sanitizers, extra dependencies can be forcibly added as well. 1601 1602func (a *apexBundle) EnableSanitizer(sanitizerName string) { 1603 if !android.InList(sanitizerName, a.properties.SanitizerNames) { 1604 a.properties.SanitizerNames = append(a.properties.SanitizerNames, sanitizerName) 1605 } 1606} 1607 1608func (a *apexBundle) IsSanitizerEnabled(config android.Config, sanitizerName string) bool { 1609 if android.InList(sanitizerName, a.properties.SanitizerNames) { 1610 return true 1611 } 1612 1613 // Then follow the global setting 1614 var globalSanitizerNames []string 1615 if a.Host() { 1616 globalSanitizerNames = config.SanitizeHost() 1617 } else { 1618 arches := config.SanitizeDeviceArch() 1619 if len(arches) == 0 || android.InList(a.Arch().ArchType.Name, arches) { 1620 globalSanitizerNames = config.SanitizeDevice() 1621 } 1622 } 1623 return android.InList(sanitizerName, globalSanitizerNames) 1624} 1625 1626func (a *apexBundle) AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string) { 1627 // TODO(jiyong): move this info (the sanitizer name, the lib name, etc.) to cc/sanitize.go 1628 // Keep only the mechanism here. 1629 if ctx.Device() && sanitizerName == "hwaddress" && strings.HasPrefix(a.Name(), "com.android.runtime") { 1630 imageVariation := a.getImageVariation(ctx) 1631 for _, target := range ctx.MultiTargets() { 1632 if target.Arch.ArchType.Multilib == "lib64" { 1633 addDependenciesForNativeModules(ctx, ApexNativeDependencies{ 1634 Native_shared_libs: []string{"libclang_rt.hwasan"}, 1635 Tests: nil, 1636 Jni_libs: nil, 1637 Binaries: nil, 1638 }, target, imageVariation) 1639 break 1640 } 1641 } 1642 } 1643} 1644 1645// apexFileFor<Type> functions below create an apexFile struct for a given Soong module. The 1646// returned apexFile saves information about the Soong module that will be used for creating the 1647// build rules. 1648func apexFileForNativeLibrary(ctx android.BaseModuleContext, ccMod *cc.Module, handleSpecialLibs bool) apexFile { 1649 // Decide the APEX-local directory by the multilib of the library In the future, we may 1650 // query this to the module. 1651 // TODO(jiyong): use the new PackagingSpec 1652 var dirInApex string 1653 switch ccMod.Arch().ArchType.Multilib { 1654 case "lib32": 1655 dirInApex = "lib" 1656 case "lib64": 1657 dirInApex = "lib64" 1658 } 1659 if ccMod.Target().NativeBridge == android.NativeBridgeEnabled { 1660 dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath) 1661 } 1662 if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), ctx.Config()) { 1663 // Special case for Bionic libs and other libs installed with them. This is to 1664 // prevent those libs from being included in the search path 1665 // /apex/com.android.runtime/${LIB}. This exclusion is required because those libs 1666 // in the Runtime APEX are available via the legacy paths in /system/lib/. By the 1667 // init process, the libs in the APEX are bind-mounted to the legacy paths and thus 1668 // will be loaded into the default linker namespace (aka "platform" namespace). If 1669 // the libs are directly in /apex/com.android.runtime/${LIB} then the same libs will 1670 // be loaded again into the runtime linker namespace, which will result in double 1671 // loading of them, which isn't supported. 1672 dirInApex = filepath.Join(dirInApex, "bionic") 1673 } 1674 // This needs to go after the runtime APEX handling because otherwise we would get 1675 // weird paths like lib64/rel_install_path/bionic rather than 1676 // lib64/bionic/rel_install_path. 1677 dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath()) 1678 1679 fileToCopy := android.OutputFileForModule(ctx, ccMod, "") 1680 androidMkModuleName := ccMod.BaseModuleName() + ccMod.Properties.SubName 1681 return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, ccMod) 1682} 1683 1684func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFile { 1685 dirInApex := "bin" 1686 if cc.Target().NativeBridge == android.NativeBridgeEnabled { 1687 dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath) 1688 } 1689 dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath()) 1690 fileToCopy := android.OutputFileForModule(ctx, cc, "") 1691 androidMkModuleName := cc.BaseModuleName() + cc.Properties.SubName 1692 af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, cc) 1693 af.symlinks = cc.Symlinks() 1694 af.dataPaths = cc.DataPaths() 1695 return af 1696} 1697 1698func apexFileForRustExecutable(ctx android.BaseModuleContext, rustm *rust.Module) apexFile { 1699 dirInApex := "bin" 1700 if rustm.Target().NativeBridge == android.NativeBridgeEnabled { 1701 dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath) 1702 } 1703 fileToCopy := android.OutputFileForModule(ctx, rustm, "") 1704 androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName 1705 af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, rustm) 1706 return af 1707} 1708 1709func apexFileForRustLibrary(ctx android.BaseModuleContext, rustm *rust.Module) apexFile { 1710 // Decide the APEX-local directory by the multilib of the library 1711 // In the future, we may query this to the module. 1712 var dirInApex string 1713 switch rustm.Arch().ArchType.Multilib { 1714 case "lib32": 1715 dirInApex = "lib" 1716 case "lib64": 1717 dirInApex = "lib64" 1718 } 1719 if rustm.Target().NativeBridge == android.NativeBridgeEnabled { 1720 dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath) 1721 } 1722 fileToCopy := android.OutputFileForModule(ctx, rustm, "") 1723 androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName 1724 return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, rustm) 1725} 1726 1727func apexFileForPyBinary(ctx android.BaseModuleContext, py *python.PythonBinaryModule) apexFile { 1728 dirInApex := "bin" 1729 fileToCopy := py.HostToolPath().Path() 1730 return newApexFile(ctx, fileToCopy, py.BaseModuleName(), dirInApex, pyBinary, py) 1731} 1732 1733func apexFileForGoBinary(ctx android.BaseModuleContext, depName string, gb bootstrap.GoBinaryTool) apexFile { 1734 dirInApex := "bin" 1735 fileToCopy := android.PathForGoBinary(ctx, gb) 1736 // NB: Since go binaries are static we don't need the module for anything here, which is 1737 // good since the go tool is a blueprint.Module not an android.Module like we would 1738 // normally use. 1739 // 1740 return newApexFile(ctx, fileToCopy, depName, dirInApex, goBinary, nil) 1741} 1742 1743func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFile { 1744 dirInApex := filepath.Join("bin", sh.SubDir()) 1745 if sh.Target().NativeBridge == android.NativeBridgeEnabled { 1746 dirInApex = filepath.Join(dirInApex, sh.Target().NativeBridgeRelativePath) 1747 } 1748 fileToCopy := sh.OutputFile() 1749 af := newApexFile(ctx, fileToCopy, sh.BaseModuleName(), dirInApex, shBinary, sh) 1750 af.symlinks = sh.Symlinks() 1751 return af 1752} 1753 1754func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, depName string) apexFile { 1755 dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir()) 1756 fileToCopy := prebuilt.OutputFile() 1757 return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, prebuilt) 1758} 1759 1760func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile { 1761 dirInApex := filepath.Join("etc", config.SubDir()) 1762 fileToCopy := config.CompatConfig() 1763 return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, config) 1764} 1765 1766// javaModule is an interface to handle all Java modules (java_library, dex_import, etc) in the same 1767// way. 1768type javaModule interface { 1769 android.Module 1770 BaseModuleName() string 1771 DexJarBuildPath() java.OptionalDexJarPath 1772 JacocoReportClassesFile() android.Path 1773 LintDepSets() java.LintDepSets 1774 Stem() string 1775} 1776 1777var _ javaModule = (*java.Library)(nil) 1778var _ javaModule = (*java.Import)(nil) 1779var _ javaModule = (*java.SdkLibrary)(nil) 1780var _ javaModule = (*java.DexImport)(nil) 1781var _ javaModule = (*java.SdkLibraryImport)(nil) 1782 1783// apexFileForJavaModule creates an apexFile for a java module's dex implementation jar. 1784func apexFileForJavaModule(ctx android.BaseModuleContext, module javaModule) apexFile { 1785 return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath().PathOrNil()) 1786} 1787 1788// apexFileForJavaModuleWithFile creates an apexFile for a java module with the supplied file. 1789func apexFileForJavaModuleWithFile(ctx android.BaseModuleContext, module javaModule, dexImplementationJar android.Path) apexFile { 1790 dirInApex := "javalib" 1791 af := newApexFile(ctx, dexImplementationJar, module.BaseModuleName(), dirInApex, javaSharedLib, module) 1792 af.jacocoReportClassesFile = module.JacocoReportClassesFile() 1793 af.lintDepSets = module.LintDepSets() 1794 af.customStem = module.Stem() + ".jar" 1795 if dexpreopter, ok := module.(java.DexpreopterInterface); ok { 1796 for _, install := range dexpreopter.DexpreoptBuiltInstalledForApex() { 1797 af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName()) 1798 } 1799 } 1800 return af 1801} 1802 1803func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile { 1804 if dexpreopter, ok := module.(java.DexpreopterInterface); ok { 1805 if profilePathOnHost := dexpreopter.OutputProfilePathOnHost(); profilePathOnHost != nil { 1806 dirInApex := "javalib" 1807 af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil) 1808 af.customStem = module.Stem() + ".jar.prof" 1809 return &af 1810 } 1811 } 1812 return nil 1813} 1814 1815// androidApp is an interface to handle all app modules (android_app, android_app_import, etc.) in 1816// the same way. 1817type androidApp interface { 1818 android.Module 1819 Privileged() bool 1820 InstallApkName() string 1821 OutputFile() android.Path 1822 JacocoReportClassesFile() android.Path 1823 Certificate() java.Certificate 1824 BaseModuleName() string 1825 LintDepSets() java.LintDepSets 1826} 1827 1828var _ androidApp = (*java.AndroidApp)(nil) 1829var _ androidApp = (*java.AndroidAppImport)(nil) 1830 1831func sanitizedBuildIdForPath(ctx android.BaseModuleContext) string { 1832 buildId := ctx.Config().BuildId() 1833 1834 // The build ID is used as a suffix for a filename, so ensure that 1835 // the set of characters being used are sanitized. 1836 // - any word character: [a-zA-Z0-9_] 1837 // - dots: . 1838 // - dashes: - 1839 validRegex := regexp.MustCompile(`^[\w\.\-\_]+$`) 1840 if !validRegex.MatchString(buildId) { 1841 ctx.ModuleErrorf("Unable to use build id %s as filename suffix, valid characters are [a-z A-Z 0-9 _ . -].", buildId) 1842 } 1843 return buildId 1844} 1845 1846func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) apexFile { 1847 appDir := "app" 1848 if aapp.Privileged() { 1849 appDir = "priv-app" 1850 } 1851 1852 // TODO(b/224589412, b/226559955): Ensure that the subdirname is suffixed 1853 // so that PackageManager correctly invalidates the existing installed apk 1854 // in favour of the new APK-in-APEX. See bugs for more information. 1855 dirInApex := filepath.Join(appDir, aapp.InstallApkName()+"@"+sanitizedBuildIdForPath(ctx)) 1856 fileToCopy := aapp.OutputFile() 1857 1858 af := newApexFile(ctx, fileToCopy, aapp.BaseModuleName(), dirInApex, app, aapp) 1859 af.jacocoReportClassesFile = aapp.JacocoReportClassesFile() 1860 af.lintDepSets = aapp.LintDepSets() 1861 af.certificate = aapp.Certificate() 1862 1863 if app, ok := aapp.(interface { 1864 OverriddenManifestPackageName() string 1865 }); ok { 1866 af.overriddenPackageName = app.OverriddenManifestPackageName() 1867 } 1868 return af 1869} 1870 1871func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, rro java.RuntimeResourceOverlayModule) apexFile { 1872 rroDir := "overlay" 1873 dirInApex := filepath.Join(rroDir, rro.Theme()) 1874 fileToCopy := rro.OutputFile() 1875 af := newApexFile(ctx, fileToCopy, rro.Name(), dirInApex, app, rro) 1876 af.certificate = rro.Certificate() 1877 1878 if a, ok := rro.(interface { 1879 OverriddenManifestPackageName() string 1880 }); ok { 1881 af.overriddenPackageName = a.OverriddenManifestPackageName() 1882 } 1883 return af 1884} 1885 1886func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram bpf.BpfModule) apexFile { 1887 dirInApex := filepath.Join("etc", "bpf", apex_sub_dir) 1888 return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram) 1889} 1890 1891func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, fs filesystem.Filesystem) apexFile { 1892 dirInApex := filepath.Join("etc", "fs") 1893 return newApexFile(ctx, buildFile, buildFile.Base(), dirInApex, etc, fs) 1894} 1895 1896// WalkPayloadDeps visits dependencies that contributes to the payload of this APEX. For each of the 1897// visited module, the `do` callback is executed. Returning true in the callback continues the visit 1898// to the child modules. Returning false makes the visit to continue in the sibling or the parent 1899// modules. This is used in check* functions below. 1900func (a *apexBundle) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) { 1901 ctx.WalkDeps(func(child, parent android.Module) bool { 1902 am, ok := child.(android.ApexModule) 1903 if !ok || !am.CanHaveApexVariants() { 1904 return false 1905 } 1906 1907 // Filter-out unwanted depedendencies 1908 depTag := ctx.OtherModuleDependencyTag(child) 1909 if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { 1910 return false 1911 } 1912 if dt, ok := depTag.(*dependencyTag); ok && !dt.payload { 1913 return false 1914 } 1915 1916 ai := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo) 1917 externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants) 1918 1919 // Visit actually 1920 return do(ctx, parent, am, externalDep) 1921 }) 1922} 1923 1924// filesystem type of the apex_payload.img inside the APEX. Currently, ext4 and f2fs are supported. 1925type fsType int 1926 1927const ( 1928 ext4 fsType = iota 1929 f2fs 1930 erofs 1931) 1932 1933func (f fsType) string() string { 1934 switch f { 1935 case ext4: 1936 return ext4FsType 1937 case f2fs: 1938 return f2fsFsType 1939 case erofs: 1940 return erofsFsType 1941 default: 1942 panic(fmt.Errorf("unknown APEX payload type %d", f)) 1943 } 1944} 1945 1946var _ android.MixedBuildBuildable = (*apexBundle)(nil) 1947 1948func (a *apexBundle) IsMixedBuildSupported(ctx android.BaseModuleContext) bool { 1949 return a.properties.ApexType == imageApex 1950} 1951 1952func (a *apexBundle) QueueBazelCall(ctx android.BaseModuleContext) { 1953 bazelCtx := ctx.Config().BazelContext 1954 bazelCtx.QueueBazelRequest(a.GetBazelLabel(ctx, a), cquery.GetApexInfo, android.GetConfigKey(ctx)) 1955} 1956 1957// GetBazelLabel returns the bazel label of this apexBundle, or the label of the 1958// override_apex module overriding this apexBundle. An apexBundle can be 1959// overridden by different override_apex modules (e.g. Google or Go variants), 1960// which is handled by the overrides mutators. 1961func (a *apexBundle) GetBazelLabel(ctx android.BazelConversionPathContext, module blueprint.Module) string { 1962 if _, ok := ctx.Module().(android.OverridableModule); ok { 1963 return android.MaybeBp2buildLabelOfOverridingModule(ctx) 1964 } 1965 return a.BazelModuleBase.GetBazelLabel(ctx, a) 1966} 1967 1968func (a *apexBundle) ProcessBazelQueryResponse(ctx android.ModuleContext) { 1969 if !a.commonBuildActions(ctx) { 1970 return 1971 } 1972 1973 a.setApexTypeAndSuffix(ctx) 1974 a.setPayloadFsType(ctx) 1975 a.setSystemLibLink(ctx) 1976 1977 if a.properties.ApexType != zipApex { 1978 a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx, a.primaryApexType) 1979 } 1980 1981 bazelCtx := ctx.Config().BazelContext 1982 outputs, err := bazelCtx.GetApexInfo(a.GetBazelLabel(ctx, a), android.GetConfigKey(ctx)) 1983 if err != nil { 1984 ctx.ModuleErrorf(err.Error()) 1985 return 1986 } 1987 a.installDir = android.PathForModuleInstall(ctx, "apex") 1988 1989 // Set the output file to .apex or .capex depending on the compression configuration. 1990 a.setCompression(ctx) 1991 if a.isCompressed { 1992 a.outputApexFile = android.PathForBazelOutRelative(ctx, ctx.ModuleDir(), outputs.SignedCompressedOutput) 1993 } else { 1994 a.outputApexFile = android.PathForBazelOutRelative(ctx, ctx.ModuleDir(), outputs.SignedOutput) 1995 } 1996 a.outputFile = a.outputApexFile 1997 1998 if len(outputs.TidyFiles) > 0 { 1999 tidyFiles := android.PathsForBazelOut(ctx, outputs.TidyFiles) 2000 a.outputFile = android.AttachValidationActions(ctx, a.outputFile, tidyFiles) 2001 } 2002 2003 // TODO(b/257829940): These are used by the apex_keys_text singleton; would probably be a clearer 2004 // interface if these were set in a provider rather than the module itself 2005 a.publicKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[0]) 2006 a.privateKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[1]) 2007 a.containerCertificateFile = android.PathForBazelOut(ctx, outputs.ContainerKeyInfo[0]) 2008 a.containerPrivateKeyFile = android.PathForBazelOut(ctx, outputs.ContainerKeyInfo[1]) 2009 2010 // Ensure ApexMkInfo.install_to_system make module names are installed as 2011 // part of a bundled build. 2012 a.makeModulesToInstall = append(a.makeModulesToInstall, outputs.MakeModulesToInstall...) 2013 2014 apexType := a.properties.ApexType 2015 switch apexType { 2016 case imageApex: 2017 a.bundleModuleFile = android.PathForBazelOut(ctx, outputs.BundleFile) 2018 a.nativeApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.SymbolsUsedByApex)) 2019 a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.BackingLibs)) 2020 // TODO(b/239084755): Generate the java api using.xml file from Bazel. 2021 a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.JavaSymbolsUsedByApex)) 2022 a.installedFilesFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.InstalledFiles)) 2023 installSuffix := imageApexSuffix 2024 if a.isCompressed { 2025 installSuffix = imageCapexSuffix 2026 } 2027 a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile, 2028 a.compatSymlinks.Paths()...) 2029 default: 2030 panic(fmt.Errorf("internal error: unexpected apex_type for the ProcessBazelQueryResponse: %v", a.properties.ApexType)) 2031 } 2032 2033 // filesInfo in mixed mode must retrieve all information about the apex's 2034 // contents completely from the Starlark providers. It should never rely on 2035 // Android.bp information, as they might not exist for fully migrated 2036 // dependencies. 2037 // 2038 // Prevent accidental writes to filesInfo in the earlier parts Soong by 2039 // asserting it to be nil. 2040 if a.filesInfo != nil { 2041 panic( 2042 fmt.Errorf("internal error: filesInfo must be nil for an apex handled by Bazel. " + 2043 "Did something else set filesInfo before this line of code?")) 2044 } 2045 for _, f := range outputs.PayloadFilesInfo { 2046 fileInfo := apexFile{ 2047 isBazelPrebuilt: true, 2048 2049 builtFile: android.PathForBazelOut(ctx, f["built_file"]), 2050 unstrippedBuiltFile: android.PathForBazelOut(ctx, f["unstripped_built_file"]), 2051 androidMkModuleName: f["make_module_name"], 2052 installDir: f["install_dir"], 2053 class: classes[f["class"]], 2054 customStem: f["basename"], 2055 moduleDir: f["package"], 2056 } 2057 2058 arch := f["arch"] 2059 fileInfo.arch = arch 2060 if len(arch) > 0 { 2061 fileInfo.multilib = "lib32" 2062 if strings.HasSuffix(arch, "64") { 2063 fileInfo.multilib = "lib64" 2064 } 2065 } 2066 2067 a.filesInfo = append(a.filesInfo, fileInfo) 2068 } 2069} 2070 2071func (a *apexBundle) setCompression(ctx android.ModuleContext) { 2072 if a.properties.ApexType != imageApex { 2073 a.isCompressed = false 2074 } else if a.testOnlyShouldForceCompression() { 2075 a.isCompressed = true 2076 } else { 2077 a.isCompressed = ctx.Config().ApexCompressionEnabled() && a.isCompressable() 2078 } 2079} 2080 2081func (a *apexBundle) setSystemLibLink(ctx android.ModuleContext) { 2082 // Optimization. If we are building bundled APEX, for the files that are gathered due to the 2083 // transitive dependencies, don't place them inside the APEX, but place a symlink pointing 2084 // the same library in the system partition, thus effectively sharing the same libraries 2085 // across the APEX boundary. For unbundled APEX, all the gathered files are actually placed 2086 // in the APEX. 2087 a.linkToSystemLib = !ctx.Config().UnbundledBuild() && a.installable() 2088 2089 // APEXes targeting other than system/system_ext partitions use vendor/product variants. 2090 // So we can't link them to /system/lib libs which are core variants. 2091 if a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { 2092 a.linkToSystemLib = false 2093 } 2094 2095 forced := ctx.Config().ForceApexSymlinkOptimization() 2096 updatable := a.Updatable() || a.FutureUpdatable() 2097 2098 // We don't need the optimization for updatable APEXes, as it might give false signal 2099 // to the system health when the APEXes are still bundled (b/149805758). 2100 if !forced && updatable && a.properties.ApexType == imageApex { 2101 a.linkToSystemLib = false 2102 } 2103 2104 // We also don't want the optimization for host APEXes, because it doesn't make sense. 2105 if ctx.Host() { 2106 a.linkToSystemLib = false 2107 } 2108} 2109 2110func (a *apexBundle) setPayloadFsType(ctx android.ModuleContext) { 2111 switch proptools.StringDefault(a.properties.Payload_fs_type, ext4FsType) { 2112 case ext4FsType: 2113 a.payloadFsType = ext4 2114 case f2fsFsType: 2115 a.payloadFsType = f2fs 2116 case erofsFsType: 2117 a.payloadFsType = erofs 2118 default: 2119 ctx.PropertyErrorf("payload_fs_type", "%q is not a valid filesystem for apex [ext4, f2fs, erofs]", *a.properties.Payload_fs_type) 2120 } 2121} 2122 2123func (a *apexBundle) setApexTypeAndSuffix(ctx android.ModuleContext) { 2124 // Set suffix and primaryApexType depending on the ApexType 2125 buildFlattenedAsDefault := ctx.Config().FlattenApex() 2126 switch a.properties.ApexType { 2127 case imageApex: 2128 if buildFlattenedAsDefault { 2129 a.suffix = imageApexSuffix 2130 } else { 2131 a.suffix = "" 2132 a.primaryApexType = true 2133 2134 if ctx.Config().InstallExtraFlattenedApexes() { 2135 a.makeModulesToInstall = append(a.makeModulesToInstall, a.Name()+flattenedSuffix) 2136 } 2137 } 2138 case zipApex: 2139 if proptools.String(a.properties.Payload_type) == "zip" { 2140 a.suffix = "" 2141 a.primaryApexType = true 2142 } else { 2143 a.suffix = zipApexSuffix 2144 } 2145 case flattenedApex: 2146 if buildFlattenedAsDefault { 2147 a.suffix = "" 2148 a.primaryApexType = true 2149 } else { 2150 a.suffix = flattenedSuffix 2151 } 2152 } 2153} 2154 2155func (a apexBundle) isCompressable() bool { 2156 return proptools.BoolDefault(a.overridableProperties.Compressible, false) && !a.testApex 2157} 2158 2159func (a *apexBundle) commonBuildActions(ctx android.ModuleContext) bool { 2160 a.checkApexAvailability(ctx) 2161 a.checkUpdatable(ctx) 2162 a.CheckMinSdkVersion(ctx) 2163 a.checkStaticLinkingToStubLibraries(ctx) 2164 a.checkStaticExecutables(ctx) 2165 if len(a.properties.Tests) > 0 && !a.testApex { 2166 ctx.PropertyErrorf("tests", "property allowed only in apex_test module type") 2167 return false 2168 } 2169 return true 2170} 2171 2172type visitorContext struct { 2173 // all the files that will be included in this APEX 2174 filesInfo []apexFile 2175 2176 // native lib dependencies 2177 provideNativeLibs []string 2178 requireNativeLibs []string 2179 2180 handleSpecialLibs bool 2181 2182 // if true, raise error on duplicate apexFile 2183 checkDuplicate bool 2184} 2185 2186func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) { 2187 encountered := make(map[string]apexFile) 2188 for _, f := range vctx.filesInfo { 2189 dest := filepath.Join(f.installDir, f.builtFile.Base()) 2190 if e, ok := encountered[dest]; !ok { 2191 encountered[dest] = f 2192 } else { 2193 if vctx.checkDuplicate && f.builtFile.String() != e.builtFile.String() { 2194 mctx.ModuleErrorf("apex file %v is provided by two different files %v and %v", 2195 dest, e.builtFile, f.builtFile) 2196 return 2197 } 2198 // If a module is directly included and also transitively depended on 2199 // consider it as directly included. 2200 e.transitiveDep = e.transitiveDep && f.transitiveDep 2201 encountered[dest] = e 2202 } 2203 } 2204 vctx.filesInfo = vctx.filesInfo[:0] 2205 for _, v := range encountered { 2206 vctx.filesInfo = append(vctx.filesInfo, v) 2207 } 2208 sort.Slice(vctx.filesInfo, func(i, j int) bool { 2209 // Sort by destination path so as to ensure consistent ordering even if the source of the files 2210 // changes. 2211 return vctx.filesInfo[i].path() < vctx.filesInfo[j].path() 2212 }) 2213} 2214 2215func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent blueprint.Module) bool { 2216 depTag := ctx.OtherModuleDependencyTag(child) 2217 if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { 2218 return false 2219 } 2220 if mod, ok := child.(android.Module); ok && !mod.Enabled() { 2221 return false 2222 } 2223 depName := ctx.OtherModuleName(child) 2224 if _, isDirectDep := parent.(*apexBundle); isDirectDep { 2225 switch depTag { 2226 case sharedLibTag, jniLibTag: 2227 isJniLib := depTag == jniLibTag 2228 switch ch := child.(type) { 2229 case *cc.Module: 2230 fi := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs) 2231 fi.isJniLib = isJniLib 2232 vctx.filesInfo = append(vctx.filesInfo, fi) 2233 // Collect the list of stub-providing libs except: 2234 // - VNDK libs are only for vendors 2235 // - bootstrap bionic libs are treated as provided by system 2236 if ch.HasStubsVariants() && !a.vndkApex && !cc.InstallToBootstrap(ch.BaseModuleName(), ctx.Config()) { 2237 vctx.provideNativeLibs = append(vctx.provideNativeLibs, fi.stem()) 2238 } 2239 return true // track transitive dependencies 2240 case *rust.Module: 2241 fi := apexFileForRustLibrary(ctx, ch) 2242 fi.isJniLib = isJniLib 2243 vctx.filesInfo = append(vctx.filesInfo, fi) 2244 return true // track transitive dependencies 2245 default: 2246 propertyName := "native_shared_libs" 2247 if isJniLib { 2248 propertyName = "jni_libs" 2249 } 2250 ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName) 2251 } 2252 case executableTag: 2253 switch ch := child.(type) { 2254 case *cc.Module: 2255 vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch)) 2256 return true // track transitive dependencies 2257 case *python.PythonBinaryModule: 2258 if ch.HostToolPath().Valid() { 2259 vctx.filesInfo = append(vctx.filesInfo, apexFileForPyBinary(ctx, ch)) 2260 } 2261 case bootstrap.GoBinaryTool: 2262 if a.Host() { 2263 vctx.filesInfo = append(vctx.filesInfo, apexFileForGoBinary(ctx, depName, ch)) 2264 } 2265 case *rust.Module: 2266 vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, ch)) 2267 return true // track transitive dependencies 2268 default: 2269 ctx.PropertyErrorf("binaries", 2270 "%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, nor (host) bootstrap_go_binary", depName) 2271 } 2272 case shBinaryTag: 2273 if csh, ok := child.(*sh.ShBinary); ok { 2274 vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, csh)) 2275 } else { 2276 ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName) 2277 } 2278 case bcpfTag: 2279 _, ok := child.(*java.BootclasspathFragmentModule) 2280 if !ok { 2281 ctx.PropertyErrorf("bootclasspath_fragments", "%q is not a bootclasspath_fragment module", depName) 2282 return false 2283 } 2284 2285 vctx.filesInfo = append(vctx.filesInfo, apexBootclasspathFragmentFiles(ctx, child)...) 2286 return true 2287 case sscpfTag: 2288 if _, ok := child.(*java.SystemServerClasspathModule); !ok { 2289 ctx.PropertyErrorf("systemserverclasspath_fragments", 2290 "%q is not a systemserverclasspath_fragment module", depName) 2291 return false 2292 } 2293 if af := apexClasspathFragmentProtoFile(ctx, child); af != nil { 2294 vctx.filesInfo = append(vctx.filesInfo, *af) 2295 } 2296 return true 2297 case javaLibTag: 2298 switch child.(type) { 2299 case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import: 2300 af := apexFileForJavaModule(ctx, child.(javaModule)) 2301 if !af.ok() { 2302 ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName) 2303 return false 2304 } 2305 vctx.filesInfo = append(vctx.filesInfo, af) 2306 return true // track transitive dependencies 2307 default: 2308 ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child)) 2309 } 2310 case androidAppTag: 2311 switch ap := child.(type) { 2312 case *java.AndroidApp: 2313 vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap)) 2314 return true // track transitive dependencies 2315 case *java.AndroidAppImport: 2316 vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap)) 2317 case *java.AndroidTestHelperApp: 2318 vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap)) 2319 case *java.AndroidAppSet: 2320 appDir := "app" 2321 if ap.Privileged() { 2322 appDir = "priv-app" 2323 } 2324 // TODO(b/224589412, b/226559955): Ensure that the dirname is 2325 // suffixed so that PackageManager correctly invalidates the 2326 // existing installed apk in favour of the new APK-in-APEX. 2327 // See bugs for more information. 2328 appDirName := filepath.Join(appDir, ap.BaseModuleName()+"@"+sanitizedBuildIdForPath(ctx)) 2329 af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(), appDirName, appSet, ap) 2330 af.certificate = java.PresignedCertificate 2331 vctx.filesInfo = append(vctx.filesInfo, af) 2332 default: 2333 ctx.PropertyErrorf("apps", "%q is not an android_app module", depName) 2334 } 2335 case rroTag: 2336 if rro, ok := child.(java.RuntimeResourceOverlayModule); ok { 2337 vctx.filesInfo = append(vctx.filesInfo, apexFileForRuntimeResourceOverlay(ctx, rro)) 2338 } else { 2339 ctx.PropertyErrorf("rros", "%q is not an runtime_resource_overlay module", depName) 2340 } 2341 case bpfTag: 2342 if bpfProgram, ok := child.(bpf.BpfModule); ok { 2343 filesToCopy, _ := bpfProgram.OutputFiles("") 2344 apex_sub_dir := bpfProgram.SubDir() 2345 for _, bpfFile := range filesToCopy { 2346 vctx.filesInfo = append(vctx.filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, bpfProgram)) 2347 } 2348 } else { 2349 ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName) 2350 } 2351 case fsTag: 2352 if fs, ok := child.(filesystem.Filesystem); ok { 2353 vctx.filesInfo = append(vctx.filesInfo, apexFileForFilesystem(ctx, fs.OutputPath(), fs)) 2354 } else { 2355 ctx.PropertyErrorf("filesystems", "%q is not a filesystem module", depName) 2356 } 2357 case prebuiltTag: 2358 if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok { 2359 vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName)) 2360 } else { 2361 ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName) 2362 } 2363 case compatConfigTag: 2364 if compatConfig, ok := child.(java.PlatformCompatConfigIntf); ok { 2365 vctx.filesInfo = append(vctx.filesInfo, apexFileForCompatConfig(ctx, compatConfig, depName)) 2366 } else { 2367 ctx.PropertyErrorf("compat_configs", "%q is not a platform_compat_config module", depName) 2368 } 2369 case testTag: 2370 if ccTest, ok := child.(*cc.Module); ok { 2371 if ccTest.IsTestPerSrcAllTestsVariation() { 2372 // Multiple-output test module (where `test_per_src: true`). 2373 // 2374 // `ccTest` is the "" ("all tests") variation of a `test_per_src` module. 2375 // We do not add this variation to `filesInfo`, as it has no output; 2376 // however, we do add the other variations of this module as indirect 2377 // dependencies (see below). 2378 } else { 2379 // Single-output test module (where `test_per_src: false`). 2380 af := apexFileForExecutable(ctx, ccTest) 2381 af.class = nativeTest 2382 vctx.filesInfo = append(vctx.filesInfo, af) 2383 } 2384 return true // track transitive dependencies 2385 } else { 2386 ctx.PropertyErrorf("tests", "%q is not a cc module", depName) 2387 } 2388 case keyTag: 2389 if key, ok := child.(*apexKey); ok { 2390 a.privateKeyFile = key.privateKeyFile 2391 a.publicKeyFile = key.publicKeyFile 2392 } else { 2393 ctx.PropertyErrorf("key", "%q is not an apex_key module", depName) 2394 } 2395 case certificateTag: 2396 if dep, ok := child.(*java.AndroidAppCertificate); ok { 2397 a.containerCertificateFile = dep.Certificate.Pem 2398 a.containerPrivateKeyFile = dep.Certificate.Key 2399 } else { 2400 ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName) 2401 } 2402 } 2403 return false 2404 } 2405 2406 if a.vndkApex { 2407 return false 2408 } 2409 2410 // indirect dependencies 2411 am, ok := child.(android.ApexModule) 2412 if !ok { 2413 return false 2414 } 2415 // We cannot use a switch statement on `depTag` here as the checked 2416 // tags used below are private (e.g. `cc.sharedDepTag`). 2417 if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) { 2418 if ch, ok := child.(*cc.Module); ok { 2419 if ch.UseVndk() && proptools.Bool(a.properties.Use_vndk_as_stable) && ch.IsVndk() { 2420 vctx.requireNativeLibs = append(vctx.requireNativeLibs, ":vndk") 2421 return false 2422 } 2423 af := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs) 2424 af.transitiveDep = true 2425 2426 // Always track transitive dependencies for host. 2427 if a.Host() { 2428 vctx.filesInfo = append(vctx.filesInfo, af) 2429 return true 2430 } 2431 2432 abInfo := ctx.Provider(ApexBundleInfoProvider).(ApexBundleInfo) 2433 if !abInfo.Contents.DirectlyInApex(depName) && (ch.IsStubs() || ch.HasStubsVariants()) { 2434 // If the dependency is a stubs lib, don't include it in this APEX, 2435 // but make sure that the lib is installed on the device. 2436 // In case no APEX is having the lib, the lib is installed to the system 2437 // partition. 2438 // 2439 // Always include if we are a host-apex however since those won't have any 2440 // system libraries. 2441 // 2442 // Skip the dependency in unbundled builds where the device image is not 2443 // being built. 2444 if ch.IsStubsImplementationRequired() && !am.DirectlyInAnyApex() && !ctx.Config().UnbundledBuild() { 2445 // we need a module name for Make 2446 name := ch.ImplementationModuleNameForMake(ctx) + ch.Properties.SubName 2447 if !android.InList(name, a.makeModulesToInstall) { 2448 a.makeModulesToInstall = append(a.makeModulesToInstall, name) 2449 } 2450 } 2451 vctx.requireNativeLibs = append(vctx.requireNativeLibs, af.stem()) 2452 // Don't track further 2453 return false 2454 } 2455 2456 // If the dep is not considered to be in the same 2457 // apex, don't add it to filesInfo so that it is not 2458 // included in this APEX. 2459 // TODO(jiyong): move this to at the top of the 2460 // else-if clause for the indirect dependencies. 2461 // Currently, that's impossible because we would 2462 // like to record requiredNativeLibs even when 2463 // DepIsInSameAPex is false. We also shouldn't do 2464 // this for host. 2465 // 2466 // TODO(jiyong): explain why the same module is passed in twice. 2467 // Switching the first am to parent breaks lots of tests. 2468 if !android.IsDepInSameApex(ctx, am, am) { 2469 return false 2470 } 2471 2472 vctx.filesInfo = append(vctx.filesInfo, af) 2473 return true // track transitive dependencies 2474 } else if rm, ok := child.(*rust.Module); ok { 2475 af := apexFileForRustLibrary(ctx, rm) 2476 af.transitiveDep = true 2477 vctx.filesInfo = append(vctx.filesInfo, af) 2478 return true // track transitive dependencies 2479 } 2480 } else if cc.IsTestPerSrcDepTag(depTag) { 2481 if ch, ok := child.(*cc.Module); ok { 2482 af := apexFileForExecutable(ctx, ch) 2483 // Handle modules created as `test_per_src` variations of a single test module: 2484 // use the name of the generated test binary (`fileToCopy`) instead of the name 2485 // of the original test module (`depName`, shared by all `test_per_src` 2486 // variations of that module). 2487 af.androidMkModuleName = filepath.Base(af.builtFile.String()) 2488 // these are not considered transitive dep 2489 af.transitiveDep = false 2490 vctx.filesInfo = append(vctx.filesInfo, af) 2491 return true // track transitive dependencies 2492 } 2493 } else if cc.IsHeaderDepTag(depTag) { 2494 // nothing 2495 } else if java.IsJniDepTag(depTag) { 2496 // Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps 2497 } else if java.IsXmlPermissionsFileDepTag(depTag) { 2498 if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok { 2499 vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName)) 2500 } 2501 } else if rust.IsDylibDepTag(depTag) { 2502 if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() { 2503 af := apexFileForRustLibrary(ctx, rustm) 2504 af.transitiveDep = true 2505 vctx.filesInfo = append(vctx.filesInfo, af) 2506 return true // track transitive dependencies 2507 } 2508 } else if rust.IsRlibDepTag(depTag) { 2509 // Rlib is statically linked, but it might have shared lib 2510 // dependencies. Track them. 2511 return true 2512 } else if java.IsBootclasspathFragmentContentDepTag(depTag) { 2513 // Add the contents of the bootclasspath fragment to the apex. 2514 switch child.(type) { 2515 case *java.Library, *java.SdkLibrary: 2516 javaModule := child.(javaModule) 2517 af := apexFileForBootclasspathFragmentContentModule(ctx, parent, javaModule) 2518 if !af.ok() { 2519 ctx.PropertyErrorf("bootclasspath_fragments", 2520 "bootclasspath_fragment content %q is not configured to be compiled into dex", depName) 2521 return false 2522 } 2523 vctx.filesInfo = append(vctx.filesInfo, af) 2524 return true // track transitive dependencies 2525 default: 2526 ctx.PropertyErrorf("bootclasspath_fragments", 2527 "bootclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child)) 2528 } 2529 } else if java.IsSystemServerClasspathFragmentContentDepTag(depTag) { 2530 // Add the contents of the systemserverclasspath fragment to the apex. 2531 switch child.(type) { 2532 case *java.Library, *java.SdkLibrary: 2533 af := apexFileForJavaModule(ctx, child.(javaModule)) 2534 vctx.filesInfo = append(vctx.filesInfo, af) 2535 if profileAf := apexFileForJavaModuleProfile(ctx, child.(javaModule)); profileAf != nil { 2536 vctx.filesInfo = append(vctx.filesInfo, *profileAf) 2537 } 2538 return true // track transitive dependencies 2539 default: 2540 ctx.PropertyErrorf("systemserverclasspath_fragments", 2541 "systemserverclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child)) 2542 } 2543 } else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok { 2544 // nothing 2545 } else if depTag == android.DarwinUniversalVariantTag { 2546 // nothing 2547 } else if am.CanHaveApexVariants() && am.IsInstallableToApex() { 2548 ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName) 2549 } 2550 return false 2551} 2552 2553func (a *apexBundle) shouldCheckDuplicate(ctx android.ModuleContext) bool { 2554 // TODO(b/263308293) remove this 2555 if a.properties.IsCoverageVariant { 2556 return false 2557 } 2558 // TODO(b/263308515) remove this 2559 if a.testApex { 2560 return false 2561 } 2562 // TODO(b/263309864) remove this 2563 if a.Host() { 2564 return false 2565 } 2566 if a.Device() && ctx.DeviceConfig().DeviceArch() == "" { 2567 return false 2568 } 2569 return true 2570} 2571 2572// Creates build rules for an APEX. It consists of the following major steps: 2573// 2574// 1) do some validity checks such as apex_available, min_sdk_version, etc. 2575// 2) traverse the dependency tree to collect apexFile structs from them. 2576// 3) some fields in apexBundle struct are configured 2577// 4) generate the build rules to create the APEX. This is mostly done in builder.go. 2578func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { 2579 //////////////////////////////////////////////////////////////////////////////////////////// 2580 // 1) do some validity checks such as apex_available, min_sdk_version, etc. 2581 if !a.commonBuildActions(ctx) { 2582 return 2583 } 2584 //////////////////////////////////////////////////////////////////////////////////////////// 2585 // 2) traverse the dependency tree to collect apexFile structs from them. 2586 // Collect the module directory for IDE info in java/jdeps.go. 2587 a.modulePaths = append(a.modulePaths, ctx.ModuleDir()) 2588 2589 // TODO(jiyong): do this using WalkPayloadDeps 2590 // TODO(jiyong): make this clean!!! 2591 vctx := visitorContext{ 2592 handleSpecialLibs: !android.Bool(a.properties.Ignore_system_library_special_case), 2593 checkDuplicate: a.shouldCheckDuplicate(ctx), 2594 } 2595 ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) }) 2596 vctx.normalizeFileInfo(ctx) 2597 if a.privateKeyFile == nil { 2598 ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.overridableProperties.Key)) 2599 return 2600 } 2601 2602 //////////////////////////////////////////////////////////////////////////////////////////// 2603 // 3) some fields in apexBundle struct are configured 2604 a.installDir = android.PathForModuleInstall(ctx, "apex") 2605 a.filesInfo = vctx.filesInfo 2606 2607 a.setApexTypeAndSuffix(ctx) 2608 a.setPayloadFsType(ctx) 2609 a.setSystemLibLink(ctx) 2610 if a.properties.ApexType != zipApex { 2611 a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx, a.primaryApexType) 2612 } 2613 2614 //////////////////////////////////////////////////////////////////////////////////////////// 2615 // 4) generate the build rules to create the APEX. This is done in builder.go. 2616 a.buildManifest(ctx, vctx.provideNativeLibs, vctx.requireNativeLibs) 2617 if a.properties.ApexType == flattenedApex { 2618 a.buildFlattenedApex(ctx) 2619 } else { 2620 a.buildUnflattenedApex(ctx) 2621 } 2622 a.buildApexDependencyInfo(ctx) 2623 a.buildLintReports(ctx) 2624 2625 // Append meta-files to the filesInfo list so that they are reflected in Android.mk as well. 2626 if a.installable() { 2627 // For flattened APEX, make sure that APEX manifest and apex_pubkey are also copied 2628 // along with other ordinary files. (Note that this is done by apexer for 2629 // non-flattened APEXes) 2630 a.filesInfo = append(a.filesInfo, newApexFile(ctx, a.manifestPbOut, "apex_manifest.pb", ".", etc, nil)) 2631 2632 // Place the public key as apex_pubkey. This is also done by apexer for 2633 // non-flattened APEXes case. 2634 // TODO(jiyong): Why do we need this CP rule? 2635 copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey") 2636 ctx.Build(pctx, android.BuildParams{ 2637 Rule: android.Cp, 2638 Input: a.publicKeyFile, 2639 Output: copiedPubkey, 2640 }) 2641 a.filesInfo = append(a.filesInfo, newApexFile(ctx, copiedPubkey, "apex_pubkey", ".", etc, nil)) 2642 } 2643} 2644 2645// apexBootclasspathFragmentFiles returns the list of apexFile structures defining the files that 2646// the bootclasspath_fragment contributes to the apex. 2647func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint.Module) []apexFile { 2648 bootclasspathFragmentInfo := ctx.OtherModuleProvider(module, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo) 2649 var filesToAdd []apexFile 2650 2651 // Add classpaths.proto config. 2652 if af := apexClasspathFragmentProtoFile(ctx, module); af != nil { 2653 filesToAdd = append(filesToAdd, *af) 2654 } 2655 2656 pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex() 2657 if pathInApex != "" { 2658 pathOnHost := bootclasspathFragmentInfo.ProfilePathOnHost() 2659 tempPath := android.PathForModuleOut(ctx, "boot_image_profile", pathInApex) 2660 2661 if pathOnHost != nil { 2662 // We need to copy the profile to a temporary path with the right filename because the apexer 2663 // will take the filename as is. 2664 ctx.Build(pctx, android.BuildParams{ 2665 Rule: android.Cp, 2666 Input: pathOnHost, 2667 Output: tempPath, 2668 }) 2669 } else { 2670 // At this point, the boot image profile cannot be generated. It is probably because the boot 2671 // image profile source file does not exist on the branch, or it is not available for the 2672 // current build target. 2673 // However, we cannot enforce the boot image profile to be generated because some build 2674 // targets (such as module SDK) do not need it. It is only needed when the APEX is being 2675 // built. Therefore, we create an error rule so that an error will occur at the ninja phase 2676 // only if the APEX is being built. 2677 ctx.Build(pctx, android.BuildParams{ 2678 Rule: android.ErrorRule, 2679 Output: tempPath, 2680 Args: map[string]string{ 2681 "error": "Boot image profile cannot be generated", 2682 }, 2683 }) 2684 } 2685 2686 androidMkModuleName := filepath.Base(pathInApex) 2687 af := newApexFile(ctx, tempPath, androidMkModuleName, filepath.Dir(pathInApex), etc, nil) 2688 filesToAdd = append(filesToAdd, af) 2689 } 2690 2691 return filesToAdd 2692} 2693 2694// apexClasspathFragmentProtoFile returns *apexFile structure defining the classpath.proto config that 2695// the module contributes to the apex; or nil if the proto config was not generated. 2696func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) *apexFile { 2697 info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo) 2698 if !info.ClasspathFragmentProtoGenerated { 2699 return nil 2700 } 2701 classpathProtoOutput := info.ClasspathFragmentProtoOutput 2702 af := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), info.ClasspathFragmentProtoInstallDir.Rel(), etc, nil) 2703 return &af 2704} 2705 2706// apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment 2707// content module, i.e. a library that is part of the bootclasspath. 2708func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule blueprint.Module, javaModule javaModule) apexFile { 2709 bootclasspathFragmentInfo := ctx.OtherModuleProvider(fragmentModule, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo) 2710 2711 // Get the dexBootJar from the bootclasspath_fragment as that is responsible for performing the 2712 // hidden API encpding. 2713 dexBootJar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(javaModule) 2714 if err != nil { 2715 ctx.ModuleErrorf("%s", err) 2716 } 2717 2718 // Create an apexFile as for a normal java module but with the dex boot jar provided by the 2719 // bootclasspath_fragment. 2720 af := apexFileForJavaModuleWithFile(ctx, javaModule, dexBootJar) 2721 return af 2722} 2723 2724/////////////////////////////////////////////////////////////////////////////////////////////////// 2725// Factory functions 2726// 2727 2728func newApexBundle() *apexBundle { 2729 module := &apexBundle{} 2730 2731 module.AddProperties(&module.properties) 2732 module.AddProperties(&module.targetProperties) 2733 module.AddProperties(&module.archProperties) 2734 module.AddProperties(&module.overridableProperties) 2735 2736 android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) 2737 android.InitDefaultableModule(module) 2738 android.InitOverridableModule(module, &module.overridableProperties.Overrides) 2739 android.InitBazelModule(module) 2740 multitree.InitExportableModule(module) 2741 return module 2742} 2743 2744func ApexBundleFactory(testApex bool) android.Module { 2745 bundle := newApexBundle() 2746 bundle.testApex = testApex 2747 return bundle 2748} 2749 2750// apex_test is an APEX for testing. The difference from the ordinary apex module type is that 2751// certain compatibility checks such as apex_available are not done for apex_test. 2752func TestApexBundleFactory() android.Module { 2753 bundle := newApexBundle() 2754 bundle.testApex = true 2755 return bundle 2756} 2757 2758// apex packages other modules into an APEX file which is a packaging format for system-level 2759// components like binaries, shared libraries, etc. 2760func BundleFactory() android.Module { 2761 return newApexBundle() 2762} 2763 2764type Defaults struct { 2765 android.ModuleBase 2766 android.DefaultsModuleBase 2767} 2768 2769// apex_defaults provides defaultable properties to other apex modules. 2770func DefaultsFactory() android.Module { 2771 module := &Defaults{} 2772 2773 module.AddProperties( 2774 &apexBundleProperties{}, 2775 &apexTargetBundleProperties{}, 2776 &apexArchBundleProperties{}, 2777 &overridableProperties{}, 2778 ) 2779 2780 android.InitDefaultsModule(module) 2781 return module 2782} 2783 2784type OverrideApex struct { 2785 android.ModuleBase 2786 android.OverrideModuleBase 2787 android.BazelModuleBase 2788} 2789 2790func (o *OverrideApex) GenerateAndroidBuildActions(_ android.ModuleContext) { 2791 // All the overrides happen in the base module. 2792} 2793 2794// override_apex is used to create an apex module based on another apex module by overriding some of 2795// its properties. 2796func OverrideApexFactory() android.Module { 2797 m := &OverrideApex{} 2798 2799 m.AddProperties(&overridableProperties{}) 2800 2801 android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon) 2802 android.InitOverrideModule(m) 2803 android.InitBazelModule(m) 2804 return m 2805} 2806 2807func (o *OverrideApex) ConvertWithBp2build(ctx android.TopDownMutatorContext) { 2808 if ctx.ModuleType() != "override_apex" { 2809 return 2810 } 2811 2812 baseApexModuleName := o.OverrideModuleBase.GetOverriddenModuleName() 2813 baseModule, baseApexExists := ctx.ModuleFromName(baseApexModuleName) 2814 if !baseApexExists { 2815 panic(fmt.Errorf("Base apex module doesn't exist: %s", baseApexModuleName)) 2816 } 2817 2818 a, baseModuleIsApex := baseModule.(*apexBundle) 2819 if !baseModuleIsApex { 2820 panic(fmt.Errorf("Base module is not apex module: %s", baseApexModuleName)) 2821 } 2822 attrs, props, commonAttrs := convertWithBp2build(a, ctx) 2823 2824 // We just want the name, not module reference. 2825 baseApexName := strings.TrimPrefix(baseApexModuleName, ":") 2826 attrs.Base_apex_name = &baseApexName 2827 2828 for _, p := range o.GetProperties() { 2829 overridableProperties, ok := p.(*overridableProperties) 2830 if !ok { 2831 continue 2832 } 2833 2834 // Manifest is either empty or a file in the directory of base APEX and is not overridable. 2835 // After it is converted in convertWithBp2build(baseApex, ctx), 2836 // the attrs.Manifest.Value.Label is the file path relative to the directory 2837 // of base apex. So the following code converts it to a label that looks like 2838 // <package of base apex>:<path of manifest file> if base apex and override 2839 // apex are not in the same package. 2840 baseApexPackage := ctx.OtherModuleDir(a) 2841 overrideApexPackage := ctx.ModuleDir() 2842 if baseApexPackage != overrideApexPackage { 2843 attrs.Manifest.Value.Label = "//" + baseApexPackage + ":" + attrs.Manifest.Value.Label 2844 } 2845 2846 // Key 2847 if overridableProperties.Key != nil { 2848 attrs.Key = bazel.LabelAttribute{} 2849 attrs.Key.SetValue(android.BazelLabelForModuleDepSingle(ctx, *overridableProperties.Key)) 2850 } 2851 2852 // Certificate 2853 if overridableProperties.Certificate == nil { 2854 // If overridableProperties.Certificate is nil, clear this out as 2855 // well with zeroed structs, so the override_apex does not use the 2856 // base apex's certificate. 2857 attrs.Certificate = bazel.LabelAttribute{} 2858 attrs.Certificate_name = bazel.StringAttribute{} 2859 } else { 2860 attrs.Certificate, attrs.Certificate_name = android.BazelStringOrLabelFromProp(ctx, overridableProperties.Certificate) 2861 } 2862 2863 // Prebuilts 2864 if overridableProperties.Prebuilts != nil { 2865 prebuiltsLabelList := android.BazelLabelForModuleDeps(ctx, overridableProperties.Prebuilts) 2866 attrs.Prebuilts = bazel.MakeLabelListAttribute(prebuiltsLabelList) 2867 } 2868 2869 // Compressible 2870 if overridableProperties.Compressible != nil { 2871 attrs.Compressible = bazel.BoolAttribute{Value: overridableProperties.Compressible} 2872 } 2873 2874 // Package name 2875 // 2876 // e.g. com.android.adbd's package name is com.android.adbd, but 2877 // com.google.android.adbd overrides the package name to com.google.android.adbd 2878 // 2879 // TODO: this can be overridden from the product configuration, see 2880 // getOverrideManifestPackageName and 2881 // PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES. 2882 // 2883 // Instead of generating the BUILD files differently based on the product config 2884 // at the point of conversion, this should be handled by the BUILD file loading 2885 // from the soong_injection's product_vars, so product config is decoupled from bp2build. 2886 if overridableProperties.Package_name != "" { 2887 attrs.Package_name = &overridableProperties.Package_name 2888 } 2889 2890 // Logging parent 2891 if overridableProperties.Logging_parent != "" { 2892 attrs.Logging_parent = &overridableProperties.Logging_parent 2893 } 2894 } 2895 2896 commonAttrs.Name = o.Name() 2897 2898 ctx.CreateBazelTargetModule(props, commonAttrs, &attrs) 2899} 2900 2901/////////////////////////////////////////////////////////////////////////////////////////////////// 2902// Vality check routines 2903// 2904// These are called in at the very beginning of GenerateAndroidBuildActions to flag an error when 2905// certain conditions are not met. 2906// 2907// TODO(jiyong): move these checks to a separate go file. 2908 2909var _ android.ModuleWithMinSdkVersionCheck = (*apexBundle)(nil) 2910 2911// Ensures that min_sdk_version of the included modules are equal or less than the min_sdk_version 2912// of this apexBundle. 2913func (a *apexBundle) CheckMinSdkVersion(ctx android.ModuleContext) { 2914 if a.testApex || a.vndkApex { 2915 return 2916 } 2917 // apexBundle::minSdkVersion reports its own errors. 2918 minSdkVersion := a.minSdkVersion(ctx) 2919 android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps) 2920} 2921 2922// Returns apex's min_sdk_version string value, honoring overrides 2923func (a *apexBundle) minSdkVersionValue(ctx android.EarlyModuleContext) string { 2924 // Only override the minSdkVersion value on Apexes which already specify 2925 // a min_sdk_version (it's optional for non-updatable apexes), and that its 2926 // min_sdk_version value is lower than the one to override with. 2927 minApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version)) 2928 if minApiLevel.IsNone() { 2929 return "" 2930 } 2931 2932 overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride() 2933 overrideApiLevel := minSdkVersionFromValue(ctx, overrideMinSdkValue) 2934 if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(minApiLevel) > 0 { 2935 minApiLevel = overrideApiLevel 2936 } 2937 2938 return minApiLevel.String() 2939} 2940 2941// Returns apex's min_sdk_version SdkSpec, honoring overrides 2942func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 2943 return a.minSdkVersion(ctx) 2944} 2945 2946// Returns apex's min_sdk_version ApiLevel, honoring overrides 2947func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 2948 return minSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx)) 2949} 2950 2951// Construct ApiLevel object from min_sdk_version string value 2952func minSdkVersionFromValue(ctx android.EarlyModuleContext, value string) android.ApiLevel { 2953 if value == "" { 2954 return android.NoneApiLevel 2955 } 2956 apiLevel, err := android.ApiLevelFromUser(ctx, value) 2957 if err != nil { 2958 ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) 2959 return android.NoneApiLevel 2960 } 2961 return apiLevel 2962} 2963 2964// Ensures that a lib providing stub isn't statically linked 2965func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext) { 2966 // Practically, we only care about regular APEXes on the device. 2967 if ctx.Host() || a.testApex || a.vndkApex { 2968 return 2969 } 2970 2971 abInfo := ctx.Provider(ApexBundleInfoProvider).(ApexBundleInfo) 2972 2973 a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool { 2974 if ccm, ok := to.(*cc.Module); ok { 2975 apexName := ctx.ModuleName() 2976 fromName := ctx.OtherModuleName(from) 2977 toName := ctx.OtherModuleName(to) 2978 2979 // If `to` is not actually in the same APEX as `from` then it does not need 2980 // apex_available and neither do any of its dependencies. 2981 // 2982 // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps(). 2983 if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) { 2984 // As soon as the dependency graph crosses the APEX boundary, don't go further. 2985 return false 2986 } 2987 2988 // The dynamic linker and crash_dump tool in the runtime APEX is the only 2989 // exception to this rule. It can't make the static dependencies dynamic 2990 // because it can't do the dynamic linking for itself. 2991 // Same rule should be applied to linkerconfig, because it should be executed 2992 // only with static linked libraries before linker is available with ld.config.txt 2993 if apexName == "com.android.runtime" && (fromName == "linker" || fromName == "crash_dump" || fromName == "linkerconfig") { 2994 return false 2995 } 2996 2997 isStubLibraryFromOtherApex := ccm.HasStubsVariants() && !abInfo.Contents.DirectlyInApex(toName) 2998 if isStubLibraryFromOtherApex && !externalDep { 2999 ctx.ModuleErrorf("%q required by %q is a native library providing stub. "+ 3000 "It shouldn't be included in this APEX via static linking. Dependency path: %s", to.String(), fromName, ctx.GetPathString(false)) 3001 } 3002 3003 } 3004 return true 3005 }) 3006} 3007 3008// checkUpdatable enforces APEX and its transitive dep properties to have desired values for updatable APEXes. 3009func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { 3010 if a.Updatable() { 3011 if a.minSdkVersionValue(ctx) == "" { 3012 ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well") 3013 } 3014 if a.UsePlatformApis() { 3015 ctx.PropertyErrorf("updatable", "updatable APEXes can't use platform APIs") 3016 } 3017 if proptools.Bool(a.properties.Use_vndk_as_stable) { 3018 ctx.PropertyErrorf("use_vndk_as_stable", "updatable APEXes can't use external VNDK libs") 3019 } 3020 if a.FutureUpdatable() { 3021 ctx.PropertyErrorf("future_updatable", "Already updatable. Remove `future_updatable: true:`") 3022 } 3023 a.checkJavaStableSdkVersion(ctx) 3024 a.checkClasspathFragments(ctx) 3025 } 3026} 3027 3028// checkClasspathFragments enforces that all classpath fragments in deps generate classpaths.proto config. 3029func (a *apexBundle) checkClasspathFragments(ctx android.ModuleContext) { 3030 ctx.VisitDirectDeps(func(module android.Module) { 3031 if tag := ctx.OtherModuleDependencyTag(module); tag == bcpfTag || tag == sscpfTag { 3032 info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo) 3033 if !info.ClasspathFragmentProtoGenerated { 3034 ctx.OtherModuleErrorf(module, "is included in updatable apex %v, it must not set generate_classpaths_proto to false", ctx.ModuleName()) 3035 } 3036 } 3037 }) 3038} 3039 3040// checkJavaStableSdkVersion enforces that all Java deps are using stable SDKs to compile. 3041func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) { 3042 // Visit direct deps only. As long as we guarantee top-level deps are using stable SDKs, 3043 // java's checkLinkType guarantees correct usage for transitive deps 3044 ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) { 3045 tag := ctx.OtherModuleDependencyTag(module) 3046 switch tag { 3047 case javaLibTag, androidAppTag: 3048 if m, ok := module.(interface { 3049 CheckStableSdkVersion(ctx android.BaseModuleContext) error 3050 }); ok { 3051 if err := m.CheckStableSdkVersion(ctx); err != nil { 3052 ctx.ModuleErrorf("cannot depend on \"%v\": %v", ctx.OtherModuleName(module), err) 3053 } 3054 } 3055 } 3056 }) 3057} 3058 3059// checkApexAvailability ensures that the all the dependencies are marked as available for this APEX. 3060func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { 3061 // Let's be practical. Availability for test, host, and the VNDK apex isn't important 3062 if ctx.Host() || a.testApex || a.vndkApex { 3063 return 3064 } 3065 3066 // Because APEXes targeting other than system/system_ext partitions can't set 3067 // apex_available, we skip checks for these APEXes 3068 if a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { 3069 return 3070 } 3071 3072 // Coverage build adds additional dependencies for the coverage-only runtime libraries. 3073 // Requiring them and their transitive depencies with apex_available is not right 3074 // because they just add noise. 3075 if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") || a.IsNativeCoverageNeeded(ctx) { 3076 return 3077 } 3078 3079 a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool { 3080 // As soon as the dependency graph crosses the APEX boundary, don't go further. 3081 if externalDep { 3082 return false 3083 } 3084 3085 apexName := ctx.ModuleName() 3086 fromName := ctx.OtherModuleName(from) 3087 toName := ctx.OtherModuleName(to) 3088 3089 // If `to` is not actually in the same APEX as `from` then it does not need 3090 // apex_available and neither do any of its dependencies. 3091 // 3092 // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps(). 3093 if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) { 3094 // As soon as the dependency graph crosses the APEX boundary, don't go 3095 // further. 3096 return false 3097 } 3098 3099 if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) { 3100 return true 3101 } 3102 ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+ 3103 "\n\nDependency path:%s\n\n"+ 3104 "Consider adding %q to 'apex_available' property of %q", 3105 fromName, toName, ctx.GetPathString(true), apexName, toName) 3106 // Visit this module's dependencies to check and report any issues with their availability. 3107 return true 3108 }) 3109} 3110 3111// checkStaticExecutable ensures that executables in an APEX are not static. 3112func (a *apexBundle) checkStaticExecutables(ctx android.ModuleContext) { 3113 // No need to run this for host APEXes 3114 if ctx.Host() { 3115 return 3116 } 3117 3118 ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) { 3119 if ctx.OtherModuleDependencyTag(module) != executableTag { 3120 return 3121 } 3122 3123 if l, ok := module.(cc.LinkableInterface); ok && l.StaticExecutable() { 3124 apex := a.ApexVariationName() 3125 exec := ctx.OtherModuleName(module) 3126 if isStaticExecutableAllowed(apex, exec) { 3127 return 3128 } 3129 ctx.ModuleErrorf("executable %s is static", ctx.OtherModuleName(module)) 3130 } 3131 }) 3132} 3133 3134// A small list of exceptions where static executables are allowed in APEXes. 3135func isStaticExecutableAllowed(apex string, exec string) bool { 3136 m := map[string][]string{ 3137 "com.android.runtime": { 3138 "linker", 3139 "linkerconfig", 3140 }, 3141 } 3142 execNames, ok := m[apex] 3143 return ok && android.InList(exec, execNames) 3144} 3145 3146// Collect information for opening IDE project files in java/jdeps.go. 3147func (a *apexBundle) IDEInfo(dpInfo *android.IdeInfo) { 3148 dpInfo.Deps = append(dpInfo.Deps, a.properties.Java_libs...) 3149 dpInfo.Deps = append(dpInfo.Deps, a.properties.Bootclasspath_fragments...) 3150 dpInfo.Deps = append(dpInfo.Deps, a.properties.Systemserverclasspath_fragments...) 3151 dpInfo.Paths = append(dpInfo.Paths, a.modulePaths...) 3152} 3153 3154var ( 3155 apexAvailBaseline = makeApexAvailableBaseline() 3156 inverseApexAvailBaseline = invertApexBaseline(apexAvailBaseline) 3157) 3158 3159func baselineApexAvailable(apex, moduleName string) bool { 3160 key := apex 3161 moduleName = normalizeModuleName(moduleName) 3162 3163 if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) { 3164 return true 3165 } 3166 3167 key = android.AvailableToAnyApex 3168 if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) { 3169 return true 3170 } 3171 3172 return false 3173} 3174 3175func normalizeModuleName(moduleName string) string { 3176 // Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build 3177 // system. Trim the prefix for the check since they are confusing 3178 moduleName = android.RemoveOptionalPrebuiltPrefix(moduleName) 3179 if strings.HasPrefix(moduleName, "libclang_rt.") { 3180 // This module has many arch variants that depend on the product being built. 3181 // We don't want to list them all 3182 moduleName = "libclang_rt" 3183 } 3184 if strings.HasPrefix(moduleName, "androidx.") { 3185 // TODO(b/156996905) Set apex_available/min_sdk_version for androidx support libraries 3186 moduleName = "androidx" 3187 } 3188 return moduleName 3189} 3190 3191// Transform the map of apex -> modules to module -> apexes. 3192func invertApexBaseline(m map[string][]string) map[string][]string { 3193 r := make(map[string][]string) 3194 for apex, modules := range m { 3195 for _, module := range modules { 3196 r[module] = append(r[module], apex) 3197 } 3198 } 3199 return r 3200} 3201 3202// Retrieve the baseline of apexes to which the supplied module belongs. 3203func BaselineApexAvailable(moduleName string) []string { 3204 return inverseApexAvailBaseline[normalizeModuleName(moduleName)] 3205} 3206 3207// This is a map from apex to modules, which overrides the apex_available setting for that 3208// particular module to make it available for the apex regardless of its setting. 3209// TODO(b/147364041): remove this 3210func makeApexAvailableBaseline() map[string][]string { 3211 // The "Module separator"s below are employed to minimize merge conflicts. 3212 m := make(map[string][]string) 3213 // 3214 // Module separator 3215 // 3216 m["com.android.appsearch"] = []string{ 3217 "icing-java-proto-lite", 3218 "libprotobuf-java-lite", 3219 } 3220 // 3221 // Module separator 3222 // 3223 m["com.android.btservices"] = []string{ 3224 // empty 3225 } 3226 // 3227 // Module separator 3228 // 3229 m["com.android.cellbroadcast"] = []string{"CellBroadcastApp", "CellBroadcastServiceModule"} 3230 // 3231 // Module separator 3232 // 3233 m["com.android.extservices"] = []string{ 3234 "error_prone_annotations", 3235 "ExtServices-core", 3236 "ExtServices", 3237 "libtextclassifier-java", 3238 "libz_current", 3239 "textclassifier-statsd", 3240 "TextClassifierNotificationLibNoManifest", 3241 "TextClassifierServiceLibNoManifest", 3242 } 3243 // 3244 // Module separator 3245 // 3246 m["com.android.neuralnetworks"] = []string{ 3247 "android.hardware.neuralnetworks@1.0", 3248 "android.hardware.neuralnetworks@1.1", 3249 "android.hardware.neuralnetworks@1.2", 3250 "android.hardware.neuralnetworks@1.3", 3251 "android.hidl.allocator@1.0", 3252 "android.hidl.memory.token@1.0", 3253 "android.hidl.memory@1.0", 3254 "android.hidl.safe_union@1.0", 3255 "libarect", 3256 "libbuildversion", 3257 "libmath", 3258 "libprocpartition", 3259 } 3260 // 3261 // Module separator 3262 // 3263 m["com.android.media"] = []string{ 3264 // empty 3265 } 3266 // 3267 // Module separator 3268 // 3269 m["com.android.media.swcodec"] = []string{ 3270 // empty 3271 } 3272 // 3273 // Module separator 3274 // 3275 m["com.android.mediaprovider"] = []string{ 3276 "MediaProvider", 3277 "MediaProviderGoogle", 3278 "fmtlib_ndk", 3279 "libbase_ndk", 3280 "libfuse", 3281 "libfuse_jni", 3282 } 3283 // 3284 // Module separator 3285 // 3286 m["com.android.runtime"] = []string{ 3287 "bionic_libc_platform_headers", 3288 "libarm-optimized-routines-math", 3289 "libc_aeabi", 3290 "libc_bionic", 3291 "libc_bionic_ndk", 3292 "libc_bootstrap", 3293 "libc_common", 3294 "libc_common_shared", 3295 "libc_common_static", 3296 "libc_dns", 3297 "libc_dynamic_dispatch", 3298 "libc_fortify", 3299 "libc_freebsd", 3300 "libc_freebsd_large_stack", 3301 "libc_gdtoa", 3302 "libc_init_dynamic", 3303 "libc_init_static", 3304 "libc_jemalloc_wrapper", 3305 "libc_netbsd", 3306 "libc_nomalloc", 3307 "libc_nopthread", 3308 "libc_openbsd", 3309 "libc_openbsd_large_stack", 3310 "libc_openbsd_ndk", 3311 "libc_pthread", 3312 "libc_static_dispatch", 3313 "libc_syscalls", 3314 "libc_tzcode", 3315 "libc_unwind_static", 3316 "libdebuggerd", 3317 "libdebuggerd_common_headers", 3318 "libdebuggerd_handler_core", 3319 "libdebuggerd_handler_fallback", 3320 "libdl_static", 3321 "libjemalloc5", 3322 "liblinker_main", 3323 "liblinker_malloc", 3324 "liblz4", 3325 "liblzma", 3326 "libprocinfo", 3327 "libpropertyinfoparser", 3328 "libscudo", 3329 "libstdc++", 3330 "libsystemproperties", 3331 "libtombstoned_client_static", 3332 "libunwindstack", 3333 "libz", 3334 "libziparchive", 3335 } 3336 // 3337 // Module separator 3338 // 3339 m["com.android.tethering"] = []string{ 3340 "android.hardware.tetheroffload.config-V1.0-java", 3341 "android.hardware.tetheroffload.control-V1.0-java", 3342 "android.hidl.base-V1.0-java", 3343 "libcgrouprc", 3344 "libcgrouprc_format", 3345 "libtetherutilsjni", 3346 "libvndksupport", 3347 "net-utils-framework-common", 3348 "netd_aidl_interface-V3-java", 3349 "netlink-client", 3350 "networkstack-aidl-interfaces-java", 3351 "tethering-aidl-interfaces-java", 3352 "TetheringApiCurrentLib", 3353 } 3354 // 3355 // Module separator 3356 // 3357 m["com.android.wifi"] = []string{ 3358 "PlatformProperties", 3359 "android.hardware.wifi-V1.0-java", 3360 "android.hardware.wifi-V1.0-java-constants", 3361 "android.hardware.wifi-V1.1-java", 3362 "android.hardware.wifi-V1.2-java", 3363 "android.hardware.wifi-V1.3-java", 3364 "android.hardware.wifi-V1.4-java", 3365 "android.hardware.wifi.hostapd-V1.0-java", 3366 "android.hardware.wifi.hostapd-V1.1-java", 3367 "android.hardware.wifi.hostapd-V1.2-java", 3368 "android.hardware.wifi.supplicant-V1.0-java", 3369 "android.hardware.wifi.supplicant-V1.1-java", 3370 "android.hardware.wifi.supplicant-V1.2-java", 3371 "android.hardware.wifi.supplicant-V1.3-java", 3372 "android.hidl.base-V1.0-java", 3373 "android.hidl.manager-V1.0-java", 3374 "android.hidl.manager-V1.1-java", 3375 "android.hidl.manager-V1.2-java", 3376 "bouncycastle-unbundled", 3377 "dnsresolver_aidl_interface-V2-java", 3378 "error_prone_annotations", 3379 "framework-wifi-pre-jarjar", 3380 "framework-wifi-util-lib", 3381 "ipmemorystore-aidl-interfaces-V3-java", 3382 "ipmemorystore-aidl-interfaces-java", 3383 "ksoap2", 3384 "libnanohttpd", 3385 "libwifi-jni", 3386 "net-utils-services-common", 3387 "netd_aidl_interface-V2-java", 3388 "netd_aidl_interface-unstable-java", 3389 "netd_event_listener_interface-java", 3390 "netlink-client", 3391 "networkstack-client", 3392 "services.net", 3393 "wifi-lite-protos", 3394 "wifi-nano-protos", 3395 "wifi-service-pre-jarjar", 3396 "wifi-service-resources", 3397 } 3398 // 3399 // Module separator 3400 // 3401 m["com.android.os.statsd"] = []string{ 3402 "libstatssocket", 3403 } 3404 // 3405 // Module separator 3406 // 3407 m[android.AvailableToAnyApex] = []string{ 3408 // TODO(b/156996905) Set apex_available/min_sdk_version for androidx/extras support libraries 3409 "androidx", 3410 "androidx-constraintlayout_constraintlayout", 3411 "androidx-constraintlayout_constraintlayout-nodeps", 3412 "androidx-constraintlayout_constraintlayout-solver", 3413 "androidx-constraintlayout_constraintlayout-solver-nodeps", 3414 "com.google.android.material_material", 3415 "com.google.android.material_material-nodeps", 3416 3417 "libclang_rt", 3418 "libprofile-clang-extras", 3419 "libprofile-clang-extras_ndk", 3420 "libprofile-extras", 3421 "libprofile-extras_ndk", 3422 "libunwind", 3423 } 3424 return m 3425} 3426 3427func init() { 3428 android.AddNeverAllowRules(createBcpPermittedPackagesRules(qBcpPackages())...) 3429 android.AddNeverAllowRules(createBcpPermittedPackagesRules(rBcpPackages())...) 3430} 3431 3432func createBcpPermittedPackagesRules(bcpPermittedPackages map[string][]string) []android.Rule { 3433 rules := make([]android.Rule, 0, len(bcpPermittedPackages)) 3434 for jar, permittedPackages := range bcpPermittedPackages { 3435 permittedPackagesRule := android.NeverAllow(). 3436 With("name", jar). 3437 WithMatcher("permitted_packages", android.NotInList(permittedPackages)). 3438 Because(jar + 3439 " bootjar may only use these package prefixes: " + strings.Join(permittedPackages, ",") + 3440 ". Please consider the following alternatives:\n" + 3441 " 1. If the offending code is from a statically linked library, consider " + 3442 "removing that dependency and using an alternative already in the " + 3443 "bootclasspath, or perhaps a shared library." + 3444 " 2. Move the offending code into an allowed package.\n" + 3445 " 3. Jarjar the offending code. Please be mindful of the potential system " + 3446 "health implications of bundling that code, particularly if the offending jar " + 3447 "is part of the bootclasspath.") 3448 3449 rules = append(rules, permittedPackagesRule) 3450 } 3451 return rules 3452} 3453 3454// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART. 3455// Adding code to the bootclasspath in new packages will cause issues on module update. 3456func qBcpPackages() map[string][]string { 3457 return map[string][]string{ 3458 "conscrypt": { 3459 "android.net.ssl", 3460 "com.android.org.conscrypt", 3461 }, 3462 "updatable-media": { 3463 "android.media", 3464 }, 3465 } 3466} 3467 3468// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART. 3469// Adding code to the bootclasspath in new packages will cause issues on module update. 3470func rBcpPackages() map[string][]string { 3471 return map[string][]string{ 3472 "framework-mediaprovider": { 3473 "android.provider", 3474 }, 3475 "framework-permission": { 3476 "android.permission", 3477 "android.app.role", 3478 "com.android.permission", 3479 "com.android.role", 3480 }, 3481 "framework-sdkextensions": { 3482 "android.os.ext", 3483 }, 3484 "framework-statsd": { 3485 "android.app", 3486 "android.os", 3487 "android.util", 3488 "com.android.internal.statsd", 3489 "com.android.server.stats", 3490 }, 3491 "framework-wifi": { 3492 "com.android.server.wifi", 3493 "com.android.wifi.x", 3494 "android.hardware.wifi", 3495 "android.net.wifi", 3496 }, 3497 "framework-tethering": { 3498 "android.net", 3499 }, 3500 } 3501} 3502 3503// For Bazel / bp2build 3504 3505type bazelApexBundleAttributes struct { 3506 Manifest bazel.LabelAttribute 3507 Android_manifest bazel.LabelAttribute 3508 File_contexts bazel.LabelAttribute 3509 Canned_fs_config bazel.LabelAttribute 3510 Key bazel.LabelAttribute 3511 Certificate bazel.LabelAttribute // used when the certificate prop is a module 3512 Certificate_name bazel.StringAttribute // used when the certificate prop is a string 3513 Min_sdk_version bazel.StringAttribute 3514 Updatable bazel.BoolAttribute 3515 Installable bazel.BoolAttribute 3516 Binaries bazel.LabelListAttribute 3517 Prebuilts bazel.LabelListAttribute 3518 Native_shared_libs_32 bazel.LabelListAttribute 3519 Native_shared_libs_64 bazel.LabelListAttribute 3520 Compressible bazel.BoolAttribute 3521 Package_name *string 3522 Logging_parent *string 3523 Tests bazel.LabelListAttribute 3524 Base_apex_name *string 3525} 3526 3527type convertedNativeSharedLibs struct { 3528 Native_shared_libs_32 bazel.LabelListAttribute 3529 Native_shared_libs_64 bazel.LabelListAttribute 3530} 3531 3532const ( 3533 minSdkVersionPropName = "Min_sdk_version" 3534) 3535 3536// ConvertWithBp2build performs bp2build conversion of an apex 3537func (a *apexBundle) ConvertWithBp2build(ctx android.TopDownMutatorContext) { 3538 // We only convert apex and apex_test modules at this time 3539 if ctx.ModuleType() != "apex" && ctx.ModuleType() != "apex_test" { 3540 return 3541 } 3542 3543 attrs, props, commonAttrs := convertWithBp2build(a, ctx) 3544 commonAttrs.Name = a.Name() 3545 ctx.CreateBazelTargetModule(props, commonAttrs, &attrs) 3546} 3547 3548func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties, android.CommonAttributes) { 3549 var manifestLabelAttribute bazel.LabelAttribute 3550 manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))) 3551 3552 var androidManifestLabelAttribute bazel.LabelAttribute 3553 if a.properties.AndroidManifest != nil { 3554 androidManifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.AndroidManifest)) 3555 } 3556 3557 var fileContextsLabelAttribute bazel.LabelAttribute 3558 if a.properties.File_contexts == nil { 3559 // See buildFileContexts(), if file_contexts is not specified the default one is used, which is //system/sepolicy/apex:<module name>-file_contexts 3560 fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, a.Name()+"-file_contexts")) 3561 } else if strings.HasPrefix(*a.properties.File_contexts, ":") { 3562 // File_contexts is a module 3563 fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.properties.File_contexts)) 3564 } else { 3565 // File_contexts is a file 3566 fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.File_contexts)) 3567 } 3568 3569 var cannedFsConfigAttribute bazel.LabelAttribute 3570 if a.properties.Canned_fs_config != nil { 3571 cannedFsConfigAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.Canned_fs_config)) 3572 } 3573 3574 productVariableProps := android.ProductVariableProperties(ctx, a) 3575 // TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but 3576 // given it's coming via config, we probably don't want to put it in here. 3577 var minSdkVersion bazel.StringAttribute 3578 if a.properties.Min_sdk_version != nil { 3579 minSdkVersion.SetValue(*a.properties.Min_sdk_version) 3580 } 3581 if props, ok := productVariableProps[minSdkVersionPropName]; ok { 3582 for c, p := range props { 3583 if val, ok := p.(*string); ok { 3584 minSdkVersion.SetSelectValue(c.ConfigurationAxis(), c.SelectKey(), val) 3585 } 3586 } 3587 } 3588 3589 var keyLabelAttribute bazel.LabelAttribute 3590 if a.overridableProperties.Key != nil { 3591 keyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.overridableProperties.Key)) 3592 } 3593 3594 // Certificate 3595 certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableProperties.Certificate) 3596 3597 nativeSharedLibs := &convertedNativeSharedLibs{ 3598 Native_shared_libs_32: bazel.LabelListAttribute{}, 3599 Native_shared_libs_64: bazel.LabelListAttribute{}, 3600 } 3601 3602 // https://cs.android.com/android/platform/superproject/+/master:build/soong/android/arch.go;l=698;drc=f05b0d35d2fbe51be9961ce8ce8031f840295c68 3603 // https://cs.android.com/android/platform/superproject/+/master:build/soong/apex/apex.go;l=2549;drc=ec731a83e3e2d80a1254e32fd4ad7ef85e262669 3604 // In Soong, decodeMultilib, used to get multilib, return "first" if defaultMultilib is set to "common". 3605 // Since apex sets defaultMultilib to be "common", equivalent compileMultilib in bp2build for apex should be "first" 3606 compileMultilib := "first" 3607 if a.CompileMultilib() != nil { 3608 compileMultilib = *a.CompileMultilib() 3609 } 3610 3611 // properties.Native_shared_libs is treated as "both" 3612 convertBothLibs(ctx, compileMultilib, a.properties.Native_shared_libs, nativeSharedLibs) 3613 convertBothLibs(ctx, compileMultilib, a.properties.Multilib.Both.Native_shared_libs, nativeSharedLibs) 3614 convert32Libs(ctx, compileMultilib, a.properties.Multilib.Lib32.Native_shared_libs, nativeSharedLibs) 3615 convert64Libs(ctx, compileMultilib, a.properties.Multilib.Lib64.Native_shared_libs, nativeSharedLibs) 3616 convertFirstLibs(ctx, compileMultilib, a.properties.Multilib.First.Native_shared_libs, nativeSharedLibs) 3617 3618 prebuilts := a.overridableProperties.Prebuilts 3619 prebuiltsLabelList := android.BazelLabelForModuleDeps(ctx, prebuilts) 3620 prebuiltsLabelListAttribute := bazel.MakeLabelListAttribute(prebuiltsLabelList) 3621 3622 binaries := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Binaries) 3623 binariesLabelListAttribute := bazel.MakeLabelListAttribute(binaries) 3624 3625 var testsAttrs bazel.LabelListAttribute 3626 if a.testApex && len(a.properties.ApexNativeDependencies.Tests) > 0 { 3627 tests := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Tests) 3628 testsAttrs = bazel.MakeLabelListAttribute(tests) 3629 } 3630 3631 var updatableAttribute bazel.BoolAttribute 3632 if a.properties.Updatable != nil { 3633 updatableAttribute.Value = a.properties.Updatable 3634 } 3635 3636 var installableAttribute bazel.BoolAttribute 3637 if a.properties.Installable != nil { 3638 installableAttribute.Value = a.properties.Installable 3639 } 3640 3641 var compressibleAttribute bazel.BoolAttribute 3642 if a.overridableProperties.Compressible != nil { 3643 compressibleAttribute.Value = a.overridableProperties.Compressible 3644 } 3645 3646 var packageName *string 3647 if a.overridableProperties.Package_name != "" { 3648 packageName = &a.overridableProperties.Package_name 3649 } 3650 3651 var loggingParent *string 3652 if a.overridableProperties.Logging_parent != "" { 3653 loggingParent = &a.overridableProperties.Logging_parent 3654 } 3655 3656 attrs := bazelApexBundleAttributes{ 3657 Manifest: manifestLabelAttribute, 3658 Android_manifest: androidManifestLabelAttribute, 3659 File_contexts: fileContextsLabelAttribute, 3660 Canned_fs_config: cannedFsConfigAttribute, 3661 Min_sdk_version: minSdkVersion, 3662 Key: keyLabelAttribute, 3663 Certificate: certificate, 3664 Certificate_name: certificateName, 3665 Updatable: updatableAttribute, 3666 Installable: installableAttribute, 3667 Native_shared_libs_32: nativeSharedLibs.Native_shared_libs_32, 3668 Native_shared_libs_64: nativeSharedLibs.Native_shared_libs_64, 3669 Binaries: binariesLabelListAttribute, 3670 Prebuilts: prebuiltsLabelListAttribute, 3671 Compressible: compressibleAttribute, 3672 Package_name: packageName, 3673 Logging_parent: loggingParent, 3674 Tests: testsAttrs, 3675 } 3676 3677 props := bazel.BazelTargetModuleProperties{ 3678 Rule_class: "apex", 3679 Bzl_load_location: "//build/bazel/rules/apex:apex.bzl", 3680 } 3681 3682 commonAttrs := android.CommonAttributes{} 3683 if a.testApex { 3684 commonAttrs.Testonly = proptools.BoolPtr(true) 3685 } 3686 3687 return attrs, props, commonAttrs 3688} 3689 3690// The following conversions are based on this table where the rows are the compile_multilib 3691// values and the columns are the properties.Multilib.*.Native_shared_libs. Each cell 3692// represents how the libs should be compiled for a 64-bit/32-bit device: 32 means it 3693// should be compiled as 32-bit, 64 means it should be compiled as 64-bit, none means it 3694// should not be compiled. 3695// multib/compile_multilib, 32, 64, both, first 3696// 32, 32/32, none/none, 32/32, none/32 3697// 64, none/none, 64/none, 64/none, 64/none 3698// both, 32/32, 64/none, 32&64/32, 64/32 3699// first, 32/32, 64/none, 64/32, 64/32 3700 3701func convert32Libs(ctx android.TopDownMutatorContext, compileMultilb string, 3702 libs []string, nativeSharedLibs *convertedNativeSharedLibs) { 3703 libsLabelList := android.BazelLabelForModuleDeps(ctx, libs) 3704 switch compileMultilb { 3705 case "both", "32": 3706 makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3707 case "first": 3708 make32SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3709 case "64": 3710 // Incompatible, ignore 3711 default: 3712 invalidCompileMultilib(ctx, compileMultilb) 3713 } 3714} 3715 3716func convert64Libs(ctx android.TopDownMutatorContext, compileMultilb string, 3717 libs []string, nativeSharedLibs *convertedNativeSharedLibs) { 3718 libsLabelList := android.BazelLabelForModuleDeps(ctx, libs) 3719 switch compileMultilb { 3720 case "both", "64", "first": 3721 make64SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3722 case "32": 3723 // Incompatible, ignore 3724 default: 3725 invalidCompileMultilib(ctx, compileMultilb) 3726 } 3727} 3728 3729func convertBothLibs(ctx android.TopDownMutatorContext, compileMultilb string, 3730 libs []string, nativeSharedLibs *convertedNativeSharedLibs) { 3731 libsLabelList := android.BazelLabelForModuleDeps(ctx, libs) 3732 switch compileMultilb { 3733 case "both": 3734 makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3735 make64SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3736 case "first": 3737 makeFirstSharedLibsAttributes(libsLabelList, nativeSharedLibs) 3738 case "32": 3739 makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3740 case "64": 3741 make64SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3742 default: 3743 invalidCompileMultilib(ctx, compileMultilb) 3744 } 3745} 3746 3747func convertFirstLibs(ctx android.TopDownMutatorContext, compileMultilb string, 3748 libs []string, nativeSharedLibs *convertedNativeSharedLibs) { 3749 libsLabelList := android.BazelLabelForModuleDeps(ctx, libs) 3750 switch compileMultilb { 3751 case "both", "first": 3752 makeFirstSharedLibsAttributes(libsLabelList, nativeSharedLibs) 3753 case "32": 3754 make32SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3755 case "64": 3756 make64SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3757 default: 3758 invalidCompileMultilib(ctx, compileMultilb) 3759 } 3760} 3761 3762func makeFirstSharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) { 3763 make32SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3764 make64SharedLibsAttributes(libsLabelList, nativeSharedLibs) 3765} 3766 3767func makeNoConfig32SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) { 3768 list := bazel.LabelListAttribute{} 3769 list.SetSelectValue(bazel.NoConfigAxis, "", libsLabelList) 3770 nativeSharedLibs.Native_shared_libs_32.Append(list) 3771} 3772 3773func make32SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) { 3774 makeSharedLibsAttributes("x86", libsLabelList, &nativeSharedLibs.Native_shared_libs_32) 3775 makeSharedLibsAttributes("arm", libsLabelList, &nativeSharedLibs.Native_shared_libs_32) 3776} 3777 3778func make64SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) { 3779 makeSharedLibsAttributes("x86_64", libsLabelList, &nativeSharedLibs.Native_shared_libs_64) 3780 makeSharedLibsAttributes("arm64", libsLabelList, &nativeSharedLibs.Native_shared_libs_64) 3781} 3782 3783func makeSharedLibsAttributes(config string, libsLabelList bazel.LabelList, 3784 labelListAttr *bazel.LabelListAttribute) { 3785 list := bazel.LabelListAttribute{} 3786 list.SetSelectValue(bazel.ArchConfigurationAxis, config, libsLabelList) 3787 labelListAttr.Append(list) 3788} 3789 3790func invalidCompileMultilib(ctx android.TopDownMutatorContext, value string) { 3791 ctx.PropertyErrorf("compile_multilib", "Invalid value: %s", value) 3792} 3793