1// Copyright (C) 2019 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 15package apex 16 17import ( 18 "strconv" 19 "strings" 20 21 "android/soong/android" 22 "android/soong/dexpreopt" 23 "android/soong/java" 24 "android/soong/provenance" 25 26 "github.com/google/blueprint" 27 "github.com/google/blueprint/proptools" 28) 29 30var ( 31 extractMatchingApex = pctx.StaticRule( 32 "extractMatchingApex", 33 blueprint.RuleParams{ 34 Command: `rm -rf "$out" && ` + 35 `${extract_apks} -o "${out}" -allow-prereleased=${allow-prereleased} ` + 36 `-sdk-version=${sdk-version} -skip-sdk-check=${skip-sdk-check} -abis=${abis} ` + 37 `-screen-densities=all -extract-single ` + 38 `${in}`, 39 CommandDeps: []string{"${extract_apks}"}, 40 }, 41 "abis", "allow-prereleased", "sdk-version", "skip-sdk-check") 42 decompressApex = pctx.StaticRule("decompressApex", blueprint.RuleParams{ 43 Command: `rm -rf $out && ${deapexer} decompress --copy-if-uncompressed --input ${in} --output ${out}`, 44 CommandDeps: []string{"${deapexer}"}, 45 Description: "decompress $out", 46 }) 47) 48 49type prebuilt interface { 50 isForceDisabled() bool 51 InstallFilename() string 52} 53 54type prebuiltCommon struct { 55 android.ModuleBase 56 java.Dexpreopter 57 prebuilt android.Prebuilt 58 59 // Properties common to both prebuilt_apex and apex_set. 60 prebuiltCommonProperties *PrebuiltCommonProperties 61 62 installDir android.InstallPath 63 installFilename string 64 installedFile android.InstallPath 65 outputApex android.WritablePath 66 67 // fragment for this apex for apexkeys.txt 68 apexKeysPath android.WritablePath 69 70 // Installed locations of symlinks for backward compatibility. 71 compatSymlinks android.InstallPaths 72 73 hostRequired []string 74 requiredModuleNames []string 75} 76 77type sanitizedPrebuilt interface { 78 hasSanitizedSource(sanitizer string) bool 79} 80 81type PrebuiltCommonProperties struct { 82 SelectedApexProperties 83 84 // Canonical name of this APEX. Used to determine the path to the activated APEX on 85 // device (/apex/<apex_name>). If unspecified, follows the name property. 86 Apex_name *string 87 88 // Name of the source APEX that gets shadowed by this prebuilt 89 // e.g. com.mycompany.android.myapex 90 // If unspecified, follows the naming convention that the source apex of 91 // the prebuilt is Name() without "prebuilt_" prefix 92 Source_apex_name *string 93 94 ForceDisable bool `blueprint:"mutated"` 95 96 // whether the extracted apex file is installable. 97 Installable *bool 98 99 // optional name for the installed apex. If unspecified, name of the 100 // module is used as the file name 101 Filename *string 102 103 // names of modules to be overridden. Listed modules can only be other binaries 104 // (in Make or Soong). 105 // This does not completely prevent installation of the overridden binaries, but if both 106 // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed 107 // from PRODUCT_PACKAGES. 108 Overrides []string 109 110 // List of bootclasspath fragments inside this prebuilt APEX bundle and for which this APEX 111 // bundle will create an APEX variant. 112 Exported_bootclasspath_fragments []string 113 114 // List of systemserverclasspath fragments inside this prebuilt APEX bundle and for which this 115 // APEX bundle will create an APEX variant. 116 Exported_systemserverclasspath_fragments []string 117 118 // Path to the .prebuilt_info file of the prebuilt apex. 119 // In case of mainline modules, the .prebuilt_info file contains the build_id that was used to 120 // generate the prebuilt. 121 Prebuilt_info *string `android:"path"` 122} 123 124// initPrebuiltCommon initializes the prebuiltCommon structure and performs initialization of the 125// module that is common to Prebuilt and ApexSet. 126func (p *prebuiltCommon) initPrebuiltCommon(module android.Module, properties *PrebuiltCommonProperties) { 127 p.prebuiltCommonProperties = properties 128 android.InitSingleSourcePrebuiltModule(module.(android.PrebuiltInterface), properties, "Selected_apex") 129 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 130} 131 132func (p *prebuiltCommon) ApexVariationName() string { 133 return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.BaseModuleName()) 134} 135 136func (p *prebuiltCommon) BaseModuleName() string { 137 return proptools.StringDefault(p.prebuiltCommonProperties.Source_apex_name, p.ModuleBase.BaseModuleName()) 138} 139 140func (p *prebuiltCommon) Prebuilt() *android.Prebuilt { 141 return &p.prebuilt 142} 143 144func (p *prebuiltCommon) isForceDisabled() bool { 145 return p.prebuiltCommonProperties.ForceDisable 146} 147 148func (p *prebuiltCommon) checkForceDisable(ctx android.ModuleContext) bool { 149 forceDisable := false 150 151 // Force disable the prebuilts when we are doing unbundled build. We do unbundled build 152 // to build the prebuilts themselves. 153 forceDisable = forceDisable || ctx.Config().UnbundledBuild() 154 155 // b/137216042 don't use prebuilts when address sanitizer is on, unless the prebuilt has a sanitized source 156 sanitized := ctx.Module().(sanitizedPrebuilt) 157 forceDisable = forceDisable || (android.InList("address", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("address")) 158 forceDisable = forceDisable || (android.InList("hwaddress", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("hwaddress")) 159 160 if forceDisable && p.prebuilt.SourceExists() { 161 p.prebuiltCommonProperties.ForceDisable = true 162 return true 163 } 164 return false 165} 166 167func (p *prebuiltCommon) InstallFilename() string { 168 return proptools.StringDefault(p.prebuiltCommonProperties.Filename, p.BaseModuleName()+imageApexSuffix) 169} 170 171func (p *prebuiltCommon) Name() string { 172 return p.prebuilt.Name(p.ModuleBase.Name()) 173} 174 175func (p *prebuiltCommon) Overrides() []string { 176 return p.prebuiltCommonProperties.Overrides 177} 178 179func (p *prebuiltCommon) installable() bool { 180 return proptools.BoolDefault(p.prebuiltCommonProperties.Installable, true) 181} 182 183// To satisfy java.DexpreopterInterface 184func (p *prebuiltCommon) IsInstallable() bool { 185 return p.installable() 186} 187 188// initApexFilesForAndroidMk initializes the prebuiltCommon.requiredModuleNames field with the install only deps of the prebuilt apex 189func (p *prebuiltCommon) initApexFilesForAndroidMk(ctx android.ModuleContext) { 190 // If this apex contains a system server jar, then the dexpreopt artifacts should be added as required 191 for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() { 192 p.requiredModuleNames = append(p.requiredModuleNames, install.FullModuleName()) 193 } 194} 195 196// If this prebuilt has system server jar, create the rules to dexpreopt it and install it alongside the prebuilt apex 197func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext, di *android.DeapexerInfo) { 198 if di == nil { 199 return 200 } 201 // If this prebuilt apex has not been selected, return 202 if p.IsHideFromMake() { 203 return 204 } 205 // Use apex_name to determine the api domain of this prebuilt apex 206 apexName := p.ApexVariationName() 207 // TODO: do not compute twice 208 dc := dexpreopt.GetGlobalConfig(ctx) 209 systemServerJarList := dc.AllApexSystemServerJars(ctx) 210 211 for i := 0; i < systemServerJarList.Len(); i++ { 212 sscpApex := systemServerJarList.Apex(i) 213 sscpJar := systemServerJarList.Jar(i) 214 if apexName != sscpApex { 215 continue 216 } 217 p.Dexpreopter.DexpreoptPrebuiltApexSystemServerJars(ctx, sscpJar, di) 218 } 219} 220 221func (p *prebuiltCommon) addRequiredModules(entries *android.AndroidMkEntries) { 222 entries.AddStrings("LOCAL_REQUIRED_MODULES", p.requiredModuleNames...) 223} 224 225func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries { 226 entriesList := []android.AndroidMkEntries{ 227 { 228 Class: "ETC", 229 OutputFile: android.OptionalPathForPath(p.outputApex), 230 Include: "$(BUILD_PREBUILT)", 231 Host_required: p.hostRequired, 232 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 233 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 234 entries.SetString("LOCAL_MODULE_PATH", p.installDir.String()) 235 entries.SetString("LOCAL_MODULE_STEM", p.installFilename) 236 entries.SetPath("LOCAL_SOONG_INSTALLED_MODULE", p.installedFile) 237 entries.SetString("LOCAL_SOONG_INSTALL_PAIRS", p.outputApex.String()+":"+p.installedFile.String()) 238 entries.AddStrings("LOCAL_SOONG_INSTALL_SYMLINKS", p.compatSymlinks.Strings()...) 239 entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable()) 240 entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.prebuiltCommonProperties.Overrides...) 241 entries.SetString("LOCAL_APEX_KEY_PATH", p.apexKeysPath.String()) 242 p.addRequiredModules(entries) 243 }, 244 }, 245 }, 246 } 247 248 // Add the dexpreopt artifacts to androidmk 249 for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() { 250 entriesList = append(entriesList, install.ToMakeEntries()) 251 } 252 253 return entriesList 254} 255 256func (p *prebuiltCommon) hasExportedDeps() bool { 257 return len(p.prebuiltCommonProperties.Exported_bootclasspath_fragments) > 0 || 258 len(p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments) > 0 259} 260 261// prebuiltApexContentsDeps adds dependencies onto the prebuilt apex module's contents. 262func (p *prebuiltCommon) prebuiltApexContentsDeps(ctx android.BottomUpMutatorContext) { 263 module := ctx.Module() 264 265 for _, dep := range p.prebuiltCommonProperties.Exported_bootclasspath_fragments { 266 prebuiltDep := android.PrebuiltNameFromSource(dep) 267 ctx.AddDependency(module, exportedBootclasspathFragmentTag, prebuiltDep) 268 } 269 270 for _, dep := range p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments { 271 prebuiltDep := android.PrebuiltNameFromSource(dep) 272 ctx.AddDependency(module, exportedSystemserverclasspathFragmentTag, prebuiltDep) 273 } 274} 275 276// Implements android.DepInInSameApex 277func (p *prebuiltCommon) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { 278 tag := ctx.OtherModuleDependencyTag(dep) 279 _, ok := tag.(exportedDependencyTag) 280 return ok 281} 282 283// apexInfoMutator marks any modules for which this apex exports a file as requiring an apex 284// specific variant and checks that they are supported. 285// 286// The apexMutator will ensure that the ApexInfo objects passed to BuildForApex(ApexInfo) are 287// associated with the apex specific variant using the ApexInfoProvider for later retrieval. 288// 289// Unlike the source apex module type the prebuilt_apex module type cannot share compatible variants 290// across prebuilt_apex modules. That is because there is no way to determine whether two 291// prebuilt_apex modules that export files for the same module are compatible. e.g. they could have 292// been built from different source at different times or they could have been built with different 293// build options that affect the libraries. 294// 295// While it may be possible to provide sufficient information to determine whether two prebuilt_apex 296// modules were compatible it would be a lot of work and would not provide much benefit for a couple 297// of reasons: 298// - The number of prebuilt_apex modules that will be exporting files for the same module will be 299// low as the prebuilt_apex only exports files for the direct dependencies that require it and 300// very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a 301// few com.android.art* apex files that contain the same contents and could export files for the 302// same modules but only one of them needs to do so. Contrast that with source apex modules which 303// need apex specific variants for every module that contributes code to the apex, whether direct 304// or indirect. 305// - The build cost of a prebuilt_apex variant is generally low as at worst it will involve some 306// extra copying of files. Contrast that with source apex modules that has to build each variant 307// from source. 308func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { 309 // Collect the list of dependencies. 310 var dependencies []android.ApexModule 311 mctx.WalkDeps(func(child, parent android.Module) bool { 312 // If the child is not in the same apex as the parent then exit immediately and do not visit 313 // any of the child's dependencies. 314 if !android.IsDepInSameApex(mctx, parent, child) { 315 return false 316 } 317 318 tag := mctx.OtherModuleDependencyTag(child) 319 depName := mctx.OtherModuleName(child) 320 if exportedTag, ok := tag.(exportedDependencyTag); ok { 321 propertyName := exportedTag.name 322 323 // It is an error if the other module is not a prebuilt. 324 if !android.IsModulePrebuilt(child) { 325 mctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName) 326 return false 327 } 328 329 // It is an error if the other module is not an ApexModule. 330 if _, ok := child.(android.ApexModule); !ok { 331 mctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName) 332 return false 333 } 334 } 335 336 // Ignore any modules that do not implement ApexModule as they cannot have an APEX specific 337 // variant. 338 if _, ok := child.(android.ApexModule); !ok { 339 return false 340 } 341 342 // Strip off the prebuilt_ prefix if present before storing content to ensure consistent 343 // behavior whether there is a corresponding source module present or not. 344 depName = android.RemoveOptionalPrebuiltPrefix(depName) 345 346 // Add the module to the list of dependencies that need to have an APEX variant. 347 dependencies = append(dependencies, child.(android.ApexModule)) 348 349 return true 350 }) 351 352 android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{}) 353 354 // Create an ApexInfo for the prebuilt_apex. 355 apexVariationName := p.ApexVariationName() 356 apexInfo := android.ApexInfo{ 357 ApexVariationName: apexVariationName, 358 InApexVariants: []string{apexVariationName}, 359 ForPrebuiltApex: true, 360 } 361 362 // Mark the dependencies of this module as requiring a variant for this module. 363 for _, am := range dependencies { 364 am.BuildForApex(apexInfo) 365 } 366} 367 368type Prebuilt struct { 369 prebuiltCommon 370 371 properties PrebuiltProperties 372 373 inputApex android.Path 374 375 provenanceMetaDataFile android.Path 376} 377 378type ApexFileProperties struct { 379 // the path to the prebuilt .apex file to import. 380 // 381 // This cannot be marked as `android:"arch_variant"` because the `prebuilt_apex` is only mutated 382 // for android_common. That is so that it will have the same arch variant as, and so be compatible 383 // with, the source `apex` module type that it replaces. 384 Src proptools.Configurable[string] `android:"path,replace_instead_of_append"` 385 Arch struct { 386 Arm struct { 387 Src *string `android:"path"` 388 } 389 Arm64 struct { 390 Src *string `android:"path"` 391 } 392 Riscv64 struct { 393 Src *string `android:"path"` 394 } 395 X86 struct { 396 Src *string `android:"path"` 397 } 398 X86_64 struct { 399 Src *string `android:"path"` 400 } 401 } 402} 403 404// prebuiltApexSelector selects the correct prebuilt APEX file for the build target. 405// 406// The ctx parameter can be for any module not just the prebuilt module so care must be taken not 407// to use methods on it that are specific to the current module. 408// 409// See the ApexFileProperties.Src property. 410func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, prebuilt android.Module) string { 411 multiTargets := prebuilt.MultiTargets() 412 if len(multiTargets) != 1 { 413 ctx.OtherModuleErrorf(prebuilt, "compile_multilib shouldn't be \"both\" for prebuilt_apex") 414 return "" 415 } 416 var src string 417 switch multiTargets[0].Arch.ArchType { 418 case android.Arm: 419 src = String(p.Arch.Arm.Src) 420 case android.Arm64: 421 src = String(p.Arch.Arm64.Src) 422 case android.Riscv64: 423 src = String(p.Arch.Riscv64.Src) 424 // HACK: fall back to arm64 prebuilts, the riscv64 ones don't exist yet. 425 if src == "" { 426 src = String(p.Arch.Arm64.Src) 427 } 428 case android.X86: 429 src = String(p.Arch.X86.Src) 430 case android.X86_64: 431 src = String(p.Arch.X86_64.Src) 432 } 433 if src == "" { 434 src = p.Src.GetOrDefault(ctx, "") 435 } 436 437 if src == "" { 438 if ctx.Config().AllowMissingDependencies() { 439 ctx.AddMissingDependencies([]string{ctx.OtherModuleName(prebuilt)}) 440 } else { 441 ctx.OtherModuleErrorf(prebuilt, "prebuilt_apex does not support %q", multiTargets[0].Arch.String()) 442 } 443 // Drop through to return an empty string as the src (instead of nil) to avoid the prebuilt 444 // logic from reporting a more general, less useful message. 445 } 446 447 return src 448} 449 450type PrebuiltProperties struct { 451 ApexFileProperties 452 453 PrebuiltCommonProperties 454} 455 456func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool { 457 return false 458} 459 460// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex. 461func PrebuiltFactory() android.Module { 462 module := &Prebuilt{} 463 module.AddProperties(&module.properties) 464 module.prebuiltCommon.prebuiltCommonProperties = &module.properties.PrebuiltCommonProperties 465 466 // init the module as a prebuilt 467 // even though this module type has srcs, use `InitPrebuiltModuleWithoutSrcs`, since the existing 468 // InitPrebuiltModule* are not friendly with Sources of Configurable type. 469 // The actual src will be evaluated in GenerateAndroidBuildActions. 470 android.InitPrebuiltModuleWithoutSrcs(module) 471 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 472 473 return module 474} 475 476func (p *prebuiltCommon) getDeapexerPropertiesIfNeeded(ctx android.ModuleContext) DeapexerProperties { 477 // Compute the deapexer properties from the transitive dependencies of this module. 478 commonModules := []string{} 479 dexpreoptProfileGuidedModules := []string{} 480 exportedFiles := []string{} 481 ctx.WalkDeps(func(child, parent android.Module) bool { 482 tag := ctx.OtherModuleDependencyTag(child) 483 484 // If the child is not in the same apex as the parent then ignore it and all its children. 485 if !android.IsDepInSameApex(ctx, parent, child) { 486 return false 487 } 488 489 name := java.ModuleStemForDeapexing(child) 490 if _, ok := tag.(android.RequiresFilesFromPrebuiltApexTag); ok { 491 commonModules = append(commonModules, name) 492 493 extract := child.(android.RequiredFilesFromPrebuiltApex) 494 requiredFiles := extract.RequiredFilesFromPrebuiltApex(ctx) 495 exportedFiles = append(exportedFiles, requiredFiles...) 496 497 if extract.UseProfileGuidedDexpreopt() { 498 dexpreoptProfileGuidedModules = append(dexpreoptProfileGuidedModules, name) 499 } 500 501 // Visit the dependencies of this module just in case they also require files from the 502 // prebuilt apex. 503 return true 504 } 505 506 return false 507 }) 508 509 // Create properties for deapexer module. 510 deapexerProperties := DeapexerProperties{ 511 // Remove any duplicates from the common modules lists as a module may be included via a direct 512 // dependency as well as transitive ones. 513 CommonModules: android.SortedUniqueStrings(commonModules), 514 DexpreoptProfileGuidedModules: android.SortedUniqueStrings(dexpreoptProfileGuidedModules), 515 } 516 517 // Populate the exported files property in a fixed order. 518 deapexerProperties.ExportedFiles = android.SortedUniqueStrings(exportedFiles) 519 return deapexerProperties 520} 521 522func prebuiltApexExportedModuleName(ctx android.BottomUpMutatorContext, name string) string { 523 // The prebuilt_apex should be depending on prebuilt modules but as this runs after 524 // prebuilt_rename the prebuilt module may or may not be using the prebuilt_ prefixed named. So, 525 // check to see if the prefixed name is in use first, if it is then use that, otherwise assume 526 // the unprefixed name is the one to use. If the unprefixed one turns out to be a source module 527 // and not a renamed prebuilt module then that will be detected and reported as an error when 528 // processing the dependency in ApexInfoMutator(). 529 prebuiltName := android.PrebuiltNameFromSource(name) 530 if ctx.OtherModuleExists(prebuiltName) { 531 name = prebuiltName 532 } 533 return name 534} 535 536type exportedDependencyTag struct { 537 blueprint.BaseDependencyTag 538 name string 539} 540 541// Mark this tag so dependencies that use it are excluded from visibility enforcement. 542// 543// This does allow any prebuilt_apex to reference any module which does open up a small window for 544// restricted visibility modules to be referenced from the wrong prebuilt_apex. However, doing so 545// avoids opening up a much bigger window by widening the visibility of modules that need files 546// provided by the prebuilt_apex to include all the possible locations they may be defined, which 547// could include everything below vendor/. 548// 549// A prebuilt_apex that references a module via this tag will have to contain the appropriate files 550// corresponding to that module, otherwise it will fail when attempting to retrieve the files from 551// the .apex file. It will also have to be included in the module's apex_available property too. 552// That makes it highly unlikely that a prebuilt_apex would reference a restricted module 553// incorrectly. 554func (t exportedDependencyTag) ExcludeFromVisibilityEnforcement() {} 555 556func (t exportedDependencyTag) RequiresFilesFromPrebuiltApex() {} 557 558var _ android.RequiresFilesFromPrebuiltApexTag = exportedDependencyTag{} 559 560var ( 561 exportedBootclasspathFragmentTag = exportedDependencyTag{name: "exported_bootclasspath_fragments"} 562 exportedSystemserverclasspathFragmentTag = exportedDependencyTag{name: "exported_systemserverclasspath_fragments"} 563) 564 565func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { 566 p.prebuiltApexContentsDeps(ctx) 567} 568 569var _ ApexInfoMutator = (*Prebuilt)(nil) 570 571func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) { 572 p.apexInfoMutator(mctx) 573} 574 575// creates the build rules to deapex the prebuilt, and returns a deapexerInfo 576func (p *prebuiltCommon) getDeapexerInfo(ctx android.ModuleContext, apexFile android.Path) *android.DeapexerInfo { 577 if !p.hasExportedDeps() { 578 // nothing to do 579 return nil 580 } 581 deapexerProps := p.getDeapexerPropertiesIfNeeded(ctx) 582 return deapex(ctx, apexFile, deapexerProps) 583} 584 585// Set a provider containing information about the jars and .prof provided by the apex 586// Apexes built from prebuilts retrieve this information by visiting its internal deapexer module 587// Used by dex_bootjars to generate the boot image 588func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext, di *android.DeapexerInfo) { 589 if di == nil { 590 return 591 } 592 javaModuleToDexPath := map[string]android.Path{} 593 for _, commonModule := range di.GetExportedModuleNames() { 594 if dex := di.PrebuiltExportPath(java.ApexRootRelativePathToJavaLib(commonModule)); dex != nil { 595 javaModuleToDexPath[commonModule] = dex 596 } 597 } 598 599 exports := android.ApexExportsInfo{ 600 ApexName: p.ApexVariationName(), 601 ProfilePathOnHost: di.PrebuiltExportPath(java.ProfileInstallPathInApex), 602 LibraryNameToDexJarPathOnHost: javaModuleToDexPath, 603 } 604 android.SetProvider(ctx, android.ApexExportsInfoProvider, exports) 605} 606 607// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file 608// with information about whether source or prebuilt of an apex was used during the build. 609func (p *prebuiltCommon) providePrebuiltInfo(ctx android.ModuleContext) { 610 info := android.PrebuiltInfo{ 611 Name: p.BaseModuleName(), 612 Is_prebuilt: true, 613 } 614 // If Prebuilt_info information is available in the soong module definition, add it to prebuilt_info.json. 615 if p.prebuiltCommonProperties.Prebuilt_info != nil { 616 info.Prebuilt_info_file_path = android.PathForModuleSrc(ctx, *p.prebuiltCommonProperties.Prebuilt_info).String() 617 } 618 android.SetProvider(ctx, android.PrebuiltInfoProvider, info) 619} 620 621// Uses an object provided by its deps to validate that the contents of bcpf have been added to the global 622// PRODUCT_APEX_BOOT_JARS 623// This validation will only run on the apex which is active for this product/release_config 624func validateApexClasspathFragments(ctx android.ModuleContext) { 625 ctx.VisitDirectDeps(func(m android.Module) { 626 if info, exists := android.OtherModuleProvider(ctx, m, java.ClasspathFragmentValidationInfoProvider); exists { 627 ctx.ModuleErrorf("%s in contents of %s must also be declared in PRODUCT_APEX_BOOT_JARS", info.UnknownJars, info.ClasspathFragmentModuleName) 628 } 629 }) 630} 631 632func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { 633 // Validate contents of classpath fragments 634 if !p.IsHideFromMake() { 635 validateApexClasspathFragments(ctx) 636 } 637 638 p.apexKeysPath = writeApexKeys(ctx, p) 639 // TODO(jungjw): Check the key validity. 640 p.inputApex = android.PathForModuleSrc(ctx, p.properties.prebuiltApexSelector(ctx, ctx.Module())) 641 p.installDir = android.PathForModuleInstall(ctx, "apex") 642 p.installFilename = p.InstallFilename() 643 if !strings.HasSuffix(p.installFilename, imageApexSuffix) { 644 ctx.ModuleErrorf("filename should end in %s for prebuilt_apex", imageApexSuffix) 645 } 646 p.outputApex = android.PathForModuleOut(ctx, p.installFilename) 647 ctx.Build(pctx, android.BuildParams{ 648 Rule: android.Cp, 649 Input: p.inputApex, 650 Output: p.outputApex, 651 }) 652 653 if p.prebuiltCommon.checkForceDisable(ctx) { 654 p.HideFromMake() 655 return 656 } 657 658 deapexerInfo := p.getDeapexerInfo(ctx, p.inputApex) 659 660 // dexpreopt any system server jars if present 661 p.dexpreoptSystemServerJars(ctx, deapexerInfo) 662 663 // provide info used for generating the boot image 664 p.provideApexExportsInfo(ctx, deapexerInfo) 665 666 p.providePrebuiltInfo(ctx) 667 668 // Save the files that need to be made available to Make. 669 p.initApexFilesForAndroidMk(ctx) 670 671 // in case that prebuilt_apex replaces source apex (using prefer: prop) 672 p.compatSymlinks = makeCompatSymlinks(p.BaseModuleName(), ctx) 673 // or that prebuilt_apex overrides other apexes (using overrides: prop) 674 for _, overridden := range p.prebuiltCommonProperties.Overrides { 675 p.compatSymlinks = append(p.compatSymlinks, makeCompatSymlinks(overridden, ctx)...) 676 } 677 678 if p.installable() { 679 p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks...) 680 p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile) 681 } 682 683 ctx.SetOutputFiles(android.Paths{p.outputApex}, "") 684} 685 686func (p *Prebuilt) ProvenanceMetaDataFile() android.Path { 687 return p.provenanceMetaDataFile 688} 689 690// prebuiltApexExtractorModule is a private module type that is only created by the prebuilt_apex 691// module. It extracts the correct apex to use and makes it available for use by apex_set. 692type prebuiltApexExtractorModule struct { 693 android.ModuleBase 694 695 properties ApexExtractorProperties 696 697 extractedApex android.WritablePath 698} 699 700// extract registers the build actions to extract an apex from .apks file 701// returns the path of the extracted apex 702func extract(ctx android.ModuleContext, apexSet android.Path, prerelease *bool) android.Path { 703 defaultAllowPrerelease := ctx.Config().IsEnvTrue("SOONG_ALLOW_PRERELEASE_APEXES") 704 extractedApex := android.PathForModuleOut(ctx, "extracted", apexSet.Base()) 705 // Filter out NativeBridge archs (b/260115309) 706 abis := java.SupportedAbis(ctx, true) 707 ctx.Build(pctx, 708 android.BuildParams{ 709 Rule: extractMatchingApex, 710 Description: "Extract an apex from an apex set", 711 Inputs: android.Paths{apexSet}, 712 Output: extractedApex, 713 Args: map[string]string{ 714 "abis": strings.Join(abis, ","), 715 "allow-prereleased": strconv.FormatBool(proptools.BoolDefault(prerelease, defaultAllowPrerelease)), 716 "sdk-version": ctx.Config().PlatformSdkVersion().String(), 717 "skip-sdk-check": strconv.FormatBool(ctx.Config().IsEnvTrue("SOONG_SKIP_APPSET_SDK_CHECK")), 718 }, 719 }, 720 ) 721 return extractedApex 722} 723 724type ApexSet struct { 725 prebuiltCommon 726 727 properties ApexSetProperties 728} 729 730type ApexExtractorProperties struct { 731 // the .apks file path that contains prebuilt apex files to be extracted. 732 Set *string `android:"path"` 733 734 Sanitized struct { 735 None struct { 736 Set *string `android:"path"` 737 } 738 Address struct { 739 Set *string `android:"path"` 740 } 741 Hwaddress struct { 742 Set *string `android:"path"` 743 } 744 } 745 746 // apexes in this set use prerelease SDK version 747 Prerelease *bool 748} 749 750func (e *ApexExtractorProperties) prebuiltSrcs(ctx android.BaseModuleContext) []string { 751 var srcs []string 752 if e.Set != nil { 753 srcs = append(srcs, *e.Set) 754 } 755 756 sanitizers := ctx.Config().SanitizeDevice() 757 758 if android.InList("address", sanitizers) && e.Sanitized.Address.Set != nil { 759 srcs = append(srcs, *e.Sanitized.Address.Set) 760 } else if android.InList("hwaddress", sanitizers) && e.Sanitized.Hwaddress.Set != nil { 761 srcs = append(srcs, *e.Sanitized.Hwaddress.Set) 762 } else if e.Sanitized.None.Set != nil { 763 srcs = append(srcs, *e.Sanitized.None.Set) 764 } 765 766 return srcs 767} 768 769type ApexSetProperties struct { 770 ApexExtractorProperties 771 772 PrebuiltCommonProperties 773} 774 775func (a *ApexSet) hasSanitizedSource(sanitizer string) bool { 776 if sanitizer == "address" { 777 return a.properties.Sanitized.Address.Set != nil 778 } 779 if sanitizer == "hwaddress" { 780 return a.properties.Sanitized.Hwaddress.Set != nil 781 } 782 783 return false 784} 785 786// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex. 787func apexSetFactory() android.Module { 788 module := &ApexSet{} 789 module.AddProperties(&module.properties) 790 module.prebuiltCommon.prebuiltCommonProperties = &module.properties.PrebuiltCommonProperties 791 792 // init the module as a prebuilt 793 // even though this module type has srcs, use `InitPrebuiltModuleWithoutSrcs`, since the existing 794 // InitPrebuiltModule* are not friendly with Sources of Configurable type. 795 // The actual src will be evaluated in GenerateAndroidBuildActions. 796 android.InitPrebuiltModuleWithoutSrcs(module) 797 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 798 799 return module 800} 801 802func (a *ApexSet) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { 803 a.prebuiltApexContentsDeps(ctx) 804} 805 806var _ ApexInfoMutator = (*ApexSet)(nil) 807 808func (a *ApexSet) ApexInfoMutator(mctx android.TopDownMutatorContext) { 809 a.apexInfoMutator(mctx) 810} 811 812func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { 813 // Validate contents of classpath fragments 814 if !a.IsHideFromMake() { 815 validateApexClasspathFragments(ctx) 816 } 817 818 a.apexKeysPath = writeApexKeys(ctx, a) 819 a.installFilename = a.InstallFilename() 820 if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) { 821 ctx.ModuleErrorf("filename should end in %s or %s for apex_set", imageApexSuffix, imageCapexSuffix) 822 } 823 824 var apexSet android.Path 825 if srcs := a.properties.prebuiltSrcs(ctx); len(srcs) == 1 { 826 apexSet = android.PathForModuleSrc(ctx, srcs[0]) 827 } else { 828 ctx.ModuleErrorf("Expected exactly one source apex_set file, found %v\n", srcs) 829 } 830 831 extractedApex := extract(ctx, apexSet, a.properties.Prerelease) 832 833 a.outputApex = android.PathForModuleOut(ctx, a.installFilename) 834 835 // Build the output APEX. If compression is not enabled, make sure the output is not compressed even if the input is compressed 836 buildRule := android.Cp 837 if !ctx.Config().ApexCompressionEnabled() { 838 buildRule = decompressApex 839 } 840 ctx.Build(pctx, android.BuildParams{ 841 Rule: buildRule, 842 Input: extractedApex, 843 Output: a.outputApex, 844 }) 845 846 if a.prebuiltCommon.checkForceDisable(ctx) { 847 a.HideFromMake() 848 return 849 } 850 851 deapexerInfo := a.getDeapexerInfo(ctx, extractedApex) 852 853 // dexpreopt any system server jars if present 854 a.dexpreoptSystemServerJars(ctx, deapexerInfo) 855 856 // provide info used for generating the boot image 857 a.provideApexExportsInfo(ctx, deapexerInfo) 858 859 a.providePrebuiltInfo(ctx) 860 861 // Save the files that need to be made available to Make. 862 a.initApexFilesForAndroidMk(ctx) 863 864 a.installDir = android.PathForModuleInstall(ctx, "apex") 865 if a.installable() { 866 a.installedFile = ctx.InstallFile(a.installDir, a.installFilename, a.outputApex) 867 } 868 869 // in case that apex_set replaces source apex (using prefer: prop) 870 a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx) 871 // or that apex_set overrides other apexes (using overrides: prop) 872 for _, overridden := range a.prebuiltCommonProperties.Overrides { 873 a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx)...) 874 } 875 876 ctx.SetOutputFiles(android.Paths{a.outputApex}, "") 877} 878 879type systemExtContext struct { 880 android.ModuleContext 881} 882 883func (*systemExtContext) SystemExtSpecific() bool { 884 return true 885} 886