1// Copyright (C) 2021 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 java 16 17import ( 18 "fmt" 19 "io" 20 "path/filepath" 21 "reflect" 22 "strings" 23 24 "android/soong/android" 25 "android/soong/dexpreopt" 26 27 "github.com/google/blueprint/proptools" 28 29 "github.com/google/blueprint" 30) 31 32func init() { 33 registerBootclasspathFragmentBuildComponents(android.InitRegistrationContext) 34 35 android.RegisterSdkMemberType(BootclasspathFragmentSdkMemberType) 36} 37 38func registerBootclasspathFragmentBuildComponents(ctx android.RegistrationContext) { 39 ctx.RegisterModuleType("bootclasspath_fragment", bootclasspathFragmentFactory) 40 ctx.RegisterModuleType("bootclasspath_fragment_test", testBootclasspathFragmentFactory) 41 ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootclasspathFragmentFactory) 42} 43 44// BootclasspathFragmentSdkMemberType is the member type used to add bootclasspath_fragments to 45// the SDK snapshot. It is exported for use by apex. 46var BootclasspathFragmentSdkMemberType = &bootclasspathFragmentMemberType{ 47 SdkMemberTypeBase: android.SdkMemberTypeBase{ 48 PropertyName: "bootclasspath_fragments", 49 SupportsSdk: true, 50 }, 51} 52 53type bootclasspathFragmentContentDependencyTag struct { 54 blueprint.BaseDependencyTag 55} 56 57// Avoid having to make bootclasspath_fragment content visible to the bootclasspath_fragment. 58// 59// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules 60// with proper dependencies. 61// TODO(b/177892522): Remove this and add needed visibility. 62func (b bootclasspathFragmentContentDependencyTag) ExcludeFromVisibilityEnforcement() { 63} 64 65// The bootclasspath_fragment contents must never depend on prebuilts. 66func (b bootclasspathFragmentContentDependencyTag) ReplaceSourceWithPrebuilt() bool { 67 return false 68} 69 70// SdkMemberType causes dependencies added with this tag to be automatically added to the sdk as if 71// they were specified using java_boot_libs or java_sdk_libs. 72func (b bootclasspathFragmentContentDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType { 73 // If the module is a java_sdk_library then treat it as if it was specified in the java_sdk_libs 74 // property, otherwise treat if it was specified in the java_boot_libs property. 75 if javaSdkLibrarySdkMemberType.IsInstance(child) { 76 return javaSdkLibrarySdkMemberType 77 } 78 79 return javaBootLibsSdkMemberType 80} 81 82func (b bootclasspathFragmentContentDependencyTag) ExportMember() bool { 83 return true 84} 85 86// Contents of bootclasspath fragments in an apex are considered to be directly in the apex, as if 87// they were listed in java_libs. 88func (b bootclasspathFragmentContentDependencyTag) CopyDirectlyInAnyApex() {} 89 90// Contents of bootclasspath fragments require files from prebuilt apex files. 91func (b bootclasspathFragmentContentDependencyTag) RequiresFilesFromPrebuiltApex() {} 92 93// The tag used for the dependency between the bootclasspath_fragment module and its contents. 94var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyTag{} 95 96var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathFragmentContentDepTag 97var _ android.ReplaceSourceWithPrebuilt = bootclasspathFragmentContentDepTag 98var _ android.SdkMemberDependencyTag = bootclasspathFragmentContentDepTag 99var _ android.CopyDirectlyInAnyApexTag = bootclasspathFragmentContentDepTag 100var _ android.RequiresFilesFromPrebuiltApexTag = bootclasspathFragmentContentDepTag 101 102func IsBootclasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool { 103 return tag == bootclasspathFragmentContentDepTag 104} 105 106// Properties that can be different when coverage is enabled. 107type BootclasspathFragmentCoverageAffectedProperties struct { 108 // The contents of this bootclasspath_fragment, could be either java_library, or java_sdk_library. 109 // 110 // A java_sdk_library specified here will also be treated as if it was specified on the stub_libs 111 // property. 112 // 113 // The order of this list matters as it is the order that is used in the bootclasspath. 114 Contents []string 115 116 // The properties for specifying the API stubs provided by this fragment. 117 BootclasspathAPIProperties 118} 119 120type bootclasspathFragmentProperties struct { 121 // The name of the image this represents. 122 // 123 // If specified then it must be one of "art" or "boot". 124 Image_name *string 125 126 // Properties whose values need to differ with and without coverage. 127 BootclasspathFragmentCoverageAffectedProperties 128 Coverage BootclasspathFragmentCoverageAffectedProperties 129 130 // Hidden API related properties. 131 HiddenAPIFlagFileProperties 132 133 // The list of additional stub libraries which this fragment's contents use but which are not 134 // provided by another bootclasspath_fragment. 135 // 136 // Note, "android-non-updatable" is treated specially. While no such module exists it is treated 137 // as if it was a java_sdk_library. So, when public API stubs are needed then it will be replaced 138 // with "android-non-updatable.stubs", with "androidn-non-updatable.system.stubs" when the system 139 // stubs are needed and so on. 140 Additional_stubs []string 141 142 // Properties that allow a fragment to depend on other fragments. This is needed for hidden API 143 // processing as it needs access to all the classes used by a fragment including those provided 144 // by other fragments. 145 BootclasspathFragmentsDepsProperties 146} 147 148type HiddenAPIPackageProperties struct { 149 Hidden_api struct { 150 // Contains prefixes of a package hierarchy that is provided solely by this 151 // bootclasspath_fragment. 152 // 153 // This affects the signature patterns file that is used to select the subset of monolithic 154 // hidden API flags. See split_packages property for more details. 155 Package_prefixes []string 156 157 // A list of individual packages that are provided solely by this 158 // bootclasspath_fragment but which cannot be listed in package_prefixes 159 // because there are sub-packages which are provided by other modules. 160 // 161 // This should only be used for legacy packages. New packages should be 162 // covered by a package prefix. 163 Single_packages []string 164 165 // The list of split packages provided by this bootclasspath_fragment. 166 // 167 // A split package is one that contains classes which are provided by multiple 168 // bootclasspath_fragment modules. 169 // 170 // This defaults to "*" - which treats all packages as being split. A module that has no split 171 // packages must specify an empty list. 172 // 173 // This affects the signature patterns file that is generated by a bootclasspath_fragment and 174 // used to select the subset of monolithic hidden API flags against which the flags generated 175 // by the bootclasspath_fragment are compared. 176 // 177 // The signature patterns file selects the subset of monolithic hidden API flags using a number 178 // of patterns, i.e.: 179 // * The qualified name (including package) of an outermost class, e.g. java/lang/Character. 180 // This selects all the flags for all the members of this class and any nested classes. 181 // * A package wildcard, e.g. java/lang/*. This selects all the flags for all the members of all 182 // the classes in this package (but not in sub-packages). 183 // * A recursive package wildcard, e.g. java/**. This selects all the flags for all the members 184 // of all the classes in this package and sub-packages. 185 // 186 // The signature patterns file is constructed as follows: 187 // * All the signatures are retrieved from the all-flags.csv file. 188 // * The member and inner class names are removed. 189 // * If a class is in a split package then that is kept, otherwise the class part is removed 190 // and replaced with a wildcard, i.e. *. 191 // * If a package matches a package prefix then the package is removed. 192 // * All the package prefixes are added with a recursive wildcard appended to each, i.e. **. 193 // * The resulting patterns are sorted. 194 // 195 // So, by default (i.e. without specifying any package_prefixes or split_packages) the signature 196 // patterns is a list of class names, because there are no package packages and all packages are 197 // assumed to be split. 198 // 199 // If any split packages are specified then only those packages are treated as split and all 200 // other packages are treated as belonging solely to the bootclasspath_fragment and so they use 201 // wildcard package patterns. 202 // 203 // So, if an empty list of split packages is specified then the signature patterns file just 204 // includes a wildcard package pattern for every package provided by the bootclasspath_fragment. 205 // 206 // If split_packages are specified and a package that is split is not listed then it could lead 207 // to build failures as it will select monolithic flags that are generated by another 208 // bootclasspath_fragment to compare against the flags provided by this fragment. The latter 209 // will obviously not contain those flags and that can cause the comparison and build to fail. 210 // 211 // If any package prefixes are specified then any matching packages are removed from the 212 // signature patterns and replaced with a single recursive package pattern. 213 // 214 // It is not strictly necessary to specify either package_prefixes or split_packages as the 215 // defaults will produce a valid set of signature patterns. However, those patterns may include 216 // implementation details, e.g. names of implementation classes or packages, which will be 217 // exported to the sdk snapshot in the signature patterns file. That is something that should be 218 // avoided where possible. Specifying package_prefixes and split_packages allows those 219 // implementation details to be excluded from the snapshot. 220 Split_packages []string 221 } 222} 223 224type SourceOnlyBootclasspathProperties struct { 225 HiddenAPIPackageProperties 226 Coverage HiddenAPIPackageProperties 227} 228 229type BootclasspathFragmentModule struct { 230 android.ModuleBase 231 android.ApexModuleBase 232 ClasspathFragmentBase 233 234 // True if this fragment is for testing purposes. 235 testFragment bool 236 237 properties bootclasspathFragmentProperties 238 239 sourceOnlyProperties SourceOnlyBootclasspathProperties 240 241 // Collect the module directory for IDE info in java/jdeps.go. 242 modulePaths []string 243 244 // Path to the boot image profile. 245 profilePath android.Path 246} 247 248// commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt 249// bootclasspath fragment modules. 250type commonBootclasspathFragment interface { 251 // produceHiddenAPIOutput produces the all-flags.csv and intermediate files and encodes the flags 252 // into dex files. 253 // 254 // Returns a *HiddenAPIOutput containing the paths for the generated files. Returns nil if the 255 // module cannot contribute to hidden API processing, e.g. because it is a prebuilt module in a 256 // versioned sdk. 257 produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput 258 259 // produceBootImageFiles will attempt to produce rules to create the boot image files at the paths 260 // predefined in the bootImageConfig. 261 // 262 // If it could not create the files then it will return nil. Otherwise, it will return a map from 263 // android.ArchType to the predefined paths of the boot image files. 264 produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs 265 266 // getImageName returns the `image_name` property of this fragment. 267 getImageName() *string 268 269 // getProfilePath returns the path to the boot image profile. 270 getProfilePath() android.Path 271} 272 273var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil) 274 275func bootclasspathFragmentFactory() android.Module { 276 m := &BootclasspathFragmentModule{} 277 m.AddProperties(&m.properties, &m.sourceOnlyProperties) 278 android.InitApexModule(m) 279 initClasspathFragment(m, BOOTCLASSPATH) 280 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 281 282 android.AddLoadHook(m, func(ctx android.LoadHookContext) { 283 // If code coverage has been enabled for the framework then append the properties with 284 // coverage specific properties. 285 if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { 286 err := proptools.AppendProperties(&m.properties.BootclasspathFragmentCoverageAffectedProperties, &m.properties.Coverage, nil) 287 if err != nil { 288 ctx.PropertyErrorf("coverage", "error trying to append coverage specific properties: %s", err) 289 return 290 } 291 292 err = proptools.AppendProperties(&m.sourceOnlyProperties.HiddenAPIPackageProperties, &m.sourceOnlyProperties.Coverage, nil) 293 if err != nil { 294 ctx.PropertyErrorf("coverage", "error trying to append hidden api coverage specific properties: %s", err) 295 return 296 } 297 } 298 299 // Initialize the contents property from the image_name. 300 bootclasspathFragmentInitContentsFromImage(ctx, m) 301 }) 302 return m 303} 304 305func testBootclasspathFragmentFactory() android.Module { 306 m := bootclasspathFragmentFactory().(*BootclasspathFragmentModule) 307 m.testFragment = true 308 return m 309} 310 311// bootclasspathFragmentInitContentsFromImage will initialize the contents property from the image_name if 312// necessary. 313func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, m *BootclasspathFragmentModule) { 314 contents := m.properties.Contents 315 if len(contents) == 0 { 316 ctx.PropertyErrorf("contents", "required property is missing") 317 return 318 } 319 320 if m.properties.Image_name == nil { 321 // Nothing to do. 322 return 323 } 324 325 imageName := proptools.String(m.properties.Image_name) 326 if imageName != "art" { 327 ctx.PropertyErrorf("image_name", `unknown image name %q, expected "art"`, imageName) 328 return 329 } 330 331 // Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is 332 // too early in the Soong processing for that to work. 333 global := dexpreopt.GetGlobalConfig(ctx) 334 modules := global.ArtApexJars 335 336 // Make sure that the apex specified in the configuration is consistent and is one for which 337 // this boot image is available. 338 commonApex := "" 339 for i := 0; i < modules.Len(); i++ { 340 apex := modules.Apex(i) 341 jar := modules.Jar(i) 342 if apex == "platform" { 343 ctx.ModuleErrorf("ArtApexJars is invalid as it requests a platform variant of %q", jar) 344 continue 345 } 346 if !m.AvailableFor(apex) { 347 ctx.ModuleErrorf("ArtApexJars configuration incompatible with this module, ArtApexJars expects this to be in apex %q but this is only in apexes %q", 348 apex, m.ApexAvailable()) 349 continue 350 } 351 if commonApex == "" { 352 commonApex = apex 353 } else if commonApex != apex { 354 ctx.ModuleErrorf("ArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex %q and %q", 355 commonApex, apex) 356 } 357 } 358} 359 360// bootclasspathImageNameContentsConsistencyCheck checks that the configuration that applies to this 361// module (if any) matches the contents. 362// 363// This should be a noop as if image_name="art" then the contents will be set from the ArtApexJars 364// config by bootclasspathFragmentInitContentsFromImage so it will be guaranteed to match. However, 365// in future this will not be the case. 366func (b *BootclasspathFragmentModule) bootclasspathImageNameContentsConsistencyCheck(ctx android.BaseModuleContext) { 367 imageName := proptools.String(b.properties.Image_name) 368 if imageName == "art" { 369 // Get the configuration for the art apex jars. 370 modules := b.getImageConfig(ctx).modules 371 configuredJars := modules.CopyOfJars() 372 373 // Skip the check if the configured jars list is empty as that is a common configuration when 374 // building targets that do not result in a system image. 375 if len(configuredJars) == 0 { 376 return 377 } 378 379 contents := b.properties.Contents 380 if !reflect.DeepEqual(configuredJars, contents) { 381 ctx.ModuleErrorf("inconsistency in specification of contents. ArtApexJars configuration specifies %#v, contents property specifies %#v", 382 configuredJars, contents) 383 } 384 } 385} 386 387var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider(BootclasspathFragmentApexContentInfo{}) 388 389// BootclasspathFragmentApexContentInfo contains the bootclasspath_fragments contributions to the 390// apex contents. 391type BootclasspathFragmentApexContentInfo struct { 392 // The configured modules, will be empty if this is from a bootclasspath_fragment that does not 393 // set image_name: "art". 394 modules android.ConfiguredJarList 395 396 // Map from the base module name (without prebuilt_ prefix) of a fragment's contents module to the 397 // hidden API encoded dex jar path. 398 contentModuleDexJarPaths bootDexJarByModule 399 400 // Path to the image profile file on host (or empty, if profile is not generated). 401 profilePathOnHost android.Path 402 403 // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not 404 // needed. 405 profileInstallPathInApex string 406} 407 408func (i BootclasspathFragmentApexContentInfo) Modules() android.ConfiguredJarList { 409 return i.modules 410} 411 412// DexBootJarPathForContentModule returns the path to the dex boot jar for specified module. 413// 414// The dex boot jar is one which has had hidden API encoding performed on it. 415func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(module android.Module) (android.Path, error) { 416 // A bootclasspath_fragment cannot use a prebuilt library so Name() will return the base name 417 // without a prebuilt_ prefix so is safe to use as the key for the contentModuleDexJarPaths. 418 name := module.Name() 419 if dexJar, ok := i.contentModuleDexJarPaths[name]; ok { 420 return dexJar, nil 421 } else { 422 return nil, fmt.Errorf("unknown bootclasspath_fragment content module %s, expected one of %s", 423 name, strings.Join(android.SortedKeys(i.contentModuleDexJarPaths), ", ")) 424 } 425} 426 427func (i BootclasspathFragmentApexContentInfo) ProfilePathOnHost() android.Path { 428 return i.profilePathOnHost 429} 430 431func (i BootclasspathFragmentApexContentInfo) ProfileInstallPathInApex() string { 432 return i.profileInstallPathInApex 433} 434 435func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { 436 tag := ctx.OtherModuleDependencyTag(dep) 437 if IsBootclasspathFragmentContentDepTag(tag) { 438 // Boot image contents are automatically added to apex. 439 return true 440 } 441 if android.IsMetaDependencyTag(tag) { 442 // Cross-cutting metadata dependencies are metadata. 443 return false 444 } 445 panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag))) 446} 447 448func (b *BootclasspathFragmentModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { 449 return nil 450} 451 452// ComponentDepsMutator adds dependencies onto modules before any prebuilt modules without a 453// corresponding source module are renamed. This means that adding a dependency using a name without 454// a prebuilt_ prefix will always resolve to a source module and when using a name with that prefix 455// it will always resolve to a prebuilt module. 456func (b *BootclasspathFragmentModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { 457 module := ctx.Module() 458 _, isSourceModule := module.(*BootclasspathFragmentModule) 459 460 for _, name := range b.properties.Contents { 461 // A bootclasspath_fragment must depend only on other source modules, while the 462 // prebuilt_bootclasspath_fragment must only depend on other prebuilt modules. 463 // 464 // TODO(b/177892522) - avoid special handling of jacocoagent. 465 if !isSourceModule && name != "jacocoagent" { 466 name = android.PrebuiltNameFromSource(name) 467 } 468 ctx.AddDependency(module, bootclasspathFragmentContentDepTag, name) 469 } 470 471} 472 473func (b *BootclasspathFragmentModule) DepsMutator(ctx android.BottomUpMutatorContext) { 474 // Add dependencies onto all the modules that provide the API stubs for classes on this 475 // bootclasspath fragment. 476 hiddenAPIAddStubLibDependencies(ctx, b.properties.apiScopeToStubLibs()) 477 478 for _, additionalStubModule := range b.properties.Additional_stubs { 479 for _, apiScope := range hiddenAPISdkLibrarySupportedScopes { 480 // Add a dependency onto a possibly scope specific stub library. 481 scopeSpecificDependency := apiScope.scopeSpecificStubModule(ctx, additionalStubModule) 482 // Use JavaApiLibraryName function to be redirected to stubs generated from .txt if applicable 483 scopeSpecificDependency = android.JavaApiLibraryName(ctx.Config(), scopeSpecificDependency) 484 tag := hiddenAPIStubsDependencyTag{apiScope: apiScope, fromAdditionalDependency: true} 485 ctx.AddVariationDependencies(nil, tag, scopeSpecificDependency) 486 } 487 } 488 489 if !dexpreopt.IsDex2oatNeeded(ctx) { 490 return 491 } 492 493 // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The 494 // path is retrieved from the dependency by GetGlobalSoongConfig(ctx). 495 dexpreopt.RegisterToolDeps(ctx) 496} 497 498func (b *BootclasspathFragmentModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) { 499 // Add dependencies on all the fragments. 500 b.properties.BootclasspathFragmentsDepsProperties.addDependenciesOntoFragments(ctx) 501} 502 503func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 504 // Only perform a consistency check if this module is the active module. That will prevent an 505 // unused prebuilt that was created without instrumentation from breaking an instrumentation 506 // build. 507 if isActiveModule(ctx.Module()) { 508 b.bootclasspathImageNameContentsConsistencyCheck(ctx) 509 } 510 511 // Generate classpaths.proto config 512 b.generateClasspathProtoBuildActions(ctx) 513 514 // Collect the module directory for IDE info in java/jdeps.go. 515 b.modulePaths = append(b.modulePaths, ctx.ModuleDir()) 516 517 // Gather the bootclasspath fragment's contents. 518 var contents []android.Module 519 ctx.VisitDirectDeps(func(module android.Module) { 520 tag := ctx.OtherModuleDependencyTag(module) 521 if IsBootclasspathFragmentContentDepTag(tag) { 522 contents = append(contents, module) 523 } 524 }) 525 526 fragments := gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag) 527 528 // Verify that the image_name specified on a bootclasspath_fragment is valid even if this is a 529 // prebuilt which will not use the image config. 530 imageConfig := b.getImageConfig(ctx) 531 532 // Perform hidden API processing. 533 hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments) 534 535 var bootImageFiles bootImageOutputs 536 if imageConfig != nil { 537 // Delegate the production of the boot image files to a module type specific method. 538 common := ctx.Module().(commonBootclasspathFragment) 539 bootImageFiles = common.produceBootImageFiles(ctx, imageConfig) 540 b.profilePath = bootImageFiles.profile 541 542 if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) { 543 // Zip the boot image files up, if available. This will generate the zip file in a 544 // predefined location. 545 buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFiles.byArch) 546 547 // Copy the dex jars of this fragment's content modules to their predefined locations. 548 copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule) 549 } 550 } 551 552 // A prebuilt fragment cannot contribute to an apex. 553 if !android.IsModulePrebuilt(ctx.Module()) { 554 // Provide the apex content info. 555 b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFiles) 556 } 557 558 // In order for information about bootclasspath_fragment modules to be added to module-info.json 559 // it is necessary to output an entry to Make. As bootclasspath_fragment modules are part of an 560 // APEX there can be multiple variants, including the default/platform variant and only one can 561 // be output to Make but it does not really matter which variant is output. The default/platform 562 // variant is the first (ctx.PrimaryModule()) and is usually hidden from make so this just picks 563 // the last variant (ctx.FinalModule()). 564 if ctx.Module() != ctx.FinalModule() { 565 b.HideFromMake() 566 } 567} 568 569// shouldCopyBootFilesToPredefinedLocations determines whether the current module should copy boot 570// files, e.g. boot dex jars or boot image files, to the predefined location expected by the rest 571// of the build. 572// 573// This ensures that only a single module will copy its files to the image configuration. 574func shouldCopyBootFilesToPredefinedLocations(ctx android.ModuleContext, imageConfig *bootImageConfig) bool { 575 // Bootclasspath fragment modules that are for the platform do not produce boot related files. 576 apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) 577 if apexInfo.IsForPlatform() { 578 return false 579 } 580 581 // If the image configuration has no modules specified then it means that the build has been 582 // configured to build something other than a boot image, e.g. an sdk, so do not try and copy the 583 // files. 584 if imageConfig.modules.Len() == 0 { 585 return false 586 } 587 588 // Only copy files from the module that is preferred. 589 return isActiveModule(ctx.Module()) 590} 591 592// provideApexContentInfo creates, initializes and stores the apex content info for use by other 593// modules. 594func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFiles bootImageOutputs) { 595 // Construct the apex content info from the config. 596 info := BootclasspathFragmentApexContentInfo{ 597 // Populate the apex content info with paths to the dex jars. 598 contentModuleDexJarPaths: hiddenAPIOutput.EncodedBootDexFilesByModule, 599 } 600 601 if imageConfig != nil { 602 info.modules = imageConfig.modules 603 global := dexpreopt.GetGlobalConfig(ctx) 604 if !global.DisableGenerateProfile { 605 info.profilePathOnHost = bootImageFiles.profile 606 info.profileInstallPathInApex = imageConfig.profileInstallPathInApex 607 } 608 } 609 610 // Make the apex content info available for other modules. 611 ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info) 612} 613 614// generateClasspathProtoBuildActions generates all required build actions for classpath.proto config 615func (b *BootclasspathFragmentModule) generateClasspathProtoBuildActions(ctx android.ModuleContext) { 616 var classpathJars []classpathJar 617 configuredJars := b.configuredJars(ctx) 618 if "art" == proptools.String(b.properties.Image_name) { 619 // ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH 620 classpathJars = configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) 621 } else { 622 classpathJars = configuredJarListToClasspathJars(ctx, configuredJars, b.classpathType) 623 } 624 b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) 625} 626 627func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { 628 if "art" == proptools.String(b.properties.Image_name) { 629 return b.getImageConfig(ctx).modules 630 } 631 632 global := dexpreopt.GetGlobalConfig(ctx) 633 634 possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag) 635 jars, unknown := global.ApexBootJars.Filter(possibleUpdatableModules) 636 637 // TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths 638 // config. However, any test specific jars would not be present in ApexBootJars. Instead, 639 // we should check if we are creating a config for apex_test via ApexInfo and amend the values. 640 // This is an exception to support end-to-end test for SdkExtensions, until such support exists. 641 if android.InList("test_framework-sdkextensions", possibleUpdatableModules) { 642 jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions") 643 } else if android.InList("test_framework-apexd", possibleUpdatableModules) { 644 jars = jars.Append("com.android.apex.test_package", "test_framework-apexd") 645 } else if global.ApexBootJars.Len() != 0 { 646 unknown = android.RemoveListFromList(unknown, b.properties.Coverage.Contents) 647 _, unknown = android.RemoveFromList("core-icu4j", unknown) 648 // This module only exists in car products. 649 // So ignore it even if it is not in PRODUCT_APEX_BOOT_JARS. 650 // TODO(b/202896428): Add better way to handle this. 651 _, unknown = android.RemoveFromList("android.car-module", unknown) 652 if len(unknown) > 0 { 653 ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown) 654 } 655 } 656 return jars 657} 658 659func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig { 660 // Get a map of the image configs that are supported. 661 imageConfigs := genBootImageConfigs(ctx) 662 663 // Retrieve the config for this image. 664 imageNamePtr := b.properties.Image_name 665 if imageNamePtr == nil { 666 return nil 667 } 668 669 imageName := *imageNamePtr 670 imageConfig := imageConfigs[imageName] 671 if imageConfig == nil { 672 ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedKeys(imageConfigs), ", ")) 673 return nil 674 } 675 return imageConfig 676} 677 678// generateHiddenAPIBuildActions generates all the hidden API related build rules. 679func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput { 680 681 // Create hidden API input structure. 682 input := b.createHiddenAPIFlagInput(ctx, contents, fragments) 683 684 // Delegate the production of the hidden API all-flags.csv file to a module type specific method. 685 common := ctx.Module().(commonBootclasspathFragment) 686 output := common.produceHiddenAPIOutput(ctx, contents, fragments, input) 687 688 // If the source or prebuilts module does not provide a signature patterns file then generate one 689 // from the flags. 690 // TODO(b/192868581): Remove once the source and prebuilts provide a signature patterns file of 691 // their own. 692 if output.SignaturePatternsPath == nil { 693 output.SignaturePatternsPath = buildRuleSignaturePatternsFile( 694 ctx, output.AllFlagsPath, []string{"*"}, nil, nil, "") 695 } 696 697 // Initialize a HiddenAPIInfo structure. 698 hiddenAPIInfo := HiddenAPIInfo{ 699 // The monolithic hidden API processing needs access to the flag files that override the default 700 // flags from all the fragments whether or not they actually perform their own hidden API flag 701 // generation. That is because the monolithic hidden API processing uses those flag files to 702 // perform its own flag generation. 703 FlagFilesByCategory: input.FlagFilesByCategory, 704 705 // Other bootclasspath_fragments that depend on this need the transitive set of stub dex jars 706 // from this to resolve any references from their code to classes provided by this fragment 707 // and the fragments this depends upon. 708 TransitiveStubDexJarsByScope: input.transitiveStubDexJarsByScope(), 709 } 710 711 // The monolithic hidden API processing also needs access to all the output files produced by 712 // hidden API processing of this fragment. 713 hiddenAPIInfo.HiddenAPIFlagOutput = output.HiddenAPIFlagOutput 714 715 // Provide it for use by other modules. 716 ctx.SetProvider(HiddenAPIInfoProvider, hiddenAPIInfo) 717 718 return output 719} 720 721// retrieveLegacyEncodedBootDexFiles attempts to retrieve the legacy encoded boot dex jar files. 722func retrieveLegacyEncodedBootDexFiles(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule { 723 // If the current bootclasspath_fragment is the active module or a source module then retrieve the 724 // encoded dex files, otherwise return an empty map. 725 // 726 // An inactive (i.e. not preferred) bootclasspath_fragment needs to retrieve the encoded dex jars 727 // as they are still needed by an apex. An inactive prebuilt_bootclasspath_fragment does not need 728 // to do so and may not yet have access to dex boot jars from a prebuilt_apex/apex_set. 729 if isActiveModule(ctx.Module()) || !android.IsModulePrebuilt(ctx.Module()) { 730 return extractEncodedDexJarsFromModules(ctx, contents) 731 } else { 732 return nil 733 } 734} 735 736// createHiddenAPIFlagInput creates a HiddenAPIFlagInput struct and initializes it with information derived 737// from the properties on this module and its dependencies. 738func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) HiddenAPIFlagInput { 739 // Merge the HiddenAPIInfo from all the fragment dependencies. 740 dependencyHiddenApiInfo := newHiddenAPIInfo() 741 dependencyHiddenApiInfo.mergeFromFragmentDeps(ctx, fragments) 742 743 // Create hidden API flag input structure. 744 input := newHiddenAPIFlagInput() 745 746 // Update the input structure with information obtained from the stub libraries. 747 input.gatherStubLibInfo(ctx, contents) 748 749 // Populate with flag file paths from the properties. 750 input.extractFlagFilesFromProperties(ctx, &b.properties.HiddenAPIFlagFileProperties) 751 752 // Populate with package rules from the properties. 753 input.extractPackageRulesFromProperties(&b.sourceOnlyProperties.HiddenAPIPackageProperties) 754 755 input.gatherPropertyInfo(ctx, contents) 756 757 // Add the stub dex jars from this module's fragment dependencies. 758 input.DependencyStubDexJarsByScope.addStubDexJarsByModule(dependencyHiddenApiInfo.TransitiveStubDexJarsByScope) 759 760 return input 761} 762 763// isTestFragment returns true if the current module is a test bootclasspath_fragment. 764func (b *BootclasspathFragmentModule) isTestFragment() bool { 765 return b.testFragment 766} 767 768// generateHiddenApiFlagRules generates rules to generate hidden API flags and compute the signature 769// patterns file. 770func (b *BootclasspathFragmentModule) generateHiddenApiFlagRules(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput, bootDexInfoByModule bootDexInfoByModule, suffix string) HiddenAPIFlagOutput { 771 // Generate the rules to create the hidden API flags and update the supplied hiddenAPIInfo with the 772 // paths to the created files. 773 flagOutput := hiddenAPIFlagRulesForBootclasspathFragment(ctx, bootDexInfoByModule, contents, input, suffix) 774 775 // If the module specifies split_packages or package_prefixes then use those to generate the 776 // signature patterns. 777 splitPackages := input.SplitPackages 778 packagePrefixes := input.PackagePrefixes 779 singlePackages := input.SinglePackages 780 if splitPackages != nil || packagePrefixes != nil || singlePackages != nil { 781 flagOutput.SignaturePatternsPath = buildRuleSignaturePatternsFile( 782 ctx, flagOutput.AllFlagsPath, splitPackages, packagePrefixes, singlePackages, suffix) 783 } else if !b.isTestFragment() { 784 ctx.ModuleErrorf(`Must specify at least one of the split_packages, package_prefixes and single_packages properties 785 If this is a new bootclasspath_fragment or you are unsure what to do add the 786 the following to the bootclasspath_fragment: 787 hidden_api: {split_packages: ["*"]}, 788 and then run the following: 789 m analyze_bcpf && analyze_bcpf --bcpf %q 790 it will analyze the bootclasspath_fragment and provide hints as to what you 791 should specify here. If you are happy with its suggestions then you can add 792 the --fix option and it will fix them for you.`, b.BaseModuleName()) 793 } 794 return flagOutput 795} 796 797// produceHiddenAPIOutput produces the hidden API all-flags.csv file (and supporting files) 798// for the fragment as well as encoding the flags in the boot dex jars. 799func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput { 800 // Gather information about the boot dex files for the boot libraries provided by this fragment. 801 bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents) 802 803 // Generate the flag file needed to encode into the dex files. 804 flagOutput := b.generateHiddenApiFlagRules(ctx, contents, input, bootDexInfoByModule, "") 805 806 // Encode those flags into the dex files of the contents of this fragment. 807 encodedBootDexFilesByModule := hiddenAPIEncodeRulesForBootclasspathFragment(ctx, bootDexInfoByModule, flagOutput.AllFlagsPath) 808 809 // Store that information for return for use by other rules. 810 output := &HiddenAPIOutput{ 811 HiddenAPIFlagOutput: flagOutput, 812 EncodedBootDexFilesByModule: encodedBootDexFilesByModule, 813 } 814 815 // Get the ApiLevel associated with SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE, defaulting to current 816 // if not set. 817 config := ctx.Config() 818 targetApiLevel := android.ApiLevelOrPanic(ctx, 819 config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", "current")) 820 821 // Filter the contents list to remove any modules that do not support the target build release. 822 // The current build release supports all the modules. 823 contentsForSdkSnapshot := []android.Module{} 824 for _, module := range contents { 825 // If the module has a min_sdk_version that is higher than the target build release then it will 826 // not work on the target build release and so must not be included in the sdk snapshot. 827 minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, module) 828 if minApiLevel.GreaterThan(targetApiLevel) { 829 continue 830 } 831 832 contentsForSdkSnapshot = append(contentsForSdkSnapshot, module) 833 } 834 835 var flagFilesByCategory FlagFilesByCategory 836 if len(contentsForSdkSnapshot) != len(contents) { 837 // The sdk snapshot has different contents to the runtime fragment so it is not possible to 838 // reuse the hidden API information generated for the fragment. So, recompute that information 839 // for the sdk snapshot. 840 filteredInput := b.createHiddenAPIFlagInput(ctx, contentsForSdkSnapshot, fragments) 841 842 // Gather information about the boot dex files for the boot libraries provided by this fragment. 843 filteredBootDexInfoByModule := extractBootDexInfoFromModules(ctx, contentsForSdkSnapshot) 844 flagOutput = b.generateHiddenApiFlagRules(ctx, contentsForSdkSnapshot, filteredInput, filteredBootDexInfoByModule, "-for-sdk-snapshot") 845 flagFilesByCategory = filteredInput.FlagFilesByCategory 846 } else { 847 // The sdk snapshot has the same contents as the runtime fragment so reuse that information. 848 flagFilesByCategory = input.FlagFilesByCategory 849 } 850 851 // Make the information available for the sdk snapshot. 852 ctx.SetProvider(HiddenAPIInfoForSdkProvider, HiddenAPIInfoForSdk{ 853 FlagFilesByCategory: flagFilesByCategory, 854 HiddenAPIFlagOutput: flagOutput, 855 }) 856 857 return output 858} 859 860// produceBootImageFiles builds the boot image files from the source if it is required. 861func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs { 862 // Only generate the boot image if the configuration does not skip it. 863 return b.generateBootImageBuildActions(ctx, imageConfig) 864} 865 866// generateBootImageBuildActions generates ninja rules to create the boot image if required for this 867// module. 868// 869// If it could not create the files then it will return nil. Otherwise, it will return a map from 870// android.ArchType to the predefined paths of the boot image files. 871func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs { 872 global := dexpreopt.GetGlobalConfig(ctx) 873 if !shouldBuildBootImages(ctx.Config(), global) { 874 return bootImageOutputs{} 875 } 876 877 // Bootclasspath fragment modules that are for the platform do not produce a boot image. 878 apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) 879 if apexInfo.IsForPlatform() { 880 return bootImageOutputs{} 881 } 882 883 // Build a profile for the image config and then use that to build the boot image. 884 profile := bootImageProfileRule(ctx, imageConfig) 885 886 // If dexpreopt of boot image jars should be skipped, generate only a profile. 887 if SkipDexpreoptBootJars(ctx) { 888 return bootImageOutputs{ 889 profile: profile, 890 } 891 } 892 893 // Build boot image files for the host variants. 894 buildBootImageVariantsForBuildOs(ctx, imageConfig, profile) 895 896 // Build boot image files for the android variants. 897 bootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile) 898 899 // Return the boot image files for the android variants for inclusion in an APEX and to be zipped 900 // up for the dist. 901 return bootImageFiles 902} 903 904func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries { 905 // Use the generated classpath proto as the output. 906 outputFile := b.outputFilepath 907 // Create a fake entry that will cause this to be added to the module-info.json file. 908 entriesList := []android.AndroidMkEntries{{ 909 Class: "FAKE", 910 OutputFile: android.OptionalPathForPath(outputFile), 911 Include: "$(BUILD_PHONY_PACKAGE)", 912 ExtraFooters: []android.AndroidMkExtraFootersFunc{ 913 func(w io.Writer, name, prefix, moduleDir string) { 914 // Allow the bootclasspath_fragment to be built by simply passing its name on the command 915 // line. 916 fmt.Fprintln(w, ".PHONY:", b.Name()) 917 fmt.Fprintln(w, b.Name()+":", outputFile.String()) 918 }, 919 }, 920 }} 921 return entriesList 922} 923 924func (b *BootclasspathFragmentModule) getImageName() *string { 925 return b.properties.Image_name 926} 927 928func (b *BootclasspathFragmentModule) getProfilePath() android.Path { 929 return b.profilePath 930} 931 932// Collect information for opening IDE project files in java/jdeps.go. 933func (b *BootclasspathFragmentModule) IDEInfo(dpInfo *android.IdeInfo) { 934 dpInfo.Deps = append(dpInfo.Deps, b.properties.Contents...) 935 dpInfo.Paths = append(dpInfo.Paths, b.modulePaths...) 936} 937 938type bootclasspathFragmentMemberType struct { 939 android.SdkMemberTypeBase 940} 941 942func (b *bootclasspathFragmentMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) { 943 ctx.AddVariationDependencies(nil, dependencyTag, names...) 944} 945 946func (b *bootclasspathFragmentMemberType) IsInstance(module android.Module) bool { 947 _, ok := module.(*BootclasspathFragmentModule) 948 return ok 949} 950 951func (b *bootclasspathFragmentMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { 952 if b.PropertyName == "boot_images" { 953 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image") 954 } else { 955 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_bootclasspath_fragment") 956 } 957} 958 959func (b *bootclasspathFragmentMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { 960 return &bootclasspathFragmentSdkMemberProperties{} 961} 962 963type bootclasspathFragmentSdkMemberProperties struct { 964 android.SdkMemberPropertiesBase 965 966 // The image name 967 Image_name *string 968 969 // Contents of the bootclasspath fragment 970 Contents []string 971 972 // Stub_libs properties. 973 Stub_libs []string 974 Core_platform_stub_libs []string 975 976 // Fragment properties 977 Fragments []ApexVariantReference 978 979 // Flag files by *hiddenAPIFlagFileCategory 980 Flag_files_by_category FlagFilesByCategory 981 982 // The path to the generated annotation-flags.csv file. 983 Annotation_flags_path android.OptionalPath 984 985 // The path to the generated metadata.csv file. 986 Metadata_path android.OptionalPath 987 988 // The path to the generated index.csv file. 989 Index_path android.OptionalPath 990 991 // The path to the generated stub-flags.csv file. 992 Stub_flags_path android.OptionalPath `supported_build_releases:"S"` 993 994 // The path to the generated all-flags.csv file. 995 All_flags_path android.OptionalPath `supported_build_releases:"S"` 996 997 // The path to the generated signature-patterns.csv file. 998 Signature_patterns_path android.OptionalPath `supported_build_releases:"Tiramisu+"` 999 1000 // The path to the generated filtered-stub-flags.csv file. 1001 Filtered_stub_flags_path android.OptionalPath `supported_build_releases:"Tiramisu+"` 1002 1003 // The path to the generated filtered-flags.csv file. 1004 Filtered_flags_path android.OptionalPath `supported_build_releases:"Tiramisu+"` 1005} 1006 1007func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { 1008 module := variant.(*BootclasspathFragmentModule) 1009 1010 b.Image_name = module.properties.Image_name 1011 b.Contents = module.properties.Contents 1012 1013 // Get the hidden API information from the module. 1014 mctx := ctx.SdkModuleContext() 1015 hiddenAPIInfo := mctx.OtherModuleProvider(module, HiddenAPIInfoForSdkProvider).(HiddenAPIInfoForSdk) 1016 b.Flag_files_by_category = hiddenAPIInfo.FlagFilesByCategory 1017 1018 // Copy all the generated file paths. 1019 b.Annotation_flags_path = android.OptionalPathForPath(hiddenAPIInfo.AnnotationFlagsPath) 1020 b.Metadata_path = android.OptionalPathForPath(hiddenAPIInfo.MetadataPath) 1021 b.Index_path = android.OptionalPathForPath(hiddenAPIInfo.IndexPath) 1022 1023 b.Stub_flags_path = android.OptionalPathForPath(hiddenAPIInfo.StubFlagsPath) 1024 b.All_flags_path = android.OptionalPathForPath(hiddenAPIInfo.AllFlagsPath) 1025 1026 b.Signature_patterns_path = android.OptionalPathForPath(hiddenAPIInfo.SignaturePatternsPath) 1027 b.Filtered_stub_flags_path = android.OptionalPathForPath(hiddenAPIInfo.FilteredStubFlagsPath) 1028 b.Filtered_flags_path = android.OptionalPathForPath(hiddenAPIInfo.FilteredFlagsPath) 1029 1030 // Copy stub_libs properties. 1031 b.Stub_libs = module.properties.Api.Stub_libs 1032 b.Core_platform_stub_libs = module.properties.Core_platform_api.Stub_libs 1033 1034 // Copy fragment properties. 1035 b.Fragments = module.properties.Fragments 1036} 1037 1038func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { 1039 if b.Image_name != nil { 1040 propertySet.AddProperty("image_name", *b.Image_name) 1041 } 1042 1043 builder := ctx.SnapshotBuilder() 1044 requiredMemberDependency := builder.SdkMemberReferencePropertyTag(true) 1045 1046 if len(b.Contents) > 0 { 1047 propertySet.AddPropertyWithTag("contents", b.Contents, requiredMemberDependency) 1048 } 1049 1050 if len(b.Stub_libs) > 0 { 1051 apiPropertySet := propertySet.AddPropertySet("api") 1052 apiPropertySet.AddPropertyWithTag("stub_libs", b.Stub_libs, requiredMemberDependency) 1053 } 1054 if len(b.Core_platform_stub_libs) > 0 { 1055 corePlatformApiPropertySet := propertySet.AddPropertySet("core_platform_api") 1056 corePlatformApiPropertySet.AddPropertyWithTag("stub_libs", b.Core_platform_stub_libs, requiredMemberDependency) 1057 } 1058 if len(b.Fragments) > 0 { 1059 propertySet.AddProperty("fragments", b.Fragments) 1060 } 1061 1062 hiddenAPISet := propertySet.AddPropertySet("hidden_api") 1063 hiddenAPIDir := "hiddenapi" 1064 1065 // Copy manually curated flag files specified on the bootclasspath_fragment. 1066 if b.Flag_files_by_category != nil { 1067 for _, category := range HiddenAPIFlagFileCategories { 1068 paths := b.Flag_files_by_category[category] 1069 if len(paths) > 0 { 1070 dests := []string{} 1071 for _, p := range paths { 1072 dest := filepath.Join(hiddenAPIDir, p.Base()) 1073 builder.CopyToSnapshot(p, dest) 1074 dests = append(dests, dest) 1075 } 1076 hiddenAPISet.AddProperty(category.PropertyName, dests) 1077 } 1078 } 1079 } 1080 1081 copyOptionalPath := func(path android.OptionalPath, property string) { 1082 if path.Valid() { 1083 p := path.Path() 1084 dest := filepath.Join(hiddenAPIDir, p.Base()) 1085 builder.CopyToSnapshot(p, dest) 1086 hiddenAPISet.AddProperty(property, dest) 1087 } 1088 } 1089 1090 // Copy all the generated files, if available. 1091 copyOptionalPath(b.Annotation_flags_path, "annotation_flags") 1092 copyOptionalPath(b.Metadata_path, "metadata") 1093 copyOptionalPath(b.Index_path, "index") 1094 1095 copyOptionalPath(b.Stub_flags_path, "stub_flags") 1096 copyOptionalPath(b.All_flags_path, "all_flags") 1097 1098 copyOptionalPath(b.Signature_patterns_path, "signature_patterns") 1099 copyOptionalPath(b.Filtered_stub_flags_path, "filtered_stub_flags") 1100 copyOptionalPath(b.Filtered_flags_path, "filtered_flags") 1101} 1102 1103var _ android.SdkMemberType = (*bootclasspathFragmentMemberType)(nil) 1104 1105// prebuiltBootclasspathFragmentProperties contains additional prebuilt_bootclasspath_fragment 1106// specific properties. 1107type prebuiltBootclasspathFragmentProperties struct { 1108 Hidden_api struct { 1109 // The path to the annotation-flags.csv file created by the bootclasspath_fragment. 1110 Annotation_flags *string `android:"path"` 1111 1112 // The path to the metadata.csv file created by the bootclasspath_fragment. 1113 Metadata *string `android:"path"` 1114 1115 // The path to the index.csv file created by the bootclasspath_fragment. 1116 Index *string `android:"path"` 1117 1118 // The path to the signature-patterns.csv file created by the bootclasspath_fragment. 1119 Signature_patterns *string `android:"path"` 1120 1121 // The path to the stub-flags.csv file created by the bootclasspath_fragment. 1122 Stub_flags *string `android:"path"` 1123 1124 // The path to the all-flags.csv file created by the bootclasspath_fragment. 1125 All_flags *string `android:"path"` 1126 1127 // The path to the filtered-stub-flags.csv file created by the bootclasspath_fragment. 1128 Filtered_stub_flags *string `android:"path"` 1129 1130 // The path to the filtered-flags.csv file created by the bootclasspath_fragment. 1131 Filtered_flags *string `android:"path"` 1132 } 1133} 1134 1135// A prebuilt version of the bootclasspath_fragment module. 1136// 1137// At the moment this is basically just a bootclasspath_fragment module that can be used as a 1138// prebuilt. Eventually as more functionality is migrated into the bootclasspath_fragment module 1139// type from the various singletons then this will diverge. 1140type PrebuiltBootclasspathFragmentModule struct { 1141 BootclasspathFragmentModule 1142 prebuilt android.Prebuilt 1143 1144 // Additional prebuilt specific properties. 1145 prebuiltProperties prebuiltBootclasspathFragmentProperties 1146} 1147 1148func (module *PrebuiltBootclasspathFragmentModule) Prebuilt() *android.Prebuilt { 1149 return &module.prebuilt 1150} 1151 1152func (module *PrebuiltBootclasspathFragmentModule) Name() string { 1153 return module.prebuilt.Name(module.ModuleBase.Name()) 1154} 1155 1156// produceHiddenAPIOutput returns a path to the prebuilt all-flags.csv or nil if none is specified. 1157func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput { 1158 pathForOptionalSrc := func(src *string, defaultPath android.Path) android.Path { 1159 if src == nil { 1160 return defaultPath 1161 } 1162 return android.PathForModuleSrc(ctx, *src) 1163 } 1164 pathForSrc := func(property string, src *string) android.Path { 1165 if src == nil { 1166 ctx.PropertyErrorf(property, "is required but was not specified") 1167 return android.PathForModuleSrc(ctx, "missing", property) 1168 } 1169 return android.PathForModuleSrc(ctx, *src) 1170 } 1171 1172 // Retrieve the dex files directly from the content modules. They in turn should retrieve the 1173 // encoded dex jars from the prebuilt .apex files. 1174 encodedBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, contents) 1175 1176 output := HiddenAPIOutput{ 1177 HiddenAPIFlagOutput: HiddenAPIFlagOutput{ 1178 AnnotationFlagsPath: pathForSrc("hidden_api.annotation_flags", module.prebuiltProperties.Hidden_api.Annotation_flags), 1179 MetadataPath: pathForSrc("hidden_api.metadata", module.prebuiltProperties.Hidden_api.Metadata), 1180 IndexPath: pathForSrc("hidden_api.index", module.prebuiltProperties.Hidden_api.Index), 1181 SignaturePatternsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Signature_patterns, nil), 1182 // TODO: Temporarily handle stub_flags/all_flags properties until prebuilts have been updated. 1183 StubFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Stub_flags, nil), 1184 AllFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.All_flags, nil), 1185 }, 1186 1187 EncodedBootDexFilesByModule: encodedBootDexJarsByModule, 1188 } 1189 1190 // TODO: Temporarily fallback to stub_flags/all_flags properties until prebuilts have been updated. 1191 output.FilteredStubFlagsPath = pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Filtered_stub_flags, output.StubFlagsPath) 1192 output.FilteredFlagsPath = pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Filtered_flags, output.AllFlagsPath) 1193 1194 return &output 1195} 1196 1197// produceBootImageFiles extracts the boot image files from the APEX if available. 1198func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs { 1199 if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) { 1200 return bootImageOutputs{} 1201 } 1202 1203 di := android.FindDeapexerProviderForModule(ctx) 1204 if di == nil { 1205 return bootImageOutputs{} // An error has been reported by FindDeapexerProviderForModule. 1206 } 1207 1208 profile := (android.WritablePath)(nil) 1209 if imageConfig.profileInstallPathInApex != "" { 1210 profile = di.PrebuiltExportPath(imageConfig.profileInstallPathInApex) 1211 } 1212 1213 // Build the boot image files for the host variants. These are always built from the dex files 1214 // provided by the contents of this module as prebuilt versions of the host boot image files are 1215 // not available, i.e. there is no host specific prebuilt apex containing them. This has to be 1216 // built without a profile as the prebuilt modules do not provide a profile. 1217 buildBootImageVariantsForBuildOs(ctx, imageConfig, profile) 1218 1219 if profile == nil && imageConfig.isProfileGuided() { 1220 ctx.ModuleErrorf("Unable to produce boot image files: profiles not found in the prebuilt apex") 1221 return bootImageOutputs{} 1222 } 1223 // Build boot image files for the android variants from the dex files provided by the contents 1224 // of this module. 1225 return buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile) 1226} 1227 1228func (b *PrebuiltBootclasspathFragmentModule) getImageName() *string { 1229 return b.properties.Image_name 1230} 1231 1232func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path { 1233 return b.profilePath 1234} 1235 1236var _ commonBootclasspathFragment = (*PrebuiltBootclasspathFragmentModule)(nil) 1237 1238// RequiredFilesFromPrebuiltApex returns the list of all files the prebuilt_bootclasspath_fragment 1239// requires from a prebuilt .apex file. 1240// 1241// If there is no image config associated with this fragment then it returns nil. Otherwise, it 1242// returns the files that are listed in the image config. 1243func (module *PrebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string { 1244 imageConfig := module.getImageConfig(ctx) 1245 if imageConfig != nil { 1246 files := []string{} 1247 if imageConfig.profileInstallPathInApex != "" { 1248 // Add the boot image profile. 1249 files = append(files, imageConfig.profileInstallPathInApex) 1250 } 1251 return files 1252 } 1253 return nil 1254} 1255 1256var _ android.RequiredFilesFromPrebuiltApex = (*PrebuiltBootclasspathFragmentModule)(nil) 1257 1258func prebuiltBootclasspathFragmentFactory() android.Module { 1259 m := &PrebuiltBootclasspathFragmentModule{} 1260 m.AddProperties(&m.properties, &m.prebuiltProperties) 1261 // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs 1262 // array. 1263 android.InitPrebuiltModule(m, &[]string{"placeholder"}) 1264 android.InitApexModule(m) 1265 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon) 1266 1267 // Initialize the contents property from the image_name. 1268 android.AddLoadHook(m, func(ctx android.LoadHookContext) { 1269 bootclasspathFragmentInitContentsFromImage(ctx, &m.BootclasspathFragmentModule) 1270 }) 1271 return m 1272} 1273